From b0611f31895130dcc27bef93bf1d54dfbfc1da43 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 20 Nov 2011 12:14:10 +1100 Subject: M4: Removed the M4/MADS engine from trunk --- AUTHORS | 6 - audio/decoders/flac.h | 1 - audio/decoders/mp3.h | 1 - audio/decoders/vorbis.h | 1 - base/plugins.cpp | 3 - configure | 1 - dists/engine-data/m4.dat | Bin 137897 -> 0 bytes dists/engine-data/mads.dat | Bin 12126 -> 0 bytes dists/scummvm.rc | 3 - engines/m4/actor.cpp | 199 ------ engines/m4/actor.h | 114 ---- engines/m4/animation.cpp | 535 --------------- engines/m4/animation.h | 127 ---- engines/m4/assets.cpp | 650 ------------------ engines/m4/assets.h | 212 ------ engines/m4/burger_data.h | 82 --- engines/m4/compression.cpp | 190 ------ engines/m4/compression.h | 77 --- engines/m4/console.cpp | 428 ------------ engines/m4/console.h | 83 --- engines/m4/converse.cpp | 1239 --------------------------------- engines/m4/converse.h | 214 ------ engines/m4/detection.cpp | 419 ------------ engines/m4/dialogs.cpp | 558 --------------- engines/m4/dialogs.h | 80 --- engines/m4/events.cpp | 365 ---------- engines/m4/events.h | 132 ---- engines/m4/font.cpp | 291 -------- engines/m4/font.h | 119 ---- engines/m4/globals.cpp | 554 --------------- engines/m4/globals.h | 346 ---------- engines/m4/graphics.cpp | 1361 ------------------------------------ engines/m4/graphics.h | 270 -------- engines/m4/gui.cpp | 1215 --------------------------------- engines/m4/gui.h | 453 ------------ engines/m4/hotspot.cpp | 283 -------- engines/m4/hotspot.h | 126 ---- engines/m4/m4.cpp | 606 ---------------- engines/m4/m4.h | 252 ------- engines/m4/m4_menus.cpp | 724 -------------------- engines/m4/m4_menus.h | 103 --- engines/m4/m4_scene.cpp | 326 --------- engines/m4/m4_scene.h | 84 --- engines/m4/m4_views.cpp | 342 ---------- engines/m4/m4_views.h | 115 ---- engines/m4/mads_anim.cpp | 745 -------------------- engines/m4/mads_anim.h | 110 --- engines/m4/mads_logic.cpp | 1038 ---------------------------- engines/m4/mads_logic.h | 117 ---- engines/m4/mads_menus.cpp | 1173 ------------------------------- engines/m4/mads_menus.h | 179 ----- engines/m4/mads_player.cpp | 789 --------------------- engines/m4/mads_player.h | 113 --- engines/m4/mads_scene.cpp | 1272 ---------------------------------- engines/m4/mads_scene.h | 195 ------ engines/m4/mads_views.cpp | 1632 -------------------------------------------- engines/m4/mads_views.h | 494 -------------- engines/m4/midi.cpp | 256 ------- engines/m4/midi.h | 59 -- engines/m4/module.mk | 49 -- engines/m4/rails.cpp | 358 ---------- engines/m4/rails.h | 97 --- engines/m4/resource.cpp | 530 -------------- engines/m4/resource.h | 147 ---- engines/m4/saveload.cpp | 166 ----- engines/m4/saveload.h | 54 -- engines/m4/scene.cpp | 208 ------ engines/m4/scene.h | 120 ---- engines/m4/script.cpp | 1389 ------------------------------------- engines/m4/script.h | 463 ------------- engines/m4/scripttab.h | 135 ---- engines/m4/sound.cpp | 276 -------- engines/m4/sound.h | 110 --- engines/m4/sprite.cpp | 207 ------ engines/m4/sprite.h | 121 ---- engines/m4/staticres.cpp | 61 -- engines/m4/staticres.h | 56 -- engines/m4/viewmgr.cpp | 444 ------------ engines/m4/viewmgr.h | 204 ------ engines/m4/woodscript.cpp | 398 ----------- engines/m4/woodscript.h | 348 ---------- engines/m4/ws_machine.cpp | 423 ------------ engines/m4/ws_sequence.cpp | 768 --------------------- gui/credits.h | 6 - 84 files changed, 28600 deletions(-) delete mode 100644 dists/engine-data/m4.dat delete mode 100644 dists/engine-data/mads.dat delete mode 100644 engines/m4/actor.cpp delete mode 100644 engines/m4/actor.h delete mode 100644 engines/m4/animation.cpp delete mode 100644 engines/m4/animation.h delete mode 100644 engines/m4/assets.cpp delete mode 100644 engines/m4/assets.h delete mode 100644 engines/m4/burger_data.h delete mode 100644 engines/m4/compression.cpp delete mode 100644 engines/m4/compression.h delete mode 100644 engines/m4/console.cpp delete mode 100644 engines/m4/console.h delete mode 100644 engines/m4/converse.cpp delete mode 100644 engines/m4/converse.h delete mode 100644 engines/m4/detection.cpp delete mode 100644 engines/m4/dialogs.cpp delete mode 100644 engines/m4/dialogs.h delete mode 100644 engines/m4/events.cpp delete mode 100644 engines/m4/events.h delete mode 100644 engines/m4/font.cpp delete mode 100644 engines/m4/font.h delete mode 100644 engines/m4/globals.cpp delete mode 100644 engines/m4/globals.h delete mode 100644 engines/m4/graphics.cpp delete mode 100644 engines/m4/graphics.h delete mode 100644 engines/m4/gui.cpp delete mode 100644 engines/m4/gui.h delete mode 100644 engines/m4/hotspot.cpp delete mode 100644 engines/m4/hotspot.h delete mode 100644 engines/m4/m4.cpp delete mode 100644 engines/m4/m4.h delete mode 100644 engines/m4/m4_menus.cpp delete mode 100644 engines/m4/m4_menus.h delete mode 100644 engines/m4/m4_scene.cpp delete mode 100644 engines/m4/m4_scene.h delete mode 100644 engines/m4/m4_views.cpp delete mode 100644 engines/m4/m4_views.h delete mode 100644 engines/m4/mads_anim.cpp delete mode 100644 engines/m4/mads_anim.h delete mode 100644 engines/m4/mads_logic.cpp delete mode 100644 engines/m4/mads_logic.h delete mode 100644 engines/m4/mads_menus.cpp delete mode 100644 engines/m4/mads_menus.h delete mode 100644 engines/m4/mads_player.cpp delete mode 100644 engines/m4/mads_player.h delete mode 100644 engines/m4/mads_scene.cpp delete mode 100644 engines/m4/mads_scene.h delete mode 100644 engines/m4/mads_views.cpp delete mode 100644 engines/m4/mads_views.h delete mode 100644 engines/m4/midi.cpp delete mode 100644 engines/m4/midi.h delete mode 100644 engines/m4/module.mk delete mode 100644 engines/m4/rails.cpp delete mode 100644 engines/m4/rails.h delete mode 100644 engines/m4/resource.cpp delete mode 100644 engines/m4/resource.h delete mode 100644 engines/m4/saveload.cpp delete mode 100644 engines/m4/saveload.h delete mode 100644 engines/m4/scene.cpp delete mode 100644 engines/m4/scene.h delete mode 100644 engines/m4/script.cpp delete mode 100644 engines/m4/script.h delete mode 100644 engines/m4/scripttab.h delete mode 100644 engines/m4/sound.cpp delete mode 100644 engines/m4/sound.h delete mode 100644 engines/m4/sprite.cpp delete mode 100644 engines/m4/sprite.h delete mode 100644 engines/m4/staticres.cpp delete mode 100644 engines/m4/staticres.h delete mode 100644 engines/m4/viewmgr.cpp delete mode 100644 engines/m4/viewmgr.h delete mode 100644 engines/m4/woodscript.cpp delete mode 100644 engines/m4/woodscript.h delete mode 100644 engines/m4/ws_machine.cpp delete mode 100644 engines/m4/ws_sequence.cpp diff --git a/AUTHORS b/AUTHORS index c20f43e7b3..e152e3a21b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -122,12 +122,6 @@ ScummVM Team Lure: Paul Gilbert - M4: - Torbjorn Andersson - Paul Gilbert - Benjamin Haisch - Filippos Karapetis - MADE: Benjamin Haisch Filippos Karapetis diff --git a/audio/decoders/flac.h b/audio/decoders/flac.h index a90675cc20..f5e31684fe 100644 --- a/audio/decoders/flac.h +++ b/audio/decoders/flac.h @@ -26,7 +26,6 @@ * - agos * - draci * - kyra - * - m4 * - queen * - saga * - sci diff --git a/audio/decoders/mp3.h b/audio/decoders/mp3.h index cb0cc8375d..df2ee44805 100644 --- a/audio/decoders/mp3.h +++ b/audio/decoders/mp3.h @@ -26,7 +26,6 @@ * - agos * - draci * - kyra - * - m4 * - mohawk * - queen * - saga diff --git a/audio/decoders/vorbis.h b/audio/decoders/vorbis.h index 9e7600af56..3a3052ed7c 100644 --- a/audio/decoders/vorbis.h +++ b/audio/decoders/vorbis.h @@ -26,7 +26,6 @@ * - agos * - draci * - kyra - * - m4 * - queen * - saga * - sci diff --git a/base/plugins.cpp b/base/plugins.cpp index 3e18e0ec4e..e587b962d6 100644 --- a/base/plugins.cpp +++ b/base/plugins.cpp @@ -133,9 +133,6 @@ public: #if PLUGIN_ENABLED_STATIC(LURE) LINK_PLUGIN(LURE) #endif - #if PLUGIN_ENABLED_STATIC(M4) - LINK_PLUGIN(M4) - #endif #if PLUGIN_ENABLED_STATIC(MADE) LINK_PLUGIN(MADE) #endif diff --git a/configure b/configure index b7b0794a25..96667e643f 100755 --- a/configure +++ b/configure @@ -98,7 +98,6 @@ add_engine kyra "Legend of Kyrandia" yes "lol" add_engine lol "Lands of Lore" yes add_engine lastexpress "The Last Express" no add_engine lure "Lure of the Temptress" yes -add_engine m4 "M4/MADS" no add_engine made "MADE" yes add_engine mohawk "Mohawk" yes "cstime myst riven" add_engine cstime "Where in Time is Carmen Sandiego?" no diff --git a/dists/engine-data/m4.dat b/dists/engine-data/m4.dat deleted file mode 100644 index 3181d0182c..0000000000 Binary files a/dists/engine-data/m4.dat and /dev/null differ diff --git a/dists/engine-data/mads.dat b/dists/engine-data/mads.dat deleted file mode 100644 index b27f9d4471..0000000000 Binary files a/dists/engine-data/mads.dat and /dev/null differ diff --git a/dists/scummvm.rc b/dists/scummvm.rc index ce287cdd42..d7d2b7f4cb 100644 --- a/dists/scummvm.rc +++ b/dists/scummvm.rc @@ -31,9 +31,6 @@ kyra.dat FILE "dists/engine-data/kyra.dat" #if ENABLE_LURE == STATIC_PLUGIN lure.dat FILE "dists/engine-data/lure.dat" #endif -#if ENABLE_M4 == STATIC_PLUGIN -m4.dat FILE "dists/engine-data/m4.dat" -#endif #if ENABLE_QUEEN == STATIC_PLUGIN queen.tbl FILE "dists/engine-data/queen.tbl" #endif diff --git a/engines/m4/actor.cpp b/engines/m4/actor.cpp deleted file mode 100644 index 80a3624475..0000000000 --- a/engines/m4/actor.cpp +++ /dev/null @@ -1,199 +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/array.h" -#include "common/textconsole.h" -#include "m4/actor.h" -#include "m4/m4_views.h" -#include "m4/assets.h" - -namespace M4 { - -#define WALKER_BURGER "Wilbur0%i" // wilbur, with a number denoting his current direction - -Actor::Actor(MadsM4Engine *vm) : _vm(vm) { - _scaling = 100; - _direction = 5; - _walkerSprites.resize(10); - loadWalkers(); -} - -Actor::~Actor() { - unloadWalkers(); -} - -int Actor::getWalkerWidth() { return _walkerSprites[kFacingSouth]->getFrame(0)->width(); } -int Actor::getWalkerHeight() { return _walkerSprites[kFacingSouth]->getFrame(0)->height(); } - -void Actor::placeWalkerSpriteAt(int spriteNum, int x, int y) { - if (_direction < 1 || _direction > 9) { - warning("Direction is %i, fixing", _direction); - _direction = 1; // TODO: this is a temporary fix - } - SpriteInfo info; - info.sprite = _walkerSprites[_direction]->getFrame(spriteNum); - info.hotX = info.hotY = 0; - info.width = info.sprite->width(); - info.height = info.sprite->height(); - info.scaleX = info.scaleY = _scaling; - info.palette = _walkerSprites[_direction]->getPalette(); - info.inverseColorTable = _m4Vm->scene()->getInverseColorTable(); - - _vm->_scene->drawSprite(x, y, info, Common::Rect(640, 400)); -} - -void Actor::loadWalkers() { - for (uint8 i = 1; i < 10; i++) { - if (i == 6) - continue; // walker sprite 6 is unused - loadWalkerDirection(i); - } -} - -void Actor::loadWalkerDirection(uint8 direction) { - char name[20]; - Common::SeekableReadStream *walkerS; - - if (_vm->getGameType() == GType_Burger) { - sprintf(name, WALKER_BURGER, direction); - } else { - //warning("Actor::loadWalkerDirection: unspecified walker type, not loading walker"); - // TODO: Master Lu walkers - return; - } - - walkerS = _vm->res()->get(name); - _walkerSprites.insert_at(direction, new SpriteAsset(_vm, walkerS, walkerS->size(), name)); - _vm->res()->toss(name); -} - -void Actor::unloadWalkers() { - for (uint8 i = 9; i > 0; i--) { - if (i == 6) - continue; // walker sprite 6 is unused - SpriteAsset *tempSprite = _walkerSprites[i]; - _walkerSprites.remove_at(i); - delete tempSprite; - } -} - -void Actor::setWalkerPalette() { - _vm->_palette->setPalette(_walkerSprites[kFacingSouthEast]->getPalette(), 0, - _walkerSprites[kFacingSouthEast]->getColorCount()); -} - -Inventory::Inventory(MadsM4Engine *vm) : _vm(vm) { -} - -Inventory::~Inventory() { - _inventory.clear(); -} - -void Inventory::registerObject(char* name, int32 scene, int32 icon) { - InventoryObject *newObject = new InventoryObject(); - int newObjectIndex = 0; - - // Capitalize registered inventory object names - str_upper(name); - - newObject->name = strdup(name); - newObject->scene = scene; - newObject->icon = icon; - - newObjectIndex = _inventory.size(); - - _inventory.push_back(newObject); - - if (scene == BACKPACK) - addToBackpack(newObjectIndex); -} - -void Inventory::moveObject(char* name, int32 scene) { - uint i = 0; - - for (i = 0; i < _inventory.size(); i++) { - if (!scumm_stricmp(_inventory[i]->name, name)) { - if (_inventory[i]->scene == BACKPACK && scene != BACKPACK) - removeFromBackpack(i); - - _inventory[i]->scene = scene; - - if (scene == BACKPACK) - addToBackpack(i); - - return; - } - } -} - -void Inventory::addToBackpack(uint32 objectIndex) { - _m4Vm->scene()->getInterface()->inventoryAdd(_inventory[objectIndex]->name, "", _inventory[objectIndex]->icon); -} - -void Inventory::removeFromBackpack(uint32 objectIndex) { - _m4Vm->scene()->getInterface()->inventoryRemove(_inventory[objectIndex]->name); -} - -bool Inventory::isInCurrentScene(char* name) { - return (getScene(name) == _vm->_scene->getCurrentScene()); -} - -int Inventory::getScene(char* name) { - uint i = 0; - - for (i = 0; i < _inventory.size(); i++) { - if (!scumm_stricmp(_inventory[i]->name, name)) - return _inventory[i]->scene; - } - return UNKNOWN_OBJECT; -} - -int Inventory::getIcon(char* name) { - uint i = 0; - - for (i = 0; i < _inventory.size(); i++) { - if (!scumm_stricmp(_inventory[i]->name, name)) - return _inventory[i]->icon; - } - return UNKNOWN_OBJECT; -} - -int Inventory::getIndex(char* name) { - uint i = 0; - - for (i = 0; i < _inventory.size(); i++) { - if (!scumm_stricmp(_inventory[i]->name, name)) - return i; - } - return UNKNOWN_OBJECT; -} - -void Inventory::clear() { - for (uint i = 0; i < _inventory.size(); i++) { - delete _inventory[i]->name; - delete _inventory[i]; - _inventory.remove_at(i); - } -} - -} // End of namespace M4 diff --git a/engines/m4/actor.h b/engines/m4/actor.h deleted file mode 100644 index e28c522df8..0000000000 --- a/engines/m4/actor.h +++ /dev/null @@ -1,114 +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. - * - */ - -#ifndef M4_ACTOR_H -#define M4_ACTOR_H - -#include "common/array.h" - -#include "m4/m4.h" -#include "m4/scene.h" -#include "m4/graphics.h" -#include "m4/assets.h" - -namespace M4 { - -struct InventoryObject { - const char* name; - int32 scene; - int32 icon; -}; - -enum inventoryObjectFlags { - UNKNOWN_OBJECT = 997, - BACKPACK = 998, - NOWHERE = 999 -}; - -enum WalkerDirection { - kFacingNorth = 1, // has shadow - kFacingNorthEast = 2, // has shadow - kFacingEast = 3, // has shadow - kFacingSouthEast = 4, // has shadow - kFacingSouth = 5, // has shadow - // 6 is unused - kFacingSouthAlt = 7, // no shadow - kFacingSouthWest = 8, // no shadow - kFacingWest = 9 // no shadow -}; - -class Actor { -public: - Actor(MadsM4Engine *vm); - ~Actor(); - void placeWalkerSpriteAt(int spriteNum, int x, int y); - void setWalkerScaling(int scaling) { _scaling = scaling; } - int getWalkerScaling() { return _scaling; } - void setWalkerDirection(uint8 direction) { _direction = direction; } - uint8 getWalkerDirection() { return _direction; } - void setWalkerPalette(); - int getWalkerWidth(); - int getWalkerHeight(); -private: - MadsM4Engine *_vm; - int _scaling; - uint8 _direction; - Common::Array _walkerSprites; - - void loadWalkers(); - void loadWalkerDirection(uint8 direction); - void unloadWalkers(); -}; - -// TODO: perhaps the inventory and its view could be merged? -// TODO: the original game capitalizes all inventory object names -// internally, which we do as well, but perhaps we could make sure -// that all object names are parsed with the same case and avoid -// case-insensitive string comparing through scumm_stricmp, using -// the normal strcmp method instead -class Inventory { -public: - Inventory(MadsM4Engine *vm); - ~Inventory(); - void clear(); - void registerObject(char* name, int32 scene, int32 icon); - void moveObject(char* name, int32 scene); - void giveToPlayer(char* name) { moveObject(name, BACKPACK); } - void addToBackpack(uint32 objectIndex); - void removeFromBackpack(uint32 objectIndex); - bool isInBackpack(char* name) { return (getScene(name) == BACKPACK); } - bool isInScene(char* name, int32 scene) { return (getScene(name) == scene); } - bool isInCurrentScene(char* name); - int getScene(char* name); - int getIcon(char* name); - int getIndex(char* name); - int getTotalItems() { return _inventory.size(); } - -private: - MadsM4Engine *_vm; - Common::Array _inventory; -}; - -} // End of namespace M4 - - -#endif diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp deleted file mode 100644 index 4f315dd396..0000000000 --- a/engines/m4/animation.cpp +++ /dev/null @@ -1,535 +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/textconsole.h" - -#include "m4/assets.h" -#include "m4/animation.h" -#include "m4/compression.h" -#include "m4/mads_scene.h" - -namespace M4 { - -// TODO: this code needs cleanup - -MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _view(view) { - _font = NULL; - _resetFlag = false; - _freeFlag = false; - _skipLoad = false; - _unkIndex = -1; - _messageCtr= 0; - _field12 = 0; - - _currentFrame = 0; - _oldFrameEntry = 0; - _nextFrameTimer = _madsVm->_currentTimer; - _nextScrollTimer = 0; -} - -MadsAnimation::~MadsAnimation() { - for (uint i = 0; i < _messages.size(); ++i) { - if (_messages[i].kernelMsgIndex >= 0) - _view->_kernelMessages.remove(_messages[i].kernelMsgIndex); - } - - // Further deletion logic - if (_field12) { - _view->_spriteSlots.deleteSprites(_spriteListIndexes[_spriteListIndex]); - } -} - -#define FILENAME_SIZE 13 - -/** - * Initializes and loads the data of an animation - */ -void MadsAnimation::initialize(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) { - MadsPack anim(filename.c_str(), _vm); - bool madsRes = filename[0] == '*'; - char buffer[20]; - int streamIndex = 1; - - // Chunk 1: header - // header - - Common::SeekableReadStream *animStream = anim.getItemStream(0); - - int spriteListCount = animStream->readUint16LE(); - int miscEntriesCount = animStream->readUint16LE(); - int frameEntryCount = animStream->readUint16LE(); - int messagesCount = animStream->readUint16LE(); - animStream->skip(1); - _flags = animStream->readByte(); - - animStream->skip(2); - _animMode = animStream->readUint16LE(); - _roomNumber = animStream->readUint16LE(); - animStream->skip(2); - _field12 = animStream->readUint16LE() != 0; - _spriteListIndex = animStream->readUint16LE(); - _scrollX = animStream->readSint16LE(); - _scrollY = animStream->readSint16LE(); - _scrollTicks = animStream->readUint16LE(); - animStream->skip(8); - - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - _interfaceFile = Common::String(buffer); - - for (int i = 0; i < 10; ++i) { - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - _spriteSetNames[i] = Common::String(buffer); - } - - animStream->skip(81); - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - _lbmFilename = Common::String(buffer); - - animStream->skip(365); - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - _spritesFilename = Common::String(buffer); - - animStream->skip(48); - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - _soundName = Common::String(buffer); - - animStream->skip(13); - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - _dsrName = Common::String(buffer); - - animStream->read(buffer, FILENAME_SIZE); - buffer[FILENAME_SIZE] = '\0'; - Common::String fontResource(buffer); - - if (_animMode == 4) - flags |= 0x4000; - if (flags & 0x100) - loadInterface(surface, depthSurface); - - // Initialize the reference list - for (int i = 0; i < spriteListCount; ++i) - _spriteListIndexes.push_back(-1); - - delete animStream; - - if (messagesCount > 0) { - // Chunk 2 - // Following is a list of any messages for the animation - - animStream = anim.getItemStream(streamIndex++); - - for (int i = 0; i < messagesCount; ++i) { - AnimMessage rec; - rec.soundId = animStream->readSint16LE(); - animStream->read(rec.msg, 64); - animStream->skip(4); - rec.pos.x = animStream->readSint16LE(); - rec.pos.y = animStream->readSint16LE(); - rec.flags = animStream->readUint16LE(); - rec.rgb1.r = animStream->readByte() << 2; - rec.rgb1.g = animStream->readByte() << 2; - rec.rgb1.b = animStream->readByte() << 2; - rec.rgb2.r = animStream->readByte() << 2; - rec.rgb2.g = animStream->readByte() << 2; - rec.rgb2.b = animStream->readByte() << 2; - animStream->skip(2); // Space for kernelMsgIndex - rec.kernelMsgIndex = -1; - animStream->skip(6); - rec.startFrame = animStream->readUint16LE(); - rec.endFrame = animStream->readUint16LE(); - animStream->skip(2); - - _messages.push_back(rec); - } - - delete animStream; - } - - if (frameEntryCount > 0) { - // Chunk 3: animation frame info - animStream = anim.getItemStream(streamIndex++); - - for (int i = 0; i < frameEntryCount; i++) { - AnimFrameEntry rec; - rec.frameNumber = animStream->readUint16LE(); - rec.seqIndex = animStream->readByte(); - rec.spriteSlot.spriteListIndex = animStream->readByte(); - rec.spriteSlot.frameNumber = animStream->readUint16LE(); - rec.spriteSlot.xp = animStream->readSint16LE(); - rec.spriteSlot.yp = animStream->readSint16LE(); - rec.spriteSlot.depth = animStream->readSByte(); - rec.spriteSlot.scale = (int8)animStream->readByte(); - - _frameEntries.push_back(rec); - } - - delete animStream; - } - - if (miscEntriesCount > 0) { - // Chunk 4: Misc Data - animStream = anim.getItemStream(streamIndex); - - for (int i = 0; i < miscEntriesCount; ++i) { - AnimMiscEntry rec; - rec.soundNum = animStream->readByte(); - rec.msgIndex = animStream->readSByte(); - rec.numTicks = animStream->readUint16LE(); - rec.posAdjust.x = animStream->readUint16LE(); - rec.posAdjust.y = animStream->readUint16LE(); - animStream->readUint16LE(); - - _miscEntries.push_back(rec); - } - - delete animStream; - } - - // If the animation specifies a font, then load it for access - if (_flags & ANIM_CUSTOM_FONT) { - Common::String fontName; - if (madsRes) - fontName += "*"; - fontName += fontResource; - - if (fontName != "") - _font = _vm->_font->getFont(fontName.c_str()); - else - warning("Attempted to set a font with an empty name"); - } - - // If a speech file is specified, then load it - if (!_dsrName.empty()) - _vm->_sound->loadDSRFile(_dsrName.c_str()); - - // Load all the sprite sets for the animation - for (int i = 0; i < spriteListCount; ++i) { - if (_field12 && (i == _spriteListIndex)) - // Skip over field, since it's manually loaded - continue; - - _spriteListIndexes[i] = _view->_spriteSlots.addSprites(_spriteSetNames[i].c_str()); - } - - - if (_field12) { - Common::String resName; - if (madsRes) - resName += "*"; - resName += _spriteSetNames[_spriteListIndex]; - - _spriteListIndexes[_spriteListIndex] = _view->_spriteSlots.addSprites(resName.c_str()); - } - - // TODO: Unknown section about handling sprite set list combined with messages size - - // TODO: The original has two separate loops for the loop below based on _animMode == 4. Is it - // perhaps that in that mode the sprite frames has a different format..? - - // Remap the sprite list index fields from the initial value to the indexes of the loaded - // sprite sets for the animation - for (uint i = 0; i < _frameEntries.size(); ++i) { - int idx = _frameEntries[i].spriteSlot.spriteListIndex; - _frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx]; - } - - if (hasScroll()) - _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; -} - -/** - * Loads an animation file for display - */ -void MadsAnimation::load(const Common::String &filename, int abortTimers) { - initialize(filename, 0, NULL, NULL); - _messageCtr = 0; - _skipLoad = true; - -/* TODO: figure out extra stuff in this routine - if (_field12) { - _unkIndex = -1; - int listIndex = _spriteListIndexes[_spriteListIndex]; - SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex); - ..?.. - } -*/ - - // Initialize miscellaneous fields - _currentFrame = 0; - _oldFrameEntry = 0; - _nextFrameTimer = _madsVm->_currentTimer; - _abortTimers = abortTimers; - _abortMode = _madsVm->scene()->_abortTimersMode2; - - if (_madsVm->_scene) - _actionNouns = _madsVm->scene()->_action._action; - - // Initialize kernel message list - for (uint i = 0; i < _messages.size(); ++i) - _messages[i].kernelMsgIndex = -1; -} - -void MadsAnimation::update() { - if (_field12) { - int spriteListIndex = _spriteListIndexes[_spriteListIndex]; - int newIndex = -1; - - for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) { - if (_frameEntries[idx].frameNumber > _currentFrame) - break; - if (_frameEntries[idx].spriteSlot.spriteListIndex == spriteListIndex) - newIndex = _frameEntries[idx].spriteSlot.frameNumber; - } - - if (newIndex >= 0) - load1(newIndex); - } - - // Check for scroll change - bool screenChanged = false; - - // Handle any scrolling of the screen surface - if (hasScroll() && (_madsVm->_currentTimer >= _nextScrollTimer)) { - _view->_bgSurface->scrollX(_scrollX); - _view->_bgSurface->scrollY(_scrollY); - - _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; - screenChanged = true; - } - - // If it's not time for the next frame, then exit - if (_madsVm->_currentTimer < _nextFrameTimer) { - if (screenChanged) - _view->_spriteSlots.fullRefresh(); - return; - } - - // Loop checks for any prior animation sprite slots to be expired - for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) { - if (_view->_spriteSlots[slotIndex].seqIndex >= 0x80) { - // Flag the frame as animation sprite slot - _view->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE; - } - } - - // Validate the current frame - if (_currentFrame >= (int)_miscEntries.size()) { - // Is the animation allowed to be repeated? - if (_resetFlag) { - _currentFrame = 0; - _oldFrameEntry = 0; - } else { - _freeFlag = true; - return; - } - } - - // Handle starting any sound for this frame - AnimMiscEntry &misc = _miscEntries[_currentFrame]; - if (misc.soundNum) - _vm->_sound->playSound(misc.soundNum); - - // Handle any offset adjustment for sprites as of this frame - if (_view->_posAdjust.x != misc.posAdjust.x) { - _view->_posAdjust.x = misc.posAdjust.x; - screenChanged = true; - } - if (_view->_posAdjust.y != misc.posAdjust.y) { - _view->_posAdjust.y = misc.posAdjust.y; - screenChanged = true; - } - - - if (screenChanged) { - // Signal the entire screen needs refreshing - _view->_spriteSlots.fullRefresh(); - } - - int spriteSlotsMax = _view->_spriteSlots.startIndex; - - // Main frame animation loop - frames get animated by being placed, as necessary, into the - // main sprite slot array - while ((uint)_oldFrameEntry < _frameEntries.size()) { - if (_frameEntries[_oldFrameEntry].frameNumber > _currentFrame) - break; - else if (_frameEntries[_oldFrameEntry].frameNumber == _currentFrame) { - // Found the correct frame - int spriteSlotIndex = 0; - int index = 0; - - for (;;) { - if ((spriteSlotIndex == 0) && (index < spriteSlotsMax)) { - int seqIndex = _frameEntries[_oldFrameEntry].seqIndex - _view->_spriteSlots[index].seqIndex; - if (seqIndex == 0x80) { - if (_view->_spriteSlots[index] == _frameEntries[_oldFrameEntry].spriteSlot) { - _view->_spriteSlots[index].spriteType = SPRITE_ZERO; - spriteSlotIndex = -1; - } - } - ++index; - continue; - } - - if (spriteSlotIndex == 0) { - int slotIndex = _view->_spriteSlots.getIndex(); - MadsSpriteSlot &slot = _view->_spriteSlots[slotIndex]; - slot.copy(_frameEntries[_oldFrameEntry].spriteSlot); - slot.seqIndex = _frameEntries[_oldFrameEntry].seqIndex + 0x80; - - SpriteAsset &spriteSet = _view->_spriteSlots.getSprite( - _view->_spriteSlots[slotIndex].spriteListIndex); - slot.spriteType = spriteSet.isBackground() ? BACKGROUND_SPRITE : FOREGROUND_SPRITE; - } - break; - } - } - - ++_oldFrameEntry; - } - - // Handle the display of any messages - for (uint idx = 0; idx < _messages.size(); ++idx) { - if (_messages[idx].kernelMsgIndex >= 0) { - // Handle currently active message - if ((_currentFrame < _messages[idx].startFrame) || (_currentFrame > _messages[idx].endFrame)) { - _view->_kernelMessages.remove(_messages[idx].kernelMsgIndex); - _messages[idx].kernelMsgIndex = -1; - --_messageCtr; - } - } else if ((_currentFrame >= _messages[idx].startFrame) && (_currentFrame <= _messages[idx].endFrame)) { - // Start displaying the message - AnimMessage &me = _messages[idx]; - - // The color index to use is dependant on how many messages are currently on-screen - uint8 colIndex; - switch (_messageCtr) { - case 1: - colIndex = 252; - break; - case 2: - colIndex = 16; - break; - default: - colIndex = 250; - break; - } - - _vm->_palette->setEntry(colIndex, me.rgb1.r, me.rgb1.g, me.rgb1.b); - _vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b); - - // Add a kernel message to display the given text - me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 0x101 + 0x100, 0, 0, INDEFINITE_TIMEOUT, me.msg); - assert(me.kernelMsgIndex >= 0); - - // Play the associated sound, if it exists - if (me.soundId > 0) - _vm->_sound->playDSRSound(me.soundId - 1, 255, false); - ++_messageCtr; - } - } - - // Move to the next frame - _currentFrame++; - if (_currentFrame >= (int)_miscEntries.size()) { - // Animation is complete - if (_abortTimers != 0) { - _view->_abortTimers = _abortTimers; - _view->_abortTimersMode = _abortMode; - - if (_abortMode != ABORTMODE_1) { - // Copy the noun list - if (_madsVm->_scene) - _madsVm->scene()->_action._action = _actionNouns; - } - } - } - - int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1); - _nextFrameTimer = _madsVm->_currentTimer + _miscEntries[frameNum].numTicks; -} - -void MadsAnimation::setCurrentFrame(int frameNumber) { - _currentFrame = frameNumber; - _oldFrameEntry = 0; - _freeFlag = false; - - _nextScrollTimer = _nextFrameTimer = _madsVm->_currentTimer; -} - -int MadsAnimation::getCurrentFrame() { - return _currentFrame; -} - -void MadsAnimation::load1(int frameNumber) { - if (_skipLoad) - return; - - Common::Point pt; - int listIndex = _spriteListIndexes[_spriteListIndex]; - SpriteAsset &spriteSet = _view->_spriteSlots.getSprite(listIndex); - - if (_unkIndex < 0) { - M4Surface *frame = spriteSet.getFrame(0); - pt.x = frame->bounds().left; - pt.y = frame->bounds().top; - } else { - pt.x = _unkList[_unkIndex].x; - pt.y = _unkList[_unkIndex].y; - _unkIndex = 1 - _unkIndex; - } - - if (proc1(spriteSet, pt, frameNumber)) - error("proc1 failure"); -} - -bool MadsAnimation::proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) { - return 0; -} - -void MadsAnimation::loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface) { - if (_animMode <= 2) { - MadsSceneResources sceneResources; - sceneResources.load(_roomNumber, _interfaceFile.c_str(), 0, depthSurface, interfaceSurface); - - } else if (_animMode == 4) { - // Load a scene interface - interfaceSurface->madsLoadInterface(_interfaceFile); - } else { - // This mode allocates two large surfaces for the animation - // TODO: Are these ever properly freed? -error("Anim mode %d - need to check free logic", _animMode); - assert(!interfaceSurface); - assert(!depthSurface); - depthSurface = new M4Surface(MADS_SURFACE_WIDTH, MADS_SCREEN_HEIGHT); - interfaceSurface = new M4Surface(MADS_SURFACE_WIDTH, MADS_SCREEN_HEIGHT); - depthSurface->clear(); - interfaceSurface->clear(); - } -} - -} // End of namespace M4 diff --git a/engines/m4/animation.h b/engines/m4/animation.h deleted file mode 100644 index 68a2883241..0000000000 --- a/engines/m4/animation.h +++ /dev/null @@ -1,127 +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. - * - */ - -#ifndef M4_ANIMATION_H -#define M4_ANIMATION_H - -#include "m4/m4.h" -#include "m4/graphics.h" -#include "m4/assets.h" -#include "m4/mads_views.h" -#include "common/array.h" - -namespace M4 { - -class MadsView; -class SpriteSlotSubset; - -class AnimMessage { -public: - int16 soundId; - char msg[64]; - Common::Point pos; - RGB8 rgb1, rgb2; - uint16 flags; - int startFrame, endFrame; - int kernelMsgIndex; -}; - -class AnimFrameEntry { -public: - int frameNumber; - int seqIndex; - SpriteSlotSubset spriteSlot; -}; - -class AnimMiscEntry { -public: - int soundNum; - int msgIndex; - int numTicks; - Common::Point posAdjust; -}; - -#define ANIM_SPRITE_SET_SIZE 50 - -enum MadsAnimationFlags {ANIM_CUSTOM_FONT = 0x20, ANIM_HAS_SOUND = 0x8000}; - -class MadsAnimation: public Animation { -private: - MadsView *_view; - - int _spriteListCount; - Common::Array _messages; - Common::Array _frameEntries; - Common::Array _miscEntries; - Font *_font; - - uint8 _flags; - int _animMode; - int _roomNumber; - bool _field12; - int _spriteListIndex; - int _scrollX; - int _scrollY; - int _scrollTicks; - Common::String _interfaceFile; - Common::String _spriteSetNames[10]; - Common::String _lbmFilename; - Common::String _spritesFilename; - Common::String _soundName; - Common::String _dsrName; - Common::Array _spriteListIndexes; - - int _currentFrame, _oldFrameEntry; - bool _resetFlag; - bool _freeFlag; - bool _skipLoad; - int _unkIndex; - Common::Point _unkList[2]; - uint32 _nextFrameTimer; - uint32 _nextScrollTimer; - int _messageCtr; - int _abortTimers; - AbortTimerMode _abortMode; - ActionDetails _actionNouns; - - void load1(int frameNumber); - bool proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber); - void loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface); - bool hasScroll() const { return (_scrollX != 0) || (_scrollY != 0); } -public: - MadsAnimation(MadsM4Engine *vm, MadsView *view); - virtual ~MadsAnimation(); - - virtual void initialize(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface); - virtual void load(const Common::String &filename, int abortTimers); - virtual void update(); - virtual void setCurrentFrame(int frameNumber); - virtual int getCurrentFrame(); - - bool freeFlag() const { return _freeFlag; } - bool getAnimMode() const { return _animMode; } - int roomNumber() const { return _roomNumber; } -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp deleted file mode 100644 index e871218ec1..0000000000 --- a/engines/m4/assets.cpp +++ /dev/null @@ -1,650 +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 "m4/assets.h" -#include "m4/globals.h" -#include "m4/compression.h" -#include "m4/graphics.h" - -#include "common/memstream.h" - -namespace M4 { - -BaseAsset::BaseAsset(MadsM4Engine *vm) : _vm(vm) { -} - -BaseAsset::~BaseAsset() { -} - -MachineAsset::MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) { - uint32 stateCount = stream->readUint32LE(); - for (uint32 curState = 0; curState < stateCount; curState++) { - uint32 stateOffset = stream->readUint32LE(); - _stateTable.push_back(stateOffset); - } - _codeSize = size - 4 - 4 * stateCount; - _code = new byte[_codeSize]; - stream->read(_code, _codeSize); -} - -MachineAsset::~MachineAsset() { - delete[] _code; -} - -void MachineAsset::getCode(byte *&code, uint32 &codeSize) { - code = _code; - codeSize = _codeSize; -} - -uint32 MachineAsset::getStateOffset(uint32 state) { - assert(state < _stateTable.size()); - return _stateTable[state]; -} - -SequenceAsset::SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) { - _localVarCount = stream->readUint32LE(); - _codeSize = size - 4; - _code = new byte[_codeSize]; - stream->read(_code, _codeSize); -} - -SequenceAsset::~SequenceAsset() { - delete[] _code; -} - -void SequenceAsset::getCode(byte *&code, uint32 &codeSize) { - code = _code; - codeSize = _codeSize; -} - - -DataAsset::DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm) { - - _recCount = stream->readUint32LE(); - _recSize = stream->readUint32LE(); - _dataSize = _recCount * _recSize; - _data = new long[_dataSize]; - for (uint32 i = 0; i < _dataSize; i++) - _data[i] = (long)stream->readUint32LE(); - -} - -DataAsset::~DataAsset() { - delete _data; -} - -long *DataAsset::getRow(int index) { - assert(index < _recCount); - return &_data[_recSize * index]; -} - -SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, - bool asStream, int flags) : - BaseAsset(vm) { - _stream = stream; - _palInterface = NULL; - _paletteData = NULL; - - if (_vm->isM4()) { - loadM4SpriteAsset(vm, stream, asStream); - } else { - loadMadsSpriteAsset(vm, stream, flags); - } -} - -SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) { - _stream = vm->res()->get(name); - _palInterface = NULL; - _paletteData = NULL; - - if (_vm->isM4()) { - loadM4SpriteAsset(vm, _stream, true); - } else { - loadMadsSpriteAsset(vm, _stream, 0); - } - - vm->res()->toss(name); -} - -SpriteAsset::~SpriteAsset() { - if (_palInterface) { - // Internally stored palette translation data, so release it - _palInterface->deleteRange(_paletteData); - delete _paletteData; - } - - // Delete the individual frames - for (Common::Array::iterator it = _frames.begin(); it != _frames.end(); ++it) { - delete (*it).frame; - } - - delete _charInfo; -} - -void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream) { - bool isBigEndian = false; - uint32 frameOffset; - - uint32 header = _stream->readUint32LE(); - if (header == HEAD_M4SS) { - debugC(kDebugGraphics, "LE-encoded sprite\n"); - } else { - debugC(kDebugGraphics, "BE-encoded sprite\n"); - isBigEndian = true; - } - - _srcSize = parseSprite(isBigEndian); - - _stream->readUint32LE(); - _frameRate = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - _pixelSpeed = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - _maxWidth = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - _maxHeight = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - _stream->skip(6 * 4); - _frameCount = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - - debugC(kDebugGraphics, "SpriteAsset::SpriteAsset() srcSize = %d; frameRate = %04X; pixelSpeed = %04X; maxWidth = %d; maxHeight = %d; frameCount = %d\n", _srcSize, _frameRate, _pixelSpeed, _maxWidth, _maxHeight, _frameCount); - - for (int curFrame = 0; curFrame < _frameCount; curFrame++) { - frameOffset = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - _frameOffsets.push_back(frameOffset); - } - _frameOffsets.push_back(_srcSize - 48 - _frameCount * 4); - - _frameStartOffset = _stream->pos(); - - // We don't need to load frames when streaming - if (asStream) - return; - - for (int curFrame = 0; curFrame < _frameCount; curFrame++) { - frameOffset = _frameStartOffset + _frameOffsets[curFrame]; - _stream->seek(frameOffset); - - SpriteAssetFrame frame; - loadFrameHeader(frame, isBigEndian); - - // Load & unpack RLE data if it's not a streaming animation - if (frame.stream != 1) { - - frame.frame = new M4Sprite(stream, frame.x, frame.y, frame.w, frame.h, true, frame.comp); -#if 0 - char fn[512]; - sprintf(fn, "%04d.raw", curFrame); - FILE *h = fopen(fn, "wb"); - fwrite((byte*)frame.frame->getBasePtr(), frame.w * frame.h, 1, h); - fclose(h); -#endif - } - - _frames.push_back(frame); - - } - -} - -void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags) { - int curFrame = 0; - uint32 frameOffset = 0; - MadsPack sprite(stream); - _frameRate = 0; - _pixelSpeed = 0; - _maxWidth = 0; - _maxHeight = 0; - - Common::SeekableReadStream *spriteStream = sprite.getItemStream(0); - _mode = spriteStream->readByte(); - spriteStream->skip(1); - int type1 = spriteStream->readUint16LE(); - int type2 = spriteStream->readUint16LE(); - _isBackground = (type1 != 0) && (type2 < 4); - spriteStream->skip(32); - _frameCount = spriteStream->readUint16LE(); - - if (_vm->isM4() || ((flags & SPRITE_SET_CHAR_INFO) == 0)) - _charInfo = NULL; - else - _charInfo = new MadsSpriteSetCharInfo(spriteStream); - - delete spriteStream; - - // Get the palette data - spriteStream = sprite.getItemStream(2); - int numColors = 0; - RGB8 *palData = Palette::decodeMadsPalette(spriteStream, &numColors); - Common::copy(palData, &palData[numColors], &_palette[0]); - if (numColors < 256) - Common::fill((byte *)&_palette[numColors], (byte *)&_palette[256], 0); - _colorCount = numColors; - delete[] palData; - delete spriteStream; - - spriteStream = sprite.getItemStream(1); - Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3); - SpriteAssetFrame frame; - Common::Array frameSizes; - for (curFrame = 0; curFrame < _frameCount; curFrame++) { - frame.stream = 0; - frame.comp = 0; - frameOffset = spriteStream->readUint32LE(); - _frameOffsets.push_back(frameOffset); - uint32 frameSize = spriteStream->readUint32LE(); - frameSizes.push_back(frameSize); - - frame.x = spriteStream->readUint16LE(); - frame.y = spriteStream->readUint16LE(); - frame.w = spriteStream->readUint16LE(); - frame.h = spriteStream->readUint16LE(); - if (curFrame == 0) - debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h); - - if (_mode == 0) { - // Create a frame and decompress the raw pixel data - uint32 currPos = (uint32)spriteDataStream->pos(); - frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false); - assert((uint32)spriteDataStream->pos() == (currPos + frameSize)); - } - - _frames.push_back(frame); - } - - if (_mode != 0) { - // Handle decompressing Fab encoded data - for (curFrame = 0; curFrame < _frameCount; curFrame++) { - FabDecompressor fab; - - int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] : - _frameOffsets[curFrame + 1] - _frameOffsets[curFrame]; - byte *srcData = (byte *)malloc(srcSize); - assert(srcData); - spriteDataStream->read(srcData, srcSize); - - byte *destData = (byte *)malloc(frameSizes[curFrame]); - assert(destData); - - fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]); - - // Load the frame - Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]); - _frames[curFrame].frame = new M4Sprite(rs, _frames[curFrame].x, _frames[curFrame].y, - _frames[curFrame].w, _frames[curFrame].h, false); - delete rs; - - free(srcData); - free(destData); - } - } - - - delete spriteStream; - delete spriteDataStream; -} - -int32 SpriteAsset::parseSprite(bool isBigEndian) { - - uint32 chunkType, chunkSize = 0; - - _colorCount = 0; - - /*format = (!isBigEndian) ? _stream->readUint32LE() : */_stream->readUint32BE(); - - chunkType = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - - if (chunkType == CELS__PAL) { - chunkSize = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - uint32 numColors = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - // TODO - //if (palette) { - // TODO: A sprite set palette specifies the indexes, which need not start at - // index 0. For now, I'm simply preloading the currently active palette - // before starting to replace existing entries - - _vm->_palette->grabPalette((byte *) _palette, 0, 256); - _colorCount = 0; - - for (uint32 i = 0; i < numColors; i++) { - uint32 paletteEntry = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - uint index = (paletteEntry >> 24) & 0xFF; - - _palette[index].r = ((paletteEntry >> 16) & 0xFF) << 2; - _palette[index].g = ((paletteEntry >> 8) & 0xFF) << 2; - _palette[index].b = (paletteEntry & 0xFF) << 2; - - _colorCount = MAX(_colorCount, index); - } - - /* - } else { - stream.seek(colorCount, ) - data += colorCount * 4; - } - */ - chunkType = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - } - - if (chunkType == CELS___SS) { - chunkSize = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - } else { - debugC(kDebugGraphics, "SpriteAsset::parseSprite() Expected chunk type %08X, got %08X", CELS___SS, chunkType); - } - - return chunkSize; - -} - -void SpriteAsset::loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian) { - _stream->readUint32LE(); - frameHeader.stream = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - frameHeader.x = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - frameHeader.y = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - frameHeader.w = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - frameHeader.h = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - frameHeader.comp = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE(); - frameHeader.frame = NULL; - _stream->seek(8 * 4, SEEK_CUR); - //debugC(kDebugGraphics, "SpriteAsset::loadFrameHeader() stream = %d; x = %d; y = %d; w = %d; h = %d; comp = %d\n", frameHeader.stream, frameHeader.x, frameHeader.y, frameHeader.w, frameHeader.h, frameHeader.comp); -} - -M4Sprite *SpriteAsset::getFrame(int frameIndex) { - if ((uint)frameIndex < _frames.size()) { - return _frames[frameIndex].frame; - } else { - debugC(kDebugGraphics, "SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size()); - return _frames[_frames.size() - 1].frame; - } -} - -void SpriteAsset::loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY) { - uint32 frameOffset = _frameStartOffset + _frameOffsets[frameIndex]; - _stream->seek(frameOffset); - - SpriteAssetFrame frameHeader; - loadFrameHeader(frameHeader); - - if (frameHeader.w > 0 && frameHeader.h > 0) { - Common::SeekableReadStream *frameData = _stream->readStream(getFrameSize(frameIndex)); - if (frameHeader.stream) { - frame->loadDeltaRle(frameData, destX - frameHeader.x, destY - frameHeader.y); - } else { - frame->loadRle(frameData); - } - delete frameData; - } - -} - -RGBList *SpriteAsset::getRgbList() { - RGBList *result = new RGBList(_colorCount); - Common::copy((byte *)&_palette[0], (byte *)&_palette[_colorCount], (byte *)result->data()); - return result; -} - -void SpriteAsset::translate(RGBList *list, bool isTransparent) { - for (int frameIndex = 0; frameIndex < _frameCount; ++frameIndex) - _frames[frameIndex].frame->translate(list, isTransparent); -} - -void SpriteAsset::translate(Palette *palette) { - _palInterface = palette; - _paletteData = this->getRgbList(); - palette->addRange(_paletteData); - this->translate(_paletteData, true); -} - - -int32 SpriteAsset::getFrameSize(int index) { - /* - if (index + 1 == _frameCount) { - } else { - - } - */ - return _frameOffsets[index + 1] - _frameOffsets[index]; -} - -AssetManager::AssetManager(MadsM4Engine *vm) { - - _vm = vm; - - /* Initialize asset arrays */ - for (int i = 0; i < 256; i++) { - _MACH[i] = NULL; - _SEQU[i] = NULL; - _DATA[i] = NULL; - _CELS[i] = NULL; - } - -} - -AssetManager::~AssetManager() { - // unload all remaining assets - clearAssets(kAssetTypeMACH, 0, 255); - clearAssets(kAssetTypeSEQU, 0, 255); - clearAssets(kAssetTypeCELS, 0, 255); - clearAssets(kAssetTypeDATA, 0, 255); -} - -bool AssetManager::clearAssets(AssetType assetType, int32 minHash, int32 maxHash) { - - minHash = MAX(0, minHash); - maxHash = MIN(maxHash, 255); - - switch (assetType) { - case kAssetTypeMACH: - for (int i = minHash; i <= maxHash; i++) - if (_MACH[i]) { - delete _MACH[i]; - _MACH[i] = NULL; - } - break; - case kAssetTypeSEQU: - for (int i = minHash; i <= maxHash; i++) - if (_SEQU[i]) { - delete _SEQU[i]; - _SEQU[i] = NULL; - } - break; - case kAssetTypeDATA: - for (int i = minHash; i <= maxHash; i++) - if (_DATA[i]) { - delete _DATA[i]; - _DATA[i] = NULL; - } - break; - case kAssetTypeCELS: - for (int i = minHash; i <= maxHash; i++) - if (_CELS[i]) { - delete _CELS[i]; - _CELS[i] = NULL; - } - break; - } - - // FIXME: no value is returned, returning true for now - return true; -} - -bool AssetManager::loadAsset(const char *assetName, RGB8 *palette) { - - debugC(kDebugGraphics, "AssetManager::loadAsset() %s\n", assetName); - - // TODO, better use MemoryReadStreamEndian? - //convertAssetToLE(assetData, assetSize); - - Common::SeekableReadStream *assetS = _vm->res()->get(assetName); - - while (assetS->pos() + 12 < assetS->size()) { - uint32 chunkType, chunkSize, chunkHash; - - chunkType = assetS->readUint32LE(); - chunkSize = assetS->readUint32LE() - 12; // sub 12 for the chunk header - chunkHash = assetS->readUint32LE(); - - debugC(kDebugGraphics, "hash = %d\n", chunkHash); - - // Until loading code is complete, so that chunks not fully read are skipped correctly - uint32 nextOfs = assetS->pos() + chunkSize; - - switch (chunkType) { - case CHUNK_MACH: - debugC(kDebugGraphics, "MACH\n"); - clearAssets(kAssetTypeMACH, chunkHash, chunkHash); - _MACH[chunkHash] = new MachineAsset(_vm, assetS, chunkSize, assetName); - break; - case CHUNK_SEQU: - debugC(kDebugGraphics, "SEQU\n"); - clearAssets(kAssetTypeSEQU, chunkHash, chunkHash); - _SEQU[chunkHash] = new SequenceAsset(_vm, assetS, chunkSize, assetName); - break; - case CHUNK_DATA: - debugC(kDebugGraphics, "DATA\n"); - clearAssets(kAssetTypeDATA, chunkHash, chunkHash); - _DATA[chunkHash] = new DataAsset(_vm, assetS, chunkSize, assetName); - break; - case CHUNK_CELS: - debugC(kDebugGraphics, "CELS\n"); - clearAssets(kAssetTypeCELS, chunkHash, chunkHash); - _CELS[chunkHash] = new SpriteAsset(_vm, assetS, chunkSize, assetName); - break; - default: - debugC(kDebugGraphics, "AssetManager::loadAsset() Unknown chunk type %08X\n", chunkType); - } - - // Until loading code is complete (see above) - assetS->seek(nextOfs); - - } - - _vm->res()->toss(assetName); - - // FIXME: no value is returned, returning true for now - return true; -} - -int32 AssetManager::addSpriteAsset(const char *assetName, int32 hash, RGB8 *palette) { - - bool alreadyLoaded = false; - - if (hash < 0) { - for (int i = 0; i <= 255; i++) { - if (_CELS[i] != NULL) { - if (_CELS[i]->getName() == assetName) { - alreadyLoaded = true; - hash = i; - break; - } - } else { - hash = i; - break; - } - } - } else { - alreadyLoaded = _CELS[hash] != NULL && _CELS[hash]->getName() == assetName; - } - - /* Not loaded and no empty slots */ - if (hash < 0) - return -1; - - if (!alreadyLoaded) { - - debugC(kDebugGraphics, "AssetManager::addSpriteAsset() asset %s not loaded, loading into %d\n", assetName, hash); - - clearAssets(kAssetTypeCELS, hash, hash); - - Common::SeekableReadStream *assetS = _vm->res()->get(assetName); - _CELS[hash] = new SpriteAsset(_vm, assetS, assetS->size(), assetName); - _vm->res()->toss(assetName); - - } else { - - debugC(kDebugGraphics, "AssetManager::addSpriteAsset() asset %s already loaded in %d\n", assetName, hash); - - /* TODO/FIXME - if (_CELS[hash].palOffset >= 0 && palette) - restorePalette(palette, _CELS[hash].data + _CELS[hash].palOffset); - */ - - } - - return hash; - -} - -void AssetManager::restorePalette(RGB8 *palette, byte *data) { - // TODO -} - -void AssetManager::convertAssetToLE(byte *assetData, uint32 assetSize) { - -} - -MachineAsset *AssetManager::getMachine(int32 hash) { - assert(_MACH[hash] != NULL); - return _MACH[hash]; -} - -SequenceAsset *AssetManager::getSequence(int32 hash) { - assert(_SEQU[hash] != NULL); - return _SEQU[hash]; -} - -DataAsset *AssetManager::getData(int32 hash) { - assert(_DATA[hash] != NULL); - return _DATA[hash]; -} - -SpriteAsset *AssetManager::getSprite(int32 hash) { - assert(_CELS[hash] != NULL); - return _CELS[hash]; -} - -M4Sprite *AssetManager::getSpriteFrame(int32 hash, int frameIndex) { - assert(_CELS[hash] != NULL); - return _CELS[hash]->getFrame(frameIndex); -} - -int32 AssetManager::getSpriteFrameCount(int32 hash) { - assert(_CELS[hash] != NULL); - return _CELS[hash]->getCount(); -} - -//-------------------------------------------------------------------------- - -MadsSpriteSetCharInfo::MadsSpriteSetCharInfo(Common::SeekableReadStream *s) { - _totalFrames = s->readByte(); - s->skip(1); - _numEntries = s->readUint16LE(); - - for (int i = 0; i < 16; ++i) - _frameList[i] = s->readUint16LE(); - for (int i = 0; i < 16; ++i) - _frameList2[i] = s->readUint16LE(); - for (int i = 0; i < 16; ++i) - _ticksList[i] = s->readUint16LE(); - - _unk1 = s->readUint16LE(); - _ticksAmount = s->readByte(); - _yScale = s->readByte(); -} - -} // End of namespace M4 diff --git a/engines/m4/assets.h b/engines/m4/assets.h deleted file mode 100644 index 25996a421e..0000000000 --- a/engines/m4/assets.h +++ /dev/null @@ -1,212 +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. - * - */ -#ifndef M4_ASSETS_H -#define M4_ASSETS_H - -#include "common/scummsys.h" -#include "common/stream.h" - -#include "m4/sprite.h" - -namespace M4 { - -// Sequence chunks -#define CHUNK_SCEN MKTAG('S','C','E','N') -#define CHUNK_MACH MKTAG('M','A','C','H') -#define CHUNK_SEQU MKTAG('S','E','Q','U') -#define CHUNK_DATA MKTAG('D','A','T','A') -#define CHUNK_CELS MKTAG('C','E','L','S') - -// Sprite chunks -#define HEAD_M4SS MKTAG('M','4','S','S') //'M4SS' -#define CELS__PAL MKTAG(' ','P','A','L') //' PAL' -#define CELS___SS MKTAG(' ',' ','S','S') //' SS' - -#define SPRITE_SET_CHAR_INFO 4 - -class MadsM4Engine; -class Palette; - -class BaseAsset { -public: - BaseAsset(MadsM4Engine *vm); - ~BaseAsset(); - const Common::String getName() const { return _name; } -protected: - MadsM4Engine *_vm; - Common::String _name; -}; - -class MachineAsset : public BaseAsset { -public: - MachineAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name); - ~MachineAsset(); - void getCode(byte *&code, uint32 &codeSize); - uint32 getStateOffset(uint32 state); -protected: - Common::Array _stateTable; - byte *_code; - uint32 _codeSize; -}; - -class SequenceAsset : public BaseAsset { -public: - SequenceAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name); - ~SequenceAsset(); - void getCode(byte *&code, uint32 &codeSize); - int localVarCount() const { return _localVarCount; } -protected: - int _localVarCount; - byte *_code; - uint32 _codeSize; -}; - -class DataAsset : public BaseAsset { -public: - DataAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name); - ~DataAsset(); - int getCount() const { return _recCount; } - long *getRow(int index); -protected: - long *_data; - uint32 _recSize, _dataSize; - int _recCount; -}; - -struct SpriteAssetFrame { - uint32 stream; - int x, y, w, h; - uint32 comp; - M4Sprite *frame; -}; - -class MadsSpriteSetCharInfo { -public: - MadsSpriteSetCharInfo(Common::SeekableReadStream *s); - - int _totalFrames; - int _numEntries; - int _frameList2[16]; - int _frameList[16]; - int _ticksList[16]; - int _unk1; - int _ticksAmount; - int _yScale; -}; - -class SpriteAsset : public BaseAsset { -public: - SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, - bool asStream = false, int flags = 0); - SpriteAsset(MadsM4Engine *vm, const char *name); - ~SpriteAsset(); - void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream); - void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags); - int32 getCount() { return _frameCount; } - int32 getFrameRate() const { return _frameRate; } - int32 getPixelSpeed() const { return _pixelSpeed; } - int32 getFrameWidth(int index); - int32 getFrameHeight(int index); - int32 getMaxFrameWidth() const { return _maxWidth; } - int32 getMaxFrameHeight() const { return _maxHeight; } - bool isBackground() const { return _isBackground; } - M4Sprite *getFrame(int frameIndex); - void loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY); - RGB8* getPalette() { return _palette; } - int getColorCount() { return _colorCount; } - RGBList *getRgbList(); - void translate(RGBList *list, bool isTransparent = false); - void translate(Palette *palette); - int32 getFrameSize(int index); - M4Sprite *operator[](int index) { return getFrame(index); } -public: - MadsSpriteSetCharInfo *_charInfo; -protected: - Common::SeekableReadStream *_stream; - RGB8 _palette[256]; - uint32 _colorCount; - uint32 _srcSize; - int32 _frameRate, _pixelSpeed; - int _maxWidth, _maxHeight; - int _frameCount; - Common::Array _frameOffsets; - Common::Array _frames; - uint32 _frameStartOffset; - - // MADS sprite set fields - uint8 _mode; - bool _isBackground; - - int32 parseSprite(bool isBigEndian = false); - void loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian = false); -private: - RGBList *_paletteData; - Palette *_palInterface; -}; - -enum AssetType { - kAssetTypeMACH, - kAssetTypeSEQU, - kAssetTypeDATA, - kAssetTypeCELS -}; - -enum CallbackHandlers { - kCallbackTriggerDispatch -}; - -class AssetManager { -public: - - AssetManager(MadsM4Engine *vm); - ~AssetManager(); - - bool clearAssets(AssetType assetType, int32 minHash, int32 maxHash); - bool loadAsset(const char *assetName, RGB8 *palette); - int32 addSpriteAsset(const char *assetName, int32 hash, RGB8 *palette); - - // TODO: Move to Palette class - void restorePalette(RGB8 *palette, byte *data); - - MachineAsset *getMachine(int32 hash); - SequenceAsset *getSequence(int32 hash); - DataAsset *getData(int32 hash); - SpriteAsset *getSprite(int32 hash); - M4Sprite *getSpriteFrame(int32 hash, int frameIndex); - int32 getSpriteFrameCount(int32 hash); - -protected: - // TODO: Check if we need _vm - MadsM4Engine *_vm; - - MachineAsset *_MACH[256]; - SequenceAsset *_SEQU[256]; - DataAsset *_DATA[256]; - SpriteAsset *_CELS[256]; - - void convertAssetToLE(byte *assetData, uint32 assetSize); - -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/burger_data.h b/engines/m4/burger_data.h deleted file mode 100644 index d30e546023..0000000000 --- a/engines/m4/burger_data.h +++ /dev/null @@ -1,82 +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. - * - */ - -#ifndef M4_BURGER_DATA_H -#define M4_BURGER_DATA_H - -#include "m4/graphics.h" -#include "m4/actor.h" - -namespace M4 { - -InventoryObject burger_inventory [] = { - // name scene icon - //-------------------- ----- ----- - { "empty jug", 303, 14 }, - { "distilled juice", 999, 15 }, - { "broken puz dispenser", 999, 16 }, - { "puz dispenser", 999, 17 }, - { "broken mouse trap", 999, 18 }, - { "mouse trap", 999, 19 }, - { "kindling", 999, 20 }, - { "burning kindling", 999, 21 }, - { "lights", 508, 22 }, - { "lights on", 508, 23 }, - { "bottle", 999, 24 }, - { "carrot juice", 999, 25 }, - { "soapy water", 999, 26 }, - { "iron filings", 999, 27 }, - { "waxed hair", 999, 28 }, - { "fish", 999, 29 }, - { "hook", 999, 30 }, - { "keys", 999, 31 }, - { "records", 999, 32 }, - { "collar", 999, 33 }, - { "amp", 999, 34 }, - { "rubber gloves", 999, 35 }, - { "sock", 504, 36 }, - { "jaws of life", 999, 37 }, - { "deed", 999, 38 }, - { "burger morsel", 999, 39 }, - { "whistle", 999, 40 }, - { "coin", 999, 41 }, - { "matches", 999, 42 }, - { "phone cord", 999, 43 }, - { "kibble", 602, 44 }, // picked up from tray - { "pantyhose", 999, 45 }, - { "fan belt", 999, 46 }, - { "spring", 999, 47 }, - { "mirror", 999, 48 }, - { "grate", 999, 49 }, - { "ray gun", 604, 50 }, // given to Wilbur when he enters 604 - { "grasshoppers", 999, 51 }, - { "rolling pin", 999, 52 }, - { "rubber duck", 999, 53 }, - { "ladder", 999, 54 }, - { "money", 999, 55 }, - { "crow bar", 999, 56 }, - { "Wilbur", 999, 57 } -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/compression.cpp b/engines/m4/compression.cpp deleted file mode 100644 index 65a25c14e3..0000000000 --- a/engines/m4/compression.cpp +++ /dev/null @@ -1,190 +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 "m4/compression.h" -#include "m4/m4.h" - -#include "common/memstream.h" -#include "common/textconsole.h" - -namespace M4 { - -const char *madsPackString = "MADSPACK"; - -bool MadsPack::isCompressed(Common::SeekableReadStream *stream) { - // Check whether the passed stream is packed - - char tempBuffer[8]; - stream->seek(0); - if (stream->read(tempBuffer, 8) == 8) { - if (!strncmp(tempBuffer, madsPackString, 8)) - return true; - } - - return false; -} - -MadsPack::MadsPack(Common::SeekableReadStream *stream) { - initialize(stream); -} - -MadsPack::MadsPack(const char *resourceName, MadsM4Engine* vm) { - Common::SeekableReadStream *stream = vm->_resourceManager->get(resourceName); - initialize(stream); - vm->_resourceManager->toss(resourceName); -} - -void MadsPack::initialize(Common::SeekableReadStream *stream) { - if (!MadsPack::isCompressed(stream)) - error("Attempted to decompress a resource that was not MadsPacked"); - - stream->seek(14); - _count = stream->readUint16LE(); - _items = new MadsPackEntry[_count]; - - byte *headerData = new byte[0xA0]; - byte *header = headerData; - stream->read(headerData, 0xA0); - - for (int i = 0; i < _count; ++i, header += 10) { - // Get header data - _items[i].hash = READ_LE_UINT16(header); - _items[i].size = READ_LE_UINT32(header + 2); - _items[i].compressedSize = READ_LE_UINT32(header + 6); - - _items[i].data = new byte[_items[i].size]; - if (_items[i].size == _items[i].compressedSize) { - // Entry isn't compressed - stream->read(_items[i].data, _items[i].size); - } else { - // Decompress the entry - byte *compressedData = new byte[_items[i].compressedSize]; - stream->read(compressedData, _items[i].compressedSize); - - FabDecompressor fab; - fab.decompress(compressedData, _items[i].compressedSize, _items[i].data, _items[i].size); - delete[] compressedData; - } - } - - delete[] headerData; - _dataOffset = stream->pos(); -} - -Common::SeekableReadStream *MadsPack::getItemStream(int index) { - return new Common::MemoryReadStream(_items[index].data, _items[index].size, DisposeAfterUse::NO); -} - -MadsPack::~MadsPack() { - for (int i = 0; i < _count; ++i) - delete[] _items[i].data; - delete[] _items; -} - -//-------------------------------------------------------------------------- - -void FabDecompressor::decompress(const byte *srcData, int srcSize, byte *destData, int destSize) { - byte copyLen, copyOfsShift, copyOfsMask, copyLenMask; - unsigned long copyOfs; - byte *destP; - - // Validate that the data starts with the FAB header - if (strncmp((const char *)srcData, "FAB", 3) != 0) - error("FabDecompressor - Invalid compressed data"); - - int shiftVal = srcData[3]; - if ((shiftVal < 10) || (shiftVal > 13)) - error("FabDecompressor - Invalid shift start"); - - copyOfsShift = 16 - shiftVal; - copyOfsMask = 0xFF << (shiftVal - 8); - copyLenMask = (1 << copyOfsShift) - 1; - copyOfs = 0xFFFF0000; - destP = destData; - - // Initialize data fields - _srcData = srcData; - _srcP = _srcData + 6; - _srcSize = srcSize; - _bitsLeft = 16; - _bitBuffer = READ_LE_UINT16(srcData + 4); - - for (;;) { - if (getBit() == 0) { - if (getBit() == 0) { - copyLen = ((getBit() << 1) | getBit()) + 2; - copyOfs = *_srcP++ | 0xFFFFFF00; - } else { - copyOfs = (((_srcP[1] >> copyOfsShift) | copyOfsMask) << 8) | _srcP[0]; - copyLen = _srcP[1] & copyLenMask; - _srcP += 2; - if (copyLen == 0) { - copyLen = *_srcP++; - if (copyLen == 0) - break; - else if (copyLen == 1) - continue; - else - copyLen++; - } else { - copyLen += 2; - } - copyOfs |= 0xFFFF0000; - } - while (copyLen-- > 0) { - if (destP - destData == destSize) - error("FabDecompressor - Decompressed data exceeded specified size"); - - *destP = destP[(signed int)copyOfs]; - destP++; - } - } else { - if (_srcP - srcData == srcSize) - error("FabDecompressor - Passed end of input buffer during decompression"); - if (destP - destData == destSize) - error("FabDecompressor - Decompressed data exceeded specified size"); - - *destP++ = *_srcP++; - } - } - - if (destP - destData != destSize) - error("FabDecompressor - Decompressed data does not match header decompressed size"); -} - -int FabDecompressor::getBit() { - _bitsLeft--; - if (_bitsLeft == 0) { - if (_srcP - _srcData == _srcSize) - error("FabDecompressor - Passed end of input buffer during decompression"); - - _bitBuffer = (READ_LE_UINT16(_srcP) << 1) | (_bitBuffer & 1); - _srcP += 2; - _bitsLeft = 16; - } - - int bit = _bitBuffer & 1; - _bitBuffer >>= 1; - return bit; -} - -} // End of namespace M4 diff --git a/engines/m4/compression.h b/engines/m4/compression.h deleted file mode 100644 index cb0ef74eb7..0000000000 --- a/engines/m4/compression.h +++ /dev/null @@ -1,77 +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. - * - */ - -#ifndef M4_COMPRESSION_H -#define M4_COMPRESSION_H - -#include "common/scummsys.h" -#include "common/stream.h" -#include "common/endian.h" - -#include "m4/m4.h" - -namespace M4 { - -struct MadsPackEntry { -public: - uint16 hash; - uint32 size; - uint32 compressedSize; - byte *data; -}; - -class MadsPack { -private: - MadsPackEntry *_items; - int _count; - int _dataOffset; - - void initialize(Common::SeekableReadStream *stream); -public: - static bool isCompressed(Common::SeekableReadStream *stream); - MadsPack(Common::SeekableReadStream *stream); - MadsPack(const char *resourceName, MadsM4Engine *vm); - ~MadsPack(); - - int getCount() const { return _count; } - MadsPackEntry &getItem(int index) const { return _items[index]; } - MadsPackEntry &operator[](int index) const { return _items[index]; } - Common::SeekableReadStream *getItemStream(int index); - int getDataOffset() const { return _dataOffset; } -}; - -class FabDecompressor { -private: - int _bitsLeft; - uint32 _bitBuffer; - const byte *_srcData, *_srcP; - int _srcSize; - - int getBit(); -public: - void decompress(const byte *srcData, int srcSize, byte *destData, int destSize); -}; - -} // End of namespace M4 - - -#endif diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp deleted file mode 100644 index fa4ca6d121..0000000000 --- a/engines/m4/console.cpp +++ /dev/null @@ -1,428 +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/textconsole.h" - -#include "m4/m4.h" -#include "m4/console.h" -#include "m4/dialogs.h" -#include "m4/scene.h" -#include "m4/staticres.h" - -namespace M4 { - -Console::Console(MadsM4Engine *vm) : GUI::Debugger() { - _vm = vm; - - DCmd_Register("scene", WRAP_METHOD(Console, cmdLoadScene)); - DCmd_Register("start", WRAP_METHOD(Console, cmdStartingScene)); - DCmd_Register("show_hotspots", WRAP_METHOD(Console, cmdShowHotSpots)); - DCmd_Register("list_hotspots", WRAP_METHOD(Console, cmdListHotSpots)); - DCmd_Register("play_sound", WRAP_METHOD(Console, cmdPlaySound)); - DCmd_Register("play_dsr_sound", WRAP_METHOD(Console, cmdPlayDSRSound)); - DCmd_Register("show_resources", WRAP_METHOD(Console, cmdShowResources)); - DCmd_Register("show_codes", WRAP_METHOD(Console, cmdShowCodes)); - DCmd_Register("dump_file", WRAP_METHOD(Console, cmdDumpFile)); - DCmd_Register("sprite", WRAP_METHOD(Console, cmdShowSprite)); - DCmd_Register("start_conv", WRAP_METHOD(Console, cmdStartConversation)); - DCmd_Register("textview", WRAP_METHOD(Console, cmdShowTextview)); - DCmd_Register("animview", WRAP_METHOD(Console, cmdShowAnimview)); -} - -Console::~Console() { -} - -static int strToInt(const char *s) { - if (!*s) - // No string at all - return 0; - else if (toupper(s[strlen(s) - 1]) != 'H') - // Standard decimal string - return atoi(s); - - // Hexadecimal string - uint tmp = 0; - int read = sscanf(s, "%xh", &tmp); - if (read < 1) - error("strToInt failed on string \"%s\"", s); - return (int)tmp; -} - -bool Console::cmdLoadScene(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Usage: %s \n", argv[0]); - return true; - } else { - if (_vm->isM4()) - _vm->_kernel->newRoom = atoi(argv[1]); - else - _vm->_scene->loadScene(atoi(argv[1])); - return false; - } -} - -bool Console::cmdStartingScene(int argc, const char **argv) { - if (_vm->getGameType() != GType_Riddle) { - if (_vm->isM4()) - _vm->_kernel->newRoom = FIRST_SCENE; - else - _vm->_scene->loadScene(FIRST_SCENE); - return false; - } else { - DebugPrintf("%s: Riddle of Master Lu is not supported", argv[0]); - return true; - } -} - -bool Console::cmdShowHotSpots(int argc, const char **argv) { - _vm->_scene->showHotSpots(); - return false; -} - -bool Console::cmdListHotSpots(int argc, const char **argv) { - DebugPrintf("Scene hotspots\n"); - _vm->_scene->getSceneResources().hotspots->dump(); - if (_vm->isM4()) { - DebugPrintf("Scene parallax\n"); - _m4Vm->scene()->getSceneResources().parallax->dump(); - DebugPrintf("Scene dynamic hotspots\n"); - _vm->_scene->getSceneResources().dynamicHotspots->dump(); - } - return true; -} - -bool Console::cmdPlaySound(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Usage: %s \n", argv[0]); - } else { - _vm->_sound->playSound(argv[1], 255, false); - } - return true; -} - -bool Console::cmdPlayDSRSound(int argc, const char **argv) { - if (argc != 2 && argc != 3) { - DebugPrintf("Usage: %s \n", argv[0]); - DebugPrintf("The DSR file parameter is optional, and specifies which DSR to load\n"); - } else { - if (argc == 3) - _vm->_sound->loadDSRFile(argv[2]); - _vm->_sound->playDSRSound(atoi(argv[1]), 255, false); - } - return true; -} - -bool Console::cmdShowResources(int argc, const char **argv) { - _vm->res()->dump(); - return true; -} - -bool Console::cmdShowCodes(int argc, const char **argv) { - _vm->_scene->showCodes(); - return false; -} - -bool Console::cmdDumpFile(int argc, const char **argv) { - if (argc != 2 && argc != 3) { - DebugPrintf("Usage: %s \n", argv[0]); - DebugPrintf("If uncompress is 1, the file is uncompressed (for MADS games)\n"); - } else { - if (argc == 2) { - _vm->dumpFile(argv[1], false); - } else { - if (argc == 3 && atoi(argv[2]) == 1) - _vm->dumpFile(argv[1], true); - else - _vm->dumpFile(argv[1], false); - } - } - return true; -} - -bool Console::cmdShowSprite(int argc, const char **argv) { - View *view = _vm->_viewManager->getView(VIEWID_SCENE); - if (view == NULL) - DebugPrintf("The scene view isn't currently active\n"); - else if (argc < 2) - DebugPrintf("Usage: %s resource_name\n", argv[0]); - else { - char resourceName[20]; - strncpy(resourceName, argv[1], 15); - resourceName[15] = '\0'; - if (!strchr(resourceName, '.')) - strcat(resourceName, ".SS"); - - _vm->_viewManager->moveToFront(view); - Common::SeekableReadStream *data = _vm->res()->get(resourceName); - SpriteAsset *asset = new SpriteAsset(_vm, data, data->size(), resourceName); - _vm->res()->toss(resourceName); - - RGBList *palData = new RGBList(asset->getColorCount(), asset->getPalette(), true); - _vm->_palette->addRange(palData); - - // Get the scene background surface - M4Surface *bg = _vm->_scene->getBackgroundSurface(); - - // Write the sprite onto the screen - int x = 0, y = 0, yMax = 0; - for (int index = 0; index < asset->getCount(); index++) { - M4Sprite *spr = asset->getFrame(index); - spr->translate(palData); // sprite pixel translation - - if ((x + spr->width() >= bg->width()) && (yMax != 0)) { - x = 0; - y += yMax; - yMax = 0; - } - - if (y >= bg->height()) - break; - - spr->copyTo(bg, x, y, (int)spr->getTransparencyIndex()); - - x += spr->width(); - yMax = MAX(yMax, spr->height()); - } - - view->restore(0, 0, view->width(), view->height()); - return false; - } - - return true; -} - -bool Console::cmdStartConversation(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Usage: %s \n", argv[0]); - return true; - } else if (_vm->isM4()) { - ((M4Engine *)_vm)->_converse->startConversation(argv[1]); - return false; - } else { - error("MADS engine does not support conversations yet"); - return false; - } -} - -bool Console::cmdShowTextview(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Usage: %s \n", argv[0]); - return true; - } - - _vm->_viewManager->showTextView(argv[1], false); - return false; -} - -bool Console::cmdShowAnimview(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Usage: %s \n", argv[0]); - return true; - } - - char resName[80]; - strcpy(resName, "@"); - strcat(resName, *argv[1] == '@' ? argv[1] + 1 : argv[1]); - - _vm->_viewManager->showAnimView(resName, false); - return false; -} - -/*--------------------------------------------------------------------------*/ - -MadsConsole::MadsConsole(MadsEngine *vm): Console(vm) { - _vm = vm; - - DCmd_Register("object", WRAP_METHOD(MadsConsole, cmdObject)); - DCmd_Register("message", WRAP_METHOD(MadsConsole, cmdMessage)); - DCmd_Register("scene_info", WRAP_METHOD(MadsConsole, cmdSceneInfo)); - DCmd_Register("anim", WRAP_METHOD(MadsConsole, cmdPlayAnimation)); -} - -bool MadsConsole::cmdObject(int argc, const char **argv) { - if (argc == 1) { - DebugPrintf("Usage: object ['list' | '#objnum' | 'add #objnum']\n"); - } else if (!strcmp(argv[1], "list")) { - // List of objects - for (uint objStart = 0; objStart < _vm->globals()->getObjectsSize(); objStart += 5) { - DebugPrintf("%2d - ", objStart); - for (uint objId = objStart; objId < MIN(_vm->globals()->getObjectsSize(), objStart + 5); ++objId) { - if (objId != objStart) DebugPrintf(", "); - uint16 descId = _vm->globals()->getObject(objId)->_descId; - DebugPrintf("%s", _vm->globals()->getVocab(descId)); - } - - DebugPrintf("\n"); - } - - DebugPrintf("\n"); - } else if (!strcmp(argv[1], "add") && (argc == 3)) { - // Add the specified object to the player's inventory - int objNum = strToInt(argv[2]); - - if ((objNum < 0) || (objNum >= (int)_vm->globals()->getObjectsSize())) - DebugPrintf("Invalid object specified\n"); - else if (_vm->isM4()) - DebugPrintf("Not implemented for M4 games\n"); - else { - _vm->_scene->getInterface()->addObjectToInventory(objNum); - return false; - } - - } else { - // Print the details of a specific object - int objNum = strToInt(argv[1]); - - if ((objNum < 0) || (objNum >= (int)_vm->globals()->getObjectsSize())) - DebugPrintf("Invalid object specified\n"); - else { - const MadsObject *obj = _vm->globals()->getObject(objNum); - - DebugPrintf("Object #%d (%s) room=%d article=%d/%s vocabs=%d", objNum, _vm->globals()->getVocab(obj->_descId), - obj->_roomNumber, (int)obj->_article, englishMADSArticleList[obj->_article], obj->_vocabCount); - - if (obj->_vocabCount > 0) { - DebugPrintf(" - "); - for (int i = 0; i < obj->_vocabCount; ++i) { - if (i != 0) DebugPrintf(", "); - DebugPrintf("%s (%d)/%d,%d", _vm->globals()->getVocab(obj->_vocabList[i].vocabId), - obj->_vocabList[i].vocabId, obj->_vocabList[i].flags1, obj->_vocabList[i].flags2); - } - } - DebugPrintf("\n"); - } - } - - return true; -} - -bool MadsConsole::cmdMessage(int argc, const char **argv) { - if (argc == 1) { - DebugPrintf("message 'objnum'\n"); - } else if (!strcmp(argv[1], "list_quotes")) { - // Dump the quotes list -#if 0 - // FIXME: The following code is not portable and hence has been disabled. - // Try replacing FILE by Common::DumpFile. - FILE *destFile = fopen("mads_quotes.txt", "wb"); - for (uint i = 0; i < _vm->globals()->getQuotesSize(); ++i) - fprintf(destFile, "%.3d - %s\n", i, _vm->globals()->getQuote(i)); - fclose(destFile); -#endif - - } else if (!strcmp(argv[1], "list_vocab")) { - // Dump the vocab list -#if 0 - // FIXME: The following code is not portable and hence has been disabled. - // Try replacing FILE by Common::DumpFile. - FILE *destFile = fopen("mads_vocab.txt", "wb"); - for (uint i = 1; i <= _vm->globals()->getVocabSize(); ++i) - fprintf(destFile, "%.3d/%.3x - %s\n", i, i, _vm->globals()->getVocab(i)); - fclose(destFile); -#endif - - } else { - int messageIdx = strToInt(argv[1]); - - if ((argc != 3) || (strcmp(argv[2], "idx") != 0)) - messageIdx = _vm->globals()->messageIndexOf(messageIdx); - - const char *msg = _vm->globals()->loadMessage(messageIdx); - if (!msg) - DebugPrintf("Unknown message\n"); - else { - Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); - - _vm->_viewManager->addView(dlg); - _vm->_viewManager->moveToFront(dlg); - - return false; - } - } - - return true; -} - -bool MadsConsole::cmdSceneInfo(int argc, const char **argv) { - DebugPrintf("Current scene is: %i\n", _vm->_scene->getCurrentScene()); - - return true; -} - -bool MadsConsole::cmdPlayAnimation(int argc, const char **argv) { - View *view = _vm->_viewManager->getView(VIEWID_SCENE); - if (view == NULL) { - DebugPrintf("The scene view isn't currently active\n"); - } else if (argc != 2 && argc != 3) { - DebugPrintf("Usage: %s \n", argv[0]); - DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n"); - } else { - char resourceName[20]; - strncpy(resourceName, argv[1], 15); - resourceName[15] = '\0'; - if (!strchr(resourceName, '.')) - strcat(resourceName, ".AA"); - - _vm->_viewManager->moveToFront(view); - if (argc == 3 && atoi(argv[2]) == 1) - _madsVm->_palette->deleteAllRanges(); - - _madsVm->scene()->_sceneAnimation->load(resourceName, 0); - - view->restore(0, 0, view->width(), view->height()); - return false; - } - - return true; -} - -/*--------------------------------------------------------------------------*/ - -M4Console::M4Console(M4Engine *vm): Console(vm) { - _vm = vm; - - DCmd_Register("scene_info", WRAP_METHOD(M4Console, cmdSceneInfo)); -} - -bool M4Console::cmdSceneInfo(int argc, const char **argv) { - DebugPrintf("Current scene is: %i\n", _m4Vm->scene()->getCurrentScene()); - - DebugPrintf("Scene resources:\n"); - DebugPrintf("artBase: %s\n", _m4Vm->scene()->getSceneResources().artBase); - DebugPrintf("pictureBase: %s\n", _m4Vm->scene()->getSceneResources().pictureBase); - DebugPrintf("hotspotCount: %i\n", _m4Vm->scene()->getSceneResources().hotspots->size()); - DebugPrintf("parallaxCount: %i\n", _m4Vm->scene()->getSceneResources().parallaxCount); - DebugPrintf("dynHotspotCount: %i\n", _m4Vm->scene()->getSceneResources().dynamicHotspots->size()); - DebugPrintf("frontY: %i\n", _m4Vm->scene()->getSceneResources().frontY); - DebugPrintf("backY: %i\n", _m4Vm->scene()->getSceneResources().backY); - DebugPrintf("frontScale: %i\n", _m4Vm->scene()->getSceneResources().frontScale); - DebugPrintf("backScale: %i\n", _m4Vm->scene()->getSceneResources().backScale); - DebugPrintf("depthTable: "); - for (uint i = 0; i < 16; i++) - DebugPrintf("%i ", _m4Vm->scene()->getSceneResources().depthTable[i]); - DebugPrintf("\n"); - DebugPrintf("railNodeCount: %i\n", _m4Vm->scene()->getSceneResources().railNodeCount); - - return true; -} - -} // End of namespace M4 diff --git a/engines/m4/console.h b/engines/m4/console.h deleted file mode 100644 index fc473b6464..0000000000 --- a/engines/m4/console.h +++ /dev/null @@ -1,83 +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. - * - */ - -#ifndef M4_CONSOLE_H -#define M4_CONSOLE_H - -#include "gui/debugger.h" - -namespace M4 { - -class MadsM4Engine; -class MadsEngine; - -class Console : public GUI::Debugger { -private: - MadsM4Engine *_vm; - - bool cmdLoadScene(int argc, const char **argv); - bool cmdStartingScene(int argc, const char **argv); - bool cmdShowHotSpots(int argc, const char **argv); - bool cmdListHotSpots(int argc, const char **argv); - bool cmdPlaySound(int argc, const char **argv); - bool cmdPlayDSRSound(int argc, const char **argv); - bool cmdShowResources(int argc, const char **argv); - bool cmdShowCodes(int argc, const char **argv); - bool cmdDumpFile(int argc, const char **argv); - bool cmdShowSprite(int argc, const char **argv); - bool cmdStartConversation(int argc, const char **argv); - bool cmdShowTextview(int argc, const char **argv); - bool cmdShowAnimview(int argc, const char **argv); - -public: - Console(MadsM4Engine *vm); - virtual ~Console(); -}; - -class MadsConsole : public Console { -private: - MadsEngine *_vm; - - bool cmdObject(int argc, const char **argv); - bool cmdMessage(int argc, const char **argv); - bool cmdSceneInfo(int argc, const char **argv); - bool cmdPlayAnimation(int argc, const char **argv); - -public: - MadsConsole(MadsEngine *vm); - virtual ~MadsConsole() {} -}; - -class M4Console : public Console { -private: - M4Engine *_vm; - - bool cmdSceneInfo(int argc, const char **argv); -public: - M4Console(M4Engine *vm); - virtual ~M4Console() {} -}; - -} // End of namespace M4 - - -#endif diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp deleted file mode 100644 index 299fafb282..0000000000 --- a/engines/m4/converse.cpp +++ /dev/null @@ -1,1239 +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/array.h" -#include "common/hashmap.h" -#include "common/substream.h" -#include "common/textconsole.h" - -#include "m4/converse.h" -#include "m4/resource.h" -#include "m4/globals.h" -#include "m4/m4_views.h" -#include "m4/compression.h" - -namespace M4 { - -#define CONV_ENTRIES_X_OFFSET 20 -#define CONV_ENTRIES_Y_OFFSET 4 -#define CONV_ENTRIES_HEIGHT 20 -#define CONV_MAX_SHOWN_ENTRIES 5 - -#define CONVERSATION_ENTRY_HIGHLIGHTED 22 -#define CONVERSATION_ENTRY_NORMAL 3 - -// Conversation chunks -// Header -#define HEAD_CONV MKTAG('C','O','N','V') // conversation -#define CHUNK_DECL MKTAG('D','E','C','L') // declaration -#define CHUNK_NODE MKTAG('N','O','D','E') // node -#define CHUNK_LNOD MKTAG('L','N','O','D') // linear node -#define CHUNK_ETRY MKTAG('E','T','R','Y') // entry -#define CHUNK_TEXT MKTAG('T','E','X','T') // text -#define CHUNK_MESG MKTAG('M','E','S','G') // message -// Conversation chunks - entry related (unconditional) -#define CHUNK_RPLY MKTAG('R','P','L','Y') // reply -#define CHUNK_HIDE MKTAG('H','I','D','E') // hide entry -#define CHUNK_UHID MKTAG('U','H','I','D') // unhide entry -#define CHUNK_DSTR MKTAG('D','S','T','R') // destroy entry -// Conversation chunks - entry related (conditional) -#define CHUNK_CRPL MKTAG('C','R','P','L') // reply -#define CHUNK_CHDE MKTAG('C','H','D','E') // hide entry -#define CHUNK_CUHD MKTAG('C','U','H','D') // unhide entry -#define CHUNK_CDST MKTAG('D','D','T','S') // destroy entry -// Conversation chunks - branching and logic (unconditional) -#define CHUNK_ASGN MKTAG('A','S','G','N') // assign -#define CHUNK_GOTO MKTAG('G','O','T','O') // goto chunk -#define CHUNK_EXIT MKTAG('E','X','I','T') // exit/return from goto -// Conversation chunks - branching and logic (conditional) -#define CHUNK_CASN MKTAG('C','A','S','N') // assign -#define CHUNK_CCGO MKTAG('C','C','G','O') // goto chunk -#define CHUNK_CEGO MKTAG('C','E','G','O') // exit/return from goto -// Others -#define CHUNK_FALL MKTAG('F','A','L','L') // fallthrough -#define CHUNK_WRPL MKTAG('W','R','P','L') // weighted reply chunk -#define CHUNK_WPRL MKTAG('W','P','R','L') // weighted preply chunk - - -ConversationView::ConversationView(MadsM4Engine *vm): View(vm, Common::Rect(0, - vm->_screen->height() - INTERFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) { - - _screenType = VIEWID_CONVERSATION; - _screenFlags.layer = LAYER_INTERFACE; - _screenFlags.visible = false; - _screenFlags.get = SCREVENT_MOUSE; - _conversationState = kNoConversation; - _currentHandle = NULL; -} - -ConversationView::~ConversationView() { - _activeItems.clear(); -} - -void ConversationView::setNode(int32 nodeIndex) { - _highlightedIndex = -1; - _xEnd = CONV_ENTRIES_X_OFFSET; - _vm->_font->setFont(FONT_CONVERSATION); - - // TODO: Conversation styles and colors - _vm->_font->current()->setColors(2, 1, 3); - - _currentNodeIndex = nodeIndex; - - _activeItems.clear(); - - if (nodeIndex != -1) { - ConvEntry *node = _m4Vm->_converse->getNode(nodeIndex); - - for (uint i = 0; i < node->entries.size(); ++i) { - if (!node->entries[i]->visible) - continue; - - if ((int)_activeItems.size() > CONV_MAX_SHOWN_ENTRIES) { - warning("TODO: scrolling. Max shown entries are %i, skipping entry %i", - CONV_MAX_SHOWN_ENTRIES, i); - } - - // Add node to active items list - _activeItems.push_back(node->entries[i]); - - if (node->entries[i]->autoSelect || node->entries[i]->text[0] == '\0') { - //warning(kDebugConversations, "Auto selecting entry %i of node %i\n", i, nodeIndex); - selectEntry(i); - return; - } - - // Figure out the longest string to determine where option highlighting ends - int tempX = _vm->_font->current()->getWidth(node->entries[i]->text, 0) + - CONV_ENTRIES_X_OFFSET + 10; - _xEnd = MAX(_xEnd, tempX); - } - - // Make sure that there aren't too many entries - //assert((int)_activeItems.size() < (height() - CONV_ENTRIES_Y_OFFSET) / CONV_ENTRIES_HEIGHT); - - // Fallthrough - if (node->fallthroughMinEntries >= 0 && node->fallthroughOffset >= 0) { - //warning(kDebugConversations, "Current node falls through node at offset %i when entries are less or equal than %i\n", - // node->fallthroughOffset, node->fallthroughMinEntries); - if (_activeItems.size() <= (uint32)node->fallthroughMinEntries) { - const EntryInfo *entryInfo = _m4Vm->_converse->getEntryInfo(node->fallthroughOffset); - //warning(kDebugConversations, "Entries are less than or equal to %i, falling through to node at offset %i, index %i\n", - // node->fallthroughMinEntries, node->fallthroughOffset, entryInfo->nodeIndex); - setNode(entryInfo->nodeIndex); - return; - } - } - - _entriesShown = true; - _conversationState = kConversationOptionsShown; - } -} - -void ConversationView::onRefresh(RectList *rects, M4Surface *destSurface) { - //if (!this->isVisible()) - // return; - clear(); - - if (_entriesShown) { - // Write out the conversation options - _vm->_font->setFont(FONT_CONVERSATION); - for (int i = 0; i < (int)_activeItems.size(); ++i) { - // TODO: scrolling - if (i > CONV_MAX_SHOWN_ENTRIES - 1) - break; - - _vm->_font->current()->setColor((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED : - CONVERSATION_ENTRY_NORMAL); - - _vm->_font->current()->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET, - CONV_ENTRIES_Y_OFFSET + CONV_ENTRIES_HEIGHT * i, 0, 0); - } - } - View::onRefresh(rects, destSurface); -} - -bool ConversationView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - //if (!this->isVisible()) - // return false; - if (!_entriesShown) - return false; - if (eventType == KEVENT_KEY) - return false; - - int localY = y - _coords.top; - int selectedIndex = _highlightedIndex; - - switch (eventType) { - case MEVENT_MOVE: - if ((x < CONV_ENTRIES_X_OFFSET) || (x >= _xEnd) || (localY < CONV_ENTRIES_Y_OFFSET)) - _highlightedIndex = -1; - else { - int index = (localY - CONV_ENTRIES_Y_OFFSET) / CONV_ENTRIES_HEIGHT; - _highlightedIndex = (index >= (int)_activeItems.size()) ? -1 : index; - } - break; - - case MEVENT_LEFT_RELEASE: - if (_highlightedIndex != -1) { - selectEntry(selectedIndex); - } - break; - - default: - break; - } - - return true; -} - -void ConversationView::selectEntry(int entryIndex) { - char buffer[20]; - sprintf(buffer, "%s.raw", _activeItems[entryIndex]->voiceFile); - - _entriesShown = false; - _conversationState = kEntryIsActive; - _vm->_player->setCommandsAllowed(false); - // Necessary, as entries can be selected programmatically - _highlightedIndex = entryIndex; - - // Play the selected entry's voice - if (_activeItems[entryIndex]->voiceFile[0] != '\0') { - _currentHandle = _vm->_sound->getHandle(); - _vm->_sound->playVoice(buffer, 255); - } else { - _currentHandle = NULL; - } - - // Hide selected entry, unless it has a persistent flag set - if (!(_activeItems[entryIndex]->flags & kEntryPersists)) { - //debugCN(kDebugConversations, "Hiding selected entry\n"); - _m4Vm->_converse->getNode(_currentNodeIndex)->entries[entryIndex]->visible = false; - } else { - //debugCN(kDebugConversations, "Selected entry is persistent, not hiding it\n"); - } -} - -void ConversationView::updateState() { - switch (_conversationState) { - case kConversationOptionsShown: - return; - case kEntryIsActive: - case kReplyIsActive: - // FIXME: for now, we determine whether a conversation entry is - // finished by waiting for its associated speech file to finish playing - if (_currentHandle != NULL && _vm->_sound->isHandleActive(_currentHandle)) { - return; - } else { - playNextReply(); - } // end else - break; - case kNoConversation: - return; - default: - error("Unknown converstation state"); - break; - } -} - -void ConversationView::playNextReply() { - char buffer[20]; - - assert(_highlightedIndex >= 0); - - // Start playing the first reply - for (uint32 i = 0; i < _activeItems[_highlightedIndex]->entries.size(); i++) { - ConvEntry *currentEntry = _activeItems[_highlightedIndex]->entries[i]; - - if (currentEntry->isConditional) { - if (!_m4Vm->_converse->evaluateCondition( - _m4Vm->_converse->getValue(currentEntry->condition.offset), - currentEntry->condition.op, currentEntry->condition.val)) - continue; // don't play this reply - } - - if (currentEntry->entryType != kWeightedReply) { - sprintf(buffer, "%s.raw", currentEntry->voiceFile); - if (currentEntry->voiceFile[0] != '\0') { - _currentHandle = _vm->_sound->getHandle(); - _vm->_sound->playVoice(buffer, 255); - // Remove reply from the list of replies - _activeItems[_highlightedIndex]->entries.remove_at(i); - _conversationState = kReplyIsActive; - return; - } else { - _currentHandle = NULL; - } - } else { - int selectedWeight = _vm->_random->getRandomNumber(currentEntry->totalWeight - 1) + 1; - //debugCN(kDebugConversations, "Selected weight: %i\n", selectedWeight); - int previousWeight = 1; - int currentWeight = 0; - - for (uint32 j = 0; j < currentEntry->entries.size(); j++) { - currentWeight += currentEntry->entries[j]->weight; - if (selectedWeight >= previousWeight && selectedWeight <= currentWeight) { - sprintf(buffer, "%s.raw", currentEntry->entries[j]->voiceFile); - if (currentEntry->entries[j]->voiceFile[0] != '\0') { - _currentHandle = _vm->_sound->getHandle(); - _vm->_sound->playVoice(buffer, 255); - // Remove reply from the list of replies - _activeItems[_highlightedIndex]->entries.remove_at(i); - _conversationState = kReplyIsActive; - return; - } else { - _currentHandle = NULL; - } - break; - } - previousWeight += currentWeight; - } // end for j - } // end if - } // end for i - - // If we reached here, there are no more replies, so perform the active entry's actions - - //debugCN(kDebugConversations, "Current selection does %i actions\n", _activeItems[entryIndex]->actions.size()); - for (uint32 i = 0; i < _activeItems[_highlightedIndex]->actions.size(); i++) { - if (!_m4Vm->_converse->performAction(_activeItems[_highlightedIndex]->actions[i])) - break; - } // end for - - // Refresh the conversation node, in case it hasn't changed - setNode(_currentNodeIndex); - - _entriesShown = true; - _vm->_player->setCommandsAllowed(true); - - // Check if the conversation has been ended - if (_currentNodeIndex == -1) { - _conversationState = kNoConversation; - } -} - -//-------------------------------------------------------------------------- - -void Converse::startConversation(const char *convName, bool showConverseBox, ConverseStyle style) { - if (_vm->isM4()) - loadConversation(convName); - else - loadConversationMads(convName); - - if (!_vm->isM4()) showConverseBox = false; // TODO: remove - - _playerCommandsAllowed = _vm->_player->commandsAllowed; - if (_vm->isM4()) // TODO: remove (interface not implemented yet in MADS games) - _interfaceWasVisible = _m4Vm->scene()->getInterface()->isVisible(); - _vm->_player->setCommandsAllowed(false); - _style = style; - - if (showConverseBox) { - _vm->_conversationView->show(); - _vm->_mouse->lockCursor(CURSOR_ARROW); - - if (_interfaceWasVisible) - _m4Vm->scene()->getInterface()->hide(); - - _vm->_conversationView->setNode(0); - _vm->_conversationView->show(); - } -} - -void Converse::endConversation() { - _vm->_conversationView->setNode(-1); - _vm->_conversationView->hide(); - // TODO: do a more proper cleanup here - _convNodes.clear(); - _variables.clear(); - _offsetMap.clear(); - _vm->_player->setCommandsAllowed(_playerCommandsAllowed); - if (_interfaceWasVisible) - _m4Vm->scene()->getInterface()->show(); -} - -void Converse::loadConversation(const char *convName) { - char name[40]; - char buffer[256]; - sprintf(name, "%s.chk", convName); - Common::SeekableReadStream *convS = _vm->res()->get(name); - uint32 header = convS->readUint32LE(); - uint32 size; - uint32 chunk; - uint32 data = 0; - uint32 i = 0; - ConvEntry* curEntry = NULL; - ConvEntry* replyEntry = NULL; - int32 currentWeightedEntry = -1; - EntryAction* curAction = NULL; - uint32 curNode = 0; - uint32 chunkPos = 0; - uint32 val; - int32 autoSelectIndex = -1; - int returnAddress = -1; - - bool debugFlag = false; // set to true for debug messages - - // Conversation *.chk files contain a 'CONV' header in LE format - if (header != HEAD_CONV) { - warning("Unexpected conversation file external header"); - return; - } - size = convS->readUint32LE(); // is this used at all? - if (debugFlag) debugCN(kDebugConversations, "Conv chunk size (external header): %i\n", size); - - // Conversation name, which is the conversation file's name - // without the extension - convS->read(buffer, 8); - if (debugFlag) debugCN(kDebugConversations, "Conversation name: %s\n", buffer); - - while (true) { - chunkPos = convS->pos(); - chunk = convS->readUint32LE(); // read chunk - if (convS->eos()) break; - - if (debugFlag) debugC(kDebugConversations, "***** Pos: %i -> ", chunkPos); - switch (chunk) { - case CHUNK_DECL: // Declare - if (debugFlag) debugCN(kDebugConversations, "DECL chunk\n"); - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Tag: %i\n", data); - if (data > 0) - warning("Tag > 0 in DECL chunk, value is: %i", data); // TODO - val = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Value: %i\n", val); - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Flags: %i\n", data); - if (data > 0) - warning("Flags != 0 in DECL chunk, value is %i", data); // TODO - setValue(chunkPos, val); - break; - // ---------------------------------------------------------------------------- - case CHUNK_NODE: // Node - case CHUNK_LNOD: // Linear node - // Create new node - curEntry = new ConvEntry(); - curEntry->offset = chunkPos; - curEntry->entryType = (chunk == CHUNK_NODE) ? kNode : kLinearNode; - curEntry->fallthroughMinEntries = -1; - curEntry->fallthroughOffset = -1; - if (chunk == CHUNK_NODE) { - if (debugFlag) debugCN(kDebugConversations, "NODE chunk\n"); - } else { - if (debugFlag) debugCN(kDebugConversations, "LNOD chunk\n"); - } - curNode = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Node number: %i\n", curNode); - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Tag: %i\n", data); - if (chunk == CHUNK_LNOD) { - autoSelectIndex = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Autoselect entry number: %i\n", autoSelectIndex); - } - size = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Number of entries: %i\n", size); - for (i = 0; i < size; i++) { - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Entry %i: %i\n", i + 1, data); - } - _convNodes.push_back(curEntry); - setEntryInfo(curEntry->offset, curEntry->entryType, curNode, -1); - break; - case CHUNK_ETRY: // Entry - // Create new entry - curEntry = new ConvEntry(); - curEntry->offset = chunkPos; - curEntry->entryType = kEntry; - strcpy(curEntry->voiceFile, ""); - strcpy(curEntry->text, ""); - if (debugFlag) debugCN(kDebugConversations, "ETRY chunk\n"); - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Unknown (attributes perhaps?): %i\n", data); - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Entry flags: "); - if (debugFlag) if (data & kEntryInitial) debugCN(kDebugConversations, "Initial "); - if (debugFlag) if (data & kEntryPersists) debugCN(kDebugConversations, "Persists "); - if (debugFlag) debugCN(kDebugConversations, "\n"); - curEntry->flags = data; - curEntry->visible = (curEntry->flags & kEntryInitial) ? true : false; - if (autoSelectIndex >= 0) { - if (_convNodes[curNode]->entries.size() == (uint32)autoSelectIndex) { - curEntry->autoSelect = true; - autoSelectIndex = -1; - } else { - curEntry->autoSelect = false; - } - } else { - curEntry->autoSelect = false; - } - _convNodes[curNode]->entries.push_back(curEntry); - setEntryInfo(curEntry->offset, curEntry->entryType, - curNode, _convNodes[curNode]->entries.size() - 1); - replyEntry = NULL; - break; - case CHUNK_WPRL: // Weighted preply - // WPRL chunks are random entries that the character would say, not an NPC - // They don't seem to be used in Orion Burger - warning("WPRL chunk - treating as WRPL chunk"); - case CHUNK_WRPL: // Weighted reply - case CHUNK_CRPL: // Conditional reply - case CHUNK_RPLY: // Reply - { - ConvEntry* weightedEntry = NULL; - // Create new reply - replyEntry = new ConvEntry(); - replyEntry->offset = chunkPos; - strcpy(replyEntry->voiceFile, ""); - - // Conditional part - if (chunk == CHUNK_CRPL) { - replyEntry->isConditional = true; - replyEntry->condition.offset = convS->readUint32LE(); - replyEntry->condition.op = convS->readUint32LE(); - replyEntry->condition.val = convS->readUint32LE(); - } else { - replyEntry->isConditional = false; - } - - if (chunk == CHUNK_WPRL || chunk == CHUNK_WRPL) { - replyEntry->entryType = kWeightedReply; - replyEntry->totalWeight = 0; - if (debugFlag) debugCN(kDebugConversations, "WRPL chunk\n"); - size = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Weighted reply %i - %i entries:\n", i, size); - for (i = 0; i < size; i++) { - weightedEntry = new ConvEntry(); - weightedEntry->offset = chunkPos; - strcpy(weightedEntry->voiceFile, ""); - weightedEntry->entryType = kWeightedReply; - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "- Weight: %i ", data); - weightedEntry->weight = data; - replyEntry->totalWeight += weightedEntry->weight; - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "offset: %i\n", data); - replyEntry->entries.push_back(weightedEntry); - } - currentWeightedEntry = 0; - } else { - replyEntry->entryType = kReply; - if (debugFlag) debugCN(kDebugConversations, "RPLY chunk\n"); - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Reply data offset: %i\n", data); - } - - if (!curEntry) - error("Converse::loadConversation(): curEntry is NULL while adding a reply"); - - curEntry->entries.push_back(replyEntry); - setEntryInfo(replyEntry->offset, replyEntry->entryType, - curNode, _convNodes[curNode]->entries.size() - 1); - // Seek to chunk data (i.e. TEXT/MESG tag, which is usually right - // after this chunk but it can be further on in conditional reply chunks - assert((int)data >= convS->pos()); - // If the entry's data is not right after the entry, remember the position - // to return to after the data is read - if (chunk == CHUNK_CRPL && (int)data != convS->pos()) - returnAddress = convS->pos(); - convS->seek(data, SEEK_SET); - } - break; - // ---------------------------------------------------------------------------- - case CHUNK_TEXT: // Text (contains text and voice) - case CHUNK_MESG: // Message (contains voice only) - { - ConvEntry* parentEntry = NULL; - if (chunk == CHUNK_TEXT) { - if (debugFlag) debugCN(kDebugConversations, "TEXT chunk\n"); - } else { - if (debugFlag) debugCN(kDebugConversations, "MESG chunk\n"); - } - - if (replyEntry == NULL) { - parentEntry = curEntry; - } else if (replyEntry != NULL && replyEntry->entryType != kWeightedReply) { - parentEntry = replyEntry; - } else if (replyEntry != NULL && replyEntry->entryType == kWeightedReply) { - parentEntry = replyEntry->entries[currentWeightedEntry]; - currentWeightedEntry++; - } else { - error("Converse::loadConversation(): Unexpected reply entry while processing TEXT/MESG chunk"); - } - - size = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Entry data size: %i\n", size); - convS->read(buffer, 8); - size -= 8; // subtract maximum length of voice file name - // If the file name is 8 characters, it will not be 0-terminated, so use strncpy - strncpy(parentEntry->voiceFile, buffer, 8); - parentEntry->voiceFile[8] = '\0'; - if (debugFlag) debugCN(kDebugConversations, "Voice file: %s\n", parentEntry->voiceFile); - - if (chunk == CHUNK_TEXT) { - convS->read(buffer, size); - if (debugFlag) debugCN(kDebugConversations, "Text: %s\n", buffer); - sprintf(parentEntry->text, "%s", buffer); - } else { - while (size > 0) { - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Unknown: %i\n", data); // TODO - size -= 4; - } - } - // Now that the data chunk has been read, if we skipped a reply node, - // jump back to it - if (returnAddress != -1) { - convS->seek(returnAddress, SEEK_SET); - returnAddress = -1; - } - } - break; - // ---------------------------------------------------------------------------- - // Entry action chunks - case CHUNK_CASN: // Conditional assign - case CHUNK_ASGN: { // Assign - curAction = new EntryAction(); - if (debugFlag) debugCN(kDebugConversations, "ASGN chunk\n"); - curAction->actionType = kAssignValue; - - // Conditional part - if (chunk == CHUNK_CASN) { - curAction->isConditional = true; - curAction->condition.offset = convS->readUint32LE(); - curAction->condition.op = convS->readUint32LE(); - curAction->condition.val = convS->readUint32LE(); - } else { - curAction->isConditional = false; - } - - curAction->targetOffset = convS->readUint32LE(); - int op = convS->readUint32LE(); - assert(op == kOpAssign); - curAction->value = convS->readUint32LE(); - break; - } - case CHUNK_CCGO: // Conditional go to entry - case CHUNK_CHDE: // Conditional hide entry - case CHUNK_CUHD: // Conditional unhide entry - case CHUNK_CDST: // Conditional destroy entry - case CHUNK_CEGO: // Conditional exit conversation / go to - - case CHUNK_GOTO: // Go to entry - case CHUNK_HIDE: // Hide entry - case CHUNK_UHID: // Unhide entry - case CHUNK_DSTR: // Destroy entry - case CHUNK_EXIT: // Exit conversation - curAction = new EntryAction(); - - // Conditional part - if (chunk == CHUNK_CCGO || chunk == CHUNK_CHDE || chunk == CHUNK_CUHD || - chunk == CHUNK_CDST || chunk == CHUNK_CEGO) { - curAction->isConditional = true; - curAction->condition.offset = convS->readUint32LE(); - curAction->condition.op = convS->readUint32LE(); - curAction->condition.val = convS->readUint32LE(); - } else { - curAction->isConditional = false; - } - - if (chunk == CHUNK_GOTO || chunk == CHUNK_CCGO) { - curAction->actionType = kGotoEntry; - if (debugFlag) debugCN(kDebugConversations, "GOTO chunk\n"); - } else if (chunk == CHUNK_HIDE || chunk == CHUNK_CHDE) { - curAction->actionType = kHideEntry; - if (debugFlag) debugCN(kDebugConversations, "HIDE chunk\n"); - } else if (chunk == CHUNK_UHID || chunk == CHUNK_CUHD) { - curAction->actionType = kUnhideEntry; - if (debugFlag) debugCN(kDebugConversations, "UHID chunk\n"); - } else if (chunk == CHUNK_DSTR || chunk == CHUNK_CDST) { - curAction->actionType = kDestroyEntry; - if (debugFlag) debugCN(kDebugConversations, "DSTR chunk\n"); - } else if (chunk == CHUNK_EXIT || chunk == CHUNK_CEGO) { - curAction->actionType = kExitConv; - if (debugFlag) debugCN(kDebugConversations, "EXIT chunk\n"); - } - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Offset: %i\n", data); - curAction->targetOffset = data; - curEntry->actions.push_back(curAction); - break; - case CHUNK_FALL: // Fallthrough - if (debugFlag) debugCN(kDebugConversations, "FALL chunk\n"); - size = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Minimum nodes: %i\n", size); - _convNodes[curNode]->fallthroughMinEntries = size; - data = convS->readUint32LE(); - if (debugFlag) debugCN(kDebugConversations, "Offset: %i\n", data); - _convNodes[curNode]->fallthroughOffset = data; - break; - // ---------------------------------------------------------------------------- - default: - // Should never happen - error("Unknown conversation chunk"); - break; - } - } - - _vm->res()->toss(name); -} - -void Converse::loadConversationMads(const char *convName) { - char name[40]; - char buffer[256]; - char *buf; - Common::SeekableReadStream *convS; - int curPos = 0; - int unk = 0; - uint32 stringIndex = 0; - uint32 stringCount = 0; - int flags = 0; - int count = 0; - uint32 i, j; - ConvEntry* curEntry = NULL; - MessageEntry *curMessage; - Common::Array messageList; - // TODO - - // CND file - sprintf(name, "%s.cnd", convName); - MadsPack convDataD(name, _vm); - - // ------------------------------------------------------------ - // Chunk 0 - convS = convDataD.getItemStream(0); - debugCN(kDebugConversations, "Chunk 0\n"); - debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - while (!convS->eos()) { // FIXME (eos changed) - debugCN(kDebugConversations, "%i ", convS->readByte()); - } - debugCN(kDebugConversations, "\n"); - - // ------------------------------------------------------------ - // Chunk 1 - convS = convDataD.getItemStream(1); - debugCN(kDebugConversations, "Chunk 1\n"); - debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - while (!convS->eos()) { // FIXME (eos changed) - debugCN(kDebugConversations, "%i ", convS->readByte()); - } - debugCN(kDebugConversations, "\n"); - - // ------------------------------------------------------------ - // Chunk 2 - convS = convDataD.getItemStream(2); - debugCN(kDebugConversations, "Chunk 2\n"); - debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - while (!convS->eos()) { // FIXME (eos changed) - debugCN(kDebugConversations, "%i ", convS->readByte()); - } - debugCN(kDebugConversations, "\n"); - - // ------------------------------------------------------------ - // CNV file - sprintf(name, "%s.cnv", convName); - MadsPack convData(name, _vm); - // *.cnv files have 7 chunks - // Here is the chunk output of conv001.cnv (from the dump_file command) - /* - Dumping conv001.cnv, size: 3431 - Dumping compressed chunk 1 of 7, size is 150 - Dumping compressed chunk 2 of 7, size is 130 - Dumping compressed chunk 3 of 7, size is 224 - Dumping compressed chunk 4 of 7, size is 92 - Dumping compressed chunk 5 of 7, size is 168 - Dumping compressed chunk 6 of 7, size is 4064 - Dumping compressed chunk 7 of 7, size is 2334 - */ - - // ------------------------------------------------------------ - // TODO: finish this - // Chunk 0 - convS = convData.getItemStream(0); - debugCN(kDebugConversations, "Chunk 0\n"); - debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - debugCN(kDebugConversations, "\n"); - count = convS->readUint16LE(); // conversation face count (usually 2) - debugCN(kDebugConversations, "Conversation faces: %i\n", count); - for (i = 0; i < 5; i++) { - convS->read(buffer, 16); - debugCN(kDebugConversations, "Face %i: %s ", i + 1, buffer); - } - debugCN(kDebugConversations, "\n"); - - // 5 face slots - // 1 = face slot has a face (with the filename specified above) - // 0 = face slot doesn't contain face data - for (i = 0; i < 5; i++) { - debugCN(kDebugConversations, "%i ", convS->readUint16LE()); - } - debugCN(kDebugConversations, "\n"); - - convS->read(buffer, 14); // speech file - debugCN(kDebugConversations, "Speech file: %s\n", buffer); - - while (!convS->eos()) { // FIXME: eos changed - debugCN(kDebugConversations, "%i ", convS->readByte()); - } - debugCN(kDebugConversations, "\n"); - - delete convS; - - // ------------------------------------------------------------ - // Chunk 1: Conversation nodes - convS = convData.getItemStream(1); - debugCN(kDebugConversations, "Chunk 1: conversation nodes\n"); - debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - while (true) { - uint16 id = convS->readUint16LE(); - if (convS->eos()) break; - - curEntry = new ConvEntry(); - curEntry->id = id; - curEntry->entryCount = convS->readUint16LE(); - curEntry->flags = convS->readUint16LE(); - if (curEntry->entryCount == 1 && curEntry->flags != 65535) { - warning("Entry count is 1 and flags is not 65535 (it's %i)", flags); - } else if (curEntry->entryCount != 1 && flags != 0) { - warning("Entry count > 1 and flags is not 0 (it's %i)", flags); - } - unk = convS->readUint16LE(); - assert (unk == 65535); - unk = convS->readUint16LE(); - assert (unk == 65535); - _convNodes.push_back(curEntry); - debugCN(kDebugConversations, "Node %i, ID %i, entries %i\n", _convNodes.size(), curEntry->id, curEntry->entryCount); - // flags = 0: node has more than 1 entry - // flags = 65535: node has 1 entry - } - debugCN(kDebugConversations, "Conversation has %i nodes\n", _convNodes.size()); - debugCN(kDebugConversations, "\n"); - - delete convS; - - // ------------------------------------------------------------ - // Chunk 4 contains the conversation string offsets of chunk 5 - // (unused, as it's unneeded - we find the offsets ourselves) - - // ------------------------------------------------------------ - // Chunk 5 contains the conversation strings - convS = convData.getItemStream(5); - //debugCN(kDebugConversations, "Chunk 5: conversation strings\n"); - //debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - *buffer = 0; - - while (true) { - //if (curPos == 0) - // debugCN(kDebugConversations, "%i: Offset %i: ", _convStrings.size(), convS->pos()); - uint8 b = convS->readByte(); - if (convS->eos()) break; - - buffer[curPos++] = b; - if (buffer[curPos - 1] == '~') { // filter out special characters - curPos--; - continue; - } - if (buffer[curPos - 1] == '\0') { - // end of string - //debugCN(kDebugConversations, "%s\n", buffer); - buf = new char[strlen(buffer) + 1]; - strcpy(buf, buffer); - _convStrings.push_back(buf); - curPos = 0; - *buffer = 0; - } - } - - delete convS; - - // ------------------------------------------------------------ - // Chunk 2: entry data - convS = convData.getItemStream(2); - //debugCN(kDebugConversations, "Chunk 2 - entry data\n"); - //debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - for (i = 0; i < _convNodes.size(); i++) { - for (j = 0; j < _convNodes[i]->entryCount; j++) { - curEntry = new ConvEntry(); - stringIndex = convS->readUint16LE(); - if (stringIndex != 65535) - sprintf(curEntry->text, "%s", _convStrings[stringIndex]); - else - *curEntry->text = 0; - curEntry->id = convS->readUint16LE(); - curEntry->offset = convS->readUint16LE(); - curEntry->size = convS->readUint16LE(); - - _convNodes[i]->entries.push_back(curEntry); - //debugCN(kDebugConversations, "Node %i, entry %i, id %i, offset %i, size %i, text: %s\n", - // i, j, curEntry->id, curEntry->offset, curEntry->size, curEntry->text); - } - } - - delete convS; - - // ------------------------------------------------------------ - // Chunk 3: message (MESG) chunks, created from the strings of chunk 5 - convS = convData.getItemStream(3); - //debugCN(kDebugConversations, "Chunk 3 - MESG chunk data\n"); - //debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - - while (true) { - uint16 index = convS->readUint16LE(); - if (convS->eos()) break; - - curMessage = new MessageEntry(); - stringIndex = index; - stringCount = convS->readUint16LE(); - *buffer = 0; - //debugCN(kDebugConversations, "Message: %i\n", _madsMessageList.size()); - for (i = stringIndex; i < stringIndex + stringCount; i++) { - //debugCN(kDebugConversations, "%i: %s\n", i, _convStrings[i]); - curMessage->messageStrings.push_back(_convStrings[i]); - } - _madsMessageList.push_back(curMessage); - //debugCN(kDebugConversations, "----------\n"); - } - //debugCN(kDebugConversations, "\n"); - - delete convS; - - // ------------------------------------------------------------ - // TODO: finish this - // Chunk 6: conversation script - convS = convData.getItemStream(6); - debugCN(kDebugConversations, "Chunk 6\n"); - debugCN(kDebugConversations, "Conv stream size: %i\n", convS->size()); - /*while (!convS->eos()) { // FIXME (eos changed) - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "%i ", convS->readByte()); - debugCN(kDebugConversations, "\n"); - } - return;*/ - - for (i = 0; i < _convNodes.size(); i++) { - for (j = 0; j < _convNodes[i]->entryCount; j++) { - debugCN(kDebugConversations, "*** Node %i entry %i data size %i\n", i, j, _convNodes[i]->entries[j]->size); - debugCN(kDebugConversations, "Entry ID %i, text %s\n", _convNodes[i]->entries[j]->id, _convNodes[i]->entries[j]->text); - Common::ReadStream *entryStream = new Common::SubReadStream(convS, _convNodes[i]->entries[j]->size); - readConvEntryActions(entryStream, _convNodes[i]->entries[j]); - delete entryStream; - debugCN(kDebugConversations, "--------------------\n"); - } - } - - delete convS; -} - -void Converse::readConvEntryActions(Common::ReadStream *convS, ConvEntry *curEntry) { - uint8 chunk; - uint8 type; // 255: normal, 11: conditional - uint8 hasText1, hasText2; - int target; - int count = 0; - int var, val; - int messageIndex = 0; - int unk = 0; - - while (true) { - chunk = convS->readByte(); - if (convS->eos()) break; - - type = convS->readByte(); - - switch (chunk) { - case 1: - debugCN(kDebugConversations, "TODO: chunk type %i\n", chunk); - break; - case 2: - debugCN(kDebugConversations, "HIDE\n"); - convS->readByte(); - count = convS->readByte(); - debugCN(kDebugConversations, "%i entries: ", count); - for (int i = 0; i < count; i++) - debugCN(kDebugConversations, "%i %d", i, convS->readUint16LE()); - debugCN(kDebugConversations, "\n"); - break; - case 3: - debugCN(kDebugConversations, "UNHIDE\n"); - convS->readByte(); - count = convS->readByte(); - debugCN(kDebugConversations, "%i entries: ", count); - for (int i = 0; i < count; i++) - debugCN(kDebugConversations, "%i %d", i, convS->readUint16LE()); - debugCN(kDebugConversations, "\n"); - break; - case 4: // MESSAGE - debugCN(kDebugConversations, "MESSAGE\n"); - - if (type == 255) { - //debugCN(kDebugConversations, "unconditional\n"); - } else if (type == 11) { - //debugCN(kDebugConversations, "conditional\n"); - } else { - debugCN(kDebugConversations, "unknown type: %i\n", type); - } - - // Conditional part - if (type == 11) { - unk = convS->readUint16LE(); // 1 - if (unk != 1) - debugCN(kDebugConversations, "Message: unk != 1 (it's %i)\n", unk); - - var = convS->readUint16LE(); - val = convS->readUint16LE(); - debugCN(kDebugConversations, "Var %i == %i\n", var, val); - } - unk = convS->readUint16LE(); // 256 - if (unk != 256) - debugCN(kDebugConversations, "Message: unk != 256 (it's %i)\n", unk); - - // it seems that the first text entry is set when the message - // chunk is supposed to be shown unconditionally, whereas the second text - // entry is set when the message is supposed to be shown conditionally - hasText1 = convS->readByte(); - hasText2 = convS->readByte(); - - if (hasText1 == 1) { - messageIndex = convS->readUint16LE(); - debugCN(kDebugConversations, "Message 1 index: %i, text:\n", messageIndex); - for (uint32 i = 0; i < _madsMessageList[messageIndex]->messageStrings.size(); i++) { - debugCN(kDebugConversations, "%s\n", _madsMessageList[messageIndex]->messageStrings[i]); - } - } - - if (hasText2 == 1) { - messageIndex = convS->readUint16LE(); - if (hasText1 == 0) { - debugCN(kDebugConversations, "Message 2 index: %i, text:\n", messageIndex); - for (uint32 i = 0; i < _madsMessageList[messageIndex]->messageStrings.size(); i++) { - debugCN(kDebugConversations, "%s\n", _madsMessageList[messageIndex]->messageStrings[i]); - } - } - } - - break; - case 5: // AUTO - debugCN(kDebugConversations, "AUTO\n"); - for (int k = 0; k < 4; k++) - convS->readByte(); - messageIndex = convS->readUint16LE(); - debugCN(kDebugConversations, "Message index: %i, text:\n", messageIndex); - for (uint32 i = 0; i < _madsMessageList[messageIndex]->messageStrings.size(); i++) { - debugCN(kDebugConversations, "%s\n", _madsMessageList[messageIndex]->messageStrings[i]); - } - - convS->readUint16LE(); - break; - case 6: - debugCN(kDebugConversations, "TODO: chunk type %i\n", chunk); - break; - case 7: // GOTO - unk = convS->readUint32LE(); // 0 - if (unk != 0 && unk != 1) - debugCN(kDebugConversations, "Goto: unk != 0 or 1 (it's %i)\n", unk); - - target = convS->readUint16LE(); - convS->readUint16LE(); // 255 - - if (unk != 0) - debugCN(kDebugConversations, "Goto: unk != 0 (it's %i)\n", unk); - - if (target != 65535) - debugCN(kDebugConversations, "GOTO node %i\n", target); - else - debugCN(kDebugConversations, "GOTO exit\n"); - break; - case 8: - debugCN(kDebugConversations, "TODO: chunk type %i\n", chunk); - break; - case 9: // ASSIGN - //debugCN(kDebugConversations, "ASSIGN\n"); - unk = convS->readUint32LE(); // 0 - - if (unk != 0) - debugCN(kDebugConversations, "Assign: unk != 0 (it's %i)\n", unk); - - val = convS->readUint16LE(); - var = convS->readUint16LE(); - //debugCN(kDebugConversations, "Var %i = %i\n", var, val); - break; - default: - debugCN(kDebugConversations, "Unknown chunk type! (%i)\n", chunk); - break; - } - } - debugCN(kDebugConversations, "\n"); -} - -void Converse::setEntryInfo(int32 offset, EntryType type, int32 nodeIndex, int32 entryIndex) { - char hashOffset[10]; - sprintf(hashOffset, "%i", offset); - EntryInfo info; - info.targetType = type; - info.nodeIndex = nodeIndex; - info.entryIndex = entryIndex; - _offsetMap[hashOffset] = info; - //debugCN(kDebugConversations, "Set entry info: offset %i, type %i, node %i, entry %i\n", offset, type, nodeIndex, entryIndex); -} - -const EntryInfo* Converse::getEntryInfo(int32 offset) { - char hashOffset[10]; - sprintf(hashOffset, "%i", offset); - OffsetHashMap::const_iterator entry = _offsetMap.find(hashOffset); - if (entry != _offsetMap.end()) - return &(entry->_value); - else - error("Undeclared entry offset: %i", offset); -} - -void Converse::setValue(int32 offset, int32 value) { - char hashOffset[10]; - sprintf(hashOffset, "%i", offset); - _variables[hashOffset] = value; -} - -int32 Converse::getValue(int32 offset) { - char hashOffset[10]; - sprintf(hashOffset, "%i", offset); - ConvVarHashMap::const_iterator entry = _variables.find(hashOffset); - if (entry != _variables.end()) - return entry->_value; - else - error("Undeclared variable offset: %i", offset); -} - -bool Converse::evaluateCondition(int32 leftVal, int32 op, int32 rightVal) { - switch (op) { - case kOpPercent: - return (leftVal % rightVal == 0); - case kOpGreaterOrEqual: - return leftVal >= rightVal; - case kOpLessOrEqual: - return leftVal <= rightVal; - case kOpGreaterThan: - return leftVal > rightVal; - case kOpLessThan: - return leftVal < rightVal; - case kOpNotEqual: - case kOpCondNotEqual: - return leftVal != rightVal; - case kOpAssign: - return leftVal == rightVal; - case kOpAnd: - return leftVal && rightVal; - case kOpOr: - return leftVal || rightVal; - default: - error("Unknown conditional operator: %i", op); - } -} - -bool Converse::performAction(EntryAction *action) { - if (action->isConditional) { - if (!evaluateCondition(getValue(action->condition.offset), - action->condition.op, action->condition.val)) - return true; // don't perform this action - } - - if (action->actionType == kAssignValue) { - //debugCN(kDebugConversations, "Assigning variable at offset %i to value %i\n", - // action->targetOffset, action->value); - setValue(action->targetOffset, action->value); - return true; // nothing else to do in an assignment action - } - - const EntryInfo *entryInfo = getEntryInfo(action->targetOffset); - ConvEntry *targetEntry; - - if (entryInfo->nodeIndex >= 0 && entryInfo->entryIndex >= 0) - targetEntry = getNode(entryInfo->nodeIndex)->entries[entryInfo->entryIndex]; - else if (entryInfo->nodeIndex >= 0) - targetEntry = getNode(entryInfo->nodeIndex); - else - error("Target node id is negative"); - - switch (action->actionType) { - case kGotoEntry: - //debugCN(kDebugConversations, "Goto entry at offset %i. Associated node is %i, entry %i\n", - // action->targetOffset, entryInfo->nodeIndex, entryInfo->entryIndex); - _vm->_conversationView->setNode(entryInfo->nodeIndex); - if (entryInfo->entryIndex >= 0) - _vm->_conversationView->selectEntry(entryInfo->entryIndex); - return false; - case kHideEntry: - //debugCN(kDebugConversations, "Hide entry at offset %i. Associated node is %i, entry %i\n", - // targetEntry->offset, entryInfo->nodeIndex, entryInfo->entryIndex); - targetEntry->visible = false; - return true; - case kUnhideEntry: - //debugCN(kDebugConversations, "Show entry at offset %i. Associated node is %i, entry %i\n", - // targetEntry->offset, entryInfo->nodeIndex, entryInfo->entryIndex); - targetEntry->visible = true; - return true; - case kDestroyEntry: - //debugCN(kDebugConversations, "Destroy entry at offset %i. Associated node is %i, entry %i\n", - // targetEntry->offset, entryInfo->nodeIndex, entryInfo->entryIndex); - if (entryInfo->entryIndex >= 0) - getNode(entryInfo->nodeIndex)->entries.remove_at(entryInfo->entryIndex); - else - warning("Target entry is a node, not destroying it"); - targetEntry->visible = true; - return true; - case kExitConv: - //debugCN(kDebugConversations, "Exit conversation\n"); - endConversation(); - return false; - default: - warning("Unknown entry action"); - return false; - } // end switch -} - -/*--------------------------------------------------------------------------*/ - -MadsConversation::MadsConversation() { - for (int i = 0; i < MADS_TALK_SIZE; ++i) { - _talkList[i].desc = NULL; - _talkList[i].id = 0; - } -} - - -} // End of namespace M4 diff --git a/engines/m4/converse.h b/engines/m4/converse.h deleted file mode 100644 index b47e8d2a6b..0000000000 --- a/engines/m4/converse.h +++ /dev/null @@ -1,214 +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. - * - */ - -#ifndef M4_CONVERSE_H -#define M4_CONVERSE_H - -#include "common/array.h" -#include "common/hashmap.h" - -#include "m4/globals.h" -#include "m4/viewmgr.h" -#include "m4/sound.h" - -namespace M4 { - -enum ConversationState { - kConversationOptionsShown = 0, - kEntryIsActive = 1, - kReplyIsActive = 2, - kNoConversation = 3 -}; - -enum EntryType { - kVariable = 0, - kNode = 1, - kLinearNode = 2, - kEntry = 3, - kReply = 4, - kWeightedReply = 5 -}; - -// Flags are: -// bit 0: if it's 1, the entry is "initial", i.e. not hidden when the dialog starts -// bit 1: if it's 1, the entry persists if selected -enum EntryFlags { - kEntryInitial = 1, // byte 0 - kEntryPersists = 2 // byte 1 -}; - -enum EntryActionType { - kUnknownAction = 0, - kGotoEntry = 1, - kHideEntry = 2, - kUnhideEntry = 3, - kDestroyEntry = 4, - kAssignValue = 5, - kExitConv = 6 -}; - -enum LogicOp { - kOpPercent = 405, - kOpGreaterOrEqual = 421, - kOpLessOrEqual = 420, - kOpGreaterThan = 413, - kOpLessThan = 412, - kOpNotEqual = 422, - kOpCondNotEqual = 448, - kOpAssign = 407, - kOpAnd = 444, - kOpOr = 445 -}; - -struct Condition { - int32 offset; - int32 op; - int32 val; -}; - -struct EntryAction { - int32 targetOffset; // absolute offset (inside the *.chk file) of the action's target - int32 value; // the value set by assignment chunks - EntryActionType actionType; - EntryType targetType; - int32 nodeId; - int32 entryId; - bool isConditional; - Condition condition; -}; - -struct ConvEntry { - EntryType entryType; - int32 id; - int32 offset; // absolute offset inside the *.chk file, referenced by other chunks - int32 size; // entry action data size (for MADS games) - int32 flags; - int32 fallthroughMinEntries; - int32 fallthroughOffset; - int32 weight; // weight for weighted replies - int32 totalWeight; - uint16 entryCount; // entries inside this node (for MADS games) - char voiceFile[10]; - char text[512]; - bool autoSelect; - bool visible; - bool isConditional; - Condition condition; - Common::Arrayactions; - Common::Arrayentries; -}; - -struct EntryInfo { - EntryType targetType; - int32 nodeIndex; - int32 entryIndex; -}; - -struct MessageEntry { - Common::ArraymessageStrings; -}; - -enum ConverseStyle {CONVSTYLE_EARTH, CONVSTYLE_SPACE}; - -typedef Common::HashMap OffsetHashMap; -typedef Common::HashMap ConvVarHashMap; - -class ConversationView : public View { -public: - ConversationView(MadsM4Engine *vm); - ~ConversationView(); - void setNode(int32 nodeIndex); - - void onRefresh(RectList *rects, M4Surface *destSurface); - bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); - int32 getCurrentNodeIndex() { return _currentNodeIndex; } - void selectEntry(int entryIndex); - -private: - void updateState(); - void playNextReply(); - - int32 _currentNodeIndex; - Common::Array _activeItems; - int _highlightedIndex; - int _xEnd; - bool _entriesShown; - ConversationState _conversationState; - SndHandle *_currentHandle; -}; - -class Converse { - -public: - Converse(MadsM4Engine *vm) : _vm(vm) {} - ~Converse() {} - - void startConversation(const char *convName, bool showConversebox = true, ConverseStyle style = CONVSTYLE_EARTH ); - void endConversation(); - const EntryInfo* getEntryInfo(int32 offset); - ConvEntry *getNode(int32 index) { return _convNodes[index]; } - - void setValue(int32 offset, int32 value); - int32 getValue(int32 offset); - bool evaluateCondition(int32 leftVal, int32 op, int32 rightVal); - bool performAction(EntryAction *action); - /* - void resume() { play(); } - void play(); - */ -private: - MadsM4Engine *_vm; - Common::Array_convNodes; - Common::Array_madsMessageList; - Common::Array_convStrings; - bool _playerCommandsAllowed; - bool _interfaceWasVisible; - ConverseStyle _style; - OffsetHashMap _offsetMap; - ConvVarHashMap _variables; - - void loadConversation(const char *convName); - void loadConversationMads(const char *convName); - void readConvEntryActions(Common::ReadStream *convS, ConvEntry *curEntry); - void setEntryInfo(int32 offset, EntryType type, int32 nodeIndex, int32 entryIndex); -}; - - -struct MadsTalkEntry { - uint16 id; - const char *desc; -}; - -#define MADS_TALK_SIZE 5 - -class MadsConversation { -private: - MadsTalkEntry _talkList[MADS_TALK_SIZE]; -public: - MadsConversation(); - - MadsTalkEntry &operator[](int index) { return _talkList[index]; } -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp deleted file mode 100644 index 6b8af6b5f2..0000000000 --- a/engines/m4/detection.cpp +++ /dev/null @@ -1,419 +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 "base/plugins.h" - -#include "engines/advancedDetector.h" - -#include "m4/m4.h" -#include "m4/resource.h" - -namespace M4 { - -struct M4GameDescription { - ADGameDescription desc; - - int gameType; - uint32 features; -}; - -int MadsM4Engine::getGameType() const { return _gameDescription->gameType; } -uint32 MadsM4Engine::getFeatures() const { return _gameDescription->features; } -Common::Language MadsM4Engine::getLanguage() const { return _gameDescription->desc.language; } -Common::Platform MadsM4Engine::getPlatform() const { return _gameDescription->desc.platform; } - -} // End of namespace M4 - -static const PlainGameDescriptor m4Games[] = { - {"m4", "MADS/M4 engine game"}, - {"riddle", "Ripley's Believe It or Not!: The Riddle of Master Lu"}, - {"burger", "Orion Burger"}, - {"rex", "Rex Nebular and the Cosmic Gender Bender"}, - {"dragon", "DragonSphere"}, - {"dragoncd", "DragonSphere CD"}, - {"phantom", "Return of the Phantom"}, - {"phantomcd", "Return of the Phantom CD"}, - {0, 0} -}; - -namespace M4 { - -const char *MadsM4Engine::getGameFile(int fileType) { - for (int i = 0; _gameDescription->desc.filesDescriptions[i].fileName; i++) { - if (_gameDescription->desc.filesDescriptions[i].fileType == fileType) - return _gameDescription->desc.filesDescriptions[i].fileName; - } - return NULL; -} - -static const M4GameDescription gameDescriptions[] = { - { - { - "burger", - "", - { - { "burger.has", kFileTypeHash, "10c8064e9c771072122f50737ac97245", 730771}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Burger, - kFeaturesCD - }, - { - { - "burger", - "", - { - { "burger.has", kFileTypeHash, "55be8693a4c36e7efcdca0f0c77758ae", 724191}, - { NULL, 0, NULL, 0} - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Burger, - kFeaturesCD - }, - { - { - "burger", - "", - { - { "burger.has", kFileTypeHash, "795c98a74e351ec437a396bb29897daf", 730771}, - { NULL, 0, NULL, 0} - }, - Common::RU_RUS, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Burger, - kFeaturesCD - }, - { - { - "burger", - "Demo", - { - { "burger.has", kFileTypeHash, "fc3f363b6153240a448bd3b7be9318da", 62159}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Burger, - kFeaturesDemo - }, - { - { - "burger", - "Demo", - { - { "overview.has", kFileTypeHash, "57aa43a3ef88a934a43e9b1890ef5e17", 10519}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Burger, - kFeaturesDemo - }, - { - { - "riddle", - "", - { - { "ripley.has", kFileTypeHash, "056d517360c89eb4c297a319f21a7071", 700469}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Riddle, - kFeaturesCD - }, - { - { - "riddle", - "", - { - { "ripley.has", kFileTypeHash, "d073582c9011d44dd0d7e2ede317a86d", 700469}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Riddle, - kFeaturesCD - }, - { - { - "riddle", - "", - { - { "ripley.has", kFileTypeHash, "d9e9f8befec432a047b1047fb2bc7aea", 710997}, - { NULL, 0, NULL, 0} - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Riddle, - kFeaturesCD - }, - { - { - "riddle", - "", - { - { "ripley.has", kFileTypeHash, "3d48c5700785d11e6a5bc832b95be918", 701973}, - { NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Riddle, - kFeaturesCD - }, - { - { - "riddle", - "", - { - { "ripley.has", kFileTypeHash, "5ee011cff7178dae3ddf6f9b7d4102ac", 701691}, - { NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Riddle, - kFeaturesCD - }, - { // Demo - { - "riddle", - "Demo", - { - { "ripley.has", kFileTypeHash, "3a90dd7052860b6e246ec7e0aaf202f6", 104527}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_UNSTABLE, - GUIO1(GUIO_NOASPECT) - }, - GType_Riddle, - kFeaturesDemo - }, - { - { - "rex", - "", - { - { "global.hag", kFileTypeHAG, "0530cbeee109fc79cc24421128dea1ce", 2083078}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOSPEECH) - }, - GType_RexNebular, - kFeaturesNone - }, - { // Demo - { - "rex", - "Demo", - { - { "global.hag", kFileTypeHAG, "d5a481d14bc1bda66e46965a39badcc7", 220429}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_UNSTABLE, - GUIO0() - }, - GType_RexNebular, - kFeaturesDemo - }, - { - { - "dragon", - "", - { - { "global.hag", kFileTypeHAG, "c3a6877665e7f21bf3d2b1e667155562", 2320567}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOSPEECH) - }, - GType_DragonSphere, - kFeaturesNone - }, - { // CD version - { - "dragoncd", - "", - { - { "global.hag", kFileTypeHAG, "c3a6877665e7f21bf3d2b1e667155562", 2320567}, - { "speech.hag", kFileTypeHAG, NULL, -1}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO0() - }, - GType_DragonSphere, - kFeaturesCD - }, - { // Demo - { - "dragon", - "Demo", - { - { "global.hag", kFileTypeHAG, "541e12d8e9aad0c65d65f150de47582e", 212718}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_UNSTABLE, - GUIO0() - }, - GType_DragonSphere, - kFeaturesDemo - }, - { - { - "phantom", - "", - { - { "global.hag", kFileTypeHAG, "bdce9ca93a015f0883d1bc0fabd0cdfa", 812150}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO1(GUIO_NOSPEECH) - }, - GType_Phantom, - kFeaturesNone - }, - { // CD version - { - "phantomcd", - "", - { - { "global.hag", kFileTypeHAG, "8a51c984eb4c64e8b30a7e6670f6bddb", 101154000}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_UNSTABLE, - GUIO0() - }, - GType_Phantom, - kFeaturesCD - }, - { // CD version - { - "phantom", - "Demo", - { - { "global.hag", kFileTypeHAG, "e810adbc6fac77ac2fec841a9ec5e20e", 115266}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_UNSTABLE, - GUIO0() - }, - GType_Phantom, - kFeaturesDemo - }, - { AD_TABLE_END_MARKER, 0, 0 } -}; - -} // End of namespace M4 - -static const char *directoryGlobs[] = { - "option1", - 0 -}; - -class M4MetaEngine : public AdvancedMetaEngine { -public: - M4MetaEngine() : AdvancedMetaEngine(M4::gameDescriptions, sizeof(M4::M4GameDescription), m4Games) { - _singleid = "m4"; - _guioptions = GUIO1(GUIO_NOMIDI); - _maxScanDepth = 2; - _directoryGlobs = directoryGlobs; - } - - virtual const char *getName() const { - return "MADS/M4"; - } - - virtual const char *getOriginalCopyright() const { - return "Riddle of Master Lu & Orion Burger (C) Sanctuary Woods"; - } - - virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const; -}; - -bool M4MetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { - const M4::M4GameDescription *gd = (const M4::M4GameDescription *)desc; - if (gd) { - if ((gd->gameType == M4::GType_Burger) || (gd->gameType == M4::GType_Riddle)) - *engine = new M4::M4Engine(syst, gd); - else - *engine = new M4::MadsEngine(syst, gd); - } - return gd != 0; -} - -#if PLUGIN_ENABLED_DYNAMIC(M4) - REGISTER_PLUGIN_DYNAMIC(M4, PLUGIN_TYPE_ENGINE, M4MetaEngine); -#else - REGISTER_PLUGIN_STATIC(M4, PLUGIN_TYPE_ENGINE, M4MetaEngine); -#endif diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp deleted file mode 100644 index 2a36fa037c..0000000000 --- a/engines/m4/dialogs.cpp +++ /dev/null @@ -1,558 +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 "m4/dialogs.h" -#include "common/file.h" -#include "common/textconsole.h" - -namespace M4 { - -static void strToUpper(char *s) { - while (*s) { - *s = toupper(*s); - ++s; - } -} - -static void strToLower(char *s) { - while (*s) { - *s = tolower(*s); - ++s; - } -} - -const RGB8 DIALOG_PALETTE[8] = { - {0x80, 0x80, 0x80}, {0x90, 0x90, 0x90}, {0x70, 0x70, 0x70}, {0x9c, 0x9c, 0x9c}, - {0x80, 0x80, 0x80}, {0x90, 0x90, 0x90}, {0xDC, 0xDC, 0xDC}, {0x00, 0x00, 0x00} -}; - -#define ROR16(v,amt) (((uint16)(v) >> amt) | ((uint16)(v) << (16 - amt))) - -const int DIALOG_SPACING = 1; - -/** - * Handles any dialog initialisation - */ -void Dialog::initDialog() { - incLine(); -} - -/** - * Adds a new line to the dialog output - */ -void Dialog::incLine() { - _lineX = 0; - _widthX = 0; - - _lines.push_back(*new DialogLine()); - assert(_lines.size() <= 20); -} - -/** - * Writes some text to the dialog output, taking care of word wrapping if the text size - * exceeds the dialog's width - */ -void Dialog::writeChars(const char *srcLine) { - char wordStr[80]; - char line[80]; - int lineLen, lineWidth; - const char *srcP = srcLine; - - while (*srcP) { - bool wordEndedP = false, newlineP = false; - char *destP = &wordStr[0]; - Common::fill(&wordStr[0], &wordStr[80], 0); - - // Try and get the next word - for (;;) { - char v = *srcP; - *destP++ = v; - - if (v == '\0') break; - if (v == '\n') { - newlineP = true; - ++srcP; - --destP; - break; - } - - if (v == ' ') { - // Word separator - ++srcP; - --destP; - wordEndedP = true; - } else { - // Standard character - if (!wordEndedP) - // Still in the initial word - ++srcP; - else { - // First character of next word, so time to break - --destP; - break; - } - } - } - - if (destP < &wordStr[0]) - destP = &wordStr[0]; - *destP = '\0'; - - strcpy(line, ""); - if (_lineX > 0) - strcat(line, " "); - strcat(line, wordStr); - - lineLen = strlen(line); - lineWidth = _vm->_font->current()->getWidth(line, DIALOG_SPACING); - - if (((_lineX + lineLen) > _widthChars) || ((_widthX + lineWidth) > _dialogWidth)) { - incLine(); - appendText(wordStr); - } else { - appendText(line); - } - - if (newlineP) - incLine(); - } -} - -/** - * Appends some text to the current dialog line - */ -void Dialog::appendText(const char *line) { - _lineX += strlen(line); - _widthX += _vm->_font->current()->getWidth(line, DIALOG_SPACING); - - strcat(_lines[_lines.size() - 1].data, line); -} - -/** - * Adds a line of text to the dialog lines list - */ -void Dialog::addLine(const char *line, bool underlineP) { - if ((_widthX > 0) || (_lineX > 0)) - incLine(); - - int lineWidth = _vm->_font->current()->getWidth(line, DIALOG_SPACING); - int lineLen = strlen(line); - - if ((lineWidth > _dialogWidth) || (lineLen >= _widthChars)) - writeChars(line); - else { - _lines[_lines.size() - 1].xp = (_dialogWidth - 10 - lineWidth) / 2; - strcpy(_lines[_lines.size() - 1].data, line); - } - - if (underlineP) - _lines[_lines.size() - 1].underline = true; - - incLine(); -} - -/** - * Adds a bar separation line to the dialog lines list - */ -void Dialog::addBarLine() { - if ((_widthX > 0) || (_lineX > 0)) - incLine(); - - // Flag the line as being a bar separator - _lines[_lines.size() - 1].barLine = true; - incLine(); -} - -/** - * Retrieves a specified vocab entry - */ -void Dialog::getVocab(int vocabId, char **line) { - assert(vocabId > 0); - const char *vocabStr = _madsVm->globals()->getVocab(vocabId); - strcpy(*line, vocabStr); - - if (_commandCase) - strToUpper(*line); - else - strToLower(*line); - - // Move the string pointer to after the added string - while (!**line) - ++*line; -} - -bool Dialog::handleNounSuffix(char *destP, int nounNum, const char *srcP) { - char srcLine[40]; - - // The next source character must be a colon in front of the first verb - if (*srcP != ':') - return false; - - // Copy the remainder of the line into a temporary buffer to get the seperate verbs - strcpy(srcLine, ++srcP); - char *altP = strchr(srcLine, ':'); - if (altP) - *altP = '\0'; - - if (*srcP != '\0') { - while (*srcP != ':') { - ++srcP; - if (!*srcP) break; - } - } - - if (*srcP != '\0') - ++srcP; - - // - char var_FC[40]; - char tempLine[40]; - strcpy(var_FC, srcP); - char *tmpP = &tempLine[0]; - char *tmp2P = tmpP; - - uint16 _vocabIds[2] = {1, 1}; // FIXME/TODO: Proper vocab ids - getVocab(_vocabIds[nounNum], &tmpP); - - if ((*(tmpP - 1) != 'S') && (*(tmpP - 1) != 's')) { - // Singular object - tmpP = &var_FC[0]; - } else if (!strcmp(tempLine, "a ")) { - // Pontially plural - char ch = tolower(*tmp2P); - - if (!((ch > 'U') || ((ch != 'A') && (ch != 'E') && (ch != 'I') && (ch != 'O')))) - strcpy(tempLine, "an "); - } - - strcpy(destP, tmpP); - return true; -} - -/** - * Sets up an area within the dialog for textual input - */ -void Dialog::setupInputArea() { - _askPosition.x = _lineX + 1; - _askPosition.y = _lines.size(); - - incLine(); -} - -/** - * Checks whether the start of an extracted command matches a specified given command constant - */ -bool Dialog::matchCommand(const char *s1, const char *s2) { - bool result = scumm_strnicmp(s1, s2, strlen(s2)) == 0; - _commandCase = isupper(static_cast(*s1)); - return result; -} - -Dialog::Dialog(MadsM4Engine *vm, const char *msgData, const char *title): View(vm, Common::Rect(0, 0, 0, 0)) { - assert(msgData); - _vm->_font->setFont(FONT_INTERFACE_MADS); - - const char *srcP = msgData; - bool skipLine = false; - bool initFlag = false; - bool cmdFlag = false; - bool crFlag = false; - bool underline = false; - - _screenType = LAYER_DIALOG; - _widthChars = 0; - _dialogIndex = 0; - _askPosition.x = 0; - _askPosition.y = 0; - _lineX = 0; - _widthX = 0; - _dialogWidth = 0; - _commandCase = false; - - char dialogLine[256]; - char cmdText[80]; - char *lineP = &dialogLine[0]; - char *cmdP = NULL; - - while (srcP && *(srcP - 1) != '\0') { - if ((*srcP == '\n') || (*srcP == '\0')) { - // Line completed - *lineP = '\0'; - ++srcP; - - if (!initFlag) { - initDialog(); - initFlag = true; - } - - if (!skipLine) - writeChars(dialogLine); - else { - addLine(dialogLine, underline); - - if (crFlag) - incLine(); - } - - // Clear the current line contents - dialogLine[0] = '\0'; - lineP = &dialogLine[0]; - skipLine = crFlag = underline = false; - continue; - - } else if (*srcP == '[') { - // Start of a command sequence - cmdFlag = true; - cmdP = &cmdText[0]; - ++srcP; - continue; - } else if (*srcP == ']') { - // End of a command sequence - *cmdP = '\0'; - cmdFlag = false; - strToUpper(cmdText); - - if (matchCommand(cmdText, "ASK")) { - setupInputArea(); - - } else if (matchCommand(cmdText, "BAR")) { - // Adds a full-width line instead of normal text - addBarLine(); - - } else if (matchCommand(cmdText, "CENTER")) { - // Center command - skipLine = true; - - } else if (matchCommand(cmdText, "CR")) { - // CR command - if (skipLine) - crFlag = true; - else if (!initFlag) { - initDialog(); - initFlag = true; - } - - } else if (matchCommand(cmdText, "NOUN1")) { - // Noun command 1 - handleNounSuffix(lineP, 1, cmdText + 5); - - } else if (matchCommand(cmdText, "NOUN2")) { - // Noun command 2 - handleNounSuffix(lineP, 2, cmdText + 5); - - } else if (matchCommand(cmdText, "SENTENCE")) { - // Sentence command - loads the title into the line buffer - strcpy(dialogLine, title); - strToUpper(dialogLine); - lineP += strlen(dialogLine) + 1; - - } else if (matchCommand(cmdText, "TAB")) { - // Specifies the X offset for the current line - _lines[_lines.size() - 1].xp = atoi(cmdText + 3); - - } else if (matchCommand(cmdText, "TITLE")) { - // Title command - specifies the dialog width in number of characters - skipLine = true; - crFlag = true; - underline = true; - - int id = atoi(cmdText + 5); - if (id > 0) { - // Suffix provided - specifies the dialog width in number of chars - _widthChars = id * 2; - _dialogWidth = id * (_vm->_font->current()->getMaxWidth() + DIALOG_SPACING) + 10; - } - - } else if (matchCommand(cmdText, "UNDER")) { - // Underline command - underline = true; - - } else if (matchCommand(cmdText, "VERB")) { - // Verb/vocab retrieval - int verbId = 1; // TODO: Get correct vocab - getVocab(verbId, &lineP); - - - } else if (matchCommand(cmdText, "INDEX")) { - // Index command - _dialogIndex = atoi(cmdText + 5); - } else { - error("Unknown dialog command '%s' encountered", cmdText); - } - } - - *lineP++ = *srcP; - if (cmdFlag) - *cmdP++ = *srcP; - ++srcP; - } - - draw(); -} - -Dialog::Dialog(MadsM4Engine *vm, int widthChars): View(vm, Common::Rect(0, 0, 0, 0)) { - _vm->_font->setFont(FONT_INTERFACE_MADS); - _widthChars = widthChars * 2; - _dialogWidth = widthChars * (_vm->_font->current()->getMaxWidth() + DIALOG_SPACING) + 10; - _screenType = LAYER_DIALOG; - _lineX = 0; - _widthX = 0; - _askPosition.x = 0; - _askPosition.y = 0; -} - -Dialog::~Dialog() { - _vm->_palette->deleteRange(_palette); - delete _palette; -} - -void Dialog::draw() { - assert(_widthChars != 0); - - // Set up the palette for this view - _palette = new RGBList(8, NULL); - _palette->setRange(0, 8, DIALOG_PALETTE); - _vm->_palette->addRange(_palette); - - // Calculate bounds - int dlgWidth = _dialogWidth; - int dlgHeight = _lines.size() * (_vm->_font->current()->getHeight() + 1) + 10; - int dialogX = (_vm->_screen->width() - dlgWidth) / 2; - int dialogY = (_vm->_screen->height() - dlgHeight) / 2; - - // Create the surface for the dialog - create(dlgWidth, dlgHeight, Graphics::PixelFormat::createFormatCLUT8()); - _coords.left = dialogX; - _coords.top = dialogY; - _coords.right = dialogX + dlgWidth + 1; - _coords.bottom = dialogY + dlgHeight + 1; - - // Set up the dialog - fillRect(Common::Rect(0, 0, width(), height()), 3); - setColor(2); - hLine(1, width() - 1, height() - 2); // Bottom edge - hLine(0, width(), height() - 1); - vLine(width() - 2, 2, height()); // Right edge - vLine(width() - 1, 1, height()); - - // Render dialog interior - uint16 seed = 0xb78e; - for (int yp = 2; yp < (height() - 2); ++yp) { - byte *destP = this->getBasePtr(2, yp); - - for (int xp = 2; xp < (width() - 2); ++xp) { - // Adjust the random seed - uint16 v = seed; - seed += 0x181D; - v = ROR16(v, 9); - seed = (seed ^ v) + ROR16(v, 3); - - *destP++ = ((seed & 0x10) != 0) ? 1 : 0; - } - } - - // If an ask position is set, create the input area frame - if (_askPosition.y > 0) { - - } - - // Handle drawing the text contents - _vm->_font->current()->setColors(7, 7, 7); - setColor(7); - - for (uint lineCtr = 0, yp = 5; lineCtr < _lines.size(); ++lineCtr, yp += _vm->_font->current()->getHeight() + 1) { - - if (_lines[lineCtr].barLine) { - // Bar separation line - hLine(5, width() - 6, ((_vm->_font->current()->getHeight() + 1) >> 1) + yp); - } else { - // Standard line - Common::Point pt(_lines[lineCtr].xp + 5, yp); - if (_lines[lineCtr].xp & 0x40) - ++pt.y; - - _vm->_font->current()->writeString(this, _lines[lineCtr].data, pt.x, pt.y, 0, DIALOG_SPACING); - - if (_lines[lineCtr].underline) - // Underline needed - hLine(pt.x, pt.x + _vm->_font->current()->getWidth(_lines[lineCtr].data, DIALOG_SPACING), - pt.y + _vm->_font->current()->getHeight()); - } - } - - // Do final translation of the dialog to game palette - this->translate(_palette); -} - -bool Dialog::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - if (_vm->_mouse->getCursorNum() != CURSOR_ARROW) - _vm->_mouse->setCursorNum(CURSOR_ARROW); - - captureEvents = true; - - if (eventType == MEVENT_LEFT_CLICK) { - captureEvents = false; - _vm->_viewManager->deleteView(this); - } - - return true; -} - -void Dialog::display(MadsM4Engine *vm, int widthChars, const char **descEntries) { - Dialog *dlg = new Dialog(vm, widthChars); - - while (*descEntries != NULL) { - dlg->incLine(); - dlg->writeChars(*descEntries); - - int lineWidth = vm->_font->current()->getWidth(*descEntries, DIALOG_SPACING); - dlg->_lines[dlg->_lines.size() - 1].xp = (dlg->_dialogWidth - 10 - lineWidth) / 2; - ++descEntries; - } - - dlg->_lines[0].underline = true; - - dlg->draw(); - vm->_viewManager->addView(dlg); - vm->_viewManager->moveToFront(dlg); -} - -void Dialog::getValue(MadsM4Engine *vm, const char *title, const char *text, int numChars, int currentValue) { - int titleLen = strlen(title); - Dialog *dlg = new Dialog(vm, titleLen + 4); - - dlg->addLine(title, true); - dlg->writeChars("\n"); - - dlg->writeChars(text); - dlg->setupInputArea(); - dlg->writeChars("\n"); - - dlg->draw(); - vm->_viewManager->addView(dlg); - vm->_viewManager->moveToFront(dlg); - - // TODO: How to wait until the dialog is closed - -} - -} // End of namespace M4 diff --git a/engines/m4/dialogs.h b/engines/m4/dialogs.h deleted file mode 100644 index ea3519c9e3..0000000000 --- a/engines/m4/dialogs.h +++ /dev/null @@ -1,80 +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. - * - */ - -#ifndef M4_DIALOGS_H -#define M4_DIALOGS_H - -#include "m4/m4.h" -#include "m4/viewmgr.h" -#include "common/list.h" - -namespace M4 { - -class DialogLine { -public: - char data[100]; - uint8 xp; - bool underline; - bool barLine; - - DialogLine() { data[0] = '\0'; xp = 0; underline = barLine = false; } -}; - -typedef void (*GetValueFn)(MadsM4Engine *vm, int result); - -class Dialog : public View { -private: - Common::Array _lines; - int _widthChars; - int _dialogWidth; - int _dialogIndex; - Common::Point _askPosition; - RGBList *_palette; - int _lineX; - int _widthX; - bool _commandCase; - - void initDialog(); - void incLine(); - bool matchCommand(const char *s1, const char *s2); - void writeChars(const char *line); - void addLine(const char *line, bool underlineP = false); - void appendText(const char *line); - void addBarLine(); - void getVocab(int vocabId, char **line); - bool handleNounSuffix(char *destP, int nounNum, const char *srcP); - void setupInputArea(); - void draw(); -public: - Dialog(MadsM4Engine *vm, const char *msgData, const char *title = NULL); - Dialog(MadsM4Engine *vm, int widthChars); - virtual ~Dialog(); - - static void display(MadsM4Engine *vm, int widthChars, const char **descEntries); - static void getValue(MadsM4Engine *vm, const char *title, const char *text, int numChars, int currentValue); - - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/events.cpp b/engines/m4/events.cpp deleted file mode 100644 index b476d08c9c..0000000000 --- a/engines/m4/events.cpp +++ /dev/null @@ -1,365 +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. - * - */ - -// TODO: There is a 'please_hyperwalk' variable that gets accessed that is meant to be global, but -// at the moment it's implemented as a local variable - -#include "graphics/cursorman.h" - -#include "m4/events.h" -#include "m4/graphics.h" -#include "m4/scene.h" -#include "m4/viewmgr.h" -#include "m4/m4.h" - -namespace M4 { - -bool please_hyperwalk = false; - -/*--------------------------------------------------------------------------* - * Events * - * * - * Implements an interface to the event system * - *--------------------------------------------------------------------------*/ - -Events::Events(MadsM4Engine *vm) : _vm(vm) { - _mouseState = MSTATE_NO_EVENT; - quitFlag = false; - _keyCode = 0; - _mouseButtons = 0; - _ctrlFlag = false; - - if (_vm->isM4()) - _console = new M4Console(_m4Vm); - else - _console = new MadsConsole(_madsVm); -} - -Events::~Events() { - delete _console; -} - -M4EventType Events::handleEvents() { - static int oldX = -1, oldY = -1; - static uint32 dclickTime = 0; - - // Handle event types - while (g_system->getEventManager()->pollEvent(_event)) { - switch (_event.type) { - case Common::EVENT_QUIT: - quitFlag = true; - break; - case Common::EVENT_KEYDOWN: - // Note: The Ctrl-D ScummVM shortcut has been specialised so it will only activate the debugger - // if it's the first key pressed after the Ctrl key is held down - if ((_event.kbd.keycode == Common::KEYCODE_LCTRL) || (_event.kbd.keycode == Common::KEYCODE_RCTRL)) - _ctrlFlag = true; - - else if (_event.kbd.hasFlags(Common::KBD_CTRL)) { - if ((_event.kbd.keycode == Common::KEYCODE_d) && _ctrlFlag) { - _console->attach(); - _console->onFrame(); - } - _ctrlFlag = false; - } - _keyCode = (int32)_event.kbd.keycode | ((_event.kbd.flags & (Common::KBD_CTRL | Common::KBD_ALT | Common::KBD_SHIFT)) << 24); - - - break; - case Common::EVENT_LBUTTONDOWN: - case Common::EVENT_LBUTTONUP: - case Common::EVENT_RBUTTONDOWN: - case Common::EVENT_RBUTTONUP: - case Common::EVENT_MBUTTONDOWN: - case Common::EVENT_MBUTTONUP: - case Common::EVENT_MOUSEMOVE: - case Common::EVENT_WHEELUP: - case Common::EVENT_WHEELDOWN: - _vm->_mouse->handleEvent(_event); - break; - default: - break; - } - } - - _mouseButtons = g_system->getEventManager()->getButtonState(); - - // State machine for moving between states - switch (_mouseState) { - case MSTATE_NO_EVENT: - if (_mouseButtons & LEFT_BUTTON_DOWN) { - if ((dclickTime != 0) && (g_system->getMillis() < dclickTime)) { - _mouseState = MSTATE_DOUBLECLICK_DOWN; - dclickTime = 0; - return MEVENT_DOUBLECLICK; - } - dclickTime = 0; - _mouseState = MSTATE_LEFT_CLICK_DOWN; - return MEVENT_LEFT_CLICK; - } - if (_mouseButtons & RIGHT_BUTTON_DOWN) { - _mouseState = MSTATE_RIGHT_CLICK_DOWN; - return MEVENT_RIGHT_CLICK; - } - if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) { - oldX = _event.mouse.x; oldY = _event.mouse.y; - return MEVENT_MOVE; - } - return MEVENT_NO_EVENT; - - case MSTATE_LEFT_CLICK_DOWN: - if (!(_mouseButtons & LEFT_BUTTON_DOWN)) { - dclickTime = g_system->getMillis() + 1000 * 15 / 60; - _mouseState = MSTATE_NO_EVENT; - return MEVENT_LEFT_RELEASE; - } - if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) { - oldX = _event.mouse.x; oldY = _event.mouse.y; - return MEVENT_LEFT_DRAG; - } - return MEVENT_LEFT_HOLD; - - case MSTATE_RIGHT_CLICK_DOWN: - if (!(_mouseButtons & RIGHT_BUTTON_DOWN)) { - _mouseState = MSTATE_NO_EVENT; - please_hyperwalk = true; - return MEVENT_RIGHT_RELEASE; - } - if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) { - oldX = _event.mouse.x; oldY = _event.mouse.y; - return MEVENT_RIGHT_DRAG; - } - return MEVENT_RIGHT_HOLD; - - case MSTATE_DOUBLECLICK_DOWN: - if (!(_mouseButtons & LEFT_BUTTON_DOWN)) { - _mouseState = MSTATE_NO_EVENT; - return MEVENT_DOUBLECLICK_RELEASE; - } - if ((_event.mouse.x != oldX) || (_event.mouse.y != oldY)) { - oldX = _event.mouse.x; oldY = _event.mouse.y; - return MEVENT_DOUBLECLICK_DRAG; - } - return MEVENT_DOUBLECLICK_HOLD; - - default: - return MEVENT_NO_EVENT; - } -} - -bool Events::kbdCheck(uint32 &keyCode) { - if (_keyCode == 0) - return false; - - keyCode = _keyCode; - _keyCode = 0; - return true; -} - - -/*--------------------------------------------------------------------------* - * Mouse * - * * - * Implements an interface to the mouse * - *--------------------------------------------------------------------------*/ - -Mouse::Mouse(MadsM4Engine *vm) : _vm(vm) { - _locked = false; - _cursorOn = false; - _cursor = NULL; - _cursorSprites = NULL; - resetMouse(); -} - -Mouse::~Mouse() { - delete _cursorSprites; -} - -bool Mouse::init(const char *seriesName, RGB8 *palette) { - Common::SeekableReadStream *stream = _vm->res()->get(seriesName); - int colorCount = 0; - RGB8* cursorPalette; - - _cursorSprites = new SpriteAsset(_vm, stream, stream->size(), seriesName); - - // Remove cursor special pixels and set the mouse cursor hotspot in MADS games - if (!_vm->isM4()) { - byte *data = NULL; - for (int i = 0; i < _cursorSprites->getCount(); i++) { - bool hotSpotSet = false; - - for (int x = 0; x < _cursorSprites->getFrame(i)->width(); x++) { - for (int y = 0; y < _cursorSprites->getFrame(i)->height(); y++) { - data = _cursorSprites->getFrame(i)->getBasePtr(x, y); - if (*data == 1) { - // It seems that some cursors have more than one hotspot - // In such a case, the first hotspot seems to set the x and - // the second one the y hotspot offset - if (!hotSpotSet) { - _cursorSprites->getFrame(i)->xOffset = x; - _cursorSprites->getFrame(i)->yOffset = y; - hotSpotSet = true; - } else { - _cursorSprites->getFrame(i)->yOffset = y; - } - *data = 0; - } - } // for y - } // for x - } // for i - } - - colorCount = _cursorSprites->getColorCount(); - cursorPalette = _cursorSprites->getPalette(); - _vm->_palette->setPalette(cursorPalette, 0, colorCount); - - //debugCN(kDebugCore, "Cursor count: %d\n", _cursorSprites->getCount()); - - _vm->res()->toss(seriesName); - - _currentCursor = -1; - return true; -} - -bool Mouse::setCursorNum(int cursorIndex) { - if ((cursorIndex < 0) || (cursorIndex >= (int)_cursorSprites->getCount())) - return false; - - _lockedCursor = cursorIndex; - if (_locked) - // Cursor is locked, so don't go ahead with changing cursor - return true; - - _currentCursor = _lockedCursor; - _cursor = _cursorSprites->getFrame(cursorIndex); - - // Set the cursor to the sprite - CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(), - _cursor->xOffset, _cursor->yOffset, TRANSPARENT_COLOR_INDEX); - - return true; -} - -int Mouse::cursorCount() { - return _cursorSprites->getCount(); -} - -void Mouse::cursorOn() { - _cursorOn = true; - CursorMan.showMouse(!inHideArea()); -} - -void Mouse::cursorOff() { - _cursorOn = false; - CursorMan.showMouse(false); -} - -void Mouse::lockCursor(int cursorIndex) { - _locked = false; - setCursorNum(cursorIndex); - _locked = true; -} - -void Mouse::unlockCursor() { - _locked = false; - setCursorNum(_lockedCursor); -} - -const char *Mouse::getVerb() { - switch (_vm->_mouse->getCursorNum()) { - case CURSOR_LOOK: - return "LOOK AT"; - case CURSOR_TAKE: - return "TAKE"; - case CURSOR_USE: - return "GEAR"; - default: - return NULL; - } -} - -void Mouse::resetMouse() { - _hideRect.left = -1; - _hideRect.top = -1; - _hideRect.right = -1; - _hideRect.bottom = -1; - _showRect.left = -1; - _showRect.top = -1; - _showRect.right = -1; - _showRect.bottom = -1; -} - -void Mouse::setHideRect(Common::Rect &r) { - _hideRect = r; -} - -void Mouse::setShowRect(Common::Rect &r) { - _showRect = r; -} - -const Common::Rect *Mouse::getHideRect() { - return &_hideRect; -} - -const Common::Rect *Mouse::getShowRect() { - if ((_showRect.top == -1) || (_showRect.left == -1)) { - // Show rectangle uninitialised - set it to current screen dimensions - _showRect.top = 0; - _showRect.left = 0; - _showRect.right = _vm->_screen->width() - 1; - _showRect.bottom = _vm->_screen->height() -1; - } - - return &_showRect; -} - -void Mouse::handleEvent(Common::Event &event) { - _currentPos.x = event.mouse.x; - _currentPos.y = event.mouse.y; - - // If mouse is turned on, check to see if the position is in the hide rect, or outside the show rect. - // If so, handle toggling the visibility of the mouse - bool showFlag = !inHideArea(); - if (_cursorOn && (CursorMan.isVisible() != showFlag)) { - CursorMan.showMouse(showFlag); - } -} - -bool Mouse::inHideArea() { - // Returns true if the mouse is inside a specified hide rect, or if a show rect is specified and - // the mouse is currently outside it - if ((_currentPos.x >= _hideRect.left) && (_currentPos.x <= _hideRect.right) && - (_currentPos.y >= _hideRect.top) && (_currentPos.y <= _hideRect.bottom)) - // Inside a hide area - return true; - - - if ((_showRect.top == -1) && (_showRect.left == -1)) - // No show rect defined - return false; - - // Return true if the mouse is outside the show area - return (_currentPos.x < _showRect.left) || (_currentPos.x > _showRect.right) || - (_currentPos.y < _showRect.top) || (_currentPos.y > _showRect.bottom); -} - -} // End of namespace M4 diff --git a/engines/m4/events.h b/engines/m4/events.h deleted file mode 100644 index 6e7cf68555..0000000000 --- a/engines/m4/events.h +++ /dev/null @@ -1,132 +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. - * - */ - -#ifndef M4_EVENTS_H -#define M4_EVENTS_H - -#include "common/events.h" -#include "common/rect.h" - -#include "m4/globals.h" -#include "m4/assets.h" -#include "m4/sprite.h" -#include "m4/graphics.h" -#include "m4/console.h" - -namespace M4 { - -#define LEFT_BUTTON_DOWN 1 << 0 -#define RIGHT_BUTTON_DOWN 1 << 1 - -enum M4EventType { - MEVENT_NO_EVENT, MEVENT_MOVE, - MEVENT_LEFT_CLICK, MEVENT_LEFT_HOLD, MEVENT_LEFT_DRAG, MEVENT_LEFT_RELEASE, - MEVENT_RIGHT_CLICK, MEVENT_RIGHT_HOLD, MEVENT_RIGHT_DRAG, MEVENT_RIGHT_RELEASE, - MEVENT_BOTH_CLICK, MEVENT_BOTH_HOLD, MEVENT_BOTH_DRAG, MEVENT_BOTH_RELEASE, - MEVENT_DOUBLECLICK, MEVENT_DOUBLECLICK_HOLD, MEVENT_DOUBLECLICK_DRAG, MEVENT_DOUBLECLICK_RELEASE, - KEVENT_KEY -}; - -enum M4MouseState { - MSTATE_NO_EVENT, MSTATE_LEFT_CLICK_DOWN, MSTATE_RIGHT_CLICK_DOWN, MSTATE_BOTH_CLICK_DOWN, - MSTATE_DOUBLECLICK_DOWN -}; - -enum M4CommonCursors { - CURSOR_ARROW = 0, - CURSOR_WAIT = 1, - CURSOR_HOURGLASS = 5, - CURSOR_LOOK = 6, - CURSOR_TAKE = 8, - CURSOR_USE = 9 -}; - -class M4Sprite; -class SpriteAsset; - -class Events { -private: - MadsM4Engine *_vm; - Common::Event _event; - M4MouseState _mouseState; - int32 _keyCode; - int _mouseButtons; - Console *_console; - bool _ctrlFlag; -public: - bool quitFlag; - Events(MadsM4Engine *vm); - virtual ~Events(); - - Common::Event &event() { return _event; } - Common::EventType type() { return _event.type; } - - // M4-centric methods - M4EventType handleEvents(); - bool kbdCheck(uint32 &keyCode); - int getMouseButtonsState() { return _mouseButtons; } - Console* getConsole() { return _console; } -}; - - -class Mouse { -private: - MadsM4Engine *_vm; - int _currentCursor, _lockedCursor; - bool _locked; - bool _cursorOn; - M4Sprite *_cursor; - SpriteAsset *_cursorSprites; - Common::Rect _hideRect, _showRect; - Common::Point _currentPos; - - void handleEvent(Common::Event &event); - bool inHideArea(); - friend class Events; -public: - Mouse(MadsM4Engine *vm); - ~Mouse(); - - bool init(const char *seriesName, RGB8 *palette); - bool setCursorNum(int cursorIndex); - int getCursorNum() { return _currentCursor; } - int cursorCount(); - Common::Point currentPos() const { return _currentPos; } - M4Sprite *cursor() { return _cursor; } - void cursorOn(); - void cursorOff(); - bool getCursorOn() { return _cursorOn; } - void lockCursor(int cursorIndex); - void unlockCursor(); - - const char *getVerb(); - - void resetMouse(); - void setHideRect(Common::Rect &r); - void setShowRect(Common::Rect &r); - const Common::Rect *getHideRect(); - const Common::Rect *getShowRect(); -}; - -} - -#endif diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp deleted file mode 100644 index d4ba714d73..0000000000 --- a/engines/m4/font.cpp +++ /dev/null @@ -1,291 +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 "m4/font.h" -#include "m4/m4.h" -#include "m4/compression.h" - -namespace M4 { - -FontManager::~FontManager() { - for (uint i = 0; i < _entries.size(); ++i) - delete _entries[i]; - _entries.clear(); -} - -Font *FontManager::getFont(const char *filename) { - // Append an extension if the filename doesn't already have one - char buffer[20]; - strncpy(buffer, filename, 19); - if (!strchr(buffer, '.')) - strcat(buffer, ".ff"); - - // Check if the font is already loaded - for (uint i = 0; i < _entries.size(); ++i) { - if (!strcmp(_entries[i]->_filename, buffer)) - return _entries[i]; - } - - Font *f = new Font(_vm, buffer); - _entries.push_back(f); - return f; -} - -void FontManager::setFont(const char *filename) { - _currentFont = getFont(filename); -} - -//-------------------------------------------------------------------------- - -Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) { - _sysFont = true; - strncpy(_filename, filename, 19); - _filename[19] = '\0'; - - //TODO: System font - _fontColors[0] = _vm->_palette->BLACK; - _fontColors[1] = _vm->_palette->WHITE; - _fontColors[2] = _vm->_palette->BLACK; - _fontColors[3] = _vm->_palette->DARK_GRAY; - - _sysFont = false; - - if (_vm->isM4()) - setFontM4(filename); - else - setFontMads(filename); -} - -void Font::setFontM4(const char *filename) { - Common::SeekableReadStream *fontFile = _vm->res()->openFile(filename); - - if (fontFile->readUint32LE() != MKTAG('F','O','N','T')) { - debugCN(kDebugGraphics, "Font::Font: FONT tag expected\n"); - return; - } - - _maxHeight = fontFile->readByte(); - _maxWidth = fontFile->readByte(); - uint32 fontSize = fontFile->readUint32LE(); - - //debugCN(kDebugGraphics, "Font::Font: _maxWidth = %d, _maxHeight = %d, fontSize = %d\n", _maxWidth, _maxHeight, fontSize); - - if (fontFile->readUint32LE() != MKTAG('W','I','D','T')) { - debugCN(kDebugGraphics, "Font::Font: WIDT tag expected\n"); - return; - } - - _charWidths = new uint8[256]; - fontFile->read(_charWidths, 256); - - if (fontFile->readUint32LE() != MKTAG('O','F','F','S')) { - debugCN(kDebugGraphics, "Font::Font: OFFS tag expected\n"); - return; - } - - _charOffs = new uint16[256]; - - for (int i = 0; i < 256; i++) - _charOffs[i] = fontFile->readUint16LE(); - - if (fontFile->readUint32LE() != MKTAG('P','I','X','S')) { - debugCN(kDebugGraphics, "Font::Font: PIXS tag expected\n"); - return; - } - - _charData = new uint8[fontSize]; - fontFile->read(_charData, fontSize); - - _vm->res()->toss(filename); -} - -void Font::setFontMads(const char *filename) { - MadsPack fontData(filename, _vm); - Common::SeekableReadStream *fontFile = fontData.getItemStream(0); - - _maxHeight = fontFile->readByte(); - _maxWidth = fontFile->readByte(); - - _charWidths = new uint8[128]; - // Char data is shifted by 1 - _charWidths[0] = 0; - fontFile->read(_charWidths + 1, 127); - fontFile->readByte(); // remainder - - _charOffs = new uint16[128]; - - uint32 startOffs = 2 + 128 + 256; - uint32 fontSize = fontFile->size() - startOffs; - - // Char data is shifted by 1 - _charOffs[0] = 0; - for (int i = 1; i < 128; i++) - _charOffs[i] = fontFile->readUint16LE() - startOffs; - fontFile->readUint16LE(); // remainder - - _charData = new uint8[fontSize]; - fontFile->read(_charData, fontSize); - - delete fontFile; -} - -Font::~Font() { - if (!_sysFont) { - delete[] _charWidths; - delete[] _charOffs; - delete[] _charData; - } -} - -void Font::setColor(uint8 color) { - if (_sysFont) - _fontColors[1] = color; - else - _fontColors[3] = color; -} - -void Font::setColors(uint8 col1, uint8 col2, uint8 col3) { - if (_sysFont) - _fontColors[1] = col3; - else { - _fontColors[0] = 0xFF; - _fontColors[1] = col1; - _fontColors[2] = col2; - _fontColors[3] = col3; - } -} - -int32 Font::write(M4Surface *surface, const char *text, int x, int y, int width, int spaceWidth, uint8 colors[]) { - - /*TODO - if (custom_ascii_converter) { // if there is a function to convert the extended ASCII characters - custom_ascii_converter(out_string); // call it with the string - } - */ - - int right; - if (width > 0) - right = MIN(surface->width(), x + width + 1); - else - right = surface->width(); - - x++; - y++; - - int skipY = 0; - if (y < 0) { - skipY = -y; - y = 0; - } - - int height = MAX(0, _maxHeight - skipY); - if (height == 0) - return x; - - int bottom = y + height - 1; - if (bottom > surface->height() - 1) { - height -= MIN(height, bottom - (surface->height() - 1)); - } - - if (height <= 0) - return x; - - uint8 *destPtr = (uint8*)surface->getBasePtr(x, y); - uint8 *oldDestPtr = destPtr; - - int xPos = x; - - while (*text) { - - unsigned char theChar = (*text++) & 0x7F; - int charWidth = _charWidths[theChar]; - - if (charWidth > 0) { - - if (xPos + charWidth > right) - return xPos; - - uint8 *charData = &_charData[_charOffs[theChar]]; - int bpp = charWidth / 4 + 1; - - if (!_vm->isM4()) { - if (charWidth > 12) - bpp = 4; - else if (charWidth > 8) - bpp = 3; - else if (charWidth > 4) - bpp = 2; - else - bpp = 1; - } - - if (skipY != 0) - charData += bpp * skipY; - - for (int i = 0; i < height; i++) { - for (int j = 0; j < bpp; j++) { - if (*charData & 0xc0) - *destPtr = colors[(*charData & 0xc0) >> 6]; - destPtr++; - if (*charData & 0x30) - *destPtr = colors[(*charData & 0x30) >> 4]; - destPtr++; - if (*charData & 0x0C) - *destPtr = colors[(*charData & 0x0C) >> 2]; - destPtr++; - if (*charData & 0x03) - *destPtr = colors[*charData & 0x03]; - destPtr++; - charData++; - } - - destPtr += surface->width() - bpp * 4; - - } - - destPtr = oldDestPtr + charWidth + spaceWidth; - oldDestPtr = destPtr; - - } - - xPos += charWidth + spaceWidth; - - } - - surface->freeData(); - return xPos; - -} - -int32 Font::getWidth(const char *text, int spaceWidth) { - /* - if (custom_ascii_converter) { // if there is a function to convert the extended ASCII characters - custom_ascii_converter(out_string); // call it with the string - } - */ - int width = -spaceWidth; // Accomodate final character not needing spacing - while (*text) - width += _charWidths[*text++ & 0x7F] + spaceWidth; - return width; -} - -} // End of namespace M4 diff --git a/engines/m4/font.h b/engines/m4/font.h deleted file mode 100644 index 5a9c73e5d5..0000000000 --- a/engines/m4/font.h +++ /dev/null @@ -1,119 +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. - * - */ - -#ifndef M4_FONT_H -#define M4_FONT_H - -#include "common/util.h" -#include "common/endian.h" - -#include "m4/graphics.h" - -/* - TODO: - - make a FontSystem class that creates/manages the fonts - (similar to FileSystem) -*/ - -namespace M4 { - -#define FONT_MENU "fontmenu.fnt" -#define FONT_INTERFACE "fontintr.fnt" -#define FONT_TINY "small.fnt" -#define FONT_SMALL "small.fnt" -#define FONT_MEDIUM "medium.fnt" -#define FONT_LINE "fontline.fnt" -#define FONT_CONVERSATION "fontconv.fnt" -#define FONT_4X6 "4x6pp.fnt" -#define FONT_5X6 "5x6pp.fnt" - -#define FONT_CONVERSATION_MADS "fontconv.ff" -#define FONT_INTERFACE_MADS "fontintr.ff" -#define FONT_MAIN_MADS "fontmain.ff" -#define FONT_MENU_MADS "fontmenu.ff" // Not in Rex (uses bitmap files for menu strings) -#define FONT_MISC_MADS "fontmisc.ff" -#define FONT_TELE_MADS "fonttele.ff" // Not in Phantom -#define FONT_PHAN_MADS "fontphan.ff" // Phantom only - -class Font { -public: - Font(MadsM4Engine *vm, const char *filename); - ~Font(); - - void setColor(uint8 color); - void setColors(uint8 col1, uint8 col2, uint8 col3); - - int32 getWidth(const char *text, int spaceWidth = -1); - int32 getHeight() const { return _maxHeight; } - int32 getMaxWidth() const { return _maxWidth; } - int32 write(M4Surface *surface, const char *text, int x, int y, int width, int spaceWidth, uint8 colors[]); - int32 writeString(M4Surface *surface, const char *text, int x, int y, int width = 0, int spaceWidth = -1) { - return write(surface, text, x, y, width, spaceWidth, _fontColors); - } -public: - char _filename[20]; -private: - void setFontM4(const char *filename); - void setFontMads(const char *filename); - - MadsM4Engine *_vm; - uint8 _maxWidth, _maxHeight; - uint8 *_charWidths; - uint16 *_charOffs; - uint8 *_charData; - bool _sysFont; - uint8 _fontColors[4]; -}; - -class FontEntry { -public: - Font *_font; - - FontEntry() { - _font = NULL; - } - ~FontEntry() { - delete _font; - } -}; - -class FontManager { -private: - MadsM4Engine *_vm; - Common::Array _entries; - Font *_currentFont; -public: - FontManager(MadsM4Engine *vm): _vm(vm) { _currentFont = NULL; } - ~FontManager(); - - Font *getFont(const char *filename); - void setFont(const char *filename); - - Font *current() { - assert(_currentFont); - return _currentFont; - } -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp deleted file mode 100644 index 7a0b776eb8..0000000000 --- a/engines/m4/globals.cpp +++ /dev/null @@ -1,554 +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/textconsole.h" - -#include "m4/m4.h" -#include "m4/globals.h" -#include "m4/graphics.h" -#include "m4/gui.h" -#include "m4/viewmgr.h" -#include "m4/script.h" -#include "m4/m4_views.h" -#include "m4/compression.h" - -namespace M4 { - -Kernel::Kernel(MadsM4Engine *vm) : _vm(vm) { - daemonTriggerAvailable = true; - firstFadeColorIndex = 0; - paused = false; - betweenRooms = false; - currentSection = 0; - newSection = 0; - previousSection = 0; - currentRoom = 0; - newRoom = 0; - previousRoom = 0; - trigger = 0; - triggerMode = KT_DAEMON; - - _globalDaemonFn = NULL; - _globalParserFn = NULL; - - _sectionInitFn = NULL; - _sectionDaemonFn = NULL; - _sectionParserFn = NULL; - - _roomInitFn = NULL; - _roomDaemonFn = NULL; - _roomPreParserFn = NULL; - _roomParserFn = NULL; - -} - -int32 Kernel::createTrigger(int32 triggerNum) { - if (triggerNum < 0) - return triggerNum; - else - return triggerNum | (currentRoom << 16) | (triggerMode << 28); -} - -bool Kernel::sendTrigger(int32 triggerNum) { - return handleTrigger(createTrigger(triggerNum)); -} - -bool Kernel::handleTrigger(int32 triggerNum) { - - debugCN(kDebugScript, "betweenRooms = %d; triggerNum = %08X\n", betweenRooms, (uint)triggerNum); - - if (betweenRooms) - return true; - - if (triggerNum < 0) - return false; - - KernelTriggerType saveTriggerMode = triggerMode; - int32 saveTrigger = trigger; - bool result = false; - - int room = (triggerNum >> 16) & 0xFFF; - - debugCN(kDebugScript, "room = %d; currentRoom = %d\n", room, currentRoom); - - if (room != currentRoom) { - debugCN(kDebugScript, "Kernel::handleTrigger() Trigger from another room\n"); - return false; - } - - trigger = triggerNum & 0xFFFF; - KernelTriggerType mode = (KernelTriggerType)(triggerNum >> 28); - - switch (mode) { - - case KT_PREPARSE: - if (trigger < 32000) { - triggerMode = KT_PREPARSE; - roomPreParser(); - result = true; - } - break; - - case KT_PARSE: - if (trigger < 32000) { - triggerMode = KT_PARSE; - // TODO player.commandReady = TRUE; - roomParser(); - /* TODO - if (player.commandReady) - globalParser(); - */ - result = true; - } - break; - - case KT_DAEMON: - debugCN(kDebugScript, "KT_DAEMON\n"); - triggerMode = KT_DAEMON; - daemonTriggerAvailable = false; - roomDaemon(); - if (daemonTriggerAvailable) { - daemonTriggerAvailable = false; - sectionDaemon(); - } - if (daemonTriggerAvailable) { - daemonTriggerAvailable = false; - globalDaemon(); - } - - break; - - default: - debugCN(kDebugScript, "Kernel::handleTrigger() Unknown trigger mode %d\n", mode); - - } - - triggerMode = saveTriggerMode; - trigger = saveTrigger; - - return result; -} - -void Kernel::loadGlobalScriptFunctions() { - _globalDaemonFn = _vm->_script->loadFunction("global_daemon"); - _globalParserFn = _vm->_script->loadFunction("global_parser"); -} - -void Kernel::loadSectionScriptFunctions() { - Common::String tempFnName; - tempFnName = Common::String::format("section_init_%d", currentSection); - _sectionInitFn = _vm->_script->loadFunction(tempFnName); - tempFnName = Common::String::format("section_daemon_%d", currentSection); - _sectionDaemonFn = _vm->_script->loadFunction(tempFnName); - tempFnName = Common::String::format("section_parser_%d", currentSection); - _sectionParserFn = _vm->_script->loadFunction(tempFnName); -} - -void Kernel::loadRoomScriptFunctions() { - Common::String tempFnName; - tempFnName = Common::String::format("room_init_%d", currentRoom); - _roomInitFn = _vm->_script->loadFunction(tempFnName); - tempFnName = Common::String::format("room_daemon_%d", currentRoom); - _roomDaemonFn = _vm->_script->loadFunction(tempFnName); - tempFnName = Common::String::format("room_pre_parser_%d", currentRoom); - _roomPreParserFn = _vm->_script->loadFunction(tempFnName); - tempFnName = Common::String::format("room_parser_%d", currentRoom); - _roomParserFn = _vm->_script->loadFunction(tempFnName); -} - -void Kernel::globalDaemon() { - if (_globalDaemonFn) - _vm->_script->runFunction(_globalDaemonFn); - else { - debugCN(kDebugScript, "Kernel::globalDaemon() _globalDaemonFn is NULL\n"); - } -} - -void Kernel::globalParser() { - if (_globalParserFn) - _vm->_script->runFunction(_globalParserFn); - else { - debugCN(kDebugScript, "Kernel::globalParser() _globalParserFn is NULL\n"); - } -} - -void Kernel::sectionInit() { - if (_sectionInitFn) - _vm->_script->runFunction(_sectionInitFn); - else { - debugCN(kDebugScript, "Kernel::sectionInit() _sectionInitFn is NULL\n"); - } -} - -void Kernel::sectionDaemon() { - if (_sectionDaemonFn) - _vm->_script->runFunction(_sectionDaemonFn); - else { - debugCN(kDebugScript, "Kernel::sectionDaemon() _sectionDaemonFn is NULL\n"); - } -} - -void Kernel::sectionParser() { - if (_sectionParserFn) - _vm->_script->runFunction(_sectionParserFn); - else { - debugCN(kDebugScript, "Kernel::sectionParser() _sectionParserFn is NULL\n"); - } -} - -void Kernel::roomInit() { - if (_roomInitFn) - _vm->_script->runFunction(_roomInitFn); - else { - debugCN(kDebugScript, "Kernel::roomInit() _roomInitFn is NULL\n"); - } -} - -void Kernel::roomDaemon() { - if (_roomDaemonFn) - _vm->_script->runFunction(_roomDaemonFn); - else { - debugCN(kDebugScript, "Kernel::roomDaemon() _roomDaemonFn is NULL\n"); - } -} - -void Kernel::roomPreParser() { - if (_roomPreParserFn) - _vm->_script->runFunction(_roomPreParserFn); - else { - debugCN(kDebugScript, "Kernel::roomPreParser() _roomPreParserFn is NULL\n"); - } -} - -void Kernel::roomParser() { - if (_roomParserFn) - _vm->_script->runFunction(_roomParserFn); - else { - debugCN(kDebugScript, "Kernel::roomParser() _roomParserFn is NULL\n"); - } -} - -void Kernel::pauseGame(bool value) { - paused = value; - - if (paused) pauseEngines(); - else unpauseEngines(); -} - -void Kernel::pauseEngines() { - // TODO: A proper implementation of game pausing. At the moment I'm using a hard-coded - // check in events.cpp on Kernel::paused to prevent any events going to the scene -} - -void Kernel::unpauseEngines() { - // TODO: A proper implementation of game unpausing -} - -/*--------------------------------------------------------------------------*/ - -Globals::Globals(MadsM4Engine *vm): _vm(vm) { -} - -bool Globals::isInterfaceVisible() { - return _m4Vm->scene()->getInterface()->isVisible(); -} - -/*--------------------------------------------------------------------------*/ - -MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) { - _vm = vm; - - playerSpriteChanged = false; - dialogType = DIALOG_NONE; - sceneNumber = -1; - for (int i = 0; i < 3; ++i) - actionNouns[i] = 0; - _difficultyLevel = 0; -} - -MadsGlobals::~MadsGlobals() { - uint32 i; - - for (i = 0; i < _madsVocab.size(); i++) - free(_madsVocab[i]); - _madsVocab.clear(); - - for (i = 0; i < _madsQuotes.size(); i++) - free(_madsQuotes[i]); - _madsQuotes.clear(); - - _madsMessages.clear(); -} - -void MadsGlobals::loadMadsVocab() { - Common::SeekableReadStream *vocabS = _vm->res()->get("vocab.dat"); - int curPos = 0; - - char buffer[30]; - strcpy(buffer, ""); - - while (true) { - uint8 b = vocabS->readByte(); - if (vocabS->eos()) break; - - buffer[curPos++] = b; - if (buffer[curPos - 1] == '\0') { - // end of string, add it to the strings list - _madsVocab.push_back(strdup(buffer)); - curPos = 0; - strcpy(buffer, ""); - } - } - - _vm->res()->toss("vocab.dat"); -} - -void MadsGlobals::loadQuotes() { - Common::SeekableReadStream *quoteS = _vm->res()->get("quotes.dat"); - int curPos = 0; - - char buffer[128]; - strcpy(buffer, ""); - - while (true) { - uint8 b = quoteS->readByte(); - if (quoteS->eos()) break; - - buffer[curPos++] = b; - if (buffer[curPos - 1] == '\0') { - // end of string, add it to the strings list - _madsQuotes.push_back(strdup(buffer)); - curPos = 0; - strcpy(buffer, ""); - } - } - - _vm->res()->toss("quotes.dat"); -} - -void MadsGlobals::loadMadsMessagesInfo() { - Common::SeekableReadStream *messageS = _vm->res()->get("messages.dat"); - - int16 count = messageS->readUint16LE(); - //debugCN(kDebugScript, "%i messages\n", count); - - for (int i = 0; i < count; i++) { - MessageItem curMessage; - curMessage.id = messageS->readUint32LE(); - curMessage.offset = messageS->readUint32LE(); - curMessage.uncompSize = messageS->readUint16LE(); - - if (i > 0) - _madsMessages[i - 1].compSize = curMessage.offset - _madsMessages[i - 1].offset; - - if (i == count - 1) - curMessage.compSize = messageS->size() - curMessage.offset; - - //debugCN(kDebugScript, "id: %i, offset: %i, uncomp size: %i\n", curMessage->id, curMessage->offset, curMessage->uncompSize); - _madsMessages.push_back(curMessage); - } - - _vm->res()->toss("messages.dat"); -} - -void MadsGlobals::loadMadsObjects() { - Common::SeekableReadStream *objList = _vm->res()->get("objects.dat"); - int numObjects = objList->readUint16LE(); - - for (int i = 0; i < numObjects; ++i) - _madsObjects.push_back(MadsObjectArray::value_type(new MadsObject(objList))); - - _vm->res()->toss("objects.dat"); -} - -int MadsGlobals::getObjectIndex(uint16 descId) { - for (uint i = 0; i < _madsObjects.size(); ++i) { - if (_madsObjects[i].get()->_descId == descId) - return i; - } - - return -1; -} - -int MadsGlobals::messageIndexOf(uint32 messageId) { - for (uint i = 0; i < _madsMessages.size(); ++i) - { - if (_madsMessages[i].id == messageId) - return i; - } - return -1; -} - -const char *MadsGlobals::loadMessage(uint index) { - if (index > _madsMessages.size() - 1) { - warning("Invalid message index: %i", index); - return NULL; - } - - FabDecompressor fab; - byte *compData = new byte[_madsMessages[index].compSize]; - byte *buffer = new byte[_madsMessages[index].uncompSize]; - - Common::SeekableReadStream *messageS = _vm->res()->get("messages.dat"); - messageS->seek(_madsMessages[index].offset, SEEK_SET); - messageS->read(compData, _madsMessages[index].compSize); - fab.decompress(compData, _madsMessages[index].compSize, buffer, _madsMessages[index].uncompSize); - - for (int i = 0; i < _madsMessages[index].uncompSize - 1; i++) - if (buffer[i] == '\0') buffer[i] = '\n'; - - _vm->res()->toss("messages.dat"); - delete[] compData; - - return (char*)buffer; -} - -/** - * Adds the specified scene number to list of scenes previously visited - */ -void MadsGlobals::addVisitedScene(int newSceneNumber) { - if (!isSceneVisited(newSceneNumber)) - _visitedScenes.push_back(newSceneNumber); -} - -/** - * Returns true if the specified scene has been previously visited - */ -bool MadsGlobals::isSceneVisited(int checkSceneNumber) { - Common::List::iterator i; - for (i = _visitedScenes.begin(); i != _visitedScenes.end(); ++i) - if (*i == checkSceneNumber) - return true; - return false; -} - -void MadsGlobals::removeVisitedScene(int oldSceneNumber) { - _visitedScenes.remove(oldSceneNumber); -} - -/*--------------------------------------------------------------------------*/ - -M4Globals::M4Globals(M4Engine *vm): Globals(vm) { - _vm = vm; -} - -/*--------------------------------------------------------------------------*/ - -Player::Player(MadsM4Engine *vm) : _vm(vm) { - commandsAllowed = true; - needToWalk = false; - readyToWalk = false; - waitingForWalk = false; - commandReady = false; - strcpy(verb, ""); - strcpy(noun, ""); - strcpy(prep, ""); - strcpy(object, ""); -} - -void Player::setCommandsAllowed(bool value) { - setCommandsAllowedFlag = true; - commandsAllowed = value; - if (value) { - // Player commands are enabled again - _vm->_mouse->lockCursor(CURSOR_ARROW); - //_m4Vm->scene()->getInterface()->cancelSentence(); - } else { - // Player commands are disabled, so show hourglass cursor - _vm->_mouse->lockCursor(CURSOR_HOURGLASS); - } -} - -bool Player::said(const char *word1, const char *word2, const char *word3) { - const char *words[3]; - words[0] = word1; - words[1] = word2; - words[2] = word2; - for (int i = 0; i < 3; i++) { - if (words[i]) - if ((scumm_stricmp(noun, words[i])) && - (scumm_stricmp(object, words[i])) && - (scumm_stricmp(verb, words[i]))) - return false; - } - return true; -} - -bool Player::saidAny(const char *word1, const char *word2, const char *word3, - const char *word4, const char *word5, const char *word6, const char *word7, - const char *word8, const char *word9, const char *word10) { - const char *words[10]; - words[0] = word1; - words[1] = word2; - words[2] = word3; - words[3] = word4; - words[4] = word5; - words[5] = word6; - words[6] = word7; - words[7] = word8; - words[8] = word9; - words[9] = word10; - for (int i = 0; i < 10; i++) { - if (words[i]) { - if (!scumm_stricmp(noun, words[i])) - return true; - if (!scumm_stricmp(object, words[i])) - return true; - if (!scumm_stricmp(verb, words[i])) - return true; - } - } - return false; -} - -/*--------------------------------------------------------------------------*/ - -MadsObject::MadsObject(Common::SeekableReadStream *stream) { - load(stream); -} - -void MadsObject::load(Common::SeekableReadStream *stream) { - // Get the next data block - uint8 obj[0x30]; - stream->read(obj, 0x30); - - // Extract object data fields - _descId = READ_LE_UINT16(&obj[0]); - _roomNumber = READ_LE_UINT16(&obj[2]); - _article = (MADSArticles)obj[4]; - _vocabCount = obj[5] & 0x7f; - // Phantom / Dragon - if (_vocabCount > 3) - warning("MadsObject::load(), vocab cound > 3 (it's %d)", _vocabCount); - - for (int i = 0; i < _vocabCount; ++i) { - _vocabList[i].flags1 = obj[6 + i * 4]; - _vocabList[i].flags2 = obj[7 + i * 4]; - _vocabList[i].vocabId = READ_LE_UINT16(&obj[8 + i * 4]); - } -} - -void MadsObject::setRoom(int roomNumber) { - -} - -} // End of namespace M4 diff --git a/engines/m4/globals.h b/engines/m4/globals.h deleted file mode 100644 index 693dc9d6c9..0000000000 --- a/engines/m4/globals.h +++ /dev/null @@ -1,346 +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. - * - */ - -#ifndef M4_GLOBALS_H -#define M4_GLOBALS_H - -#include "common/scummsys.h" -#include "common/array.h" -#include "common/hashmap.h" -#include "common/rect.h" -#include "common/list.h" -#include "common/ptr.h" - -namespace Common { -class SeekableReadStream; -} - -namespace M4 { - -class MadsM4Engine; -class M4Engine; -class MadsEngine; -class ScriptInterpreter; -class ScriptFunction; - -// Globals -enum WoodScriptGlobals { - kGlobTime = 0, - kGlobTimeDelta = 1, - kGlobMinY = 2, - kGlobMaxY = 3, - kGlobMinScale = 4, - kGlobMaxScale = 5, - kGlobScaler = 6, - kGlobTemp1 = 7, - kGlobTemp2 = 8, - kGlobTemp3 = 9, - kGlobTemp4 = 10, - kGlobTemp5 = 11, - kGlobTemp6 = 12, - kGlobTemp7 = 13, - kGlobTemp8 = 14, - kGlobTemp9 = 15, - kGlobTemp10 = 16, - kGlobTemp11 = 17, - kGlobTemp12 = 18, - kGlobTemp13 = 19, - kGlobTemp14 = 20, - kGlobTemp15 = 21, - kGlobTemp16 = 22, - kGlobTemp17 = 23, - kGlobTemp18 = 24, - kGlobTemp19 = 25, - kGlobTemp20 = 26, - kGlobTemp21 = 27, - kGlobTemp22 = 28, - kGlobTemp23 = 29, - kGlobTemp24 = 30, - kGlobTemp25 = 31, - kGlobTemp26 = 32, - kGlobTemp27 = 33, - kGlobTemp28 = 34, - kGlobTemp29 = 35, - kGlobTemp30 = 36, - kGlobTemp31 = 37, - kGlobTemp32 = 38 -}; - -const uint32 SERIES_FORWARD = 0; -const uint32 SERIES_PINGPONG = 1; -const uint32 SERIES_BACKWARD = 2; -const uint32 SERIES_RANDOM = 4; -const uint32 SERIES_NO_TOSS = 8; -const uint32 SERIES_STICK = 16; -const uint32 SERIES_LOOP_TRIGGER = 32; -const uint32 SERIES_LOAD_PALETTE = 64; -const uint32 SERIES_HORZ_FLIP =128; - -enum KernelTriggerType { - KT_PARSE = 1, - KT_DAEMON, - KT_PREPARSE -}; - -class Kernel { -private: - MadsM4Engine *_vm; - ScriptFunction *_globalDaemonFn, *_globalParserFn; - ScriptFunction *_sectionInitFn, *_sectionDaemonFn, *_sectionParserFn; - ScriptFunction *_roomInitFn, *_roomDaemonFn, *_roomPreParserFn, *_roomParserFn; - void pauseEngines(); - void unpauseEngines(); -public: - Kernel(MadsM4Engine *vm); - - // TODO: Move to some palette/fading class - int fadeUpDuration, firstFadeColorIndex; - int minPalEntry, maxPalEntry; - - bool paused; - //machine* myWalker; - bool repeatedlyCallDeamon; - bool daemonTriggerAvailable; - bool betweenRooms; - int currentSection, newSection, previousSection; - int currentRoom, newRoom, previousRoom; - - int32 trigger; - KernelTriggerType triggerMode; - - int32 createTrigger(int32 triggerNum); - bool sendTrigger(int32 triggerNum); - bool handleTrigger(int32 triggerNum); - - void loadGlobalScriptFunctions(); - void loadSectionScriptFunctions(); - void loadRoomScriptFunctions(); - - void globalDaemon(); - void globalParser(); - - void sectionInit(); - void sectionDaemon(); - void sectionParser(); - - void roomInit(); - void roomDaemon(); - void roomPreParser(); - void roomParser(); - - void pauseGame(bool value); -}; - -#define TOTAL_NUM_VARIABLES 210 - -#define PLAYER_INVENTORY 2 - -enum MADSArticles { - kArticleNone = 0, - kArticleWith = 1, - kArticleTo = 2, - kArticleAt = 3, - kArticleFrom = 4, - kArticleOn = 5, - kArticleIn = 6, - kArticleUnder = 7, - kArticleBehind = 8 -}; - -struct VocabEntry { - uint8 flags1; - uint8 flags2; - uint16 vocabId; -}; - -class MadsObject { -public: - MadsObject() {} - MadsObject(Common::SeekableReadStream *stream); - void load(Common::SeekableReadStream *stream); - bool isInInventory() const { return _roomNumber == PLAYER_INVENTORY; } - void setRoom(int roomNumber); - - uint16 _descId; - uint16 _roomNumber; - MADSArticles _article; - uint8 _vocabCount; - VocabEntry _vocabList[3]; -}; - -typedef Common::Array > MadsObjectArray; - -class Globals { -private: - MadsM4Engine *_vm; -public: - Globals(MadsM4Engine *vm); - virtual ~Globals() {} - - bool isInterfaceVisible(); - -}; - -class M4Globals : public Globals { -private: - M4Engine *_vm; -public: - M4Globals(M4Engine *vm); - virtual ~M4Globals() {} - - bool invSuppressClickSound; -}; - -enum RexPlayerSex { SEX_MALE = 0, SEX_FEMALE = 2, SEX_UNKNOWN = 1}; - -enum MadsDialogType { DIALOG_NONE = 0, DIALOG_GAME_MENU = 1, DIALOG_SAVE = 2, DIALOG_RESTORE = 3, DIALOG_OPTIONS = 4, - DIALOG_DIFFICULTY = 5, DIALOG_ERROR = 6}; - -struct MadsConfigData { - bool musicFlag; - bool soundFlag; - bool easyMouse; - bool invObjectsStill; - bool textWindowStill; - int storyMode; - int screenFades; -}; - -#define GET_GLOBAL(x) (_madsVm->globals()->_globals[x]) -#define GET_GLOBAL32(x) (((uint32)_madsVm->globals()->_globals[x + 1] << 16) | _madsVm->globals()->_globals[x]) -#define SET_GLOBAL(x,y) _madsVm->globals()->_globals[x] = y -#define SET_GLOBAL32(x,y) { _madsVm->globals()->_globals[x] = (y) & 0xffff; _madsVm->globals()->_globals[(x) + 1] = (y) >> 16; } - -typedef int (*IntFunctionPtr)(); - -union DataMapEntry { - bool *boolValue; - uint16 *uint16Value; - int *intValue; - IntFunctionPtr fnPtr; -}; - -typedef Common::HashMap DataMapHash; - -class MadsGlobals : public Globals { -private: - struct MessageItem { - uint32 id; - uint32 offset; - uint16 uncompSize; - uint16 compSize; - }; - - MadsEngine *_vm; - Common::Array _madsVocab; - Common::Array _madsQuotes; - Common::Array _madsMessages; - MadsObjectArray _madsObjects; - Common::List _visitedScenes; -public: - MadsGlobals(MadsEngine *vm); - ~MadsGlobals(); - - // MADS variables - uint16 _globals[TOTAL_NUM_VARIABLES]; - MadsConfigData _config; - bool playerSpriteChanged; - MadsDialogType dialogType; - int sceneNumber; - int previousScene; - int16 _nextSceneId; - uint16 actionNouns[3]; - DataMapHash _dataMap; - int _difficultyLevel; - - void loadMadsVocab(); - uint32 getVocabSize() { return _madsVocab.size(); } - const char *getVocab(uint32 index) { - // Vocab list is 1-based, so always subtract one from index provided - assert((index > 0) && (index <= _madsVocab.size())); - return _madsVocab[index - 1]; - } - - void loadQuotes(); - uint32 getQuotesSize() { return _madsQuotes.size(); } - const char *getQuote(uint32 index) { return _madsQuotes[index - 1]; } - // DEPRECATED: ScummVM re-implementation keeps all the quotes loaded, so the methods below are stubs - void clearQuotes() {} - void loadQuoteRange(int startNum, int endNum) {} - void loadQuoteSet(...) {} - void loadQuote(int quoteNum) {} - - void loadMadsMessagesInfo(); - uint32 getMessagesSize() { return _madsMessages.size(); } - int messageIndexOf(uint32 messageId); - const char *loadMessage(uint index); - - void loadMadsObjects(); - uint32 getObjectsSize() { return _madsObjects.size(); } - MadsObject *getObject(uint32 index) { return _madsObjects[index].get(); } - int getObjectIndex(uint16 descId); - int getObjectFolder(uint32 folderId) { warning("TODO: getObjectFolder"); return -1; } - - void addVisitedScene(int sceneNumber); - bool isSceneVisited(int sceneNumber); - void removeVisitedScene(int sceneNumber); -}; - -#define PLAYER_FIELD_LENGTH 40 - -class Player { -public: - Player(MadsM4Engine *vm); - void setCommandsAllowed(bool value); - - // Variables - Common::Point position; // Player's current position - int facing; // Facing direction - - char verb[PLAYER_FIELD_LENGTH]; // Action strings - char noun[PLAYER_FIELD_LENGTH]; - char prep[PLAYER_FIELD_LENGTH]; - char object[PLAYER_FIELD_LENGTH]; - Common::String assetName, shadowName; - int walkerType, shadowType; - bool needToWalk, readyToWalk, waitingForWalk; - bool commandsAllowed; - bool commandReady; - bool visible; - bool beenInRoomBefore; - bool walkerInCurrentRoom; - int32 walkerTriggerNum; - int walkFacing; - bool setCommandsAllowedFlag; - - bool said(const char *word1, const char *word2 = NULL, const char *word3 = NULL); - bool saidAny(const char *word1, const char *word2, const char *word3, - const char *word4, const char *word5, const char *word6, const char *word7, - const char *word8, const char *word9, const char *word10); - -private: - MadsM4Engine *_vm; -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp deleted file mode 100644 index 99130aee08..0000000000 --- a/engines/m4/graphics.cpp +++ /dev/null @@ -1,1361 +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/util.h" -#include "common/ptr.h" -#include "common/textconsole.h" - -#include "graphics/palette.h" - -#include "m4/globals.h" -#include "m4/graphics.h" -#include "m4/sprite.h" -#include "m4/m4.h" -#include "m4/compression.h" - -namespace M4 { - -RGBList::RGBList(int numEntries, RGB8 *srcData, bool freeData) { - _size = numEntries; - assert(numEntries <= 256); - - if (srcData == NULL) { - _data = new RGB8[numEntries]; - _freeData = true; - } else { - _data = srcData; - _freeData = freeData; - } - - _palIndexes = new byte[numEntries]; - Common::fill(&_palIndexes[0], &_palIndexes[numEntries], 0); -} - -RGBList::~RGBList() { - if (_freeData) - delete[] _data; - delete[] _palIndexes; -} - -void RGBList::setRange(int start, int count, const RGB8 *src) { - assert((start + count) <= _size); - - Common::copy(&src[0], &src[count], &_data[start]); -} - -/** - * Creates a duplicate of the given rgb list - */ -RGBList *RGBList::clone() const { - RGBList *dest = new RGBList(_size, _data, false); - _madsVm->_palette->addRange(dest); - return dest; -} - -//-------------------------------------------------------------------------- - -#define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2) - -M4Surface::~M4Surface() { - if (_rgbList) { - _madsVm->_palette->deleteRange(_rgbList); - delete _rgbList; - } - if (_ownsData) - free(); -} - -void M4Surface::loadCodesM4(Common::SeekableReadStream *source) { - if (!source) { - free(); - return; - } - - uint16 widthVal = source->readUint16LE(); - uint16 heightVal = source->readUint16LE(); - - create(widthVal, heightVal, Graphics::PixelFormat::createFormatCLUT8()); - source->read(pixels, widthVal * heightVal); -} - -void M4Surface::loadCodesMads(Common::SeekableReadStream *source) { - if (!source) { - free(); - return; - } - - uint16 widthVal = 320; - uint16 heightVal = 156; - byte *walkMap = new byte[source->size()]; - - create(widthVal, heightVal, Graphics::PixelFormat::createFormatCLUT8()); - source->read(walkMap, source->size()); - - byte *ptr = (byte *)getBasePtr(0, 0); - - for (int y = 0; y < heightVal; y++) { - for (int x = 0; x < widthVal; x++) { - int ofs = x + (y * widthVal); - if ((walkMap[ofs / 8] << (ofs % 8)) & 0x80) - *ptr++ = 1; // walkable - else - *ptr++ = 0; - } - } - - delete[] walkMap; -} - -// Sprite related methods - -void M4Surface::vLine(int x, int y1, int y2) { - Graphics::Surface::vLine(x, y1, y2, _color); -} - -void M4Surface::hLine(int x1, int x2, int y) { - Graphics::Surface::hLine(x1, y, x2, _color); -} - -void M4Surface::vLineXor(int x, int y1, int y2) { - // Clipping - if (x < 0 || x >= w) - return; - - if (y2 < y1) - SWAP(y2, y1); - - if (y1 < 0) - y1 = 0; - if (y2 >= h) - y2 = h - 1; - - byte *ptr = (byte *)getBasePtr(x, y1); - while (y1++ <= y2) { - *ptr ^= 0xFF; - ptr += pitch; - } - -} - -void M4Surface::hLineXor(int x1, int x2, int y) { - // Clipping - if (y < 0 || y >= h) - return; - - if (x2 < x1) - SWAP(x2, x1); - - if (x1 < 0) - x1 = 0; - if (x2 >= w) - x2 = w - 1; - - if (x2 < x1) - return; - - byte *ptr = (byte *)getBasePtr(x1, y); - while (x1++ <= x2) - *ptr++ ^= 0xFF; - -} - -void M4Surface::drawLine(int x1, int y1, int x2, int y2, byte color) { - Graphics::Surface::drawLine(x1, y1, x2, y2, color); -} - - -void M4Surface::frameRect(int x1, int y1, int x2, int y2) { - Graphics::Surface::frameRect(Common::Rect(x1, y1, x2, y2), _color); -} - -void M4Surface::fillRect(int x1, int y1, int x2, int y2) { - Graphics::Surface::fillRect(Common::Rect(x1, y1, x2, y2), _color); -} - -void M4Surface::drawSprite(int x, int y, SpriteInfo &info, const Common::Rect &clipRect) { - - enum { - kStatusSkip, - kStatusScale, - kStatusDraw - }; - - // NOTE: The current clipping code assumes that the top left corner of the clip - // rectangle is always 0, 0 - assert(clipRect.top == 0 && clipRect.left == 0); - - // TODO: Put err* and scaled* into SpriteInfo - int errX = info.hotX * info.scaleX % 100; - int errY = info.hotY * info.scaleY % 100; - int scaledWidth = scaleValue(info.width, info.scaleX, errX); - int scaledHeight = scaleValue(info.height, info.scaleY, errY); - - /* - debugCN(kDebugGraphics, "M4Surface::drawSprite() info.width = %d; info.scaleX = %d; info.height = %d; info.scaleY = %d; scaledWidth = %d; scaledHeight = %d\n", - info.width, info.scaleX, info.height, info.scaleY, scaledWidth, scaledHeight); - */ - - int clipX = 0, clipY = 0; - // Clip the sprite's width and height according to the clip rectangle's dimensions - // This clips the sprite to the bottom and right - if (x >= 0) { - scaledWidth = MIN(x + scaledWidth, clipRect.right) - x; - } else { - clipX = x; - scaledWidth = x + scaledWidth; - } - if (y >= 0) { - scaledHeight = MIN(y + scaledHeight, clipRect.bottom) - y; - } else { - clipY = y; - scaledHeight = y + scaledHeight; - } - - //debugCN(kDebugGraphics, "M4Surface::drawSprite() width = %d; height = %d; scaledWidth = %d; scaledHeight = %d\n", info.width, info.height, scaledWidth, scaledHeight); - - // Check if sprite is inside the screen. If it's not, there's no need to draw it - if (scaledWidth + x <= 0 || scaledHeight + y <= 0) // check left and top (in case x,y are negative) - return; - if (scaledWidth <= 0 || scaledHeight <= 0) // check right and bottom - return; - int heightAmt = scaledHeight; - - byte *src = info.sprite->getBasePtr(); - byte *dst = getBasePtr(x - info.hotX - clipX, y - info.hotY - clipY); - - int status = kStatusSkip; - byte *scaledLineBuf = new byte[scaledWidth]; - - while (heightAmt > 0) { - - if (status == kStatusSkip) { - // Skip line - errY -= info.scaleY; - if (errY < 0) - status = kStatusScale; - else - src += info.width; - } else { - - if (status == kStatusScale) { - // Scale current line - byte *lineDst = scaledLineBuf; - int curErrX = errX; - int widthVal = scaledWidth; - byte *tempSrc = src; - int startX = clipX; - while (widthVal > 0) { - byte pixel = *tempSrc++; - curErrX -= info.scaleX; - while (curErrX < 0) { - if (startX == 0) { - *lineDst++ = pixel; - widthVal--; - } else { - startX++; - } - curErrX += 100; - } - } - src += info.width; - status = kStatusDraw; - } - - if (status == kStatusDraw && clipY == 0) { - // Draw previously scaled line - // TODO Implement different drawing types (depth, shadow etc.) - byte *tempDst = dst; - for (int lineX = 0; lineX < scaledWidth; lineX++) { - byte pixel = scaledLineBuf[lineX]; - - if (info.encoding & 0x80) { - - if (pixel == 0x80) { - pixel = 0; - } else { - byte destPixel = *tempDst; - byte r, g, b; - r = CLIP((info.palette[destPixel].r * pixel) >> 10, 0, 31); - g = CLIP((info.palette[destPixel].g * pixel) >> 10, 0, 31); - b = CLIP((info.palette[destPixel].b * pixel) >> 10, 0, 31); - pixel = info.inverseColorTable[(b << 10) | (g << 5) | r]; - } - } - - if (pixel) - *tempDst = pixel; - - tempDst++; - } - dst += pitch; - heightAmt--; - // TODO depth etc. - //depthAddress += Destination -> Width; - - errY += 100; - if (errY >= 0) - status = kStatusSkip; - } else if (status == kStatusDraw && clipY < 0) { - clipY++; - - errY += 100; - if (errY >= 0) - status = kStatusSkip; - } - - } - - } - - delete[] scaledLineBuf; - -} - -// Surface methods - -void M4Surface::freeData() { -} - -void M4Surface::clear() { - Common::fill((byte *)pixels, (byte *)pixels + w * h, _vm->_palette->BLACK); -} - -void M4Surface::reset() { - ::free(pixels); - pixels = NULL; - if (_rgbList) { - _vm->_palette->deleteRange(_rgbList); - delete _rgbList; - _rgbList = NULL; - } -} - -void M4Surface::frameRect(const Common::Rect &r, uint8 color) { - Graphics::Surface::frameRect(r, color); -} - -void M4Surface::fillRect(const Common::Rect &r, uint8 color) { - Graphics::Surface::fillRect(r, color); -} - -void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, - int transparentColor) { - // Validation of the rectangle and position - if ((destX >= w) || (destY >= h)) - return; - - Common::Rect copyRect = srcBounds; - if (destX < 0) { - copyRect.left += -destX; - destX = 0; - } else if (destX + copyRect.width() > w) { - copyRect.right -= destX + copyRect.width() - w; - } - if (destY < 0) { - copyRect.top += -destY; - destY = 0; - } else if (destY + copyRect.height() > h) { - copyRect.bottom -= destY + copyRect.height() - h; - } - - if (!copyRect.isValidRect()) - return; - - // Copy the specified area - - byte *data = src->getBasePtr(); - byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); - byte *destPtr = (byte *)pixels + (destY * width()) + destX; - - for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { - if (transparentColor == -1) - // No transparency, so copy line over - Common::copy(srcPtr, srcPtr + copyRect.width(), destPtr); - else { - // Copy each byte one at a time checking for the transparency color - for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) - if (srcPtr[xCtr] != transparentColor) destPtr[xCtr] = srcPtr[xCtr]; - } - - srcPtr += src->width(); - destPtr += width(); - } - - src->freeData(); -} - -/** - * Copies a given image onto a destination surface with scaling, transferring only pixels that meet - * the specified depth requirement on a secondary surface contain depth information - */ -void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, - M4Surface *depthsSurface, int scale, int transparentColor) { - - if (scale == 100) { - // Copy the specified area - Common::Rect copyRect(0, 0, src->width(), src->height()); - - if (destX < 0) { - copyRect.left += -destX; - destX = 0; - } else if (destX + copyRect.width() > w) { - copyRect.right -= destX + copyRect.width() - w; - } - if (destY < 0) { - copyRect.top += -destY; - destY = 0; - } else if (destY + copyRect.height() > h) { - copyRect.bottom -= destY + copyRect.height() - h; - } - - if (!copyRect.isValidRect()) - return; - - byte *data = src->getBasePtr(); - byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); - byte *depthsData = depthsSurface->getBasePtr(); - byte *depthsPtr = depthsData + (depthsSurface->pitch * destY) + destX; - byte *destPtr = (byte *)pixels + (destY * pitch) + destX; - - // 100% scaling variation - for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { - // Copy each byte one at a time checking against the depth - for (int xCtr = 0; xCtr < copyRect.width(); ++xCtr) { - if ((depth <= (depthsPtr[xCtr] & 0x7f)) && (srcPtr[xCtr] != transparentColor)) - destPtr[xCtr] = srcPtr[xCtr]; - } - - srcPtr += src->width(); - depthsPtr += depthsSurface->width(); - destPtr += width(); - } - - src->freeData(); - depthsSurface->freeData(); - return; - } - - // Start of draw logic for scaled sprites - const byte *srcPixelsP = src->getBasePtr(); - - int destRight = this->width() - 1; - int destBottom = this->height() - 1; - bool normalFrame = true; // TODO: false for negative frame numbers - int frameWidth = src->width(); - int frameHeight = src->height(); - - int highestDim = MAX(frameWidth, frameHeight); - bool lineDist[MADS_SURFACE_WIDTH]; - int distIndex = 0; - int distXCount = 0, distYCount = 0; - - int distCtr = 0; - do { - distCtr += scale; - if (distCtr < 100) { - lineDist[distIndex] = false; - } else { - lineDist[distIndex] = true; - distCtr -= 100; - - if (distIndex < frameWidth) - ++distXCount; - - if (distIndex < frameHeight) - ++distYCount; - } - } while (++distIndex < highestDim); - - destX -= distXCount / 2; - destY -= distYCount - 1; - - // Check x bounding area - int spriteLeft = 0; - int spriteWidth = distXCount; - int widthAmount = destX + distXCount - 1; - - if (destX < 0) { - spriteWidth += destX; - spriteLeft -= destX; - } - widthAmount -= destRight; - if (widthAmount > 0) - spriteWidth -= widthAmount; - - int spriteRight = spriteLeft + spriteWidth; - if (spriteWidth <= 0) - return; - if (!normalFrame) { - destX += distXCount - 1; - spriteLeft = -(distXCount - spriteRight); - spriteRight = (-spriteLeft + spriteWidth); - } - - // Check y bounding area - int spriteTop = 0; - int spriteHeight = distYCount; - int heightAmount = destY + distYCount - 1; - - if (destY < 0) { - spriteHeight += destY; - spriteTop -= destY; - } - heightAmount -= destBottom; - if (heightAmount > 0) - spriteHeight -= heightAmount; - int spriteBottom = spriteTop + spriteHeight; - - if (spriteHeight <= 0) - return; - - byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); - const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop); - - spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); - - // Loop through the lines of the sprite - for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) { - if (!lineDist[yp]) - // Not a display line, so skip it - continue; - // Check whether the sprite line is in the display range - ++sprY; - if ((sprY >= spriteBottom) || (sprY < spriteTop)) - continue; - - // Found a line to display. Loop through the pixels - const byte *srcP = srcPixelsP; - const byte *depthP = depthPixelsP; - byte *destP = destPixelsP; - for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { - if (xp < spriteLeft) - // Not yet reached start of display area - continue; - if (!lineDist[sprX++]) - // Not a display pixel - continue; - - if ((*srcP != transparentColor) && (depth <= (*depthP & 0x7f))) - *destP = *srcP; - - ++destP; - ++depthP; - } - - // Move to the next destination line - destPixelsP += this->pitch; - depthPixelsP += depthsSurface->pitch; - } - - src->freeData(); - depthsSurface->freeData(); - this->freeData(); -} - -void M4Surface::loadBackgroundRiddle(const char *sceneName) { - char resourceName[20]; - Common::SeekableReadStream *stream; - // Loads a Riddle scene - sprintf(resourceName, "%s.tt", sceneName); - stream = _vm->_resourceManager->get(resourceName); - m4LoadBackground(stream); - _vm->_resourceManager->toss(resourceName); -} - -void M4Surface::loadBackground(int sceneNumber, RGBList **palData) { - if (_vm->isM4() || (_vm->getGameType() == GType_RexNebular)) { - char resourceName[20]; - Common::SeekableReadStream *stream; - - if (_vm->getGameType() == GType_RexNebular) { - // Load Rex Nebular screen - bool hasPalette = palData != NULL; - if (!hasPalette) - palData = &_rgbList; - - sprintf(resourceName, "rm%d.art", sceneNumber); - stream = _vm->_resourceManager->get(resourceName); - rexLoadBackground(stream, palData); - - if (!hasPalette) { - _vm->_palette->addRange(_rgbList); - this->translate(_rgbList); - } - } else { - // Loads M4 game scene - if (palData) - *palData = NULL; - sprintf(resourceName, "%i.tt", sceneNumber); - stream = _vm->_resourceManager->get(resourceName); - m4LoadBackground(stream); - } - - _vm->_resourceManager->toss(resourceName); - - } else { - madsLoadBackground(sceneNumber, palData); - } -} - -void M4Surface::madsLoadBackground(int roomNumber, RGBList **palData) { - // Get a MadsPack reference to the tile set and mapping - char resourceName[20]; - int i; - - // Uncompressed tile map resource - sprintf(resourceName, "rm%d.mm", roomNumber); - MadsPack tileMapFile(resourceName, _vm); - Common::SeekableReadStream *mapStream = tileMapFile.getItemStream(0); - - // Get the details of the tiles and map - mapStream->readUint32LE(); - int tileCountX = mapStream->readUint16LE(); - int tileCountY = mapStream->readUint16LE(); - int tileWidthMap = mapStream->readUint16LE(); - int tileHeightMap = mapStream->readUint16LE(); - int screenWidth = mapStream->readUint16LE(); - int screenHeight = mapStream->readUint16LE(); - int tileCountMap = tileCountX * tileCountY; - delete mapStream; - - // Obtain tile map information - typedef Common::List > TileSetList; - typedef TileSetList::iterator TileSetIterator; - TileSetList tileSet; - uint16 *tileMap = new uint16[tileCountMap]; - mapStream = tileMapFile.getItemStream(1); - for (i = 0; i < tileCountMap; ++i) - tileMap[i] = mapStream->readUint16LE(); - delete mapStream; - _vm->res()->toss(resourceName); - - // -------------------------------------------------------------------------------- - - // Tile map data, which needs to be kept compressed, as the tile offsets refer to - // the compressed data. Each tile is then uncompressed separately - sprintf(resourceName, "rm%d.tt", roomNumber); - Common::SeekableReadStream *tileDataComp = _vm->_resourceManager->get(resourceName); - MadsPack tileData(tileDataComp); - Common::SeekableReadStream *tileDataUncomp = tileData.getItemStream(0); - - // Validate that the data matches between the tiles and tile map file and is valid - int tileCount = tileDataUncomp->readUint16LE(); - int tileWidth = tileDataUncomp->readUint16LE(); - int tileHeight = tileDataUncomp->readUint16LE(); - delete tileDataUncomp; - assert(tileCountMap == tileCount); - assert(tileWidth == tileWidthMap); - assert(tileHeight == tileHeightMap); - assert(screenWidth == _vm->_screen->width()); - assert(screenHeight <= _vm->_screen->height()); - - // -------------------------------------------------------------------------------- - - // Get the palette to use - tileDataUncomp = tileData.getItemStream(2); - // Set palette - if (!palData) { - _vm->_palette->setMadsPalette(tileDataUncomp, 4); - } else { - int numColors; - RGB8 *rgbList = _vm->_palette->decodeMadsPalette(tileDataUncomp, &numColors); - *palData = new RGBList(numColors, rgbList, true); - } - delete tileDataUncomp; - - // -------------------------------------------------------------------------------- - - // Get tile data - - tileDataUncomp = tileData.getItemStream(1); - FabDecompressor fab; - uint32 compressedTileDataSize = 0; - - for (i = 0; i < tileCount; i++) { - tileDataUncomp->seek(i * 4, SEEK_SET); - uint32 tileOfs = tileDataUncomp->readUint32LE(); - M4Surface* newTile = new M4Surface(tileWidth, tileHeight); - - if (i == tileCount - 1) - compressedTileDataSize = tileDataComp->size() - tileOfs; - else - compressedTileDataSize = tileDataUncomp->readUint32LE() - tileOfs; - - //debugCN(kDebugGraphics, "Tile: %i, compressed size: %i\n", i, compressedTileDataSize); - - newTile->clear(); - - byte *compressedTileData = new byte[compressedTileDataSize]; - - tileDataComp->seek(tileData.getDataOffset() + tileOfs, SEEK_SET); - tileDataComp->read(compressedTileData, compressedTileDataSize); - - fab.decompress(compressedTileData, compressedTileDataSize, (byte*)newTile->pixels, tileWidth * tileHeight); - tileSet.push_back(TileSetList::value_type(newTile)); - delete[] compressedTileData; - } - - delete tileDataUncomp; - - // -------------------------------------------------------------------------------- - - // Loop through the mapping data to place the tiles on the screen - - uint16 *tIndex = &tileMap[0]; - for (int y = 0; y < tileCountY; y++) { - for (int x = 0; x < tileCountX; x++) { - int tileIndex = *tIndex++; - assert(tileIndex < tileCount); - TileSetIterator tile = tileSet.begin(); - for (i = 0; i < tileIndex; i++) - ++tile; - ((*tile).get())->copyTo(this, x * tileWidth, y * tileHeight); - } - } - tileSet.clear(); - _vm->res()->toss(resourceName); -} - -void M4Surface::rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData) { - MadsPack packData(source); - Common::SeekableReadStream *sourceUnc = packData.getItemStream(0); - - int sceneWidth = sourceUnc->readUint16LE(); - int sceneHeight = sourceUnc->readUint16LE(); - int sceneSize = sceneWidth * sceneHeight; - - // Set palette - if (!palData) { - _vm->_palette->setMadsPalette(sourceUnc, 4); - } else { - int numColors; - RGB8 *rgbList = _vm->_palette->decodeMadsPalette(sourceUnc, &numColors); - *palData = new RGBList(numColors, rgbList, true); - } - delete sourceUnc; - - // Get the raw data for the background - sourceUnc = packData.getItemStream(1); - assert((int)sourceUnc->size() >= sceneSize); - - create(sceneWidth, sceneHeight, Graphics::PixelFormat::createFormatCLUT8()); - byte *pData = (byte *)pixels; - sourceUnc->read(pData, sceneSize); - - freeData(); - delete sourceUnc; -} - -#undef COL_TRANS - -void M4Surface::m4LoadBackground(Common::SeekableReadStream *source) { - M4Surface *tileBuffer = new M4Surface(); - uint curTileX = 0, curTileY = 0; - int clipX = 0, clipY = 0; - RGB8 palette[256]; - - source->readUint32LE(); // magic, unused - /*uint32 size =*/ source->readUint32LE(); - uint32 widthVal = source->readUint32LE(); - uint32 heightVal = source->readUint32LE(); - uint32 tilesX = source->readUint32LE(); - uint32 tilesY = source->readUint32LE(); - uint32 tileWidth = source->readUint32LE(); - uint32 tileHeight = source->readUint32LE(); - uint8 blackIndex = 0; - - // Debug - //debugCN(kDebugGraphics, "loadBackground(): %dx%d picture (%d bytes) - %dx%d tiles of size %dx%d\n", - // widthVal, heightVal, size, tilesX, tilesY, tileWidth, tileHeight); - - // BGR data, which is converted to RGB8 - for (uint i = 0; i < 256; i++) { - palette[i].b = source->readByte() << 2; - palette[i].g = source->readByte() << 2; - palette[i].r = source->readByte() << 2; - // FIXME - Removed u field from RGB8 as the OSystem palette is now RGB. - // If this is needed, then the system setPalette() call will need changing to skip this. - uint8 u = source->readByte() << 2; - if (u != 0) - debugC(1, kDebugGraphics, "Unused u field in Palette data non-zero: %d", u); - - if ((blackIndex == 0) && !palette[i].r && !palette[i].g && !palette[i].b) - blackIndex = i; - } - - _vm->_palette->setPalette(palette, 0, 256); - - // resize or create the surface - // note that the height of the scene in game scenes is smaller than 480, as the bottom part of the - // screen is the inventory - assert(width() == (int)widthVal); - //debugCN(kDebugGraphics, "width(): %d, widthVal: %d, height(): %d, heightVal: %d\n", width(), widthVal, height(), heightVal); - - tileBuffer->create(tileWidth, tileHeight, Graphics::PixelFormat::createFormatCLUT8()); - - for (curTileY = 0; curTileY < tilesY; curTileY++) { - clipY = MIN(heightVal, (1 + curTileY) * tileHeight) - (curTileY * tileHeight); - - for (curTileX = 0; curTileX < tilesX; curTileX++) { - clipX = MIN(widthVal, (1 + curTileX) * tileWidth) - (curTileX * tileWidth); - - // Read a tile and copy it to the destination surface - source->read(tileBuffer->pixels, tileWidth * tileHeight); - Common::Rect srcBounds(0, 0, clipX, clipY); - copyFrom(tileBuffer, srcBounds, curTileX * tileWidth, curTileY * tileHeight); - } - } - - if (heightVal < (uint)height()) - fillRect(Common::Rect(0, heightVal, width(), height()), blackIndex); - - delete tileBuffer; -} - -void M4Surface::madsLoadInterface(const Common::String &filename) { - MadsPack intFile(filename.c_str(), _vm); - RGB8 *palette = new RGB8[16]; - - // Chunk 0, palette - Common::SeekableReadStream *intStream = intFile.getItemStream(0); - - for (int i = 0; i < 16; i++) { - palette[i].r = intStream->readByte() << 2; - palette[i].g = intStream->readByte() << 2; - palette[i].b = intStream->readByte() << 2; - intStream->readByte(); - intStream->readByte(); - intStream->readByte(); - } - _rgbList = new RGBList(16, palette, true); - delete intStream; - - // Chunk 1, data - intStream = intFile.getItemStream(1); - create(320, 44, Graphics::PixelFormat::createFormatCLUT8()); - intStream->read(pixels, 320 * 44); - delete intStream; - - // Translate the interface palette - _vm->_palette->addRange(_rgbList); - this->translate(_rgbList); -} - -void M4Surface::scrollX(int xAmount) { - if (xAmount == 0) - return; - - byte buffer[80]; - int direction = (xAmount > 0) ? -1 : 1; - int xSize = ABS(xAmount); - assert(xSize <= 80); - - byte *srcP = (byte *)getBasePtr(0, 0); - - for (int y = 0; y < height(); ++y, srcP += pitch) { - if (direction < 0) { - // Copy area to be overwritten - Common::copy(srcP, srcP + xSize, &buffer[0]); - // Shift the remainder of the line over the given area - Common::copy(srcP + xSize, srcP + width(), srcP); - // Move buffered area to the end of the line - Common::copy(&buffer[0], &buffer[xSize], srcP + width() - xSize); - } else { - // Copy area to be overwritten - Common::copy_backward(srcP + width() - xSize, srcP + width(), &buffer[80]); - // Shift the remainder of the line over the given area - Common::copy_backward(srcP, srcP + width() - xSize, srcP + width()); - // Move buffered area to the start of the line - Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize); - } - } -} - -void M4Surface::scrollY(int yAmount) { - if (yAmount == 0) - return; - - int direction = (yAmount > 0) ? 1 : -1; - int ySize = ABS(yAmount); - assert(ySize < (height() / 2)); - assert(width() == pitch); - - int blockSize = ySize * width(); - byte *tempData = (byte *)malloc(blockSize); - byte *pixelsP = (byte *)getBasePtr(0, 0); - - if (direction > 0) { - // Buffer the lines to be overwritten - byte *srcP = (byte *)getBasePtr(0, height() - ySize); - Common::copy(srcP, srcP + (pitch * ySize), tempData); - // Vertically shift all the lines - Common::copy_backward(pixelsP, pixelsP + (pitch * (height() - ySize)), - pixelsP + (pitch * height())); - // Transfer the buffered lines top the top of the screen - Common::copy(tempData, tempData + blockSize, pixelsP); - } else { - // Buffer the lines to be overwritten - Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData); - // Vertically shift all the lines - Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * height()), pixelsP); - // Transfer the buffered lines to the bottom of the screen - Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (height() - ySize))); - } - - ::free(tempData); -} - - -void M4Surface::translate(RGBList *list, bool isTransparent) { - byte *p = getBasePtr(0, 0); - byte *palIndexes = list->palIndexes(); - - for (int i = 0; i < width() * height(); ++i, ++p) { - if (!isTransparent || (*p != TRANSPARENT_COLOR_INDEX)) { - if (*p < list->size()) - *p = palIndexes[*p]; - else - warning("Pal index %d exceeds list size %d", *p, list->size()); - } - } - - freeData(); -} - -M4Surface *M4Surface::flipHorizontal() const { - M4Surface *dest = new M4Surface(width(), height()); - dest->_rgbList = (this->_rgbList == NULL) ? NULL : this->_rgbList->clone(); - - byte *destP = dest->getBasePtr(); - - for (int y = 0; y < height(); ++y) { - const byte *srcP = getBasePtr(width() - 1, y); - for (int x = 0; x < width(); ++x) - *destP++ = *srcP--; - } - - return dest; -} - -//-------------------------------------------------------------------------- -// Palette class -// - -#define GREEN_START 32 -#define NUM_GREENS 32 -#define GREEN_END (GREEN_START + NUM_GREENS - 1) -#define NORMAL_START 64 -#define NORMAL_END 255 -#define NUM_NORMAL (NORMAL_END - NORMAL_START + 1) - -// Support function for creating a list of palette indexes to change entries in the shaded range to - -static void makeTranslationList(RGB8 *palData, byte transList[NUM_GREENS]) { - int i, j, minDistance; - byte bestIndex; - - for (i = 0; i < NUM_GREENS; ++i) { - bestIndex = NORMAL_START; - minDistance = 255; - - uint8 findCol = palData[GREEN_START + i].g; - - // Find the closest matching palette color - for (j = NORMAL_START; j <= NORMAL_END; ++j) { - int greenVal = palData[j].g; - if (ABS(findCol - greenVal) < minDistance) { - minDistance = ABS(findCol - greenVal); - bestIndex = j; - } - - if (minDistance == 0) - break; - } - - transList[i] = bestIndex; - } -} - -// Support function for fading in or out - -static void fadeRange(MadsM4Engine *vm, RGB8 *srcPal, RGB8 *destPal, int startIndex, int endIndex, - int numSteps, uint delayAmount) { - RGB8 tempPal[256]; - - // perform the fade - for (int stepCtr = 1; stepCtr <= numSteps; ++stepCtr) { - // Delay the specified amount - uint32 startTime = g_system->getMillis(); - while ((g_system->getMillis() - startTime) < delayAmount) { - vm->_events->handleEvents(); - g_system->delayMillis(10); - } - - for (int i = startIndex; i <= endIndex; ++i) { - // Handle the intermediate rgb values for fading - tempPal[i].r = (byte) (srcPal[i].r + (destPal[i].r - srcPal[i].r) * stepCtr / numSteps); - tempPal[i].g = (byte) (srcPal[i].g + (destPal[i].g - srcPal[i].g) * stepCtr / numSteps); - tempPal[i].b = (byte) (srcPal[i].b + (destPal[i].b - srcPal[i].b) * stepCtr / numSteps); - } - - vm->_palette->setPalette(&tempPal[startIndex], startIndex, endIndex - startIndex + 1); - vm->_viewManager->refreshAll(); - } - - // Make sure the end palette exactly matches what is wanted - vm->_palette->setPalette(&destPal[startIndex], startIndex, endIndex - startIndex + 1); -} - -Palette::Palette(MadsM4Engine *vm) : _vm(vm) { - reset(); - _fading_in_progress = false; - Common::fill(&_usageCount[0], &_usageCount[256], 0); -} - -void Palette::setPalette(const byte *colors, uint start, uint num) { - g_system->getPaletteManager()->setPalette(colors, start, num); - reset(); -} - -void Palette::setPalette(const RGB8 *colors, uint start, uint num) { - g_system->getPaletteManager()->setPalette((const byte *)colors, start, num); - reset(); -} - -void Palette::grabPalette(byte *colors, uint start, uint num) { - g_system->getPaletteManager()->grabPalette(colors, start, num); -} - -void Palette::setEntry(uint index, uint8 r, uint8 g, uint8 b) { - RGB8 c; - c.r = r; - c.g = g; - c.b = b; - g_system->getPaletteManager()->setPalette((const byte *)&c, index, 1); -} - -uint8 Palette::palIndexFromRgb(byte r, byte g, byte b, RGB8 *paletteData) { - byte index = 0; - int32 minDist = 0x7fffffff; - RGB8 palData[256]; - int Rdiff, Gdiff, Bdiff; - - if (paletteData == NULL) { - g_system->getPaletteManager()->grabPalette((byte *)palData, 0, 256); - paletteData = &palData[0]; - } - - for (int palIndex = 0; palIndex < 256; ++palIndex) { - Rdiff = r - paletteData[palIndex].r; - Gdiff = g - paletteData[palIndex].g; - Bdiff = b - paletteData[palIndex].b; - - if (Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff < minDist) { - minDist = Rdiff * Rdiff + Gdiff * Gdiff + Bdiff * Bdiff; - index = (uint8)palIndex; - } - } - - return (uint8)index; -} - -void Palette::reset() { - RGB8 palData[256]; - g_system->getPaletteManager()->grabPalette((byte *)palData, 0, 256); - - BLACK = palIndexFromRgb(0, 0, 0, palData); - BLUE = palIndexFromRgb(0, 0, 255, palData); - GREEN = palIndexFromRgb(0, 255, 0, palData); - CYAN = palIndexFromRgb(0, 255, 255, palData); - RED = palIndexFromRgb(255, 0, 0, palData); - VIOLET = palIndexFromRgb(255, 0, 255, palData); - BROWN = palIndexFromRgb(168, 84, 84, palData); - LIGHT_GRAY = palIndexFromRgb(168, 168, 168, palData); - DARK_GRAY = palIndexFromRgb(84, 84, 84, palData); - LIGHT_BLUE = palIndexFromRgb(0, 0, 127, palData); - LIGHT_GREEN = palIndexFromRgb(0, 127, 0, palData); - LIGHT_CYAN = palIndexFromRgb(0, 127, 127, palData); - LIGHT_RED = palIndexFromRgb(84, 0, 0, palData); - PINK = palIndexFromRgb(84, 0, 0, palData); - YELLOW = palIndexFromRgb(0, 84, 84, palData); - WHITE = palIndexFromRgb(255, 255, 255, palData); -} - -void Palette::fadeToGreen(int numSteps, uint delayAmount) { - if (_fading_in_progress) - return; - _fading_in_progress = true; - byte translationList[NUM_GREENS]; - - int i; - byte *tempP; - uint8 greenAmount = 0; - RGB8 *srcPalette = (RGB8 *) &_originalPalette[0]; - RGB8 *destPalette = (RGB8 *) &_fadedPalette[0]; - - _vm->_palette->grabPalette(srcPalette, 0, 256); - - // Create the destination 'greenish' palette to fade to by setting the green component - // to the average of the RGB bytes, and leaving the Red and Blue parts as 0 - - Common::copy(&srcPalette[0], &srcPalette[256], &destPalette[0]); - for (i = 32; i < 256; ++i) { - byte luminance = (byte)((destPalette[i].r + destPalette[i].g + destPalette[i].b) / 3); - destPalette[i].g = MIN((byte)255, luminance); - destPalette[i].r = destPalette[i].b = 0; - } - - // Handle the actual fading - fadeRange(_vm, srcPalette, destPalette, 21, 255, numSteps, delayAmount); - - // Create a translation table to be used in translating pixels in the game surface - // using palette indexes in the range the range #32-63 into values from #64-255 - - makeTranslationList(destPalette, translationList); - - // Use palette indexes from #32-63 for the range of possible shades - - for (i = GREEN_START; i <= GREEN_END; ++i, greenAmount += 8) { - destPalette[i].g = greenAmount; - destPalette[i].r = destPalette[i].b = 0; - } - - // Remap all pixels into the #32-63 range - - tempP = _vm->_scene->getBasePtr(); - for (int pixelCtr = 0; pixelCtr < _vm->_scene->width() * _vm->_scene->height(); - ++pixelCtr, ++tempP) { - // If pixel is in #32-63 range already, remap to higher palette entries - if ((*tempP >= GREEN_START) && (*tempP <= GREEN_END)) - *tempP = translationList[*tempP - GREEN_START]; - - *tempP = (uint8) (GREEN_START + (destPalette[*tempP].g >> 3)); - } - - _vm->_palette->setPalette(&destPalette[GREEN_START], GREEN_START, NUM_GREENS); - _vm->_viewManager->refreshAll(); - _fading_in_progress = false; -} - -void Palette::fadeFromGreen(int numSteps, uint delayAmount, bool fadeToBlack) { - if (_fading_in_progress) - return; - _fading_in_progress = true; - RGB8 blackPalette[256]; - RGB8 *fadedPalette = (RGB8 *) &_fadedPalette[0]; - RGB8 *destPalette = (RGB8 *) &_originalPalette[0]; - - if (fadeToBlack) { - Common::fill((byte *)&blackPalette[0], (byte *)&blackPalette[256], 0); - destPalette = &blackPalette[0]; - } - - // Initially restore the faded palette - _vm->_palette->setPalette(fadedPalette, 0, 256); - _vm->_viewManager->refreshAll(); - - // Restore the pixel data from the original screen - _vm->_scene->update(); - - // Handle the actual fading - fadeRange(_vm, fadedPalette, destPalette, GREEN_START, NORMAL_END, numSteps, delayAmount); - - _fading_in_progress = false; -} - -void Palette::fadeIn(int numSteps, uint delayAmount, RGBList *destPalette) { - fadeIn(numSteps, delayAmount, destPalette->data(), destPalette->size()); -} - -void Palette::fadeIn(int numSteps, uint delayAmount, RGB8 *destPalette, int numColors) { - if (_fading_in_progress) - return; - - _fading_in_progress = true; - RGB8 blackPalette[256]; - Common::fill((byte *)&blackPalette[0], (byte *)&blackPalette[256], 0); - - // Initially set the black palette - _vm->_palette->setPalette(blackPalette, 0, numColors); - - // Handle the actual fading - fadeRange(_vm, blackPalette, destPalette, 0, numColors - 1, numSteps, delayAmount); - - _fading_in_progress = false; -} - -RGB8 *Palette::decodeMadsPalette(Common::SeekableReadStream *palStream, int *numColors) { - *numColors = palStream->readUint16LE(); - assert(*numColors <= 252); - - RGB8 *palData = new RGB8[*numColors]; - Common::fill((byte *)&palData[0], (byte *)&palData[*numColors], 0); - - for (int i = 0; i < *numColors; ++i) { - byte r = palStream->readByte(); - byte g = palStream->readByte(); - byte b = palStream->readByte(); - palData[i].r = VGA_COLOR_TRANS(r); - palData[i].g = VGA_COLOR_TRANS(g); - palData[i].b = VGA_COLOR_TRANS(b); - - // The next 3 bytes are unused - palStream->skip(3); - } - - return palData; -} - -int Palette::setMadsPalette(Common::SeekableReadStream *palStream, int indexStart) { - int colorCount; - RGB8 *palData = Palette::decodeMadsPalette(palStream, &colorCount); - _vm->_palette->setPalette(palData, indexStart, colorCount); - delete palData; - return colorCount; -} - -void Palette::setMadsSystemPalette() { - // Rex Nebular default system palette - resetColorCounts(); - - RGB8 palData[4]; - palData[0].r = palData[0].g = palData[0].b = 0; - palData[1].r = palData[1].g = palData[1].b = 0x54; - palData[2].r = palData[2].g = palData[2].b = 0xb4; - palData[3].r = palData[3].g = palData[3].b = 0xff; - - setPalette(palData, 0, 4); - blockRange(0, 4); -} - -void Palette::resetColorCounts() { - Common::fill(&_usageCount[0], &_usageCount[256], 0); -} - -void Palette::blockRange(int startIndex, int size) { - // Use a reference count of -1 to signal a palette index shouldn't be used - Common::fill(&_usageCount[startIndex], &_usageCount[startIndex + size], -1); -} - -void Palette::addRange(RGBList *list) { - RGB8 *data = list->data(); - byte *palIndexes = list->palIndexes(); - RGB8 palData[256]; - g_system->getPaletteManager()->grabPalette((byte *)&palData[0], 0, 256); - bool paletteChanged = false; - - for (int colIndex = 0; colIndex < list->size(); ++colIndex) { - // Scan through for an existing copy of the RGB value - int palIndex = -1; - while (++palIndex < 256) { - if (_usageCount[palIndex] <= 0) - // Palette index is to be skipped - continue; - - if ((palData[palIndex].r == data[colIndex].r) && - (palData[palIndex].g == data[colIndex].g) && - (palData[palIndex].b == data[colIndex].b)) - // Match found - break; - } - - if (palIndex == 256) { - // No match found, so find a free slot to use - palIndex = -1; - while (++palIndex < 256) { - if (_usageCount[palIndex] == 0) - break; - } - - if (palIndex == 256) - error("addRange - Ran out of palette space to allocate"); - - palData[palIndex].r = data[colIndex].r; - palData[palIndex].g = data[colIndex].g; - palData[palIndex].b = data[colIndex].b; - paletteChanged = true; - } - - palIndexes[colIndex] = palIndex; - ++_usageCount[palIndex]; - } - - if (paletteChanged) { - g_system->getPaletteManager()->setPalette((byte *)&palData[0], 0, 256); - reset(); - } -} - -void Palette::deleteRange(RGBList *list) { - // Release the reference count on each of the palette entries - for (int colIndex = 0; colIndex < list->size(); ++colIndex) { - int palIndex = list->palIndexes()[colIndex]; - assert(_usageCount[palIndex] > 0); - --_usageCount[palIndex]; - } -} - -void Palette::deleteAllRanges() { - for (int colIndex = 0; colIndex < 255; ++colIndex) - _usageCount[colIndex] = 0; -} - -//-------------------------------------------------------------------------- -// Support methods - -void decompressRle(byte *rleData, int rleSize, byte *celData, int w, int h) { - byte *src = rleData; - byte *dst = celData; - byte len; - while (1) { - len = *src++; - if (len == 0) { - len = *src++; - if (len <= 2) { - if (len == 1) // end of sprite marker - break; - } else { - while (len--) - *dst++ = *src++; - } - } else { - while (len--) - *dst++ = *src; - src++; - } - } -} - -int scaleValue(int value, int scale, int err) { - int scaled = 0; - while (value--) { - err -= scale; - while (err < 0) { - scaled++; - err += 100; - } - } - return scaled; -} - -} // End of namespace M4 diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h deleted file mode 100644 index f3dde454f3..0000000000 --- a/engines/m4/graphics.h +++ /dev/null @@ -1,270 +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. - * - */ - -#ifndef M4_GRAPHICS_H -#define M4_GRAPHICS_H - -#include "common/rect.h" -#include "common/system.h" -#include "common/stream.h" -#include "graphics/surface.h" - -#include "m4/globals.h" - -namespace M4 { - -#define MADS_SURFACE_WIDTH 320 -#define MADS_SURFACE_HEIGHT 156 -#define MADS_SCREEN_HEIGHT 200 -#define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2) - -#define TRANSPARENT_COLOR_INDEX 0xFF - -struct BGR8 { - uint8 b, g, r; -}; - -struct RGB8 { - uint8 r, g, b; -}; - -//later use ScummVM's Rect? -struct M4Rect { - int32 x1, y1, x2, y2; -}; - -class M4Surface; - -// RGBList -// Implements a list of RGB entries - -class RGBList { -private: - int _size; - RGB8 *_data; - byte *_palIndexes; - bool _freeData; -public: - RGBList(int numEntries = 256, RGB8 *srcData = NULL, bool freeData = true); - ~RGBList(); - - RGB8 *data() { return _data; } - byte *palIndexes() { return _palIndexes; } - int size() { return _size; } - RGB8 &operator[](int idx) { return _data[idx]; } - void setRange(int start, int count, const RGB8 *src); - RGBList *clone() const; -}; - -// M4Surface -// Class representing either a buffered surface or the physical screen. - -class M4Sprite; - -struct SpriteInfo { - M4Sprite *sprite; - int hotX, hotY; - int width, height; - int scaleX, scaleY; - uint8 encoding; - byte *inverseColorTable; - RGB8 *palette; -}; - -class M4Surface : protected Graphics::Surface { -private: - byte _color; - bool _isScreen; - RGBList *_rgbList; - bool _ownsData; - - void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL); - void madsLoadBackground(int roomNumber, RGBList **palData = NULL); - void m4LoadBackground(Common::SeekableReadStream *source); -public: - M4Surface(bool isScreen = false) { - create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, Graphics::PixelFormat::createFormatCLUT8()); - _isScreen = isScreen; - _rgbList = NULL; - _ownsData = true; - } - M4Surface(int width_, int height_) { - create(width_, height_, Graphics::PixelFormat::createFormatCLUT8()); - _isScreen = false; - _rgbList = NULL; - _ownsData = true; - } - M4Surface(int width_, int height_, byte *srcPixels, int pitch_) { - format = Graphics::PixelFormat::createFormatCLUT8(); - w = width_; - h = height_; - pitch = pitch_; - pixels = srcPixels; - _rgbList = NULL; - _ownsData = false; - } - - virtual ~M4Surface(); - - // loads a .COD file into the M4Surface - // TODO: maybe move this to the rail system? check where it makes sense - // The sprite drawing needs this, too, so should be more global. - void loadCodesM4(Common::SeekableReadStream *source); - void loadCodesMads(Common::SeekableReadStream *source); - - // loads the specified background - void loadBackground(int sceneNumber, RGBList **palData = NULL); - void loadBackgroundRiddle(const char *sceneName); - void madsLoadInterface(int index, RGBList **palData = NULL); - void madsLoadInterface(const Common::String &filename); - - void setColor(byte value) { _color = value; } - inline byte getColor() const { return _color; } - void vLine(int x, int y1, int y2); - void hLine(int x1, int x2, int y); - void vLineXor(int x, int y1, int y2); - void hLineXor(int x1, int x2, int y); - void drawLine(int x1, int y1, int x2, int y2, byte color); - void frameRect(int x1, int y1, int x2, int y2); - void fillRect(int x1, int y1, int x2, int y2); - - void drawSprite(int x, int y, SpriteInfo &info, const Common::Rect &clipRect); - - // Surface methods - inline Common::Rect bounds() const { return Common::Rect(0, 0, width(), height()); } - inline int width() const { return w; } - inline int height() const { return h; } - inline int getPitch() const { return pitch; } - void setSize(int sizeX, int sizeY) { create(sizeX, sizeY, Graphics::PixelFormat::createFormatCLUT8()); } - inline byte *getBasePtr() { - return (byte *)pixels; - } - inline byte *getBasePtr(int x, int y) { - return (byte *)Graphics::Surface::getBasePtr(x, y); - } - inline const byte *getBasePtr(int x, int y) const { - return (const byte *)Graphics::Surface::getBasePtr(x, y); - } - void freeData(); - void clear(); - void reset(); - void frameRect(const Common::Rect &r, uint8 color); - void fillRect(const Common::Rect &r, uint8 color); - void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColor = -1); - void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface, - int scale, int transparentColor = -1); - - void update() { - if (_isScreen) { - g_system->copyRectToScreen((const byte *)pixels, pitch, 0, 0, w, h); - g_system->updateScreen(); - } - } - - // copyTo methods - inline void copyTo(M4Surface *dest, int transparentColor = -1) { - dest->copyFrom(this, Common::Rect(width(), height()), 0, 0, transparentColor); - } - inline void copyTo(M4Surface *dest, int x, int y, int transparentColor = -1) { - dest->copyFrom(this, Common::Rect(width(), height()), x, y, transparentColor); - } - inline void copyTo(M4Surface *dest, const Common::Rect &srcBounds, int destX, int destY, - int transparentColor = -1) { - dest->copyFrom(this, srcBounds, destX, destY, transparentColor); - } - inline void copyTo(M4Surface *dest, int destX, int destY, int depth, M4Surface *depthsSurface, int scale, - int transparentColor = -1) { - dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColor); - } - - void scrollX(int xAmount); - void scrollY(int yAmount); - - void translate(RGBList *list, bool isTransparent = false); - M4Surface *flipHorizontal() const; -}; - -enum FadeType {FT_TO_GREY, FT_TO_COLOR, FT_TO_BLOCK}; - -class Palette { -private: - MadsM4Engine *_vm; - bool _colorsChanged; - bool _fading_in_progress; - byte _originalPalette[256 * 3]; - byte _fadedPalette[256 * 3]; - int _usageCount[256]; - - void reset(); -public: - Palette(MadsM4Engine *vm); - - void setPalette(const byte *colors, uint start, uint num); - void setPalette(const RGB8 *colors, uint start, uint num); - void grabPalette(byte *colors, uint start, uint num); - void grabPalette(RGB8 *colors, uint start, uint num) { - grabPalette((byte *)colors, start, num); - } - void setEntry(uint index, uint8 r, uint8 g, uint8 b); - uint8 palIndexFromRgb(byte r, byte g, byte b, RGB8 *paletteData = NULL); - - void fadeToGreen(int numSteps, uint delayAmount); - void fadeFromGreen(int numSteps, uint delayAmount, bool fadeToBlack); - void fadeIn(int numSteps, uint delayAmount, RGB8 *destPalette, int numColors); - void fadeIn(int numSteps, uint delayAmount, RGBList *destPalette); - static RGB8 *decodeMadsPalette(Common::SeekableReadStream *palStream, int *numColors); - int setMadsPalette(Common::SeekableReadStream *palStream, int indexStart = 0); - void setMadsSystemPalette(); - - // Methods used for reference counting color usage - void resetColorCounts(); - void blockRange(int startIndex, int size); - void addRange(RGBList *list); - void deleteRange(RGBList *list); - void deleteAllRanges(); - - // Color indexes - uint8 BLACK; - uint8 BLUE; - uint8 GREEN; - uint8 CYAN; - uint8 RED; - uint8 VIOLET; - uint8 BROWN; - uint8 LIGHT_GRAY; - uint8 DARK_GRAY; - uint8 LIGHT_BLUE; - uint8 LIGHT_GREEN; - uint8 LIGHT_CYAN; - uint8 LIGHT_RED; - uint8 PINK; - uint8 YELLOW; - uint8 WHITE; -}; - -void decompressRle(byte *rleData, int rleSize, byte *celData, int w, int h); -void decompressRle(Common::SeekableReadStream &rleData, byte *celData, int w, int h); -int scaleValue(int value, int scale, int err); - -} // End of namespace M4 - -#endif diff --git a/engines/m4/gui.cpp b/engines/m4/gui.cpp deleted file mode 100644 index 6bedfa7e9b..0000000000 --- a/engines/m4/gui.cpp +++ /dev/null @@ -1,1215 +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/events.h" -#include "common/keyboard.h" -#include "common/textconsole.h" - -#include "m4/globals.h" -#include "m4/events.h" -#include "m4/font.h" -#include "m4/graphics.h" -#include "m4/viewmgr.h" -#include "m4/gui.h" -#include "m4/midi.h" -#include "m4/scene.h" -#include "m4/m4.h" - -namespace M4 { - -//-------------------------------------------------------------------------- -// DialogView class -// -// Defines a generic base class for dialogs, that some of the classes -// in the object hierharchy require as a parent -//-------------------------------------------------------------------------- - -void DialogView::close() { - // Default to simply destroying the given dialog - _vm->_viewManager->deleteView(this); -} - -//-------------------------------------------------------------------------- -// GUIObject class -// -// Defines a generic object that appears in a view -//-------------------------------------------------------------------------- - -GUIObject::GUIObject(View *owner, const Common::Rect &bounds) { - _parent = owner; - _bounds = bounds; -} - -//-------------------------------------------------------------------------- -// MenuObject class -// -// Defines a specialised GUI object that appears in a dialog -//-------------------------------------------------------------------------- - -MenuObject::MenuObject(DialogView *owner, int objectId, int xs, int ys, int width, int height, - bool greyed, bool transparent): - GUIObject(owner, Common::Rect(xs, ys, xs + width, ys + height)) { - - _objectId = objectId; - _bounds.top = ys; - _bounds.bottom = ys + height - 1; - _bounds.left = xs; - _bounds.right = xs + width - 1; - _transparent = transparent; - _objectState = greyed ? OS_GREYED : OS_NORMAL; - _callback = NULL; - - if (transparent) { - _background = new M4Surface(width, height); - Common::Rect srcBounds(xs, ys, xs + width - 1, ys + height - 1); - _background->copyFrom(owner, srcBounds, 0, 0); - } else { - _background = NULL; - } -} - -MenuObject::~MenuObject() { - delete _background; -} - -void MenuObject::onExecute() { - // If a callback function has been specified, then execute it - if (_callback) - _callback(parent(), this); -} - -//-------------------------------------------------------------------------- -// MenuButton class -// -// Defines a button object -//-------------------------------------------------------------------------- - -MenuButton::MenuButton(DialogView *owner, int buttonId, int xs, int ys, int width, int height, - MenuButton::Callback callbackFn, bool greyed, bool transparent, - ObjectType buttonType): - MenuObject(owner, buttonId, xs, ys, width, height, greyed, transparent) { - - _objectType = buttonType; - _callback = callbackFn; -} - -bool MenuButton::onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem) { - bool redrawFlag = false; - bool callbackFlag = false; - bool handledFlag = true; - - if (_objectState == OS_GREYED) - return false; - - switch (event) { - case MEVENT_LEFT_CLICK: - case MEVENT_DOUBLECLICK: - if (isInside(x, y)) { - _objectState = OS_PRESSED; - if (currentItem != NULL) - currentItem = this; - redrawFlag = true; - } else { - currentItem = NULL; - if (_objectState != OS_NORMAL) { - _objectState = OS_PRESSED; - redrawFlag = true; - } - } - break; - - case MEVENT_LEFT_DRAG: - case MEVENT_DOUBLECLICK_DRAG: - if (!currentItem) { - return true; - } - if (isInside(x, y)) { - if (_objectState != OS_PRESSED) { - _objectState = OS_PRESSED; - redrawFlag = true; - } - } - else { - if (_objectState != OS_MOUSEOVER) { - _objectState = OS_MOUSEOVER; - redrawFlag = true; - } - } - break; - - case MEVENT_LEFT_RELEASE: - case MEVENT_DOUBLECLICK_RELEASE: - if (isInside(x, y)) { - if (currentItem) { - callbackFlag = true; - if (_objectType == OBJTYPE_OM_SWITCH_ON) - _objectType = OBJTYPE_OM_SWITCH_OFF; - else if (_objectType == OBJTYPE_OM_SWITCH_OFF) - _objectType = OBJTYPE_OM_SWITCH_ON; - } - else { - currentItem = this; - } - - _objectState = OS_MOUSEOVER; - redrawFlag = true; - - } else { - currentItem = NULL; - _objectState = OS_MOUSEOVER; - redrawFlag = true; - handledFlag = false; - } - break; - - case MEVENT_MOVE: - if (isInside(x, y)) { - currentItem = this; - if (_objectState != OS_MOUSEOVER) { - _objectState = OS_MOUSEOVER; - redrawFlag = true; - } - } - else { - currentItem = NULL; - if (_objectState != OS_NORMAL) { - _objectState = OS_NORMAL; - redrawFlag = true; - handledFlag = false; - } - } - break; - - case MEVENT_LEFT_HOLD: - case MEVENT_DOUBLECLICK_HOLD: - break; - - default: - break; - } - - //see if we need to redraw the button - if (redrawFlag) { - onRefresh(); - - // TODO: There may be a more efficient mechanism than refreshing the entire screen - // when a menu object refreshes itself - if (parent()->screenFlags().visible) - _vm->_viewManager->refreshAll(); - } - - // If a callback is flagged, then handle it - - if (callbackFlag) - onExecute(); - - return handledFlag; -} - -void MenuButton::onRefresh() { - M4Sprite *sprite = NULL; - SpriteAsset &sprites = *parent()->sprites(); - - // Switch handling for the various button types - switch (_objectType) { - case OBJTYPE_BUTTON: - sprite = sprites[GM_BUTTON_GREYED + _objectState]; - break; - - case OBJTYPE_OM_SWITCH_ON: - switch (_objectState) { - case OS_MOUSEOVER: - sprite = sprites[MENU_SS_SWITCH_ON_MOUSEOVER]; - break; - case OS_PRESSED: - sprite = sprites[MENU_SS_SWITCH_ON_PRESSED]; - break; - default: - sprite = sprites[MENU_SS_SWITCH_ON_NORMAL]; - break; - } - break; - - case OBJTYPE_OM_SWITCH_OFF: - switch (_objectState) { - case OS_MOUSEOVER: - sprite = sprites[MENU_SS_SWITCH_OFF_MOUSEOVER]; - break; - case OS_PRESSED: - sprite = sprites[MENU_SS_SWITCH_OFF_PRESSED]; - break; - default: - sprite = sprites[MENU_SS_SWITCH_OFF_NORMAL]; - break; - } - break; - - case OBJTYPE_OM_DONE: - sprite = sprites[OM_DONE_BTN_GREYED + _objectState]; - break; - - case OBJTYPE_OM_CANCEL: - sprite = (_objectState == OS_GREYED) ? sprites[OM_CANCEL_BTN_NORMAL] : - sprites[OM_CANCEL_BTN_NORMAL + _objectState - 1]; - break; - - case OBJTYPE_SL_SAVE: - sprite = sprites[SL_SAVE_BTN_GREYED + _objectState]; - break; - - case OBJTYPE_SL_LOAD: - sprite = sprites[SL_LOAD_BTN_GREYED + _objectState]; - break; - - case OBJTYPE_SL_CANCEL: - sprite = (_objectState == OS_GREYED) ? sprites[SL_CANCEL_BTN_NORMAL] : - sprites[SL_CANCEL_BTN_NORMAL + _objectState - 1]; - break; - - case OBJTYPE_SL_TEXT: - switch (_objectState) { - case OS_MOUSEOVER: - _vm->_font->current()->setColors(TEXT_COLOR_MOUSEOVER_SHADOW, TEXT_COLOR_MOUSEOVER_FOREGROUND, - TEXT_COLOR_MOUSEOVER_HILIGHT); - sprite = sprites[SL_LINE_MOUSEOVER]; - break; - - case OS_PRESSED: - _vm->_font->current()->setColors(TEXT_COLOR_PRESSED_SHADOW, TEXT_COLOR_PRESSED_FOREGROUND, - TEXT_COLOR_PRESSED_HILIGHT); - sprite = sprites[SL_LINE_PRESSED]; - break; - - case OS_GREYED: - _vm->_font->current()->setColors(TEXT_COLOR_GREYED_SHADOW, TEXT_COLOR_GREYED_FOREGROUND, - TEXT_COLOR_GREYED_HILIGHT); - sprite = sprites[SL_LINE_NORMAL]; - break; - - default: - case OS_NORMAL: - _vm->_font->current()->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND, - TEXT_COLOR_NORMAL_HILIGHT); - sprite = sprites[SL_LINE_NORMAL]; - break; - } - break; - - default: - error("Unknown object type"); - break; - } - - // If no sprite object was set, then exit without doing anything - if (!sprite) - return; - - // Draw the button - if (_transparent) { - // Transparent button, so restore original background - if (!_background) - return; - else - _background->copyTo(parent(), _bounds.left, _bounds.top); - } - - sprite->copyTo(parent(), _bounds.left, _bounds.top, 0); -} - -//-------------------------------------------------------------------------- -// MenuHorizSlider class -// -// Defines a horizontal slider that allows selection of a percentage -//-------------------------------------------------------------------------- - -MenuHorizSlider::MenuHorizSlider(DialogView *owner, int objectId, int xs, int ys, - int width, int height, int initialPercentage, Callback callbackFn, bool transparent): - MenuObject(owner, objectId, xs, ys, width, height, false, transparent) { - - _objectType = OBJTYPE_SLIDER; - _callback = callbackFn; - - SpriteAsset &sprites = *owner->sprites(); - _sliderState = HSLIDER_THUMB_NORMAL; - _thumbSize.x = sprites[OM_SLIDER_BTN_NORMAL]->width(); - _thumbSize.y = sprites[OM_SLIDER_BTN_NORMAL]->height(); - _maxThumbX = width - _thumbSize.x; - _percent = MAX(MIN(initialPercentage, 100), 0); - _thumbX = initialPercentage * _maxThumbX / 100; -} - -void MenuHorizSlider::onRefresh() { - // If the slider is transparent, first copy in the background - if (_transparent) { - // Transparent button - if (!_background) - return; - - _background->copyTo(parent(), _bounds.left, _bounds.top, 0); - } - - // Get the thumb sprite for the slider - SpriteAsset &sprites = *parent()->sprites(); - M4Sprite *sprite = sprites[OM_SLIDER_BTN_NORMAL + _sliderState]; - assert(sprite); - - // Fill in the area to the left of the thumbnail - if (_thumbX > 2) { - Common::Rect leftBounds(_bounds.left + 3, _bounds.top + 9, _bounds.left + _thumbX, - _bounds.top + _thumbSize.y - 9); - parent()->fillRect(leftBounds, SLIDER_BAR_COLOR); - } - - // Draw the thumbnail - sprite->copyTo(parent(), _bounds.left + _thumbX, _bounds.top, 0); -} - -bool MenuHorizSlider::onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem) { - static bool movingFlag = false; - static int movingX = 0; - bool redrawFlag = false, handledFlag = false, callbackFlag = false; - - if (event == KEVENT_KEY) - return false; - - switch (event) { - case MEVENT_LEFT_CLICK: - case MEVENT_DOUBLECLICK: - if (isInside(x, y) && (x - _bounds.left >= _thumbX) && - (x - _bounds.left <= _thumbX + _thumbSize.x - 1)) { - // The thumbnail has been clicked - _sliderState = HSLIDER_THUMB_PRESSED; - movingFlag = true; - movingX = x; - currentItem = this; - redrawFlag = true; - } else { - currentItem = NULL; - _sliderState = HSLIDER_THUMB_NORMAL; - redrawFlag = true; - } - redrawFlag = true; - break; - - case MEVENT_LEFT_DRAG: - case MEVENT_DOUBLECLICK_DRAG: - if (!currentItem) - return true; - - if (movingFlag) { - if (x != movingX) { - if (x < movingX) - _thumbX -= MIN(_thumbX, movingX - x); - else - _thumbX += MIN(_maxThumbX - _thumbX, x - movingX); - _percent = _thumbX * 100 / _maxThumbX; - redrawFlag = callbackFlag = true; - } - movingX = CLIP(x, _bounds.left + _thumbX, - _bounds.left + _thumbX + _thumbSize.x - 1); - } else { - currentItem = NULL; - } - break; - - case MEVENT_LEFT_RELEASE: - case MEVENT_DOUBLECLICK_RELEASE: - if (!currentItem) - return true; - - movingFlag = false; - if (isInside(x, y) && (x - _bounds.left >= _thumbX) && - (x - _bounds.left <= _thumbX + _thumbSize.x - 1)) { - _sliderState = HSLIDER_THUMB_MOUSEOVER; - currentItem = this; - } else { - _sliderState = HSLIDER_THUMB_NORMAL; - currentItem = NULL; - } - - redrawFlag = true; - callbackFlag = true; - break; - - case MEVENT_MOVE: - if (isInside(x, y) && (x - _bounds.left >= _thumbX) && - (x - _bounds.left <= _thumbX + _thumbSize.x - 1)) { - if (_sliderState != HSLIDER_THUMB_MOUSEOVER) { - _sliderState = HSLIDER_THUMB_MOUSEOVER; - currentItem = this; - } - } else { - if (_sliderState != HSLIDER_THUMB_NORMAL) { - _sliderState = HSLIDER_THUMB_NORMAL; - currentItem = NULL; - handledFlag = false; - } - } - redrawFlag = true; - break; - - default: - break; - } - - if (redrawFlag) - onRefresh(); - - if (callbackFlag) - onExecute(); - - return handledFlag; -} - -//-------------------------------------------------------------------------- -// MenuVertSlider class -// -// Defines a vertical slider that's used in the save/load dialog -//-------------------------------------------------------------------------- - -MenuVertSlider::MenuVertSlider(DialogView *owner, int objectId, int xs, int ys, - int width, int height, int initialPercentage, Callback callbackFn, bool transparent): - MenuObject(owner, objectId, xs, ys, width, height, false, transparent) { - - _objectType = OBJTYPE_SLIDER; - _callback = callbackFn; - - SpriteAsset &sprites = *owner->sprites(); - _sliderState = VSLIDER_NONE; - _thumbSize.x = sprites[SL_SLIDER_BTN_NORMAL]->width(); - _thumbSize.y = sprites[SL_SLIDER_BTN_NORMAL]->height(); - _minThumbY = sprites[SL_UP_BTN_NORMAL]->height() + 1; - _maxThumbY = sprites[SL_UP_BTN_NORMAL]->height() + sprites[SL_SCROLLBAR]->height() - - sprites[SL_SLIDER_BTN_NORMAL]->height() - 1; - - _percent = MAX(MIN(initialPercentage, 100), 0); - _thumbY = _minThumbY + ((_percent * (_maxThumbY - _minThumbY)) / 100); -} - -MenuVertSliderState MenuVertSlider::getSliderArea(int y) { - if (y < _minThumbY) - return VSLIDER_UP; - else if (y < _thumbY) - return VSLIDER_PAGE_UP; - else if (y < _thumbY + _thumbSize.y) - return VSLIDER_THUMBNAIL; - else if (y < _maxThumbY + _thumbSize.y) - return VSLIDER_PAGE_DOWN; - else - return VSLIDER_DOWN; -} - -void MenuVertSlider::onRefresh() { - // If the slider is transparent, first copy in the background - if (_transparent) { - // Transparent button - if (!_background) - return; - - _background->copyTo(parent(), _bounds.left, _bounds.top, 0); - } - - // Get the various needed sprites - SpriteAsset &sprites = *parent()->sprites(); - M4Sprite *barSprite = sprites[SL_SCROLLBAR]; - M4Sprite *thumbSprite = sprites[SL_SLIDER_BTN_NORMAL]; - M4Sprite *upSprite = sprites[SL_UP_BTN_NORMAL]; - M4Sprite *downSprite = sprites[SL_DOWN_BTN_NORMAL]; - - if (_objectState == OS_GREYED) { - upSprite = sprites[SL_UP_BTN_GREYED]; - downSprite = sprites[SL_DOWN_BTN_GREYED]; - thumbSprite = NULL; - - } else if (_objectState == OS_MOUSEOVER) { - if (_sliderState == VSLIDER_UP) - upSprite = sprites[SL_UP_BTN_MOUSEOVER]; - else if (_sliderState == VSLIDER_THUMBNAIL) - thumbSprite = sprites[SL_SLIDER_BTN_MOUSEOVER]; - else if (_sliderState == VSLIDER_DOWN) - downSprite = sprites[SL_DOWN_BTN_MOUSEOVER]; - } - else if (_objectState == OS_PRESSED) { - if (_sliderState == VSLIDER_UP) - upSprite = sprites[SL_UP_BTN_PRESSED]; - else if (_sliderState == VSLIDER_THUMBNAIL) - thumbSprite = sprites[SL_SLIDER_BTN_PRESSED]; - else if (_sliderState == VSLIDER_DOWN) - downSprite = sprites[SL_DOWN_BTN_PRESSED]; - } - - // Draw the sprites - upSprite->copyTo(parent(), _bounds.left, _bounds.top, 0); - barSprite->copyTo(parent(), _bounds.left, _bounds.top + upSprite->height(), 0); - downSprite->copyTo(parent(), _bounds.left, _bounds.top + upSprite->height() + barSprite->height(), 0); - if (thumbSprite) - thumbSprite->copyTo(parent(), _bounds.left, _bounds.top + _thumbY, 0); -} - -bool MenuVertSlider::onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem) { - static bool movingFlag = false; - static int movingY = 0; - static uint32 callbackTime; - MenuVertSliderState tempState; - int delta; - uint32 currentTime = g_system->getMillis(); - bool redrawFlag = false; - bool handledFlag = true; - bool callbackFlag = false; - - if (event == KEVENT_KEY) - return false; - - if (_objectState == OS_GREYED) { - currentItem = NULL; - return false; - } - - switch (event) { - case MEVENT_LEFT_CLICK: - case MEVENT_DOUBLECLICK: - if (isInside(x, y)) { - currentItem = this; - tempState = getSliderArea(y - _bounds.top); - if (tempState == VSLIDER_THUMBNAIL) { - movingFlag = true; - movingY = y; - } - if ((tempState == VSLIDER_PAGE_UP) || (tempState == VSLIDER_PAGE_DOWN)) { - _sliderState = tempState; - setState(OS_NORMAL); - } else { - _sliderState = tempState; - setState(OS_PRESSED); - redrawFlag = true; - } - callbackFlag = true; - } else { - currentItem = NULL; - setState(OS_NORMAL); - redrawFlag = true; - } - break; - - case MEVENT_LEFT_DRAG: - case MEVENT_DOUBLECLICK_DRAG: - if (!currentItem) - return true; - - if (movingFlag) { - if (y < movingY) { - delta = MIN(_thumbY - _minThumbY, movingY - y); - if (delta > 0) { - _thumbY -= delta; - _percent = ((_thumbY - _minThumbY) * 100) / (_maxThumbY - _minThumbY); - redrawFlag = true; - callbackFlag = true; - } - } - else if (y > movingY) { - delta = MIN(_maxThumbY - _thumbY, y - movingY); - if (delta > 0) { - _thumbY += delta; - _percent = ((_thumbY - _minThumbY) * 100) / (_maxThumbY - _minThumbY); - redrawFlag = true; - callbackFlag = true; - } - } - movingY = y; - - if (movingY < (_thumbY + _bounds.top)) - movingY = _thumbY + _bounds.top; - else if (movingY > (_bounds.top + _thumbY + _thumbSize.y - 1)) - movingY = _bounds.top + _thumbY + _thumbSize.y - 1; - - } else { - if (isInside(x, y)) { - tempState = getSliderArea(y - _bounds.top); - if (_sliderState == tempState) { - if ((tempState != VSLIDER_PAGE_UP) && (tempState != VSLIDER_PAGE_DOWN) && - (_objectState != OS_PRESSED)) { - _sliderState = tempState; - setState(OS_PRESSED); - redrawFlag = true; - } - if (currentTime - callbackTime > 100) - callbackFlag = true; - - } else { - if (_objectState != OS_MOUSEOVER) - setState(OS_MOUSEOVER); - redrawFlag = true; - } - callbackFlag = true; - - } else { - if (_objectState != OS_MOUSEOVER) { - setState(OS_MOUSEOVER); - redrawFlag = true; - } - } - } - break; - - case MEVENT_LEFT_RELEASE: - case MEVENT_DOUBLECLICK_RELEASE: - movingFlag = false; - if (isInside(x, y)) { - tempState = getSliderArea(y - _bounds.top); - if ((tempState == VSLIDER_PAGE_UP) || (tempState == VSLIDER_PAGE_DOWN)) - setState(OS_NORMAL); - else { - setState(OS_MOUSEOVER); - currentItem = this; - } - } else { - setState(OS_NORMAL); - currentItem = NULL; - } - - redrawFlag = true; - if (parent()->getMenuType() == LOAD_MENU) - updateThumbnails(); - break; - - case MEVENT_MOVE: - if (isInside(x, y)) { - currentItem = this; - tempState = getSliderArea(y - _bounds.top); - if (_sliderState != tempState) { - if ((tempState == VSLIDER_PAGE_UP) || (tempState == VSLIDER_PAGE_DOWN)) - _objectState = OS_NORMAL; - else { - _sliderState = tempState; - _objectState = OS_MOUSEOVER; - } - redrawFlag = true; - } - } else { - currentItem = NULL; - - if (_objectState != OS_NORMAL) { - _objectState = OS_NORMAL; - redrawFlag = true; - handledFlag = false; - } - } - break; - - case MEVENT_LEFT_HOLD: - case MEVENT_DOUBLECLICK_HOLD: - if (!currentItem) - return true; - - if (isInside(x, y)) { - tempState = getSliderArea(y - _bounds.top); - - if (_sliderState == tempState) { - if (currentTime - callbackTime > 100) - callbackFlag = true; - } - } - break; - - default: - break; - } - - if (redrawFlag) - onRefresh(); - - if (callbackFlag) { - callbackTime = currentTime; - onExecute(); - } - - return handledFlag; -} - -void MenuVertSlider::setPercentage(int value) { - _percent = value; - _thumbY = _minThumbY + ((_percent * (_maxThumbY - _minThumbY)) / 100); - onRefresh(); -} - -//-------------------------------------------------------------------------- -// MenuMessage class -// -// Defines a message menu object -//-------------------------------------------------------------------------- - -MenuMessage::MenuMessage(DialogView *owner, int objectId, int xs, int ys, int width, int height, - bool transparent): - MenuObject(owner, objectId, xs, ys, width, height, false, transparent) { -} - -void MenuMessage::onRefresh() { - SpriteAsset &sprites = *parent()->sprites(); - M4Surface *sprite = NULL; - - // Get the correct sprite to use - switch (_objectId) { - case SLTAG_SAVELOAD_LABEL: - sprite = (parent()->getMenuType() == SAVE_MENU) ? sprites[SL_SAVE_LABEL] : - sprites[SL_LOAD_LABEL]; - break; - } - assert(sprite); - - // Draw the sprite - if (_transparent) { - // Transparent button - if (!_background) - return; - - // Restore original background and then do a transparent copy of the sprite - _background->copyTo(parent(), _bounds.left, _bounds.top); - } - - sprite->copyTo(parent(), _bounds.left, _bounds.top, 0); -} - -//-------------------------------------------------------------------------- -// MenuImage class -// -// Defines a menu item that displays a given surface -//-------------------------------------------------------------------------- - -MenuImage::MenuImage(DialogView *owner, int objectId, int xs, int ys, int width, int height, - M4Surface *image, bool transparent): - MenuObject(owner, objectId, xs, ys, width, height, false, transparent) { - - _sprite = image; -} - -void MenuImage::onRefresh() { - if (!_sprite) - return; - - // Draw the sprite - if (_transparent) { - // Transparent button - if (!_background) - return; - - // Restore original background and then do a transparent copy of the sprite - _background->copyTo(parent(), _bounds.left, _bounds.top); - } - - _sprite->copyTo(parent(), _bounds.left + (_bounds.width() - _sprite->width()) / 2, - _bounds.top + (_bounds.height() - _sprite->height()) / 2, 0); -} - -//-------------------------------------------------------------------------- -// MenuSaveLoadText class -// -// Defines a save/load dialog text entry -//-------------------------------------------------------------------------- - -MenuSaveLoadText::MenuSaveLoadText(DialogView *owner, int textId, int xs, int ys, - int width, int height, Callback callbackFn, bool greyed, bool transparent, - bool loadFlag, const char *displayText, int displayValue): - MenuButton(owner, textId, xs, ys, width, height, callbackFn, greyed, transparent, OBJTYPE_SL_TEXT) { - - _loadFlag = loadFlag; - _displayText = displayText; - _displayValue = displayValue; - _index = textId - SLTAG_SLOTS_START; - _visible = true; -} - -void MenuSaveLoadText::onRefresh() { - if (!_visible) return; - _vm->_font->setFont(FONT_MENU); - MenuButton::onRefresh(); - - if ((_objectType == OBJTYPE_SL_TEXT) && (_displayText != NULL)) { - int xp = _bounds.left + 4; - if (_displayValue != 0) { - char tempBuffer[5]; - sprintf(tempBuffer, "%02d", _displayValue); - _vm->_font->current()->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1); - xp = _bounds.left + 26; - } - - _vm->_font->current()->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1); - } -} - -bool MenuSaveLoadText::onEvent(M4::M4EventType event, int32 param, int x, int y, M4::MenuObject *¤tItem) { - if (!_visible) return false; - bool handledFlag = MenuButton::onEvent(event, param, x, y, currentItem); - - // Further handling will only be done when in load mode and a slot hasn't been selected - if (!_loadFlag || (parent()->_selectedSlot != -1)) - return handledFlag; - - // Only handling for certain event types - if ((event != MEVENT_MOVE) && (event != MEVENT_LEFT_DRAG) && - (event != MEVENT_LEFT_RELEASE) && (event != MEVENT_DOUBLECLICK_DRAG) && - (event != MEVENT_DOUBLECLICK_RELEASE)) - return handledFlag; - - MenuImage *thumbnail = (MenuImage *) parent()->getItem(SLTAG_THUMBNAIL); - - // Check whether the cursor is over the button - if ((_objectState == OS_MOUSEOVER) || (_objectState == OS_PRESSED)) { - if (_index != parent()->_highlightedSlot) { - // Selected slot has changed - if (parent()->_savegameThumbnail != NULL) - delete parent()->_savegameThumbnail; - - parent()->_highlightedSlot = _index; - parent()->_savegameThumbnail = _vm->_saveLoad->getThumbnail(_index + 1); - thumbnail->setSprite(parent()->_savegameThumbnail); - } - - } else { - // If the mouse has moved outside the area of all the save slots, then the - // thumbnail needs to be removed - - Common::Rect slotArea(50, 256, 288, 377); - if (isInside(x, y) || !slotArea.contains(x, y)) { - if (parent()->_savegameThumbnail) { - delete parent()->_savegameThumbnail; - parent()->_savegameThumbnail = NULL; - } - - thumbnail->setSprite(parent()->sprites()->getFrame(SL_EMPTY_THUMBNAIL)); - parent()->_highlightedSlot = -1; - } - } - - return handledFlag; -} - -void MenuSaveLoadText::setVisible(bool value) { - _visible = value; - parent()->refresh(_bounds); -} - -//-------------------------------------------------------------------------- -// MenuTextField class -// -// Defines a text entry field -//-------------------------------------------------------------------------- - -MenuTextField::MenuTextField(DialogView *owner, int fieldId, int xs, int ys, int width, - int height, bool greyed, Callback callbackFn, - const char *displayText, int displayValue, bool transparent): - MenuObject(owner, fieldId, xs, ys, width, height, greyed, transparent) { - - _displayValue = displayValue; - _callback = callbackFn; - _pixelWidth = width - 27; - if (displayText) { - strcpy(_displayText, displayText); - _promptEnd = &_displayText[strlen(_displayText)]; - } else { - _displayText[0] = '\0'; - _promptEnd = &_displayText[0]; - } - _cursor = _promptEnd; -} - -void MenuTextField::onRefresh() { - bool focused = _objectState != OS_GREYED; - - // Get the thumb sprite for the slider - SpriteAsset &sprites = *parent()->sprites(); - M4Sprite *sprite = sprites[SL_LINE_NORMAL + OS_MOUSEOVER - 1]; - - // If the slider is transparent, first copy in the background - if (_transparent) { - // Transparent button - if (!_background) - return; - - _background->copyTo(parent(), _bounds.left, _bounds.top, 0); - } - - // Draw the sprite - sprite->copyTo(parent(), _bounds.left, _bounds.top, 0); - - // Draw the text - - _vm->_font->setFont(FONT_MENU); - _vm->_font->current()->setColors(TEXT_COLOR_NORMAL_SHADOW, TEXT_COLOR_NORMAL_FOREGROUND, - TEXT_COLOR_NORMAL_HILIGHT); - int xp = _bounds.left + 4; - - if (_displayValue != 0) { - char tempBuffer[5]; - sprintf(tempBuffer, "%02d", _displayValue); - _vm->_font->current()->writeString(_parent, tempBuffer, xp, _bounds.top + 1, 0, -1); - xp = _bounds.left + 26; - } - - _vm->_font->current()->writeString(_parent, _displayText, xp, _bounds.top + 1, 0, -1); - - if (focused) { - // Draw in the cursor - - if (_cursor) { - // Get the width of the string up to the cursor position - char tempCh = *_cursor; - *_cursor = '\0'; - int stringWidth = _vm->_font->current()->getWidth(_displayText); - *_cursor = tempCh; - - parent()->setColor(TEXT_COLOR_MOUSEOVER_FOREGROUND); - parent()->vLine(xp + stringWidth + 1, _bounds.top + 1, _bounds.top + 12); - } - } -} - -bool MenuTextField::onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem) { - char tempStr[MAX_SAVEGAME_NAME]; - int tempLen; - char *tempP; - bool handledFlag = false, redrawFlag = false, callbackFlag = false; - - if (_objectState == OS_GREYED) - return false; - - switch (event) { - case MEVENT_LEFT_CLICK: - case MEVENT_DOUBLECLICK: - parent()->_deleteSaveDesc = false; - if (isInside(x, y)) - currentItem = this; - break; - - case MEVENT_LEFT_RELEASE: - case MEVENT_DOUBLECLICK_RELEASE: - if (!currentItem) - return true; - currentItem = NULL; - - if (isInside(x, y)) { - if (_objectState == OS_MOUSEOVER) { - tempLen = strlen(_displayText); - if (tempLen > 0) { - strcpy(tempStr, _displayText); - tempP = &tempStr[tempLen]; - _vm->_font->setFont(FONT_MENU); - - tempLen = _vm->_font->current()->getWidth(tempStr); - while ((tempP != &tempStr[0]) && (tempLen > x - _bounds.left - 26)) { - *--tempP = '\0'; - tempLen = _vm->_font->current()->getWidth(tempStr); - } - - _cursor = &_displayText[tempP - &tempStr[0]]; - redrawFlag = true; - } - } else if (event == MEVENT_DOUBLECLICK_RELEASE) { - callbackFlag = true; - } - } - break; - - case KEVENT_KEY: - switch (param) { - case Common::KEYCODE_RETURN: - case Common::KEYCODE_KP_ENTER: - parent()->_deleteSaveDesc = false; - callbackFlag = true; - break; - break; - - case Common::KEYCODE_HOME: - parent()->_deleteSaveDesc = false; - _cursor = &_displayText[0]; - redrawFlag = true; - break; - - case Common::KEYCODE_END: - parent()->_deleteSaveDesc = false; - _cursor = _promptEnd; - redrawFlag = true; - break; - - case Common::KEYCODE_LEFT: - case Common::KEYCODE_KP4: - parent()->_deleteSaveDesc = false; - if (_cursor > &_displayText[0]) { - --_cursor; - redrawFlag = true; - } - break; - - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_KP6: - parent()->_deleteSaveDesc = false; - if (_cursor < _promptEnd) { - ++_cursor; - redrawFlag = true; - } - break; - - case Common::KEYCODE_DELETE: - if (parent()->_deleteSaveDesc) { - _displayText[0] = '\0'; - _promptEnd = &_displayText[0]; - _cursor = _promptEnd; - redrawFlag = true; - } else if (_cursor < _promptEnd) { - strcpy(tempStr, _cursor + 1); - strcpy(_cursor, tempStr); - --_promptEnd; - redrawFlag = true; - } - break; - - case Common::KEYCODE_BACKSPACE: - parent()->_deleteSaveDesc = false; - if (_cursor > &_displayText[0]) { - strcpy(tempStr, _cursor); - --_promptEnd; - --_cursor; - strcpy(_cursor, tempStr); - redrawFlag = true; - } - break; - - default: - parent()->_deleteSaveDesc = false; - _vm->_font->setFont(FONT_MENU); - - tempLen = _vm->_font->current()->getWidth(_displayText); - if ((strlen(_displayText) < MAX_SAVEGAME_NAME - 1) && - (tempLen < _pixelWidth - 12) && (param >= 32) && (param <= 127)) { - - // Valid displayable character - if (_cursor < _promptEnd) { - strcpy(tempStr, _cursor); - sprintf(_cursor, "%c%s", (char)param, tempStr); - } else { - *_cursor = (char)param; - *(_cursor + 1) = '\0'; - } - ++_cursor; - ++_promptEnd; - - redrawFlag = true; - } - break; - } - break; - - default: - break; - } - - if (redrawFlag) - onRefresh(); - - if (callbackFlag) - onExecute(); - - return handledFlag; -} - -//-------------------------------------------------------------------------- - - -GUITextField::GUITextField(View *owner, const Common::Rect &bounds): GUIRect(owner, bounds, 0) { -} - -void GUITextField::onRefresh() { - _parent->fillRect(_bounds, _vm->_palette->BLACK); - _vm->_font->current()->setColors(3, 3, 3); - _vm->_font->setFont(FONT_INTERFACE); - _vm->_font->current()->writeString(_parent, _text.c_str(), _bounds.left, _bounds.top, 0, 1); -} - -//-------------------------------------------------------------------------- - -GUIButton::GUIButton(View *owner, const Common::Rect &bounds, int tag, - M4Surface *normalSprite, M4Surface *mouseOverSprite, M4Surface *pressedSprite): - GUIRect(owner, bounds, tag) { - - _normalSprite = normalSprite; - _mouseOverSprite = mouseOverSprite; - _pressedSprite = pressedSprite; - _visible = true; - _tracking = false; -} - -void GUIButton::onRefresh() { - _parent->fillRect(_bounds, _vm->_palette->BLACK); - - if (_visible) { - switch (_buttonState) { - case BUTTON_MOUSEOVER: - _mouseOverSprite->copyTo(_parent, _bounds.left, _bounds.top, 0); - break; - case BUTTON_PRESSED: - _pressedSprite->copyTo(_parent, _bounds.left, _bounds.top, 0); - break; - default: - _normalSprite->copyTo(_parent, _bounds.left, _bounds.top, 0); - break; - } - } -} - -bool GUIButton::onEvent(M4EventType eventType, int32 param, int x, int y, GUIObject *¤tItem) { - bool result = false; - bool isPressed = (eventType == MEVENT_LEFT_CLICK) || (eventType == MEVENT_LEFT_HOLD) || - (eventType == MEVENT_LEFT_DRAG); - bool isOver = isInside(x, y); - GUIButtonState oldState = _buttonState; - - if (isOver) { - if (isPressed) { - // Button is pressed - if (!_tracking) { - _tracking = true; - _buttonState = BUTTON_PRESSED; - } - - if (_vm->isM4()) - _m4Vm->globals()->invSuppressClickSound = false; - } else { - // Button isn't pressed - if (_tracking) - result = true; - else { - result = false; - _buttonState = BUTTON_MOUSEOVER; - _tracking = false; - } - } - } else { - _tracking = false; - _buttonState = BUTTON_NORMAL; - } - - if (oldState != _buttonState) - onRefresh(); - - return result; -} - -} // End of namespace M4 diff --git a/engines/m4/gui.h b/engines/m4/gui.h deleted file mode 100644 index 2b673d624c..0000000000 --- a/engines/m4/gui.h +++ /dev/null @@ -1,453 +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. - * - */ - -#ifndef M4_GUI_H -#define M4_GUI_H - -#include "common/list.h" -#include "common/rect.h" - -#include "m4/viewmgr.h" -#include "m4/events.h" -#include "m4/globals.h" -#include "m4/graphics.h" -#include "m4/saveload.h" -#include "m4/sprite.h" -#include "m4/assets.h" - -namespace M4 { - -class GUIObject; -class MenuObject; -class GUIObjectButton; -class SpriteAsset; -class View; - -enum MenuType {GAME_MENU, OPTIONS_MENU, SAVE_MENU, LOAD_MENU, MAIN_MENU}; - -enum { - BTNID_QUIT = 1, - BTNID_OPTIONS = 2, - BTNID_RESUME = 3, - BTNID_SAVE = 4, - BTNID_LOAD = 5, - BTNID_MAIN = 6, - - OPTIONID_DONE = 1, - OPTIONID_CANCEL = 2, - OPTIONID_HSLIDER_DIGI = 3, - OPTIONID_HSLIDER_MIDI = 4, - - SAVELOADID_SAVE = 1, - SAVELOADID_CANCELSAVE = 2, - SAVELOADID_LOAD = 3, - SAVELOADID_CANCELLOAD = 4, - - SLTAG_SAVELOAD = 100, - SLTAG_SAVELOAD_LABEL = 101, - SLTAG_CANCEL = 102, - SLTAG_VSLIDER = 103, - SLTAG_THUMBNAIL = 104, - - SLTAG_SLOTS_START = 1001, - SLTAG_TEXTFIELD = 2000 -}; - -enum ObjectType { - OBJTYPE_BUTTON, - - OBJTYPE_SLIDER, - OBJTYPE_OM_SWITCH_ON, - OBJTYPE_OM_SWITCH_OFF, - OBJTYPE_OM_DONE, - OBJTYPE_OM_CANCEL, - - OBJTYPE_SL_SAVE, - OBJTYPE_SL_LOAD, - OBJTYPE_SL_CANCEL, - OBJTYPE_SL_TEXT -}; - -enum GameMenuSpriteType { - GM_DIALOG_BOX, - - GM_BUTTON_GREYED, - GM_BUTTON_NORMAL, - GM_BUTTON_MOUSEOVER, - GM_BUTTON_PRESSED -}; - -enum OptionMenuSpriteType { - OM_DIALOG_BOX, - - OM_SLIDER_BTN_NORMAL, - OM_SLIDER_BTN_MOUSEOVER, - OM_SLIDER_BTN_PRESSED, - OM_SLIDER_BAR, - OM_DONE_BTN_GREYED, - OM_DONE_BTN_NORMAL, - OM_DONE_BTN_MOUSEOVER, - OM_DONE_BTN_PRESSED, - OM_CANCEL_BTN_NORMAL, - OM_CANCEL_BTN_MOUSEOVER, - OM_CANCEL_BTN_PRESSED -}; - - -enum SaveLoadSpriteType { - SL_DIALOG_BOX, - SL_EMPTY_THUMBNAIL, - - SL_SAVE_BTN_GREYED, - SL_SAVE_BTN_NORMAL, - SL_SAVE_BTN_MOUSEOVER, - SL_SAVE_BTN_PRESSED, - - SL_LOAD_BTN_GREYED, - SL_LOAD_BTN_NORMAL, - SL_LOAD_BTN_MOUSEOVER, - SL_LOAD_BTN_PRESSED, - - SL_CANCEL_BTN_NORMAL, - SL_CANCEL_BTN_MOUSEOVER, - SL_CANCEL_BTN_PRESSED, - - SL_UP_BTN_GREYED, - SL_UP_BTN_NORMAL, - SL_UP_BTN_MOUSEOVER, - SL_UP_BTN_PRESSED, - - SL_DOWN_BTN_GREYED, - SL_DOWN_BTN_NORMAL, - SL_DOWN_BTN_MOUSEOVER, - SL_DOWN_BTN_PRESSED, - - SL_SAVE_LABEL, - SL_LOAD_LABEL, - - SL_SLIDER_BTN_NORMAL, - SL_SLIDER_BTN_MOUSEOVER, - SL_SLIDER_BTN_PRESSED, - - SL_LINE_NORMAL, - SL_LINE_MOUSEOVER, - SL_LINE_PRESSED, - - SL_SCROLLBAR -}; - -enum TextColors { - TEXT_COLOR_NORMAL = 1, - TEXT_COLOR_GREYED = 1, - TEXT_COLOR_MOUSEOVER = 2, - TEXT_COLOR_PRESSED = 2, - - TEXT_COLOR_GREYED_HILIGHT = 236, - TEXT_COLOR_GREYED_FOREGROUND = 131, - TEXT_COLOR_GREYED_SHADOW = 186, - - TEXT_COLOR_NORMAL_HILIGHT = 129, - TEXT_COLOR_NORMAL_FOREGROUND = 130, - TEXT_COLOR_NORMAL_SHADOW = 236, - - TEXT_COLOR_MOUSEOVER_HILIGHT = 129, - TEXT_COLOR_MOUSEOVER_FOREGROUND = 130, - TEXT_COLOR_MOUSEOVER_SHADOW = 236, - - TEXT_COLOR_PRESSED_HILIGHT = 236, - TEXT_COLOR_PRESSED_FOREGROUND = 130, - TEXT_COLOR_PRESSED_SHADOW = 129 -}; - -#define MENU_SS_FIELD_NORMAL 5 -#define MENU_SS_FIELD_MOUSEOVER 6 - -#define MENU_SS_H_SLIDER_NORMAL 5 -#define MENU_SS_H_SLIDER_MOUSE_OVER 6 -#define MENU_SS_H_SLIDER_PRESSED 7 - -#define MENU_SS_SWITCH_ON_NORMAL 8 -#define MENU_SS_SWITCH_ON_MOUSEOVER 9 -#define MENU_SS_SWITCH_ON_PRESSED 13 - -#define MENU_SS_SWITCH_OFF_PRESSED 10 -#define MENU_SS_SWITCH_OFF_NORMAL 11 -#define MENU_SS_SWITCH_OFF_MOUSEOVER 12 - -#define MENU_GUI "gui menu" -#define MENU_GAME "gamemenu" -#define MENU_OPTIONS "opmenu" -#define MENU_ERROR "errmenu" -#define MENU_SAVELOAD "slmenu" -#define MENU_BURGMAIN "903menu" -#define MENU_BURGDEMOMAIN "901menu" - -#define SL_NUM_VISIBLE_SLOTS 8 -#define SL_THUMBNAIL_WIDTH 215 -#define SL_THUMBNAIL_HEIGHT 162 - -enum MenuObjectState {OS_GREYED = 0, OS_NORMAL = 1, OS_MOUSEOVER = 2, OS_PRESSED = 3}; - -class DialogView : public View { -public: - DialogView(MadsM4Engine *Vm, const Common::Rect &viewBounds, bool transparent = false): - View(Vm, viewBounds, transparent) {} - DialogView(MadsM4Engine *Vm, int x = 0, int y = 0, bool transparent = false): - View(Vm, x, y, transparent) {} - - MadsM4Engine *vm() { return _vm; } - virtual SpriteAsset *sprites() = 0; - virtual MenuType getMenuType() = 0; - virtual MenuObject *getItem(int objectId) { return NULL; } - virtual void refresh(const Common::Rect &areaRect) {} - virtual void close(); - - int _topSaveSlotIndex, _selectedSlot; - int _highlightedSlot; - bool _deleteSaveDesc; - M4Surface *_savegameThumbnail; -}; - -class GUIObject { -protected: - View *_parent; - Common::Rect _bounds; - M4Surface *_background; -public: - GUIObject(View *owner, const Common::Rect &bounds); - virtual ~GUIObject() {} - - bool isInside(int x, int y) { return _bounds.contains(x, y); } - Common::Rect getBounds() const { return _bounds; } - - virtual void onRefresh() {} -}; - -class MenuObject : public GUIObject { -public: - typedef void (*Callback)(DialogView *view, MenuObject *item); -protected: - MenuObject::Callback _callback; - ObjectType _objectType; - MenuObjectState _objectState; - bool _transparent; - int _objectId; -public: - MenuObject(DialogView *owner, int objectId, int xs, int ys, int width, int height, - bool greyed = false, bool transparent = false); - ~MenuObject(); - - DialogView *parent() { return (DialogView *)_parent; } - MenuObjectState getState() { return _objectState; } - virtual void setState(MenuObjectState state) { - _objectState = state; - onRefresh(); - } - int getObjectId() { return _objectId; } - - void onExecute(); - virtual bool onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem) { return false; } -}; - -class MenuButton : public MenuObject { -public: - MenuButton(DialogView *owner, int buttonId, int xs, int ys, int width, int height, - Callback callbackFn = NULL, bool greyed = false, bool transparent = false, - ObjectType buttonType = OBJTYPE_BUTTON); - - void onRefresh(); - bool onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem); - bool getToggled() { return _objectType == OBJTYPE_OM_SWITCH_ON; } -}; - -enum MenuHorizSliderState {HSLIDER_THUMB_NORMAL = 0, HSLIDER_THUMB_MOUSEOVER = 1, HSLIDER_THUMB_PRESSED = 2}; -#define SLIDER_BAR_COLOR 129 - -class MenuHorizSlider : public MenuObject { -protected: - MenuHorizSliderState _sliderState; - Common::Point _thumbSize; - int _maxThumbX; - int _percent; - int _thumbX; -public: - MenuHorizSlider(DialogView *owner, int sliderId, int xs, int ys, int width, int height, - int initialPercentage, Callback callbackFn = NULL, bool transparent = false); - - void onRefresh(); - bool onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem); - int percent() { return _percent; } -}; - -enum MenuVertSliderState { - VSLIDER_NONE = 0x0000, - VSLIDER_UP = 0x0010, - VSLIDER_PAGE_UP = 0x0020, - VSLIDER_THUMBNAIL = 0x0030, - VSLIDER_PAGE_DOWN = 0x0040, - VSLIDER_DOWN = 0x0050 -}; - -class MenuVertSlider : public MenuObject { -protected: - MenuVertSliderState _sliderState; - Common::Point _thumbSize; - int _percent; - int _thumbY; - int _minThumbY; - int _maxThumbY; - - MenuVertSliderState getSliderArea(int y); - void updateThumbnails() {} -public: - MenuVertSlider(DialogView *owner, int sliderId, int xs, int ys, int width, int height, - int initialPercentage, Callback callbackFn = NULL, bool transparent = false); - - void onRefresh(); - bool onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem); - MenuVertSliderState sliderState() { return _sliderState; } - int percent() { return _percent; } - void setPercentage(int value); -}; - -class MenuMessage : public MenuObject { -public: - MenuMessage(DialogView *owner, int objectId, int x, int y, int w, int h, bool transparent = false); - - void onRefresh(); -}; - -class MenuImage : public MenuObject { -private: - M4Surface *_sprite; -public: - MenuImage(DialogView *owner, int objectId, int xs, int ys, int width, int height, - M4Surface *image, bool transparent = false); - - void onRefresh(); - const M4Surface *sprite() { return _sprite; } - void setSprite(M4Surface *v) { - _sprite = v; - onRefresh(); - } -}; - -class MenuSaveLoadText : public MenuButton { -private: - bool _loadFlag; - const char *_displayText; - int _displayValue; - int _index; - bool _visible; -public: - MenuSaveLoadText(DialogView *owner, int textId, int xs, int ys, int width, int height, - Callback callbackFn = NULL, bool greyed = false, bool transparent = false, - bool loadFlag = false, const char *displayText = NULL, int displayValue = 0); - - void onRefresh(); - bool onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem); - void setDisplay(int value, const char *text) { _displayValue = value; _displayText = text; } - int getIndex() { return _index; } - const char *getText() { return _displayText; } - bool getVisible() const { return _visible; } - void setVisible(bool value); -}; - -class MenuTextField : public MenuObject { -private: - int _displayValue; - char _displayText[MAX_SAVEGAME_NAME]; - int _pixelWidth; - char *_promptEnd; - char *_cursor; -public: - MenuTextField(DialogView *owner, int fieldId, int xs, int ys, int width, int height, - bool greyed, Callback callbackFn = NULL, const char *displayText = NULL, - int displayValue = 0, bool transparent = true); - - void onRefresh(); - bool onEvent(M4EventType event, int32 param, int x, int y, MenuObject *¤tItem); - - const char *getText() { return _displayText; } - int getDisplayValue() { return _displayValue; } - -}; - -class GUIRect : public GUIObject { -private: - int _tag; -public: - GUIRect(View *owner, const Common::Rect &bounds, int tag): GUIObject(owner, bounds) { _tag = tag; } - - virtual bool onEvent(M4EventType eventType, int32 param, int x, int y, GUIObject *¤tItem) { return false; } - int getTag() const { return _tag; } -}; - -enum GUIButtonState {BUTTON_NORMAL, BUTTON_MOUSEOVER, BUTTON_PRESSED}; - -class GUIButton : public GUIRect { -protected: - M4Surface *_normalSprite, *_mouseOverSprite, *_pressedSprite; - GUIButtonState _buttonState; - bool _visible; - bool _tracking; -public: - GUIButton(View *owner, const Common::Rect &bounds, int tag, - M4Surface *normalSprite, M4Surface *mouseOverSprite, M4Surface *pressedSprite); - - void onRefresh(); - bool onEvent(M4EventType eventType, int32 param, int x, int y, GUIObject *¤tItem); - GUIButtonState getState() const { return _buttonState; } -}; - -class GUITextField : public GUIRect { -private: - Common::String _text; -public: - GUITextField(View *owner, const Common::Rect &bounds); - void setText(const char *value) { - _text = value; - onRefresh(); - } - - void onRefresh(); -}; - - -class Dialogs { -public: - void keyMouseCollision() {} -}; - -class GameInterfaceView : public View { -public: - GameInterfaceView(MadsM4Engine *vm, const Common::Rect &rect): View(vm, rect) {} - ~GameInterfaceView() {} - - virtual void initialize() {} - virtual void setSelectedObject(int objectNumber) {} - virtual void addObjectToInventory(int objectNumber) {} -}; - -} - -#endif diff --git a/engines/m4/hotspot.cpp b/engines/m4/hotspot.cpp deleted file mode 100644 index a424d9fa23..0000000000 --- a/engines/m4/hotspot.cpp +++ /dev/null @@ -1,283 +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 "m4/m4.h" -#include "m4/events.h" -#include "m4/hotspot.h" -#include "gui/debugger.h" - -namespace M4 { - -/* - HotSpot -*/ - -HotSpot::HotSpot(int x1, int y1, int x2, int y2) : - _vocab(NULL), _verb(NULL), _prep(NULL), _sprite(NULL) { - - _rect.left = x1; - _rect.top = y1; - _rect.right = x2 + 1; - _rect.bottom = y2 + 1; - _active = true; - - _syntax = 0; - _cursor = 0; - _facing = 5; - _feetX = 32767; - _feetY = 32767; -} - -HotSpot::~HotSpot() { - free(_vocab); -} - -void HotSpot::setRect(int x1, int y1, int x2, int y2) { - _rect.left = x1; - _rect.top = y1; - _rect.right = x2 + 1; - _rect.bottom = y2 + 1; -} - -void HotSpot::setFeet(int x, int y) { - _feetX = x; - _feetY = y; -} - -void HotSpot::setVocab(const char *value) { - free(_vocab); - _vocab = strdup(value); -} - -void HotSpot::setVerb(const char *value) { - free(_verb); - _verb = strdup(value); -} - -void HotSpot::setPrep(const char *value) { - free(_prep); - _prep = strdup(value); -} - -void HotSpot::setSprite(const char *value) { - free(_sprite); - _sprite = strdup(value); -} - -Common::Rect HotSpot::getRect() const { - Common::Rect tempRect; - tempRect.left = _rect.left; - tempRect.top = _rect.top; - tempRect.right = _rect.right - 1; - tempRect.bottom = _rect.bottom - 1; - - return tempRect; -} - -/* - HotSpotList -*/ - -HotSpotList::HotSpotList() { -} - -HotSpotList::~HotSpotList() { - clear(); -} - -int HotSpotList::add(HotSpot *hotspot, bool head) { - if (head || _hotspots.size() == 0) { - _hotspots.insert_at(0, hotspot); - return 0; - } else { - int32 area = hotspot->area(); - int index = _hotspots.size(); - for (uint i = 0; i < _hotspots.size(); i++) { - if (area < _hotspots[i]->area()) { - index = i; - break; - } - } - _hotspots.insert_at(index, hotspot); - return index; - } -} - -void HotSpotList::remove(HotSpot *hotspot) { - unlinkItem(hotspot); - delete hotspot; //TODO: check this? -} - -void HotSpotList::unlinkItem(HotSpot *hotspot) { - uint index = 0; - while (index < _hotspots.size()) { - if (_hotspots[index] == hotspot) { - _hotspots.remove_at(index); - } else { - index++; - } - } -} - -void HotSpotList::clear() { - for (uint i = 0; i < _hotspots.size(); i++) - delete _hotspots[i]; - _hotspots.clear(); -} - -HotSpot *HotSpotList::findByXY(int x, int y) { - for (uint i = 0; i < _hotspots.size(); i++) { - if (_hotspots[i]->getActive() && _hotspots[i]->pointInside(x, y)) { - return _hotspots[i]; - } - } - return NULL; -} - -void HotSpotList::setActive(const char *name, bool active) { - for (uint i = 0; i < _hotspots.size(); i++) { - if (!scumm_stricmp(_hotspots[i]->_vocab, name)) { - _hotspots[i]->setActive(active); - } - } -} - -void HotSpotList::setActiveXY(const char *name, int x, int y, bool active) { - for (uint i = 0; i < _hotspots.size(); i++) { - if (_hotspots[i]->pointInside(x, y) && !scumm_stricmp(_hotspots[i]->_vocab, name)) { - _hotspots[i]->setActive(active); - } - } -} - -void HotSpotList::dump() { - _vm->_events->getConsole()->DebugPrintf("%d hotspots in the list\n", _hotspots.size()); - - for (uint index = 0; index < _hotspots.size(); index++) { - _vm->_events->getConsole()->DebugPrintf("(%d): %p x1 = %d; y1 = %d; x2 = %d; y2 = %d\n", - index, (void *)_hotspots[index], - _hotspots[index]->_rect.left, _hotspots[index]->_rect.top, - _hotspots[index]->_rect.right - 1, _hotspots[index]->_rect.bottom - 1); - } -} - -uint32 HotSpotList::readHotSpotInteger(Common::SeekableReadStream* hotspotStream) { - if (_vm->isM4()) - return hotspotStream->readSint32LE(); - else - return hotspotStream->readSint16LE(); -} - -void HotSpotList::loadHotSpots(Common::SeekableReadStream* hotspotStream, int hotspotCount) { - HotSpot *currentHotSpot; - uint32 x1, y1, x2, y2; - char buffer[256]; - uint32 strLength = 0; - uint32 index = 0; - int feetX, feetY; - int cursorOffset = (_vm ->isM4()) ? 0 : 1; - - for (int i = 0; i < hotspotCount; i++) { - x1 = readHotSpotInteger(hotspotStream); - y1 = readHotSpotInteger(hotspotStream); - x2 = readHotSpotInteger(hotspotStream); - y2 = readHotSpotInteger(hotspotStream); - index = add(new HotSpot(x1, y1, x2, y2), i == 0); - currentHotSpot = get(index); - currentHotSpot->setIndex(index); - feetX = readHotSpotInteger(hotspotStream); - feetY = readHotSpotInteger(hotspotStream); - currentHotSpot->setFeet(feetX, feetY); - currentHotSpot->setFacing((uint8)hotspotStream->readByte()); - currentHotSpot->setActive(hotspotStream->readByte() != 0); - - if (!_vm->isM4()) - hotspotStream->readByte(); // unused (always 255) - - index = hotspotStream->readByte(); // cursor - if (index == 0) - currentHotSpot->setCursor(0); - else - currentHotSpot->setCursor(index - cursorOffset); - - // Rex Nebular doesn't have this field - if (!_vm->isM4() && _vm->getGameType() != GType_RexNebular) { - // This looks to be some sort of bitmask. Perhaps it signifies - // the valid verbs for this hotspot - index = hotspotStream->readUint16LE(); // unknown - //debugC(kDebugCore, "%i ", index); - } - - if (_vm->isM4()) - hotspotStream->readByte(); // syntax (unused) - - currentHotSpot->setVocabID(readHotSpotInteger(hotspotStream)); - currentHotSpot->setVerbID(readHotSpotInteger(hotspotStream)); - - // Load hotspot related strings (verb, vocab/noun etc) - // These are loaded inside the hotspot data in M4 games, - // and inside the global vocab data (vocab.dat) in MADS games - if (_vm->isM4()) { - strLength = hotspotStream->readUint32LE(); // vocabLength - hotspotStream->read(buffer, strLength); // vocab (the hotspot's name) - // Capitalize the hotspot's name here - str_upper(buffer); - currentHotSpot->setVocab(buffer); - // Verbs are used internally by the game scripts in Orion Burger - strLength = hotspotStream->readUint32LE(); // verbLength - hotspotStream->read(buffer, strLength); // verb - // Capitalize the hotspot's verb here - str_upper(buffer); - currentHotSpot->setVerb(buffer); - - /* Hotspot names for non-English versions are stored in prep. - Prep can be set two ways: For English versions, copy the - text from vocab. For non-English versions, use the prep text - from the room file. - */ - strLength = hotspotStream->readUint32LE(); // prepLength - hotspotStream->read(buffer, strLength); // prep - str_upper(buffer); - - if (buffer[0] != '\0' && strcmp(buffer, "--") != 0 && strcmp(buffer, "ON") != 0) - currentHotSpot->setPrep(buffer); - else - currentHotSpot->setPrep(currentHotSpot->getVocab()); - - // The following values are not used at all by Orion Burger - strLength = hotspotStream->readUint32LE(); // spriteLength - hotspotStream->read(buffer, strLength); // sprite - hotspotStream->readUint16LE(); // sprite hash - } else { - currentHotSpot->setVocab(""); - currentHotSpot->setVerb(""); - - if (currentHotSpot->getVocabID() > 0) - currentHotSpot->setVocab(_madsVm->globals()->getVocab(currentHotSpot->getVocabID())); - - if (currentHotSpot->getVerbID() > 0) - currentHotSpot->setVerb(_madsVm->globals()->getVocab(currentHotSpot->getVerbID())); - } - } -} - -} // End of namespace M4 diff --git a/engines/m4/hotspot.h b/engines/m4/hotspot.h deleted file mode 100644 index 86fe21bcab..0000000000 --- a/engines/m4/hotspot.h +++ /dev/null @@ -1,126 +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. - * - */ - -#ifndef M4_HOTSPOT_H -#define M4_HOTSPOT_H - -#include "common/array.h" -#include "common/rect.h" -#include "common/util.h" - -/* - TODO: - - check if hotspot_duplicate is needed - NOTES: - - hotspot_add_dynamic unused in Orion Burger -*/ - -//???: should String be used instead of char* here? - -namespace M4 { - -class HotSpot { - friend class HotSpotList;//just for debugging, to be removed later -public: - - HotSpot(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0); - ~HotSpot(); - - void setVocab(const char *value); - void setVocabID(int32 value) { _vocabID = value; } - void setVerb(const char *value); - void setVerbID(int32 value) { _verbID = value; } - void setPrep(const char *value); - void setSprite(const char *value); - void setActive(bool value) { _active = value; } - void setCursor(uint8 value) { _cursor = value; } - void setRect(int x1, int y1, int x2, int y2); - void setFeet(int x, int y); - void setFacing(uint8 facing) { _facing = facing; } - void setArticle(int8 v) { _articleNumber = v; } - char *getVocab() const { return _vocab; } - int32 getVocabID() { return _vocabID; } - char *getVerb() const { return _verb; } - int32 getVerbID() { return _verbID; } - char *getPrep() const { return _prep; } - char *getSprite() const { return _sprite; } - uint8 getCursor() const { return _cursor; } - bool getActive() const { return _active; } - uint8 getFacing() const { return _facing; } - int getFeetX() { return _feetX; } - int getFeetY() { return _feetY; } - int8 getArticle() const { return _articleNumber; } - Common::Rect getRect() const; - int getIndex() const { return _index; } - void setIndex(int index) { _index = index; } - - int32 area() const { return (_rect.width() - 1) * (_rect.height() - 1); } - bool pointInside(int x, int y) { return _rect.contains(x, y); } - -private: - char *_vocab, *_verb, *_prep, *_sprite; - Common::Rect _rect; - bool _active; - int _feetX, _feetY; - uint8 _facing, _cursor; - int _index; - - // Unused in Orion Burger, used in MADS games - uint8 _syntax; - int32 _vocabID, _verbID; - int8 _articleNumber; - - //TODO: check if this is actually needed by the game - int16 _hash; -}; - -class HotSpotList { -public: - HotSpotList(); - ~HotSpotList(); - - int add(HotSpot *hotspot, bool head = false); - HotSpot *get(int index) { return _hotspots[index]; } - HotSpot &operator[](int idx) { return *get(idx); } - int size() const { return _hotspots.size(); } - void remove(HotSpot *hotspot); - void unlinkItem(HotSpot *hotspot); - void clear(); - HotSpot *findByXY(int x, int y); - void setActive(const char *name, bool active); - void setActiveXY(const char *name, int x, int y, bool active); - - void dump(); - - void loadHotSpots(Common::SeekableReadStream* hotspotStream, int hotspotCount); - - uint32 readHotSpotInteger(Common::SeekableReadStream* hotspotStream); -private: - typedef Common::Array HotSpotArray; - HotSpotArray _hotspots; -}; - - -} // End of namespace M4 - - -#endif diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp deleted file mode 100644 index efc7943114..0000000000 --- a/engines/m4/m4.cpp +++ /dev/null @@ -1,606 +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. - * - */ - -//#define SCRIPT_TEST -//#define INTRO_TEST - -#include "m4/globals.h" -#include "m4/burger_data.h" -#include "m4/m4.h" -#include "m4/resource.h" -#include "m4/hotspot.h" -#include "m4/font.h" -#include "m4/rails.h" -#include "m4/midi.h" -#include "m4/events.h" -#include "m4/graphics.h" -#include "m4/viewmgr.h" -#include "m4/gui.h" -#include "m4/woodscript.h" -#include "m4/actor.h" -#include "m4/sound.h" -#include "m4/script.h" -#include "m4/compression.h" -#include "m4/animation.h" -#include "m4/m4_menus.h" -#include "m4/m4_views.h" -#include "m4/mads_anim.h" -#include "m4/mads_menus.h" - -#include "common/error.h" -#include "common/file.h" -#include "common/fs.h" -#include "common/system.h" -#include "common/config-manager.h" -#include "common/debug-channels.h" -#include "common/textconsole.h" -#include "engines/util.h" - -namespace M4 { - -// FIXME: remove global -MadsM4Engine *_vm; -MadsEngine *_madsVm; -M4Engine *_m4Vm; - -void escapeHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) { - // For now, simply exit the game - vm->_events->quitFlag = true; -} - -// Temporary hotkey handler for use in testing the TextviewView class - -void textviewHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) { - // Deactivate the scene if it's currently active - View *sceneView = vm->_viewManager->getView(VIEWID_SCENE); - if (sceneView != NULL) - vm->_viewManager->deleteView(sceneView); - - // Activate the textview view - vm->_font->setFont(FONT_CONVERSATION_MADS); - TextviewView *textView = new TextviewView(vm); - vm->_viewManager->addView(textView); - textView->setScript("quotes", NULL); -} - -void saveGameHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) { - // TODO: See CreateF2SaveMenu - save menu should only be activated when - // certain conditions are met, such as player_commands_allowed, and isInterfaceVisible - vm->loadMenu(SAVE_MENU, true); -} - -void loadGameHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) { - // TODO: See CreateF3LoadMenu - save menu should only be activated when - // certain conditions are met, such as player_commands_allowed, and isInterfaceVisible - vm->loadMenu(LOAD_MENU, true); -} - -void gameMenuHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) { - vm->loadMenu(GAME_MENU); -} - -MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) : - Engine(syst), _gameDescription(gameDesc) { - // Setup mixer - syncSoundSettings(); - - // FIXME - _vm = this; - _madsVm = NULL; - - const Common::FSNode gameDataDir(ConfMan.get("path")); - - SearchMan.addSubDirectoryMatching(gameDataDir, "goodstuf"); - SearchMan.addSubDirectoryMatching(gameDataDir, "resource"); - SearchMan.addSubDirectoryMatching(gameDataDir, "option1"); - - DebugMan.addDebugChannel(kDebugScript, "script", "Script debug level"); - DebugMan.addDebugChannel(kDebugGraphics, "graphics", "Graphics debug level"); - DebugMan.addDebugChannel(kDebugConversations, "conversations", "Conversations debugging"); - DebugMan.addDebugChannel(kDebugSound, "sound", "Sounds debug level"); - DebugMan.addDebugChannel(kDebugCore, "core", "Core debug level"); - - _resourceManager = NULL; - _globals = NULL; -} - - -MadsM4Engine::~MadsM4Engine() { - delete _midi; - delete _saveLoad; - delete _kernel; - delete _player; - delete _mouse; - delete _events; - delete _font; - delete _actor; -// delete _scene; // deleted by the viewmanager - delete _dialogs; - delete _screen; - delete _inventory; - delete _viewManager; - delete _rails; - delete _script; - delete _ws; - delete _random; - delete _palette; - delete _globals; - delete _sound; - delete _resourceManager; -} - -Common::Error MadsM4Engine::run() { - // Initialize backend - _screen = new M4Surface(true); // Special form for creating screen reference - - _midi = new MidiPlayer(this); - _midi->setGM(true); // FIXME: Really? Always? - - _saveLoad = new SaveLoad(this); - _palette = new Palette(this); - _mouse = new Mouse(this); - _events = new Events(this); - _kernel = new Kernel(this); - _player = new Player(this); - _font = new FontManager(this); - if (getGameType() == GType_Burger) { - _actor = new Actor(this); - _conversationView = new ConversationView(this); - } else { - _actor = NULL; - } - _rails = new Rails(); // needs to be initialized before _scene - _dialogs = new Dialogs(); - _viewManager = new ViewManager(this); - _inventory = new Inventory(this); - _sound = new Sound(this, _mixer, 255); - _script = new ScriptInterpreter(this); - _ws = new WoodScript(this); - //_callbacks = new Callbacks(this); - _random = new Common::RandomSource("m4"); - - return Common::kNoError; -} - -void MadsM4Engine::eventHandler() { - M4EventType event; - uint32 keycode = 0; - - if ((event = _events->handleEvents()) != MEVENT_NO_EVENT) { - if (_viewManager->containsViews()) - _viewManager->handleMouseEvents(event); - } - - if (_events->kbdCheck(keycode)) - _viewManager->handleKeyboardEvents(keycode); -} - -bool MadsM4Engine::delay(int duration, bool keyAborts, bool clickAborts) { - uint32 endTime = g_system->getMillis() + duration; - M4EventType event; - uint32 keycode = 0; - - while (!_events->quitFlag && (g_system->getMillis() < endTime)) { - event = _events->handleEvents(); - if (clickAborts && ((event == MEVENT_LEFT_RELEASE) || (event == MEVENT_RIGHT_RELEASE))) - return true; - - if (_events->kbdCheck(keycode)) { - if (keyAborts) - return true; - } - - g_system->delayMillis(10); - } - - return false; -} - -void MadsM4Engine::loadMenu(MenuType menuType, bool loadSaveFromHotkey, bool calledFromMainMenu) { - if (isM4() && (menuType != MAIN_MENU)) { - bool menuActive = _viewManager->getView(VIEWID_MENU) != NULL; - - if (!menuActive) - _palette->fadeToGreen(M4_DIALOG_FADE_STEPS, M4_DIALOG_FADE_DELAY); - } - - View *view; - - switch (menuType) { - case MAIN_MENU: - if (getGameType() == GType_RexNebular) - view = new RexMainMenuView(this); - else if (getGameType() == GType_DragonSphere) - view = new DragonMainMenuView(this); - else - view = new MadsMainMenuView(this); - break; - case GAME_MENU: - view = new OrionMenuView(this, 200, 100, GAME_MENU, calledFromMainMenu, loadSaveFromHotkey); - break; - case OPTIONS_MENU: - view = new OrionMenuView(this, 172, 160, OPTIONS_MENU, calledFromMainMenu, loadSaveFromHotkey); - break; - case LOAD_MENU: - case SAVE_MENU: - view = new OrionMenuView(this, 145, 10, menuType, calledFromMainMenu, loadSaveFromHotkey); - break; - default: - error("Unknown menu type"); - break; - } - - _viewManager->addView(view); - _viewManager->moveToFront(view); -} - -#define DUMP_BUFFER_SIZE 1024 - -void MadsM4Engine::dumpFile(const char *filename, bool uncompress) { - Common::DumpFile f; - byte buffer[DUMP_BUFFER_SIZE]; - Common::SeekableReadStream *fileS = res()->get(filename); - - if (!f.open(filename)) - error("Could not open '%s' for writing", filename); - - int bytesRead = 0; - warning("Dumping %s, size: %i\n", filename, fileS->size()); - - if (!uncompress) { - while (!fileS->eos()) { - bytesRead = fileS->read(buffer, DUMP_BUFFER_SIZE); - f.write(buffer, bytesRead); - } - } else { - MadsPack packData(fileS); - Common::SeekableReadStream *sourceUnc; - for (int i = 0; i < packData.getCount(); i++) { - sourceUnc = packData.getItemStream(i); - debugCN(kDebugCore, "Dumping compressed chunk %i of %i, size is %i\n", i + 1, packData.getCount(), sourceUnc->size()); - while (!sourceUnc->eos()) { - bytesRead = sourceUnc->read(buffer, DUMP_BUFFER_SIZE); - f.write(buffer, bytesRead); - } - delete sourceUnc; - } - } - - f.close(); - res()->toss(filename); - res()->purge(); -} - -/*--------------------------------------------------------------------------*/ - -M4Engine::M4Engine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4Engine(syst, gameDesc) { - // FIXME - _m4Vm = this; - - _globals = new M4Globals(this); -} - -M4Engine::~M4Engine() { - delete _converse; -} - -Common::Error M4Engine::run() { - // Set up the graphics mode - initGraphics(640, 480, true); - - // Necessary pre-initialisation - _resourceManager = new M4ResourceManager(this); - - // Set up needed common functionality - MadsM4Engine::run(); - - // M4 specific initialisation - _converse = new Converse(this); - - _scene = new M4Scene(this); - _script->open("m4.dat"); - -#ifdef SCRIPT_TEST - -#if 0 - ScriptFunction *func = _script->loadFunction("room_parser_142"); - _script->runFunction(func); -#endif - -#if 1 - ScriptFunction *func = _script->loadFunction("room_daemon_951"); - for (int i = 1; i < 58; i++) { - _vm->_kernel->trigger = i; - _script->runFunction(func); - debugCN(kDebugCore, "=================================\n"); - } -#endif - - return Common::kNoError; -#endif - - // Set up the inventory - - // Set up the game interface view - //_interfaceView->inventoryAdd("Money", "", 55); // Sample item - - if (getGameType() == GType_Burger) { - for (int i = 0; i < ARRAYSIZE(burger_inventory); i++) { - char* itemName = strdup(burger_inventory[i].name); - _inventory->registerObject(itemName, burger_inventory[i].scene, - burger_inventory[i].icon); - _inventory->addToBackpack(i); // debug: this adds ALL objects to the player's backpack - } - } - - // Show intro - - if (getGameType() == GType_Burger) { - _kernel->newRoom = TITLE_SCENE_BURGER; - } else { - _scene->getBackgroundSurface()->loadBackgroundRiddle("main menu"); - _ws->setBackgroundSurface(_scene->getBackgroundSurface()); - } - - _viewManager->addView(_scene); - - // Setup game wide hotkeys. Note that Orion Burger used F2/F3 for Save/Restore, - // but for standardisation with most other games, F5/F7 are also mapped - - _viewManager->systemHotkeys().add(Common::KEYCODE_ESCAPE, &escapeHotkeyHandler); - _viewManager->systemHotkeys().add(Common::KEYCODE_F2, &saveGameHotkeyHandler); - _viewManager->systemHotkeys().add(Common::KEYCODE_F3, &loadGameHotkeyHandler); - _viewManager->systemHotkeys().add(Common::KEYCODE_F5, &saveGameHotkeyHandler); - _viewManager->systemHotkeys().add(Common::KEYCODE_F7, &loadGameHotkeyHandler); - _viewManager->systemHotkeys().add(Common::KEYCODE_F9, &gameMenuHotkeyHandler); - - // Start playing Orion Burger intro music - //_midi->playMusic("999intro", 255, false, -1, -1); - - // TODO: start playing intro animations - - // TODO: Master Lu - - // Test for mouse - _mouse->init("cursor", NULL); - _mouse->setCursorNum(0); - _mouse->cursorOn(); - - _ws->assets()->loadAsset("SHOW SCRIPT", NULL); - _ws->assets()->loadAsset("STREAM SCRIPT", NULL); - -#ifdef INTRO_TEST - int curPart = 0; - Machine *mach = NULL; -#endif - - _ws->setSurfaceView(_scene); - - uint32 nextFrame = g_system->getMillis(); - while (!_events->quitFlag) { - - // This should probably be moved to either Scene or Kernel - if (_kernel->currentRoom != _kernel->newRoom) { - - _ws->clear(); - - _kernel->currentSection = _kernel->newRoom / 100; - _kernel->currentRoom = _kernel->newRoom; - - _scene->loadScene(_kernel->currentRoom); - - _ws->setBackgroundSurface(_scene->getBackgroundSurface()); - _ws->setInverseColorTable(scene()->getInverseColorTable()); - - _kernel->loadSectionScriptFunctions(); - _kernel->loadRoomScriptFunctions(); - - _kernel->roomInit(); - - _scene->show(); - -#ifdef INTRO_TEST - if (_kernel->currentRoom == 951) { - curPart = 0; - mach = _ws->streamSeries("PLANET X HILLTOP A", 1, 0x1000, 0); - } -#endif - - } - - eventHandler(); - - // Call the updateState method of all views - _viewManager->updateState(); - - // Handle frame updates - if (g_system->getMillis() >= nextFrame) { -#ifdef INTRO_TEST - // Orion Burger intro test (scene 951) - // This is ugly and bad, machine is not deleted so there's a huge memory - // leak too. But hey, we can see some of the intro! - if (mach && mach->getState() == -1) { - if (curPart == 0) - mach = _ws->streamSeries("Planet X Low Ground Shot", 1, 0x1000, 0); - else if (curPart == 1) - mach = _ws->streamSeries("Planet X Hilltop B", 1, 0x1000, 0); - else if (curPart == 2) - mach = _ws->streamSeries("Space Station Panorama A", 1, 0x1000, 0); - else if (curPart == 3) - mach = _ws->streamSeries("Cargo Transfer Area A", 1, 0x1000, 0); - else if (curPart == 4) - mach = _ws->streamSeries("VP's Office A", 1, 0x1000, 0); - else if (curPart == 5) - mach = _ws->streamSeries("Hologram", 1, 0x1000, 0); - else if (curPart == 6) - mach = _ws->streamSeries("VP's Office B", 1, 0x1000, 0); - else if (curPart == 7) - mach = _ws->streamSeries("Cargo Transfer Area B", 1, 0x1000, 0); - else if (curPart == 8) - mach = _ws->streamSeries("Cargo Transfer Controls", 1, 0x1000, 0); - else if (curPart == 9) - mach = _ws->streamSeries("Space Station Panorama B", 1, 0x1000, 0); - // This last scene is from the rolling demo - //else if (curPart == 10) - // mach = _ws->streamSeries("Call To Action", 1, 0x1000, 0); - curPart++; - } -#endif - _ws->update(); - _viewManager->refreshAll(); - nextFrame = g_system->getMillis();// + GAME_FRAME_DELAY; - - // TEST STUFF ONLY - if (_player->commandReady) { - _kernel->roomParser(); - _player->commandReady = false; - } - - } - - g_system->delayMillis(10); - } - - return Common::kNoError; -} - -/*--------------------------------------------------------------------------*/ - -MadsEngine::MadsEngine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4Engine(syst, gameDesc) { - // FIXME - _madsVm = this; - - _globals = new MadsGlobals(this); - _currentTimer = 0; -} - -MadsEngine::~MadsEngine() { -} - -Common::Error MadsEngine::run() { - // Set up the graphics mode - initGraphics(320, 200, false); - - // Necessary pre-initialisation - _resourceManager = new MADSResourceManager(this); - - // Set up needed common functionality - MadsM4Engine::run(); - - _palette->setMadsSystemPalette(); - - _mouse->init("cursor.ss", NULL); - _mouse->setCursorNum(0); - - // Load MADS data files - MadsGlobals *globs = (MadsGlobals *)_globals; - globs->loadMadsVocab(); // vocab.dat - globs->loadQuotes(); // quotes.dat - globs->loadMadsMessagesInfo(); // messages.dat - globs->loadMadsObjects(); - - // Setup globals - globs->_config.easyMouse = true; - globs->_config.invObjectsStill = false; - globs->_config.textWindowStill = false; - globs->_config.storyMode = 1; // Naughty - globs->_config.screenFades = 0; - - // Test code to dump all messages to the console - //for (int i = 0; i < _globals->getMessagesSize(); i++) - //debugCN(kDebugCore, "%s\n----------\n", _globals->loadMessage(i)); - - if (getGameType() == GType_RexNebular) { - MadsGameLogic::initializeGlobals(); - - _scene = NULL; - loadMenu(MAIN_MENU); - } else { - // Test code - _scene = new MadsScene(this); - - startScene(FIRST_SCENE); - RGBList *_bgPalData; - _scene->loadBackground(FIRST_SCENE, &_bgPalData); - _palette->addRange(_bgPalData); - _scene->translate(_bgPalData); - - _scene->show(); - - _font->setFont(FONT_MAIN_MADS); - _font->current()->setColors(2, 1, 3); - _font->current()->writeString(_scene->getBackgroundSurface(), "Testing the M4/MADS ScummVM engine", 5, 160, 310, 2); - _font->current()->writeString(_scene->getBackgroundSurface(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 5, 180, 310, 2); - - if (getGameType() == GType_DragonSphere) { - //_scene->showMADSV2TextBox("Test", 10, 10, NULL); - } - - _mouse->cursorOn(); - } - - _viewManager->systemHotkeys().add(Common::KEYCODE_ESCAPE, &escapeHotkeyHandler); - _viewManager->systemHotkeys().add(Common::KEYCODE_KP_MULTIPLY, &textviewHotkeyHandler); - - uint32 nextFrame = g_system->getMillis(); - while (!_events->quitFlag) { - eventHandler(); - - if (g_system->getMillis() >= nextFrame) { - nextFrame = g_system->getMillis() + GAME_FRAME_DELAY; - ++_currentTimer; - - // Call the updateState method of all views - _viewManager->updateState(); - - // Refresh the display - _viewManager->refreshAll(); - } - - g_system->delayMillis(10); - - if (globals()->dialogType != DIALOG_NONE) - showDialog(); - } - - return Common::kNoError; -} - -void MadsEngine::showDialog() { - // Switch to showing the given dialog - RexDialogView *dlg = NULL; - switch (globals()->dialogType) { - case DIALOG_GAME_MENU: - dlg = new RexGameMenuDialog(); - break; - case DIALOG_OPTIONS: - dlg = new RexOptionsDialog(); - break; - default: - error("Unknown dialog type"); - }; - - globals()->dialogType = DIALOG_NONE; - _viewManager->addView(dlg); -} - -} // End of namespace M4 diff --git a/engines/m4/m4.h b/engines/m4/m4.h deleted file mode 100644 index b40ba0e878..0000000000 --- a/engines/m4/m4.h +++ /dev/null @@ -1,252 +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. - * - */ - -#ifndef M4_H -#define M4_H - -#include "common/scummsys.h" -#include "common/util.h" -#include "common/random.h" - -#include "engines/engine.h" - -#include "m4/globals.h" -#include "m4/graphics.h" -#include "m4/resource.h" -#include "m4/saveload.h" -#include "m4/viewmgr.h" -#include "m4/gui.h" -#include "m4/events.h" -#include "m4/font.h" -#include "m4/scene.h" -#include "m4/mads_player.h" -#include "m4/mads_scene.h" -#include "m4/m4_scene.h" -#include "m4/actor.h" -#include "m4/sound.h" -#include "m4/rails.h" -#include "m4/converse.h" -#include "m4/animation.h" - -//#define DUMP_SCRIPTS - -/** - * This is the namespace of the M4 engine. - * - * Status of this engine: - * This engine is eventually intended to compromise two evolutions of the same engine: 'MADS' for the - * first generation of the engine, and 'M4' for the second generation. This engine is called M4 overall - * simply because work first began on the M4 side (focusing on the game 'Orion Burger'). - * - * MADS Status: The current game being focused on is 'Rex Nebular' by DreamMaster, who is implementing - * functionality as he disassembles the games original executables. Currently the engine has no particular - * game logic implemented, although it does have the title screen implemented, and displays the initial - * game screen and some game interface elements - * - * M4 Status: Work on this engine began with the game 'Orion Burger'. Some of the user interface - * functionality has been implemented. No further work has been done on this for some time, so progress - * on this part of the engine can be considered frozen. - * - * Games using this engine: - * MADS Games: Dragonsphere, Return of the Phantom, Rex Nebular and the Cosmic Gender Bender - * M4 Games: Orion Burger, The Riddle of Master Lu - */ -namespace M4 { - -class MidiPlayer; -class FileSystem; -class ResourceManager; -class Mouse; -class Events; -class Scene; -class ViewManager; -class View; -class Inventory; -class M4InterfaceView; -class ConversationView; -class Actor; -class Converse; -class MadsConversation; -class ScriptInterpreter; -class WoodScript; -class Animation; - -enum M4GameType { - GType_Riddle = 1, - GType_Burger = 2, - GType_RexNebular = 3, - GType_DragonSphere = 4, - GType_Phantom = 5 -}; - -enum Features { - kFeaturesNone = 0, - kFeaturesCD = 1 << 0, - kFeaturesDemo = 1 << 1 -}; - -enum { - kFileTypeHash, - kFileTypeHAG -}; - -enum { - kDebugScript = 1 << 0, - kDebugConversations = 1 << 1, - kDebugGraphics = 1 << 2, - kDebugSound = 1 << 3, - kDebugCore = 1 << 4 -}; - -#define MESSAGE_BASIC 1 -#define MESSAGE_INTERMEDIATE 2 -#define MESSAGE_DETAILED 3 - -struct M4GameDescription; - -#define GAME_FRAME_DELAY 20 - -#define VALIDATE_MADS assert(!_vm->isM4()) - -inline void str_lower(char *s) { while (*s) { *s = tolower(*s); s++; } } -inline void str_upper(char *s) { while (*s) { *s = toupper(*s); s++; } } - -inline long FixedMul(long a, long b) { return (long)(((float)a * (float)b) / 65536.0); } -inline long FixedDiv(long a, long b) { return (long)(((float)a / (float)b) * 65536.0); } - -class MadsM4Engine : public Engine { -private: - Common::Error goMADS(); - Common::Error goM4(); - -protected: - // Engine APIs - virtual Common::Error run(); - - void shutdown(); - - MidiPlayer *_midi; - -public: - MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc); - virtual ~MadsM4Engine(); - - int getGameType() const; - uint32 getFeatures() const; - Common::Language getLanguage() const; - Common::Platform getPlatform() const; - bool isM4() const { return (getGameType() == GType_Riddle) || (getGameType() == GType_Burger); } - - const char *getGameFile(int fileType); - Common::EventManager *eventMan() { return _eventMan; } - - const M4GameDescription *_gameDescription; - - ResourceManager *res() const { return _resourceManager; } - MidiPlayer *midi() { return _midi; } - Common::SaveFileManager *saveManager() { return _saveFileMan; } - void dumpFile(const char *filename, bool uncompress); - void eventHandler(); - bool delay(int duration, bool keyAborts = true, bool clickAborts = true); - void loadMenu(MenuType menuType, bool loadSaveFromHotkey = false, - bool calledFromMainMenu = false); - - // TODO: eventually these have to be removed - int32 seed; - void imath_seed(int32 seednum) { seed = seednum; } - uint32 imath_random() { return(seed = (25173*seed + 13849) & 0xffff); } - int32 imath_ranged_rand(int32 a, int32 b) { return (a + (((1 + ABS(b-a))*imath_random())>>16)); } - long imath_ranged_rand16(long a, long b) { return ((a + FixedMul(1+ABS(b-a),imath_random()))); } - // - - ResourceManager *_resourceManager; - Globals *_globals; - - SaveLoad *_saveLoad; - ViewManager *_viewManager; - Palette *_palette; - Kernel *_kernel; - Player *_player; - Mouse *_mouse; - Events *_events; - FontManager *_font; - Actor *_actor; - Scene *_scene; - Dialogs *_dialogs; - M4Surface *_screen; - Inventory *_inventory; - ConversationView *_conversationView; - Sound *_sound; - Rails *_rails; - ScriptInterpreter *_script; - WoodScript *_ws; - Common::RandomSource *_random; - - Scene *scene() { return _scene; } -}; - -class MadsEngine : public MadsM4Engine { -private: - void showDialog(); -public: - MadsConversation _converse; - uint32 _currentTimer; - MadsPlayer _player; -public: - MadsEngine(OSystem *syst, const M4GameDescription *gameDesc); - virtual ~MadsEngine(); - - virtual Common::Error run(); - - MadsGlobals *globals() { return (MadsGlobals *)_globals; } - MadsScene *scene() { return (MadsScene *)_scene; } - void startScene(int sceneNum) { - if (!_scene) { - _scene = new MadsScene(this); - ((MadsScene *)_scene)->initialize(); - } - _scene->show(); - _scene->loadScene(101); - } -}; - -class M4Engine : public MadsM4Engine { -public: - Converse *_converse; -public: - M4Engine(OSystem *syst, const M4GameDescription *gameDesc); - virtual ~M4Engine(); - - virtual Common::Error run(); - - M4Globals *globals() { return (M4Globals *)_globals; } - M4Scene *scene() { return (M4Scene *)_scene; } -}; - -// FIXME: remove globals -extern MadsM4Engine *_vm; -extern MadsEngine *_madsVm; -extern M4Engine *_m4Vm; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/m4_menus.cpp b/engines/m4/m4_menus.cpp deleted file mode 100644 index 3384a82c8b..0000000000 --- a/engines/m4/m4_menus.cpp +++ /dev/null @@ -1,724 +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/algorithm.h" // for find() -#include "common/textconsole.h" -#include "common/translation.h" -#include "gui/dialog.h" -#include "gui/message.h" - -#include "m4/m4_menus.h" -#include "m4/m4_views.h" -#include "m4/woodscript.h" -#include "m4/midi.h" - -namespace M4 { - -const char *EmptySaveString = ""; - -//-------------------------------------------------------------------------- -// Callback methods -// -// Following is a set of callback methods used to handle the execution -// of buttons in the various dialogs -//-------------------------------------------------------------------------- - -// General function which simply closes the active menu - -void OrionCallbacks::closeMenuFn(DialogView *view, MenuObject *item) { - view->close(); -} - -void OrionCallbacks::closeMenuFn(OrionMenuView *view) { - closeMenuFn(view, NULL); -} - -/* Game menu functions */ - -void OrionCallbacks::gameOptionsMenuFn(DialogView *view, MenuObject *item) { - view->vm()->loadMenu(OPTIONS_MENU); - view->close(); -} - -void OrionCallbacks::gameSaveGameFn(DialogView *view, MenuObject *item) { - view->vm()->loadMenu(SAVE_MENU); - view->close(); -} - -void OrionCallbacks::gameLoadGameFn(DialogView *view, MenuObject *item) { - view->vm()->loadMenu(LOAD_MENU); - view->close(); -} - -void OrionCallbacks::gameExitFn(DialogView *view, MenuObject *item) { - view->vm()->_events->quitFlag = true; - view->close(); -} - -/* Options menu */ - -void OrionCallbacks::optionsDigiSliderFn(DialogView *view, MenuObject *item) { - // Digi volume slider changed - int percent = ((MenuHorizSlider *) item)->percent(); - - view->vm()->_sound->setVolume(percent * 255 / 100); -} - -void OrionCallbacks::optionsMidiSliderFn(DialogView *view, MenuObject *item) { - // Midi volume slider changed - int percent = ((MenuHorizSlider *) item)->percent(); - - view->vm()->midi()->setVolume(percent * 255 / 100); -} - -void OrionCallbacks::optionsScrollingFn(DialogView *view, MenuObject *item) { - // TODO: Change current Digi volume settings here -} - -void OrionCallbacks::optionsCancelFn(DialogView *view, MenuObject *item) { - // TODO: Reset original option settings here - OrionMenuView *vw = (OrionMenuView *) view; - - vw->vm()->midi()->setVolume(vw->_originalMidiVolume); - - vw->vm()->loadMenu(GAME_MENU); - vw->close(); -} - -void OrionCallbacks::optionsDoneFn(DialogView *view, MenuObject *item) { - view->vm()->loadMenu(GAME_MENU); - view->close(); -} - -void OrionCallbacks::optionsReturnFn(OrionMenuView *view) { - optionsDoneFn(view, NULL); -} - -void OrionCallbacks::optionsEscapeFn(OrionMenuView *view) { - optionsCancelFn(view, NULL); -} - -/* Save/Load dialog functions */ - -// Save the current game - -void OrionCallbacks::saveLoadSaveFn(DialogView *view, MenuObject *item) { - if (view->_selectedSlot == -1) - return; - - MenuTextField *textItem = (MenuTextField *) view->getItem(SLTAG_TEXTFIELD); - if (!textItem) - return; - - textItem->setState(OS_NORMAL); - - // Save the game - bool succeeded = view->vm()->_saveLoad->save(view->_selectedSlot + 1, textItem->getText()); - - if (!succeeded) { - GUI::MessageDialog dialog(_("Save game failed!")); - dialog.runModal(); - } - - // Close the menu - closeMenuFn(view, item); -} - -void OrionCallbacks::saveLoadLoadFn(DialogView *view, MenuObject *item) { - // TODO: load the selected save game - closeMenuFn(view, item); -} - -void OrionCallbacks::saveLoadSlotFn(DialogView *view, MenuObject *item) { - OrionMenuView *vw = (OrionMenuView *) view; - MenuSaveLoadText *button = (MenuSaveLoadText *) item; - - view->_selectedSlot = button->getIndex(); - view->_deleteSaveDesc = true; - - // Disable all the slots except the selected one - for (int index = 0; index < SL_NUM_VISIBLE_SLOTS; ++index) { - MenuSaveLoadText *currentItem = (MenuSaveLoadText *) view->getItem(SLTAG_SLOTS_START + index); - if (currentItem->getIndex() != button->getIndex()) { - currentItem->setState(OS_GREYED); - } - } - - // Get a copy of the slot bounds - Common::Rect slotBounds = button->getBounds(); - - if (view->getMenuType() == SAVE_MENU) { - // Add in a text field for entry of the savegame name - vw->items().push_back(new MenuTextField(view, SLTAG_TEXTFIELD, - slotBounds.left, slotBounds.top, slotBounds.width(), slotBounds.height(), false, - saveLoadSaveFn, (button->getText() == EmptySaveString) ? NULL : button->getText(), - button->getIndex() + 1)); - - } else { - vw->items().push_back(new MenuTextField(view, SLTAG_TEXTFIELD, - slotBounds.left, slotBounds.top, slotBounds.width(), slotBounds.height(), true, - saveLoadLoadFn, button->getText(), button->getIndex() + 1)); - } - - // Hide the existing slot - button->setVisible(false); - - // Disable the slider - - MenuVertSlider *slider = (MenuVertSlider *) view->getItem(SLTAG_VSLIDER); - slider->setState(OS_GREYED); - - // Enable the save/load button - MenuButton *btn = (MenuButton *) view->getItem(SLTAG_SAVELOAD); - btn->setState(OS_NORMAL); -} - -void OrionCallbacks::saveLoadCancelFn(DialogView *view, MenuObject *item) { - OrionMenuView *vw = (OrionMenuView *) view; - - if (view->_selectedSlot != -1) { - // Pressed cancel with a save selected, so revert back to no selection - - // Re-enable all the other slots - - for (int index = 0; index < SL_NUM_VISIBLE_SLOTS; ++index) { - if (index != view->_selectedSlot) { - MenuSaveLoadText *currentItem = (MenuSaveLoadText *) view->getItem(SLTAG_SLOTS_START + index); - currentItem->setState(OS_NORMAL); - } - } - - // Show the previously hidden slot again - MenuSaveLoadText *slot = (MenuSaveLoadText *) view->getItem(SLTAG_SLOTS_START + view->_selectedSlot); - slot->setVisible(true); - slot->setState(OS_NORMAL); - - // Remove the text selection - MenuTextField *textField = (MenuTextField *) view->getItem(SLTAG_TEXTFIELD); - delete textField; - vw->items().remove(textField); - - // Set button enablement - MenuButton *btn = (MenuButton *) view->getItem(SLTAG_SAVELOAD); - btn->setState(OS_GREYED); - btn = (MenuButton *) view->getItem(SLTAG_CANCEL); - btn->setState(OS_NORMAL); - - // Re-enable the slider - - MenuVertSlider *slider = (MenuVertSlider *) view->getItem(SLTAG_VSLIDER); - slider->setState(OS_NORMAL); - - view->_selectedSlot = -1; - - } else { - // Close the dialog - if (vw->_loadSaveFromHotkey) - // Since dialog was called from hotkey, return directly to the game - closeMenuFn(view, item); - else { - // Return to the game menu - view->vm()->loadMenu(GAME_MENU); - view->close(); - } - } -} - -void OrionCallbacks::saveLoadSliderFn(DialogView *view, MenuObject *item) { - OrionMenuView *vw = (OrionMenuView *) view; - MenuVertSlider *slider = (MenuVertSlider *) item; - - if (slider->sliderState() == VSLIDER_THUMBNAIL) { - // Callback generated by slider thumb, so set top slot using slider percentage - vw->setTopSaveSlot(slider->percent() * 89 / 100); - - } else { - int newIndex = view->_topSaveSlotIndex; - - switch (slider->sliderState()) { - case VSLIDER_UP: - if (newIndex > 0) - --newIndex; - break; - - case VSLIDER_PAGE_UP: - if (newIndex > 0) - newIndex = MAX(newIndex - 10, 0); - break; - - case VSLIDER_PAGE_DOWN: - if (newIndex < 89) - newIndex = MIN(newIndex + 10, 89); - break; - - case VSLIDER_DOWN: - if (newIndex < 89) - ++newIndex; - break; - - default: - break; - } - - if (newIndex != view->_topSaveSlotIndex) { - // Set the new top slot - vw->setTopSaveSlot(newIndex); - - // Set the new slider position - slider->setPercentage(newIndex * 100 / 89); - } - } -} - -void OrionCallbacks::saveLoadEscapeFn(OrionMenuView *view) { - saveLoadCancelFn(view, NULL); -} - -void OrionCallbacks::saveLoadReturnFn(OrionMenuView *view) { - MenuTextField *textItem = (MenuTextField *) view->getItem(SLTAG_TEXTFIELD); - if (textItem) { - if (view->getMenuType() == SAVE_MENU) - saveLoadSaveFn(view, NULL); - else - saveLoadLoadFn(view, NULL); - } -} - -//-------------------------------------------------------------------------- - -OrionMenuView::OrionMenuView(MadsM4Engine *Vm, int x, int y, MenuType menuType, bool calledFromMainMenu, - bool loadSaveFromHotkey): DialogView(Vm, x, y, true) { - _menuType = menuType; - _screenType = VIEWID_MENU; - _screenFlags.layer = LAYER_MENU; - _screenFlags.get = SCREVENT_ALL; - _screenFlags.blocks = SCREVENT_ALL; - _screenFlags.immovable = true; - //_screenFlags.immovable = false; // uncomment to make menu movable - _coords.left = x; - _coords.top = y; - _currentItem = NULL; - _escapeHandler = &OrionCallbacks::closeMenuFn; - _returnHandler = NULL; - _saveNames = NULL; - _savegameThumbnail = NULL; - _deleteSaveDesc = false; - _closeFlag = false; - - _calledFromMainMenu = calledFromMainMenu; - _loadSaveFromHotkey = loadSaveFromHotkey; - - _interfaceWasVisible = _m4Vm->scene()->getInterface()->isVisible(); - if (_interfaceWasVisible) - _m4Vm->scene()->getInterface()->hide(); - - _vm->_mouse->setCursorNum(CURSOR_ARROW); - - switch (menuType) { - case GAME_MENU: - loadSprites(MENU_GAME); - - // Add menu contents - _menuObjects.push_back(new MenuButton(this, BTNID_MAIN, 45, 53, 24, 24, &OrionCallbacks::closeMenuFn)); - _menuObjects.push_back(new MenuButton(this, BTNID_OPTIONS, 45, 94, 24, 24, &OrionCallbacks::gameOptionsMenuFn)); - _menuObjects.push_back(new MenuButton(this, BTNID_RESUME, 45, 135, 24, 24, &OrionCallbacks::closeMenuFn)); - _menuObjects.push_back(new MenuButton(this, BTNID_QUIT, 141, 135, 24, 24, &OrionCallbacks::gameExitFn)); - _menuObjects.push_back(new MenuButton(this, BTNID_SAVE, 141, 53, 24, 24, &OrionCallbacks::gameSaveGameFn, _calledFromMainMenu)); - _menuObjects.push_back(new MenuButton(this, BTNID_LOAD, 141, 94, 24, 24, &OrionCallbacks::gameLoadGameFn, - !_vm->_saveLoad->hasSaves())); - - _escapeHandler = &OrionCallbacks::closeMenuFn; - _returnHandler = &OrionCallbacks::closeMenuFn; - break; - - case OPTIONS_MENU: - loadSprites(MENU_OPTIONS); - - // Store the original settings in case user aborts dialog - _originalMidiVolume = _vm->midi()->getVolume(); - - // Add menu contents - // TODO: Currently the Digi slider isn't hooked up to anything - _menuObjects.push_back(new MenuButton(this, OPTIONID_CANCEL, 93, 141, 74, 43, - &OrionCallbacks::optionsCancelFn, false, false, OBJTYPE_OM_CANCEL)); - _menuObjects.push_back(new MenuButton(this, OPTIONID_DONE, 168, 141, 74, 43, - &OrionCallbacks::optionsDoneFn, false, false, OBJTYPE_OM_DONE)); - _menuObjects.push_back(new MenuHorizSlider(this, OPTIONID_HSLIDER_MIDI, 47, 64, 212, 24, - _originalMidiVolume * 100 / 255, &OrionCallbacks::optionsMidiSliderFn, true)); - _menuObjects.push_back(new MenuHorizSlider(this, OPTIONID_HSLIDER_DIGI, 47, 104, 212, 24, - 0, &OrionCallbacks::optionsDigiSliderFn, true)); - - _escapeHandler = &OrionCallbacks::optionsEscapeFn; - _returnHandler = &OrionCallbacks::optionsReturnFn; - break; - - case SAVE_MENU: - case LOAD_MENU: - loadSprites(MENU_SAVELOAD); - - // Set up the defaults for the window - _topSaveSlotIndex = 0; - _selectedSlot = -1; - _highlightedSlot = -1; - _saveNames = _vm->_saveLoad->getSaves(); - - // Set up menu elements - _menuObjects.push_back(new MenuMessage(this, SLTAG_SAVELOAD_LABEL, 50, 241, 70, 16)); - _menuObjects.push_back(new MenuButton(this, SLTAG_SAVELOAD, 214, 384, 72, 41, - (menuType == SAVE_MENU) ? &OrionCallbacks::saveLoadSaveFn : &OrionCallbacks::saveLoadLoadFn, - true, true, (menuType == SAVE_MENU) ? OBJTYPE_SL_SAVE : OBJTYPE_SL_LOAD)); - _menuObjects.push_back(new MenuButton(this, SLTAG_CANCEL, 139, 384, 74, 43, - &OrionCallbacks::saveLoadCancelFn, false, false, OBJTYPE_SL_CANCEL)); - _menuObjects.push_back(new MenuVertSlider(this, SLTAG_VSLIDER, 291, 255, 23, 127, 0, - &OrionCallbacks::saveLoadSliderFn)); - - if (_menuType == SAVE_MENU) - _savegameThumbnail = createThumbnail(); - - _menuObjects.push_back(new MenuImage(this, SLTAG_THUMBNAIL, 66, 28, 215, 162, - (_savegameThumbnail == NULL) ? _sprites->getFrame(SL_EMPTY_THUMBNAIL) : _savegameThumbnail)); - - - { - SaveGameIterator slot = _saveNames->begin(); - for (uint slotIndex = 0; slotIndex < SL_NUM_VISIBLE_SLOTS; ++slotIndex, ++slot) { - // Get save slot - bool isEmpty = (slotIndex >= _saveNames->size()) || (*slot).empty(); - - _menuObjects.push_back(new MenuSaveLoadText(this, SLTAG_SLOTS_START + slotIndex, - 50, 256 + slotIndex * 15, 238, 15, &OrionCallbacks::saveLoadSlotFn, - (menuType == LOAD_MENU) && isEmpty, true, (menuType == LOAD_MENU), - isEmpty ? EmptySaveString : slot->c_str(), slotIndex + 1)); - } - } - - _escapeHandler = &OrionCallbacks::saveLoadEscapeFn; - _returnHandler = &OrionCallbacks::saveLoadReturnFn; - break; - - default: - error("Unknown menu type"); - break; - } - - // Draw all the items onto the background surface - for (MenuObjectsIterator i = _menuObjects.begin(); i != _menuObjects.end(); ++i) - (*i)->onRefresh(); -} - -OrionMenuView::~OrionMenuView() { - delete _sprites; - - for (MenuObjectList::iterator i = _menuObjects.begin(); i != _menuObjects.end(); ++i) - delete *i; - _menuObjects.clear(); - - delete _saveNames; - delete _savegameThumbnail; -} - -bool OrionMenuView::loadSprites(const char *seriesName) { - Common::SeekableReadStream *data = _vm->res()->get(seriesName); - RGB8 *palette; - - _sprites = new SpriteAsset(_vm, data, data->size(), seriesName); - palette = _sprites->getPalette(); - _vm->_palette->setPalette(palette, 0, _sprites->getColorCount()); - - _vm->res()->toss(seriesName); - - // Update the palette - //_vm->setPalette((byte *) _menuPalette, 59, 197); - - // The first sprite is the menu background - - M4Sprite *bg = _sprites->getFrame(0); - this->setSize(bg->width(), bg->height()); - _coords.setWidth(bg->width()); - _coords.setHeight(bg->height()); - bg->copyTo(this); - - return true; -} - -// Creates a thumbnail based on the current background screen - -M4Surface *OrionMenuView::createThumbnail() { - M4Surface srcSurface(_vm->_screen->width(), _vm->_screen->height()); - M4Surface *result = new M4Surface(_vm->_screen->width() / 3, _vm->_screen->height() / 3); - - // Translate the scene data - - _vm->_scene->onRefresh(NULL, &srcSurface); - byte *srcP = srcSurface.getBasePtr(0, 0); - byte *destP = result->getBasePtr(0, 0); - - for (int yCtr = 0; yCtr < _vm->_scene->height() / 3; ++yCtr, srcP += g_system->getWidth() * 3) { - byte *src0P = srcP; - byte *src1P = srcP + _vm->_screen->width(); - byte *src2P = src1P + _vm->_screen->width(); - - for (int xCtr = 0; xCtr < result->width(); ++xCtr) { - *destP = (byte)((uint32)(( - *src0P + *(src0P + 1) + *(src0P + 2) + - *src1P + *(src1P + 1) + *(src1P + 2) + - *src2P + *(src2P + 1) + *(src2P + 2)) / 9)); - if (*destP == 0) - *destP = 21; - - ++destP; - src0P += 3; - src1P += 3; - src2P += 3; - } - } - - // Translate the game interface view - since it's using standard colors that can't be - // averaged, simply take the top left pixel of every 3x3 pixel block - - _m4Vm->scene()->getInterface()->onRefresh(NULL, &srcSurface); - destP = result->getBasePtr(0, 0) + (_vm->_screen->width() / 3) * (_m4Vm->scene()->getInterface()->bounds().top / 3); - - int yStart = _m4Vm->scene()->getInterface()->bounds().top; - int yEnd = MIN(_vm->_screen->height() - 1, (int) _m4Vm->scene()->getInterface()->bounds().bottom - 1); - for (int yCtr = yStart; yCtr <= yEnd; yCtr += 3) { - srcP = (byte *)srcSurface.getBasePtr(0, yCtr) + (yCtr * _vm->_screen->width()); - - for (int xCtr = 0; xCtr < result->width(); ++xCtr, srcP += 3) - *destP++ = *srcP; - } - - return result; -} - -void OrionMenuView::destroyView() { - MadsM4Engine *engine = _vm; - bool interfaceVisible = _interfaceWasVisible; - engine->_viewManager->deleteView(this); - - // Fade the game back in if no menu views are active (such as if a button was pressed in one menu - // to activate another menu dialog) - bool fadeIn = engine->_viewManager->getView(VIEWID_MENU) == NULL; - - if (fadeIn) { - bool fadeToBlack = engine->_events->quitFlag; - engine->_ws->update(); - engine->_palette->fadeFromGreen(M4_DIALOG_FADE_STEPS, M4_DIALOG_FADE_DELAY, fadeToBlack); - - if (interfaceVisible) - engine->scene()->showInterface(); - } -} - -bool OrionMenuView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - static Common::Point movingPos(0, 0); - static bool movingFlag = false; - - bool handledFlag = false; - int localX, localY; - MenuObjectsIterator i; - - if (!_screenFlags.visible) - return false; - - if (!movingFlag) - captureEvents = false; - - // If the escape key is pressed, then pass onto the Escape handler - - if (eventType == KEVENT_KEY) { - if ((param == Common::KEYCODE_ESCAPE) && (_escapeHandler != NULL)) { - // Execute the Escape handler function - _currentItem = NULL; - captureEvents = false; - _escapeHandler(this); - destroyView(); - return true; - } - - if (((param == Common::KEYCODE_RETURN) || (param == Common::KEYCODE_KP_ENTER)) && - (_returnHandler != NULL)) { - // Execute the Return handler function - _currentItem = NULL; - captureEvents = false; - _returnHandler(this); - return true; - } - - MenuTextField *textItem = (MenuTextField *) getItem(SLTAG_TEXTFIELD); - if (textItem && textItem->onEvent(KEVENT_KEY, param, x, y, _currentItem)) - return true; - } - - // Convert the screen position to a relative position within the menu surface - localX = x - _coords.left; - localY = y - _coords.top; - - // If there is an active object handling events, pass it on until it releases control - - if (_currentItem) { - handledFlag = _currentItem->onEvent(eventType, param, localX, localY, _currentItem); - - if (_closeFlag) { - // Dialog has been flagged to be closed - captureEvents = false; - destroyView(); - return true; - } - - if (_currentItem) { - captureEvents = - (Common::find(_menuObjects.begin(), _menuObjects.end(), _currentItem) != _menuObjects.end()); - if (!captureEvents) - // The menu object is no longer active, so reset current item - _currentItem = NULL; - } else { - captureEvents = false; - } - - if (handledFlag) - return true; - } - - if (eventType == KEVENT_KEY) { - // Handle keypresses by looping through the item list to see if any of them want it - - for (i = _menuObjects.begin(); (i != _menuObjects.end()) && !handledFlag; ++i) { - MenuObject *menuObj = *i; - MenuObject *dummyItem; - handledFlag = menuObj->onEvent(eventType, param, localX, localY, dummyItem); - } - - return handledFlag; - - } else { - // Handle mouse events by scanning the item list to see if the cursor is within any - - for (i = _menuObjects.begin(); (i != _menuObjects.end()) && !handledFlag; ++i) { - MenuObject *menuObj = *i; - - if (menuObj->isInside(localX, localY)) { - // Found an item, so pass it the event - menuObj->onEvent(eventType, param, localX, localY, _currentItem); - - if (_closeFlag) { - // Dialog has been flagged to be closed - captureEvents = false; - destroyView(); - return true; - } - - if (_currentItem) { - captureEvents = - (Common::find(_menuObjects.begin(), _menuObjects.end(), _currentItem) != _menuObjects.end()); - if (!captureEvents) - // The menu object is no longer active, so reset current item - _currentItem = NULL; - } else { - captureEvents = false; - } - - return true; - } - } - } - - // None of the items have handled the event, so fall back on menu-wide event handling - - switch (eventType) { - case MEVENT_LEFT_CLICK: - case MEVENT_DOUBLECLICK: - if (!_screenFlags.immovable) { - // Move the entire dialog - captureEvents = true; - movingFlag = true; - movingPos.x = x; - movingPos.y = y; - } - break; - - case MEVENT_LEFT_DRAG: - case MEVENT_DOUBLECLICK_DRAG: - if (movingFlag) { - moveRelative(x - movingPos.x, y - movingPos.y); - movingPos.x = x; - movingPos.y = y; - } - break; - - case MEVENT_LEFT_RELEASE: - case MEVENT_DOUBLECLICK_RELEASE: - captureEvents = false; - movingFlag = false; - break; - - default: - break; - } - - return true; -} - -MenuObject *OrionMenuView::getItem(int objectId) { - MenuObjectsIterator i; - for (i = _menuObjects.begin(); i != _menuObjects.end(); ++i) { - MenuObject *obj = *i; - if (obj->getObjectId() == objectId) - return obj; - } - - return NULL; -} - -void OrionMenuView::setTopSaveSlot(int slotNumber) { - _topSaveSlotIndex = MAX(MIN(slotNumber, 89), 0); - - // Update the details of the load/save slots - - // Get save slot - SaveGameIterator slot = _saveNames->begin(); - for (int i = 0; i < _topSaveSlotIndex; ++i) - ++slot; - - for (uint index = 0; index < SL_NUM_VISIBLE_SLOTS; ++index, ++slot) { - MenuSaveLoadText *item = (MenuSaveLoadText *) getItem(SLTAG_SLOTS_START + index); - uint slotIndex = _topSaveSlotIndex + index; - - bool isEmpty = (slotIndex >= _saveNames->size()) || slot->empty(); - item->setDisplay(slotIndex + 1, isEmpty ? EmptySaveString : slot->c_str()); - - item->setState((_menuType == SAVE_MENU) || !isEmpty ? OS_NORMAL : OS_GREYED); - } -} - -void OrionMenuView::refresh(const Common::Rect &areaRect) { - // Copy the selected portion of the background - _sprites->getFrame(0)->copyTo(this, areaRect, areaRect.left, areaRect.top); - - for (MenuObjectsIterator i = _menuObjects.begin(); i != _menuObjects.end(); ++i) { - MenuObject *obj = *i; - if (obj->getBounds().intersects(areaRect)) - obj->onRefresh(); - } -} - -} diff --git a/engines/m4/m4_menus.h b/engines/m4/m4_menus.h deleted file mode 100644 index 9abf71e9db..0000000000 --- a/engines/m4/m4_menus.h +++ /dev/null @@ -1,103 +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. - * - */ - -#ifndef M4_M4_MENUS_H -#define M4_M4_MENUS_H - -#include "common/list.h" -#include "common/ptr.h" - -#include "m4/viewmgr.h" -#include "m4/m4.h" -#include "m4/gui.h" -#include "m4/saveload.h" - -namespace M4 { - -#define M4_DIALOG_FADE_STEPS 5 -#define M4_DIALOG_FADE_DELAY 30 - -typedef Common::List MenuObjectList; - -class OrionMenuView : public DialogView { - typedef MenuObjectList::iterator MenuObjectsIterator; -private: - MenuType _menuType; - SpriteAsset *_sprites; - MenuObjectList _menuObjects; - MenuObject *_currentItem; - typedef void (*Callback)(OrionMenuView *view); - OrionMenuView::Callback _escapeHandler, _returnHandler; - bool _closeFlag; - bool _calledFromMainMenu; - bool _interfaceWasVisible; - int _firstSlotIndex; - - bool loadSprites(const char *seriesName); - M4Surface *createThumbnail(); - void destroyView(); -public: - OrionMenuView(MadsM4Engine *vm, int x, int y, MenuType menuType, bool calledFromMainMenu, - bool loadSaveFromHotkey); - ~OrionMenuView(); - MenuType getMenuType() { return _menuType; } - SpriteAsset *sprites() { return _sprites; } - MenuObjectList &items() { return _menuObjects; } - MenuObject *getItem(int objectId); - void setTopSaveSlot(int slotNumber); - void refresh(const Common::Rect &areaRect); - void close() { _closeFlag = true; } - - bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); - - int _originalMidiVolume; - SaveGameList *_saveNames; - bool _loadSaveFromHotkey; -}; - -class OrionCallbacks { -public: - static void closeMenuFn(DialogView *view, MenuObject *item); - static void closeMenuFn(OrionMenuView *view); - static void gameOptionsMenuFn(DialogView *view, MenuObject *item); - static void gameSaveGameFn(DialogView *view, MenuObject *item); - static void gameLoadGameFn(DialogView *view, MenuObject *item); - static void gameExitFn(DialogView *view, MenuObject *item); - static void optionsDigiSliderFn(DialogView *view, MenuObject *item); - static void optionsMidiSliderFn(DialogView *view, MenuObject *item); - static void optionsScrollingFn(DialogView *view, MenuObject *item); - static void optionsCancelFn(DialogView *view, MenuObject *item); - static void optionsDoneFn(DialogView *view, MenuObject *item); - static void optionsReturnFn(OrionMenuView *view); - static void optionsEscapeFn(OrionMenuView *view); - static void saveLoadSaveFn(DialogView *view, MenuObject *item); - static void saveLoadLoadFn(DialogView *view, MenuObject *item); - static void saveLoadSlotFn(DialogView *view, MenuObject *item); - static void saveLoadCancelFn(DialogView *view, MenuObject *item); - static void saveLoadSliderFn(DialogView *view, MenuObject *item); - static void saveLoadEscapeFn(OrionMenuView *view); - static void saveLoadReturnFn(OrionMenuView *view); -}; - -} - -#endif diff --git a/engines/m4/m4_scene.cpp b/engines/m4/m4_scene.cpp deleted file mode 100644 index 1a2e00e50d..0000000000 --- a/engines/m4/m4_scene.cpp +++ /dev/null @@ -1,326 +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/m4_scene.h" -#include "m4/dialogs.h" -#include "m4/globals.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" - -namespace M4 { - -M4Scene::M4Scene(M4Engine *vm): _sceneResources(), Scene(vm, &_sceneResources) { - _vm = vm; - _sceneSprites = NULL; - _inverseColorTable = NULL; - - _sceneResources.hotspots = new HotSpotList(); - _sceneResources.parallax = new HotSpotList(); - _sceneResources.dynamicHotspots = new HotSpotList(); - _interfaceSurface = new M4InterfaceView(vm); -} - -M4Scene::~M4Scene() { - delete _sceneSprites; -} - -void M4Scene::loadSceneSprites(int sceneNumber) { - char filename[kM4MaxFilenameSize]; - sprintf(filename, "%i.ssb", sceneNumber); - - Common::SeekableReadStream *sceneS = _vm->res()->get(filename); - _sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename); - _vm->res()->toss(filename); - - debugCN(kDebugGraphics, "Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount()); -} - -void M4Scene::loadSceneResources(int sceneNumber) { - char filename[kM4MaxFilenameSize]; - int i = 0, x = 0, y = 0; - sprintf(filename, "%i.chk", sceneNumber); - - Common::SeekableReadStream *sceneS = _vm->res()->get(filename); - - if (sceneS != NULL) { - sceneS->read(_sceneResources.artBase, MAX_CHK_FILENAME_SIZE); - sceneS->read(_sceneResources.pictureBase, MAX_CHK_FILENAME_SIZE); - int hotspotCount = sceneS->readUint32LE(); - _sceneResources.parallaxCount = sceneS->readUint32LE(); - int dynHotspotCount = sceneS->readUint32LE(); - _sceneResources.frontY = sceneS->readUint32LE(); - _sceneResources.backY = sceneS->readUint32LE(); - _sceneResources.frontScale = sceneS->readUint32LE(); - _sceneResources.backScale = sceneS->readUint32LE(); - for (i = 0; i < 16; i++) - _sceneResources.depthTable[i] = sceneS->readUint16LE(); - _sceneResources.railNodeCount = sceneS->readUint32LE(); - - // Clear rails from previous scene - _vm->_rails->clearRails(); - - for (i = 0; i < _sceneResources.railNodeCount; i++) { - x = sceneS->readUint32LE(); - y = sceneS->readUint32LE(); - if (_vm->_rails->addRailNode(x, y, true) < 0) { - warning("Too many rail nodes defined for scene"); - } - } - - // Clear current hotspot lists - _sceneResources.hotspots->clear(); - _sceneResources.parallax->clear(); - _sceneResources.dynamicHotspots->clear(); - - _sceneResources.hotspots->loadHotSpots(sceneS, hotspotCount); - _sceneResources.parallax->loadHotSpots(sceneS, _sceneResources.parallaxCount); - _sceneResources.dynamicHotspots->loadHotSpots(sceneS, dynHotspotCount); - - // Note that toss() deletes the MemoryReadStream - _vm->res()->toss(filename); - } -} - -void M4Scene::loadSceneInverseColorTable(int sceneNumber) { - char filename[kM4MaxFilenameSize]; - Common::SeekableReadStream *iplS; - - sprintf(filename, "%i.ipl", sceneNumber); - iplS = _vm->res()->openFile(filename); - delete[] _inverseColorTable; - _inverseColorTable = new byte[iplS->size()]; - iplS->read(_inverseColorTable, iplS->size()); - _vm->res()->toss(filename); -} - -void M4Scene::loadSceneSpriteCodes(int sceneNumber) { - char filename[kM4MaxFilenameSize]; - sprintf(filename, "%i.ssc", sceneNumber); - - Common::SeekableReadStream *sceneS = _vm->res()->get(filename); - - // TODO - - if (sceneS != NULL) { - SpriteAsset* _sceneSpriteCodes = new SpriteAsset(_vm, sceneS, sceneS->size(), filename); - int colorCount = _sceneSpriteCodes->getColorCount(); -// RGB8* spritePalette = _sceneSpriteCodes->getPalette(); - //_vm->_palette->setPalette(spritePalette, 0, colorCount); - - debugCN(kDebugGraphics, "Scene has %d sprite codes, each one having %d colors\n", _sceneSpriteCodes->getCount(), colorCount); - - // Note that toss() deletes the MemoryReadStream - _vm->res()->toss(filename); - } -} - -void M4Scene::loadScene(int sceneNumber) { - Scene::loadScene(sceneNumber); - - _backgroundSurface->loadBackground(sceneNumber); - _palData = NULL; - - if (_vm->getGameType() == GType_Burger && - sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) - setStatusText(""); - - // Load scene def file (*.CHK) - loadSceneResources(sceneNumber); - - // TODO: set walker scaling - // TODO: destroy woodscript buffer - - // Load scene walk path file (*.COD/*.WW?) - loadSceneCodes(sceneNumber); - - // Load inverse color table file (*.IPL) - loadSceneInverseColorTable(sceneNumber); - - if (_vm->getGameType() != GType_Burger) { - // Load scene sprites file (*.SSB) - loadSceneSprites(sceneNumber); - - // Load scene sprite codes file (*.SSC) - loadSceneSpriteCodes(sceneNumber); - } - - - if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) { - _m4Vm->scene()->getInterface()->show(); - showSprites(); - } - - // Purge resources - _vm->res()->purge(); -} - -void M4Scene::loadSceneCodes(int sceneNumber, int index) { - char filename[kM4MaxFilenameSize]; - Common::SeekableReadStream *sceneS; - - sprintf(filename, "%i.cod", sceneNumber); - sceneS = _vm->res()->openFile(filename); - _walkSurface->loadCodesM4(sceneS); - _vm->res()->toss(filename); -} - -void M4Scene::show() { - Scene::show(); - _vm->_viewManager->addView(_interfaceSurface); -} - -void M4Scene::leaveScene() { - _sceneResources.parallax->clear(); - - delete _sceneResources.parallax; - delete[] _inverseColorTable; - - Scene::leaveScene(); -} - -void M4Scene::mouseMove(int x, int y) { - if (_vm->getGameType() == GType_Riddle) - return; - - // TODO: loads of things to do here, only the mouse cursor and the status - // text is changed for now - - // Only scene hotspots are checked for now, not parallax/props, as the - // latter ones are not used by Orion Burger - HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); - if (currentHotSpot != NULL && currentHotSpot->getActive()) { - if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && - _vm->_mouse->getCursorNum() != CURSOR_TAKE && - _vm->_mouse->getCursorNum() != CURSOR_USE && - _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { - _vm->_mouse->setCursorNum(currentHotSpot->getCursor()); - } - _m4Vm->scene()->getInterface()->setStatusText(currentHotSpot->getPrep()); - } else { - if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && - _vm->_mouse->getCursorNum() != CURSOR_TAKE && - _vm->_mouse->getCursorNum() != CURSOR_USE && - _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { - _vm->_mouse->setCursorNum(0); - } else { - - } - } -} - -void M4Scene::leftClick(int x, int y) { - if (_vm->getGameType() == GType_Burger) { - // Place a Wilbur sprite with the correct facing - HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y); - if (currentHotSpot != NULL && currentHotSpot->getActive()) { - update(); - _vm->_actor->setWalkerDirection(currentHotSpot->getFacing()); - /* - int posX = currentHotSpot->getFeetX(); - int posY = currentHotSpot->getFeetY() - - scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0); - //_vm->_actor->placeWalkerSpriteAt(0, posX, posY); - */ - - // Player said.... (for scene scripts) - debugCN(kDebugGraphics, "Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab()); - - // FIXME: This should be moved somewhere else, and is incomplete - if (_m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { - if (_vm->_mouse->getVerb() == NULL) { - strcpy(_vm->_player->verb, currentHotSpot->getVerb()); - } else { - strcpy(_vm->_player->verb, _vm->_mouse->getVerb()); - } - } else { - strcpy(_vm->_player->verb, _m4Vm->scene()->getInterface()->_inventory.getSelectedObjectName()); - } - strcpy(_vm->_player->noun, currentHotSpot->getVocab()); - strcpy(_vm->_player->object, ""); - _vm->_player->commandReady = true; - - debugCN(kDebugGraphics, "## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun); - - } - } -} - -void M4Scene::rightClick(int x, int y) { - if (_vm->getGameType() == GType_Burger) { - nextCommonCursor(); - _m4Vm->scene()->getInterface()->_inventory.clearSelected(); - } -} - -void M4Scene::setAction(int action, int objectId) { -} - -void M4Scene::setStatusText(const char *text) { - getInterface()->setStatusText(text); -} - -void M4Scene::update() { - -} - -void M4Scene::nextCommonCursor() { - int cursorIndex = _vm->_mouse->getCursorNum(); - - switch (cursorIndex) { - case CURSOR_ARROW: - cursorIndex = CURSOR_LOOK; - break; - case CURSOR_LOOK: - cursorIndex = CURSOR_TAKE; - break; - case CURSOR_TAKE: - cursorIndex = CURSOR_USE; - break; - case CURSOR_USE: - cursorIndex = CURSOR_ARROW; - break; - default: - cursorIndex = CURSOR_ARROW; - } - - _vm->_mouse->setCursorNum(cursorIndex); -} - -void M4Scene::showHotSpots() { - Scene::showHotSpots(); - - // parallax (yellow) - for (int i = 0; i < _sceneResources.parallaxCount; i++) { - HotSpot *currentHotSpot = _sceneResources.parallax->get(i); - _backgroundSurface->frameRect(currentHotSpot->getRect(), _vm->_palette->YELLOW); - } -} - -} // End of namespace M4 diff --git a/engines/m4/m4_scene.h b/engines/m4/m4_scene.h deleted file mode 100644 index a0ba497cf7..0000000000 --- a/engines/m4/m4_scene.h +++ /dev/null @@ -1,84 +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. - * - */ - -#ifndef M4_M4_SCENE_H -#define M4_M4_SCENE_H - -class View; - -#include "m4/scene.h" - -namespace M4 { - -#define TITLE_SCENE_BURGER 951 // 951 = intro, 901 = demo menu, 971 = first scene -#define MAINMENU_SCENE_BURGER 903 -#define FIRST_SCENE 101 - -class M4SceneResources : public SceneResources { -public: - int32 frontY, backY; - int32 frontScale, backScale; - int16 depthTable[16]; - int32 railNodeCount; // # of rails - - int32 parallaxCount; - HotSpotList *parallax; -}; - -class M4Scene : public Scene { -private: - M4Engine *_vm; - M4SceneResources _sceneResources; - SpriteAsset *_sceneSprites; - SpriteAsset *_walkerSprite; - byte *_inverseColorTable; - - void loadSceneSprites(int sceneNumber); - void loadSceneResources(int sceneNumber); - void loadSceneInverseColorTable(int sceneNumber); - void loadSceneSpriteCodes(int sceneNumber); - void nextCommonCursor(); -public: - M4Scene(M4Engine *vm); - virtual ~M4Scene(); - - // Methods that differ between engines - virtual void loadScene(int sceneNumber); - virtual void leaveScene(); - virtual void loadSceneCodes(int sceneNumber, int index = 0); - virtual void show(); - virtual void mouseMove(int x, int y); - virtual void leftClick(int x, int y); - virtual void rightClick(int x, int y); - virtual void update(); - virtual void showHotSpots(); - - byte *getInverseColorTable() const { return _inverseColorTable; } - M4InterfaceView *getInterface() { return (M4InterfaceView *)_interfaceSurface; } - M4SceneResources &getSceneResources() { return _sceneResources; } - void setStatusText(const char *text); - void setAction(int action, int objectId = -1); -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/m4_views.cpp b/engines/m4/m4_views.cpp deleted file mode 100644 index 1324526ab5..0000000000 --- a/engines/m4/m4_views.cpp +++ /dev/null @@ -1,342 +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/textconsole.h" - -#include "m4/m4_views.h" -#include "m4/events.h" -#include "m4/font.h" -#include "m4/globals.h" -#include "m4/m4.h" - -namespace M4 { - -GUIInventory::GUIInventory(View *owner, MadsM4Engine *vm, const Common::Rect &bounds, int horizCells, - int vertCells, int cellWidth, int cellHeight, int tag): GUIRect(owner, bounds, tag) { - - _vm = vm; - _cellCount.x = horizCells; - _cellCount.y = vertCells; - _cellSize.x = cellWidth; - _cellSize.y = cellHeight; - - // Validate the cell settings - if ((_cellCount.x * _cellSize.x > _bounds.width()) || - (_cellCount.y * _cellSize.y > _bounds.height())) - error("Cell settings for inventory display exceeded control size"); - - _visible = true; - _scrollPosition = 0; - _scrollable = false; - _highlightedIndex = -1; - _selectedIndex = -1; -} - -void GUIInventory::onRefresh() { - _parent->fillRect(_bounds, _vm->_palette->BLACK); - //_parent->frameRect(_bounds, _vm->_palette->LIGHT_GRAY); - - if (_visible) { - //kernel_trigger_dispatch(kernel_trigger_create(TRIG_INV_CLICK)); - - _scrollable = false; - - // Get to the starting inventory position for display - ItemsIterator i = _inventoryItems.begin(); - int index = _scrollPosition; - while (index-- > 0) ++i; - - // Loop through displaying entries - for (index = 0; (i != _inventoryItems.end()) && (index < _cellCount.x * _cellCount.y); ++index, ++i) { - GUIInventoryItem *item = (*i).get(); - const Common::Point cellPos = getCellPosition(index); -/* Common::Rect cellBounds(_bounds.left + cellPos.x + xOffset, - _bounds.top + cellPos.y + yOffset, - _bounds.left + cellPos.x + xOffset + _cellSize.x, - _bounds.top + cellPos.y + _cellSize.y);*/ - Common::Rect cellBounds(_bounds.left + cellPos.x, _bounds.top + cellPos.y, - _bounds.left + cellPos.x + _cellSize.x, _bounds.top + cellPos.y + _cellSize.y); - - Common::Point iconPt( - cellBounds.left + (cellBounds.width() - item->icon->width()) / 2, - cellBounds.top + (cellBounds.height() - item->icon->height()) / 2); - - item->icon->copyTo(_parent, iconPt.x, iconPt.y, 0); - - if (_highlightedIndex == index) - _parent->frameRect(Common::Rect(iconPt.x - 2, iconPt.y - 2, - iconPt.x + item->icon->width() + 2, iconPt.y + item->icon->height() + 2), - _vm->_palette->LIGHT_GRAY); - } - } -} - -bool GUIInventory::onEvent(M4EventType eventType, int32 param, int x, int y, GUIObject *¤tItem) { - bool result = false; - int overIndex = getInsideIndex(x, y); - bool isPressed = (eventType == MEVENT_LEFT_CLICK) || (eventType == MEVENT_LEFT_HOLD) || - (eventType == MEVENT_LEFT_DRAG); - ItemsIterator curItem = _inventoryItems.begin(); - - if (isPressed) { - if (_selectedIndex == -1 && overIndex != -1) { - setHighlight(overIndex); - _selectedIndex = overIndex; - for (int i = 0; i < _scrollPosition + _selectedIndex; i++) - ++curItem; - if (_scrollPosition + _selectedIndex < (int)_inventoryItems.size()) - _vm->_mouse->setCursorNum(curItem->get()->iconIndex); - result = true; - } else { - // We are over something being tracked - if (_selectedIndex == overIndex) { - setHighlight(overIndex); - result = true; - } else { - // Otherwise reset highlighting - setHighlight(-1); - result = false; - } - } - } else { - // No button pressed - if (_selectedIndex == overIndex) { - result = (_selectedIndex != -1); - } else { - result = (overIndex + _scrollPosition < (int)_inventoryItems.size()); - if (result) { - for (int i = 0; i < overIndex + _scrollPosition; i++) - ++curItem; - _m4Vm->scene()->getInterface()->setStatusText(curItem->get()->name); - } - } - - // Stop tracking anything - setHighlight(overIndex); - } - - return result; -} - -void GUIInventory::add(const char *name, const char *verb, M4Surface *icon, int iconIndex) { - // First scan through the list to prevent duplicate objects - for (ItemsIterator i = _inventoryItems.begin(); i != _inventoryItems.end(); ++i) { - if (!strcmp(name, ((*i).get())->name)) - return; - } - - _inventoryItems.push_back(InventoryList::value_type(new GUIInventoryItem(name, verb, icon, iconIndex))); -} - -bool GUIInventory::remove(const char *name) { - for (ItemsIterator i = _inventoryItems.begin(); i != _inventoryItems.end(); ++i) { - if (!strcmp(name, ((*i).get())->name)) { - _inventoryItems.erase(i); - _scrollPosition = 0; - return true; - } - } - - return false; -} - -int GUIInventory::getInsideIndex(int x, int y) { - if (!_bounds.contains(x, y)) - return -1; - - int localX = x - _bounds.left; - int localY = y - _bounds.top; - return (localX / _cellSize.x) * _cellCount.y + (localY / _cellSize.y); -} - -const char *GUIInventory::getSelectedObjectName() { - if (_selectedIndex != -1) { - ItemsIterator curItem = _inventoryItems.begin(); - for (int i = 0; i < _selectedIndex; i++) - ++curItem; - return curItem->get()->name; - } else { - return NULL; - } -} - -const Common::Point &GUIInventory::getCellPosition(int index) { - static Common::Point result; - - if (_cellCount.x > _cellCount.y) { - // Horizontal orientation - result.x = (index / _cellCount.y) * _cellSize.x; - result.y = (index % _cellCount.y) * _cellSize.x; - } else { - // Vertical orientation - result.x = (index / _cellCount.x) * _cellSize.y; - result.y = (index % _cellCount.x) * _cellSize.y; - } - - return result; -} - -void GUIInventory::setHighlight(int index) { - if (_highlightedIndex == index) - return; - - _highlightedIndex = index; -} - -void GUIInventory::setScrollPosition(int value) { - if (value < 0) - return; - else if (value >= (int)_inventoryItems.size() - (_cellCount.x * _cellCount.y)) - return; - - _scrollPosition = value; -} - -//-------------------------------------------------------------------------- - -const char *INTERFACE_SERIES = "999intr"; - -#define SPR(x) _sprites->getFrame(x) - -M4InterfaceView::M4InterfaceView(MadsM4Engine *vm): - GameInterfaceView(vm, Common::Rect(0, vm->_screen->height() - INTERFACE_HEIGHT, - vm->_screen->width(), vm->_screen->height())), - _statusText(GUITextField(this, Common::Rect(200, 1, 450, 21))), - _inventory(GUIInventory(this, vm, Common::Rect(188, 22, 539, 97), 9, 1, 39, 75, 3)) { - - _screenType = VIEWID_INTERFACE; - _screenFlags.layer = LAYER_INTERFACE; - _screenFlags.visible = false; - _screenFlags.get = SCREVENT_MOUSE; - _highlightedIndex = -1; - _selected = false; - - Common::SeekableReadStream *data = _vm->res()->get(INTERFACE_SERIES); - _sprites = new SpriteAsset(_vm, data, data->size(), INTERFACE_SERIES); - - //RGB8 *palette = _sprites->getPalette(); - //Palette.setPalette(palette, 0, _sprites->getColorCount()); - - _vm->res()->toss(INTERFACE_SERIES); - - // Setup the interface buttons - - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(15, 35, 47, 66), 0, SPR(0), SPR(1), SPR(2)))); // look - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(60, 35, 92, 66), 1, SPR(3), SPR(4), SPR(5)))); // take - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(105, 35, 137, 66), 2, SPR(6), SPR(7), SPR(8)))); // manipulate - - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(580, 10, 620, 69), 3, SPR(69), SPR(70), SPR(71)))); // abduction - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(582, 70, 619, 105), 4, SPR(76), SPR(77), SPR(78)))); // menu - - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(168, 22, 188, 97), 5, SPR(60), SPR(61), SPR(62)))); // Scroll left - _buttons.push_back(ButtonList::value_type(new GUIButton(this, Common::Rect(539, 22, 559, 97), 6, SPR(64), SPR(65), SPR(66)))); // Scroll right -} - -#undef SPR - -M4InterfaceView::~M4InterfaceView() { - delete _sprites; -} - -void M4InterfaceView::setHighlightedButton(int index) { - if (index == _highlightedIndex) - return; - - _selected = (index == -1); - _highlightedIndex = index; -} - -bool M4InterfaceView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - static bool selectionFlag = false; - if (eventType == MEVENT_LEFT_RELEASE) - selectionFlag = false; - - captureEvents = isInside(x, y); - if (!captureEvents) - return false; - - int localX = x - _coords.left; - int localY = y - _coords.top; - GUIObject *currentItem; - - _statusText.onEvent(eventType, param, localX, localY, currentItem); - _inventory.onEvent(eventType, param, localX, localY, currentItem); - - if (_vm->_mouse->getCursorNum() != CURSOR_LOOK && - _vm->_mouse->getCursorNum() != CURSOR_TAKE && - _vm->_mouse->getCursorNum() != CURSOR_USE && - _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) { - if (_vm->_mouse->getCursorNum() != 0) - _vm->_mouse->setCursorNum(0); - } - - for (ButtonsIterator i = _buttons.begin(); i != _buttons.end(); ++i) { - GUIButton *btn = (*i).get(); - btn->onEvent(eventType, param, localX, localY, currentItem); - if ((btn->getState() == BUTTON_PRESSED) && !selectionFlag) { - selectionFlag = true; - _highlightedIndex = btn->getTag(); - - switch (_highlightedIndex) { - case 0: - _vm->_mouse->setCursorNum(CURSOR_LOOK); - break; - case 1: - _vm->_mouse->setCursorNum(CURSOR_TAKE); - break; - case 2: - _vm->_mouse->setCursorNum(CURSOR_USE); - break; - case 3: - // TODO: Jump to abduction - break; - case 4: - _vm->loadMenu(GAME_MENU); - break; - case 5: - _inventory.scrollLeft(); - break; - case 6: - _inventory.scrollRight(); - break; - default: - break; - } - } - } - - return true; -} - -void M4InterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { - clear(); - - _statusText.onRefresh(); - _inventory.onRefresh(); - for (ButtonsIterator i = _buttons.begin(); i != _buttons.end(); ++i) - ((*i).get())->onRefresh(); - - View::onRefresh(rects, destSurface); -} - - -} // End of namespace M4 diff --git a/engines/m4/m4_views.h b/engines/m4/m4_views.h deleted file mode 100644 index 4ca2a74593..0000000000 --- a/engines/m4/m4_views.h +++ /dev/null @@ -1,115 +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. - * - */ - -#ifndef M4_M4_VIEWS_H -#define M4_M4_VIEWS_H - -#include "m4/gui.h" -#include "m4/viewmgr.h" -#include "common/rect.h" -#include "common/list.h" -#include "common/ptr.h" - -namespace M4 { - -class GUIInventoryItem { -public: - const char *name; - const char *verb; - M4Surface *icon; - int iconIndex; - - GUIInventoryItem(const char *_name, const char *_verb, M4Surface *_icon, int _iconIndex) { - name = _name; verb = _verb; icon = _icon; iconIndex = _iconIndex; - } -}; - -class GUIInventory : public GUIRect { - typedef Common::List > InventoryList; - typedef InventoryList::iterator ItemsIterator; -private: - InventoryList _inventoryItems; - Common::Point _cellSize; - Common::Point _cellCount; - bool _visible; - bool _scrollable; - int _scrollPosition; - int _highlightedIndex; - int _selectedIndex; - MadsM4Engine *_vm; -public: - GUIInventory(View *owner, MadsM4Engine *vm, const Common::Rect &bounds, - int horizCells, int vertCells, int cellWidth, int cellHeight, int tag); - - void onRefresh(); - bool onEvent(M4EventType eventType, int32 param, int x, int y, GUIObject *¤tItem); - - void add(const char *name, const char *verb, M4Surface *icon, int iconIndex); - bool remove(const char *name); - int getInsideIndex(int x, int y); - int getSelectedIndex() { return _selectedIndex; } - const char *getSelectedObjectName(); - void clearSelected() { - _selectedIndex = -1; - setHighlight(-1); - } - const Common::Point &getCellPosition(int index); - void setHighlight(int index); - bool needLeftButton() { return _scrollPosition != 0; } - bool needRightButton() { - return (uint)(_inventoryItems.size() - _scrollPosition) > (uint)(_cellCount.x * _cellCount.y); - } - void setScrollPosition(int value); - void scrollLeft() { setScrollPosition(_scrollPosition - 1); } - void scrollRight() { setScrollPosition(_scrollPosition + 1); } - void setVisible(bool value) { _visible = value; } -}; - -class M4InterfaceView : public GameInterfaceView { - typedef Common::List > ButtonList; - typedef ButtonList::iterator ButtonsIterator; -public: - SpriteAsset *_sprites; - ButtonList _buttons; - GUITextField _statusText; - GUIInventory _inventory; - int _highlightedIndex; - bool _selected; -private: - void setHighlightedButton(int index); -public: - M4InterfaceView(MadsM4Engine *vm); - ~M4InterfaceView(); - - void onRefresh(RectList *rects, M4Surface *destSurface); - bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); - void setStatusText(const char *text) { _statusText.setText(text); } - void cancelSentence() { setStatusText(NULL); } - void inventoryAdd(const char *name, const char *verb, int iconIndex) { - _inventory.add(name, verb, _sprites->getFrame(iconIndex), iconIndex); - } - bool inventoryRemove(const char *name) { return _inventory.remove(name); } -}; - -} - -#endif diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp deleted file mode 100644 index aac21ae65d..0000000000 --- a/engines/m4/mads_anim.cpp +++ /dev/null @@ -1,745 +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/textconsole.h" - -#include "m4/mads_anim.h" -#include "m4/m4.h" -#include "m4/compression.h" - -namespace M4 { - -#define TEXTVIEW_LINE_SPACING 2 -#define TEXT_ANIMATION_DELAY 100 -#define TV_NUM_FADE_STEPS 40 -#define TV_FADE_DELAY_MILLI 50 - -TextviewView::TextviewView(MadsM4Engine *vm): - View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())), - _bgSurface(vm->_screen->width(), MADS_SURFACE_HEIGHT), - _textSurface(vm->_screen->width(), MADS_SURFACE_HEIGHT + vm->_font->current()->getHeight() + - TEXTVIEW_LINE_SPACING) { - - _screenType = VIEWID_TEXTVIEW; - _screenFlags.layer = LAYER_BACKGROUND; - _screenFlags.visible = true; - _screenFlags.get = SCREVENT_ALL; - _callback = NULL; - _script = NULL; - _spareScreen = NULL; - _bgCurrent = NULL; - _bgSpare = NULL; - reset(); - - // Set up system palette colors and the two colors for text display - _vm->_palette->setMadsSystemPalette(); - RGB8 palData[3]; - palData[0].r = palData[0].g = palData[0].b = 0; - palData[1].r = 0; palData[1].g = palData[1].b = 252; - palData[2].r = 0; palData[2].g = palData[2].b = 180; - _vm->_palette->setPalette(&palData[0], 4, 3); - _vm->_palette->blockRange(4, 3); - - _vm->_font->current()->setColors(5, 6, 4); - - clear(); - _bgSurface.clear(); - _textSurface.clear(); - - int y = (height() - MADS_SURFACE_HEIGHT) / 2; - setColor(2); - hLine(0, width() - 1, y - 2); - hLine(0, width() - 1, height() - y + 1); -} - -TextviewView::~TextviewView() { - if (_script) - _vm->res()->toss(_resourceName); - delete _spareScreen; - delete _bgCurrent; - delete _bgSpare; -} - -void TextviewView::reset() { - _bgSurface.clear(); - _textSurface.clear(); - _animating = false; - _panX = 0; - _panY = 0; - _panSpeed = 0; - _soundDriverLoaded = false; - Common::fill(&_spareScreens[0], &_spareScreens[10], 0); - _scrollCount = 0; - _lineY = -1; - _scrollTimeout = 0; - _panCountdown = 0; - _processEvents = true; -} - -void TextviewView::setScript(const char *resourceName, TextviewCallback callback) { - _callback = callback; - if (_script) - _vm->res()->toss(_resourceName); - if (_spareScreen) { - delete _spareScreen; - _spareScreen = NULL; - } - - reset(); - - strncpy(_resourceName, resourceName, 15); - _resourceName[15] = '\0'; - if (!strchr(_resourceName, '.')) - strcat(_resourceName, ".txr"); - - _script = _vm->res()->get(_resourceName); - - processLines(); -} - -bool TextviewView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - if (!_processEvents) - return false; - - // Wait for the Escape key or a mouse press - if (((eventType == KEVENT_KEY) && (param == Common::KEYCODE_ESCAPE)) || - (eventType == MEVENT_LEFT_RELEASE) || (eventType == MEVENT_RIGHT_RELEASE)) { - scriptDone(); - captureEvents = false; - return true; - } - - return false; -} - -void TextviewView::updateState() { - if (!_animating) - return; - - // Only update state if wait period has expired - uint32 currTime = g_system->getMillis(); - - // If a screen transition is in progress and it's time for another column, handle it - if (_spareScreen) { - byte *srcP = _spareScreen->getBasePtr(_translationX, 0); - byte *destP = _bgSurface.getBasePtr(_translationX, 0); - - for (int y = 0; y < _bgSurface.height(); ++y, srcP += _spareScreen->width(), - destP += _bgSurface.width()) { - *destP = *srcP; - } - - if (++_translationX >= _bgSurface.width()) { - // Surface transition is complete - delete _spareScreen; - _spareScreen = NULL; - - _vm->_palette->deleteRange(_bgCurrent); - delete _bgCurrent; - _bgCurrent = _bgSpare; - _bgSpare = NULL; - } - } - - // Make sure it's time for an update - if (currTime < _scrollTimeout) - return; - _scrollTimeout = g_system->getMillis() + TEXT_ANIMATION_DELAY; - - // If any panning values are set, pan the background surface - if ((_panX != 0) || (_panY != 0)) { - if (_panCountdown > 0) { - --_panCountdown; - return; - } - - // Handle horizontal panning - if (_panX != 0) { - byte *lineTemp = new byte[_panX]; - for (int y = 0; y < _bgSurface.height(); ++y) { - byte *pixelsP = _bgSurface.getBasePtr(0, y); - - // Copy the first X pixels into temp buffer, move the rest of the line - // to the start of the line, and then move temp buffer pixels to end of line - Common::copy(pixelsP, pixelsP + _panX, lineTemp); - Common::copy(pixelsP + _panX, pixelsP + _bgSurface.width(), pixelsP); - Common::copy(lineTemp, lineTemp + _panX, pixelsP + _bgSurface.width() - _panX); - } - - delete[] lineTemp; - } - - // Handle vertical panning - if (_panY != 0) { - // Store the bottom Y lines into a temp buffer, move the rest of the lines down, - // and then copy the stored lines back to the top of the screen - byte *linesTemp = new byte[_panY * _bgSurface.width()]; - byte *pixelsP = _bgSurface.getBasePtr(0, _bgSurface.height() - _panY); - Common::copy(pixelsP, pixelsP + _bgSurface.width() * _panY, linesTemp); - - for (int y = _bgSurface.height() - 1; y >= _panY; --y) { - byte *destP = _bgSurface.getBasePtr(0, y); - byte *srcP = _bgSurface.getBasePtr(0, y - _panY); - Common::copy(srcP, srcP + _bgSurface.width(), destP); - } - - Common::copy(linesTemp, linesTemp + _panY * _bgSurface.width(), _bgSurface.getBasePtr(0, 0)); - delete[] linesTemp; - } - } - - // Scroll the text surface up by one row - byte *pixelsP = _textSurface.getBasePtr(0, 0); - Common::copy(pixelsP + width(), pixelsP + _textSurface.width() * _textSurface.height(), pixelsP); - pixelsP = _textSurface.getBasePtr(0, _textSurface.height() - 1); - Common::fill(pixelsP, pixelsP + _textSurface.width(), _vm->_palette->BLACK); - - if (_scrollCount > 0) { - // Handling final scrolling of text off of screen - if (--_scrollCount == 0) { - scriptDone(); - return; - } - } else { - // Handling a text row - if (++_lineY == (_vm->_font->current()->getHeight() + TEXTVIEW_LINE_SPACING)) - processLines(); - } - - // Refresh the view - int yp = (height() - _bgSurface.height()) / 2; - _bgSurface.copyTo(this, 0, yp); - _textSurface.copyTo(this, Common::Rect(0, 0, _textSurface.width(), _bgSurface.height()), - 0, yp, _vm->_palette->BLACK); -} - -void TextviewView::scriptDone() { - TextviewCallback fn = _callback; - MadsM4Engine *vm = _vm; - - // Remove this view from manager and destroy it - _vm->_viewManager->deleteView(this); - - if (fn) - fn(vm); -} - -void TextviewView::processLines() { - strncpy(_currentLine, _script->readLine().c_str(), 79); - if (_script->eos() || _script->err()) - error("Attempted to read past end of response file"); - - while (!_script->eos() && !_script->err()) { - // Commented out line, so go loop for another - if (_currentLine[0] == '#') { - strncpy(_currentLine, _script->readLine().c_str(), 79); - continue; - } - - // Process the line - char *cStart = strchr(_currentLine, '['); - if (cStart) { - while (cStart) { - // Loop for possible multiple commands on one line - char *cEnd = strchr(_currentLine, ']'); - if (!cEnd) - error("Unterminated command '%s' in response file", _currentLine); - - *cEnd = '\0'; - processCommand(); - - // Copy rest of line (if any) to start of buffer - strcpy(_currentLine, cEnd + 1); - - cStart = strchr(_currentLine, '['); - } - - if (_currentLine[0]) { - processText(); - break; - } - - } else { - processText(); - break; - } - - strncpy(_currentLine, _script->readLine().c_str(), 79); - } -} - -void TextviewView::processCommand() { - char commandStr[80]; - char *paramP; - strcpy(commandStr, _currentLine + 1); - str_upper(commandStr); - - if (!strncmp(commandStr, "BACKGROUND", 10)) { - // Set the background - paramP = commandStr + 10; - int screenId = getParameter(¶mP); - _bgSurface.loadBackground(screenId, &_bgCurrent); - _vm->_palette->addRange(_bgCurrent); - _bgSurface.translate(_bgCurrent); - - } else if (!strncmp(commandStr, "GO", 2)) { - _animating = true; - - // Grab what the final palete will be - RGB8 destPalette[256]; - _vm->_palette->grabPalette(destPalette, 0, 256); - - // Copy the loaded background, if any, to the view surface - int yp = (height() - _bgSurface.height()) / 2; - _bgSurface.copyTo(this, 0, yp); - - // Handle fade-in - _processEvents = false; // stop processing events during fade-in - _vm->_palette->fadeIn(TV_NUM_FADE_STEPS, TV_FADE_DELAY_MILLI, destPalette, 256); - _processEvents = true; - - } else if (!strncmp(commandStr, "PAN", 3)) { - // Set panning values - paramP = commandStr + 3; - int panX = getParameter(¶mP); - int panY = getParameter(¶mP); - int panSpeed = getParameter(¶mP); - - if ((panX != 0) || (panY != 0)) { - _panX = panX; - _panY = panY; - _panSpeed = panSpeed; - } - - } else if (!strncmp(commandStr, "DRIVER", 6)) { - // Set the driver to use - // TODO: Handling of the sound drivers - - } else if (!strncmp(commandStr, "SOUND", 5)) { - // Set sound number - paramP = commandStr + 5; - //int soundId = getParameter(¶mP); - - //TODO: Proper handling of the sound drivers/sounds - //if (!_soundDriverLoaded) - // error("Attempted to set sound without loading any driver"); - - } else if (!strncmp(commandStr, "COLOR", 5) && ((commandStr[5] == '0') || (commandStr[5] == '1'))) { - // Set the text colors - int index = commandStr[5] - '0'; - paramP = commandStr + 6; - - RGB8 palEntry; - palEntry.r = getParameter(¶mP) << 2; - palEntry.g = getParameter(¶mP) << 2; - palEntry.b = getParameter(¶mP) << 2; - _vm->_palette->setPalette(&palEntry, 5 + index, 1); - - } else if (!strncmp(commandStr, "SPARE", 5)) { - // Sets a secondary background number that can be later switched in with a PAGE command - paramP = commandStr + 6; - int spareIndex = commandStr[5] - '0'; - if ((spareIndex >= 0) && (spareIndex <= 9)) { - int screenId = getParameter(¶mP); - - _spareScreens[spareIndex] = screenId; - } - - } else if (!strncmp(commandStr, "PAGE", 4)) { - // Signals to change to a previous specified secondary background - paramP = commandStr + 4; - int spareIndex = getParameter(¶mP); - - // Only allow background switches if one isn't currently in progress - if (!_spareScreen && (_spareScreens[spareIndex] != 0)) { - _spareScreen = new M4Surface(width(), MADS_SURFACE_HEIGHT); - _spareScreen->loadBackground(_spareScreens[spareIndex], &_bgSpare); - _vm->_palette->addRange(_bgSpare); - _spareScreen->translate(_bgSpare); - - _translationX = 0; - } - - } else { - error("Unknown response command: '%s'", commandStr); - } -} - -int TextviewView::getParameter(char **paramP) { - if ((**paramP != '=') && (**paramP != ',')) - return 0; - - int result = 0; - ++*paramP; - while ((**paramP >= '0') && (**paramP <= '9')) { - result = result * 10 + (**paramP - '0'); - ++*paramP; - } - - return result; -} - -void TextviewView::processText() { - int lineWidth, xStart; - - if (!strcmp(_currentLine, "***")) { - // Special signifier for end of script - _scrollCount = _vm->_font->current()->getHeight() * 13; - _lineY = -1; - return; - } - - _lineY = 0; - - // Lines are always centered, except if line contains a '@', in which case the - // '@' marks the position that must be horizontally centered - char *centerP = strchr(_currentLine, '@'); - if (centerP) { - *centerP = '\0'; - xStart = (width() / 2) - _vm->_font->current()->getWidth(_currentLine); - - // Delete the @ character and shift back the remainder of the string - char *p = centerP + 1; - if (*p == ' ') ++p; - strcpy(centerP, p); - - } else { - lineWidth = _vm->_font->current()->getWidth(_currentLine); - xStart = (width() - lineWidth) / 2; - } - - // Copy the text line onto the bottom of the textSurface surface, which will allow it - // to gradually scroll onto the screen - int yp = _textSurface.height() - _vm->_font->current()->getHeight() - TEXTVIEW_LINE_SPACING; - _textSurface.fillRect(Common::Rect(0, yp, _textSurface.width(), _textSurface.height()), - _vm->_palette->BLACK); - _vm->_font->current()->writeString(&_textSurface, _currentLine, xStart, yp); -} - - -//-------------------------------------------------------------------------- - -AnimviewView::AnimviewView(MadsM4Engine *vm): - View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())), - MadsView(this), _backgroundSurface(MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT), - _codeSurface(MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT) { - - MadsView::_bgSurface = &_backgroundSurface; - MadsView::_depthSurface = &_codeSurface; - MadsView::setViewport(Common::Rect(0, MADS_Y_OFFSET, MADS_SURFACE_WIDTH, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT)); - - _screenType = VIEWID_ANIMVIEW; - _screenFlags.layer = LAYER_BACKGROUND; - _screenFlags.visible = true; - _screenFlags.get = SCREVENT_ALL; - _callback = NULL; - _script = NULL; - _palData = NULL; - _previousUpdate = 0; - _transition = kTransitionNone; - _activeAnimation = NULL; - _bgLoadFlag = true; - _startFrame = -1; - _scriptDone = false; - - reset(); - - // Set up system palette colors - _vm->_palette->setMadsSystemPalette(); - - // Block reserved palette ranges - _vm->_palette->blockRange(16, 2); - _vm->_palette->blockRange(250, 4); - - clear(); - _backgroundSurface.clear(); - - setColor(2); - hLine(0, width() - 1, MADS_Y_OFFSET - 2); - hLine(0, width() - 1, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT + 2); -} - -AnimviewView::~AnimviewView() { - if (_script) - _vm->res()->toss(_resourceName); - delete _activeAnimation; -} - -void AnimviewView::reset() { - _backgroundSurface.clear(); - _soundDriverLoaded = false; -} - -void AnimviewView::setScript(const char *resourceName, AnimviewCallback callback) { - _callback = callback; - if (_script) - _vm->res()->toss(_resourceName); - - reset(); - - strncpy(_resourceName, resourceName, 15); - _resourceName[15] = '\0'; - if (!strchr(_resourceName, '.')) - strcat(_resourceName, ".res"); - - _script = _vm->res()->get(_resourceName); -} - -bool AnimviewView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - // Wait for the Escape key or a mouse press - if (((eventType == KEVENT_KEY) && (param == Common::KEYCODE_ESCAPE)) || - (eventType == MEVENT_LEFT_RELEASE) || (eventType == MEVENT_RIGHT_RELEASE)) { - scriptDone(); - captureEvents = false; - return true; - } - - return false; -} - -void AnimviewView::updateState() { - MadsView::update(); - - if (!_script || _scriptDone) - return; - - if (!_activeAnimation) { - readNextCommand(); - assert(_activeAnimation); - } - - // Update the current animation - _activeAnimation->update(); - if (_activeAnimation->freeFlag()) { - delete _activeAnimation; - _activeAnimation = NULL; - - // Clear up current background and sprites - _backgroundSurface.reset(); - clearLists(); - - // Reset flags - _startFrame = -1; - - readNextCommand(); - - // Check if script is finished - if (_scriptDone) { - scriptDone(); - return; - } - } - - refresh(); -} - -void AnimviewView::readNextCommand() { -static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several intro scenes **** - - while (!_script->eos() && !_script->err()) { - if (!tempFlag) { - tempFlag = true; - strncpy(_currentLine, _script->readLine().c_str(), 79); - strncpy(_currentLine, _script->readLine().c_str(), 79); - } - - strncpy(_currentLine, _script->readLine().c_str(), 79); - - // Process any switches on the line - char *cStart = strchr(_currentLine, '-'); - while (cStart) { - // Loop for possible multiple commands on one line - char *cEnd = strchr(_currentLine, ' '); - if (!cEnd) - error("Unterminated command '%s' in response file", _currentLine); - - *cEnd = '\0'; - processCommand(); - - // Copy rest of line (if any) to start of buffer - // Don't use strcpy() here, because if the - // rest of the line is the longer of the two - // strings, the memory areas will overlap. - memmove(_currentLine, cEnd + 1, strlen(cEnd + 1) + 1); - - cStart = strchr(_currentLine, '-'); - } - - // If there's something left, presume it's a resource name to process - if (_currentLine[0]) - break; - } - - if (!_currentLine[0]) { - // A blank line at this point means that the end of the animation has been reached - _scriptDone = true; - return; - } - - if (strchr(_currentLine, '.') == NULL) - strcat(_currentLine, ".aa"); - - uint16 flags = 0; - if (_bgLoadFlag) - flags |= 0x100; - - _activeAnimation = new MadsAnimation(_vm, this); - _activeAnimation->initialize(_currentLine, flags, &_backgroundSurface, &_codeSurface); - - if (_startFrame != -1) - _activeAnimation->setCurrentFrame(_startFrame); - - _spriteSlots.fullRefresh(); -/* - // Handle scene transition - switch (_transition) { - case kTransitionNone: - // nothing to do - break; - case kTransitionFadeIn: - case kTransitionFadeIn2: - _vm->_palette->fadeIn(TV_NUM_FADE_STEPS, TV_FADE_DELAY_MILLI, destPalette, 256); - break; - case kTransitionBoxInBottomLeft: - case kTransitionBoxInBottomRight: - case kTransitionBoxInTopLeft: - case kTransitionBoxInTopRight: - // unused - warning("Unsupported box in scene effect"); - break; - case kTransitionPanLeftToRight: - // TODO - break; - case kTransitionPanRightToLeft: - // TODO - break; - case kTransitionCircleIn: - // TODO - break; - default: - // nothing to do - break; - } -*/ - - _vm->_resourceManager->toss(_currentLine); -} - - -void AnimviewView::scriptDone() { -return; - AnimviewCallback fn = _callback; - MadsM4Engine *vm = _vm; - - // Remove this view from manager and destroy it - _vm->_viewManager->deleteView(this); - - if (fn) - fn(vm); -} - -/* -Switches are: (taken from the help of the original executable) - -b Toggle background load status off/on. - -c:char Specify sound card id letter. - -f:num Specify a specific starting frame number - -g Stay in graphics mode on exit. - -h[:ex] Disable EMS/XMS high memory support. - -i Switch sound interrupts mode off/on. - -j Wait for music to finish at end. - -k Keystroke jumps to end instead of abort. - -m Operate in non-MADS mode. - -o:xxx Specify opening special effect. - -p Switch MADS path mode to CONCAT. - -r[:abn] Resynch timer (always, beginning, never). - -s:file Specify sound file. - -u[:...] Use DMA speech [optional: addr,type,irq,drq]. - -w Toggle white bars off/on. - -x Exit immediately after last frame. - -y Do not clear screen initially - -z Display statistics after run. - - Opening special effects are: - 0: no effect - 1: fade in - 2: fade in (looks to be the same as 1) - 3: box in from bottom left (unused) - 4: box in from bottom right (unused) - 5: box in from top left (unused) - 6: box in from top right (unused) - 7: pan in from left to right - 8: pan in from right to left - 9: circle in (new scene appears in a circle that expands) - - Animview is ran like this from the original games: - animview.exe @resfilename -c:P,220,20 -u:220,20,07,01 -p -a:mainmenu -p - - Note that the first -p is necessary to watch the animation, otherwise - the program just exits - - To watch an animation within the *.res file, just run animview like this: - animview.exe -x -r:b -o:2 animfilename -p -*/ -void AnimviewView::processCommand() { - char commandStr[80]; - strcpy(commandStr, _currentLine + 1); - str_upper(commandStr); - char *param = commandStr; - - switch (commandStr[0]) { - case 'B': - // Toggle background load flag - _bgLoadFlag = !_bgLoadFlag; - break; - - case 'F': - // Start animation at a specific frame - ++param; - assert(*param == ':'); - _startFrame = atoi(++param); - break; - - case 'O': - param = param + 2; - //warning(kDebugGraphics, "O:%i ", atoi(param)); - _transition = atoi(param); - break; - - case 'R': - param = param + 2; - //warning(kDebugGraphics, "R:%s ", param); - break; - - case 'W': - //warning(kDebugGraphics, "W "); - break; - - case 'X': - //warning(kDebugGraphics, "X "); - break; - - default: - error("Unknown response command: '%s'", commandStr); - } -} - -} diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h deleted file mode 100644 index 411d575d59..0000000000 --- a/engines/m4/mads_anim.h +++ /dev/null @@ -1,110 +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. - * - */ - -#ifndef M4_MADS_ANIM_H -#define M4_MADS_ANIM_H - -#include "m4/viewmgr.h" -#include "m4/compression.h" -#include "m4/animation.h" - -#include "common/str-array.h" - -namespace M4 { - -typedef void (*TextviewCallback)(MadsM4Engine *vm); - -class TextviewView : public View { -private: - bool _animating; - - char _resourceName[80]; - Common::SeekableReadStream *_script; - uint16 _spareScreens[10]; - M4Surface *_spareScreen; - RGBList *_bgCurrent, *_bgSpare; - int _translationX; - int _panX, _panY, _panSpeed; - int _panCountdown; - char _currentLine[80]; - uint32 _scrollTimeout; - int _scrollCount; - int _lineY; - M4Surface _bgSurface; - M4Surface _textSurface; - TextviewCallback _callback; - bool _soundDriverLoaded; - bool _processEvents; - - void reset(); - void processLines(); - void processCommand(); - void processText(); - int getParameter(char **paramP); -public: - TextviewView(MadsM4Engine *vm); - ~TextviewView(); - - void setScript(const char *resourceName, TextviewCallback callback); - bool isAnimating() { return _animating; } - void scriptDone(); - - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); - void updateState(); -}; - -typedef void (*AnimviewCallback)(MadsM4Engine *vm); - -class AnimviewView : public View, MadsView { -private: - char _resourceName[80]; - Common::SeekableReadStream *_script; - bool _scriptDone; - uint32 _previousUpdate; - char _currentLine[80]; - M4Surface _backgroundSurface; - M4Surface _codeSurface; - AnimviewCallback _callback; - bool _soundDriverLoaded; - RGBList *_palData; - int _transition; - MadsAnimation *_activeAnimation; - bool _bgLoadFlag; - int _startFrame; - - void reset(); - void readNextCommand(); - void processCommand(); -public: - AnimviewView(MadsM4Engine *vm); - ~AnimviewView(); - - void setScript(const char *resourceName, AnimviewCallback callback); - void scriptDone(); - - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); - void updateState(); -}; - -} - -#endif diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp deleted file mode 100644 index a7838d0e26..0000000000 --- a/engines/m4/mads_logic.cpp +++ /dev/null @@ -1,1038 +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/textconsole.h" - -#include "m4/m4.h" -#include "m4/dialogs.h" -#include "m4/mads_logic.h" -#include "m4/scene.h" - -#define MAX_CALL_PARAMS 10 - -namespace M4 { - -void MadsGameLogic::initializeGlobals() { - // Clear the entire globals list - Common::fill(&_madsVm->globals()->_globals[0], &_madsVm->globals()->_globals[TOTAL_NUM_VARIABLES], 0); - - SET_GLOBAL(4, 8); - SET_GLOBAL(33, 1); - SET_GLOBAL(10, 0xFFFF); - SET_GLOBAL(13, 0xFFFF); - SET_GLOBAL(15, 0xFFFF); - SET_GLOBAL(19, 0xFFFF); - SET_GLOBAL(20, 0xFFFF); - SET_GLOBAL(21, 0xFFFF); - SET_GLOBAL(95, 0xFFFF); - - // TODO: unknown sub call - - // Put the values 0 through 3 in a random ordering in global slots 83 - 86 - for (int idx = 0; idx < 4; ) { - int randVal = _madsVm->_random->getRandomNumber(4); - SET_GLOBAL(83 + idx, randVal); - - // Check whether the given value has already been used - bool flag = false; - for (int idx2 = 0; idx2 < idx; ++idx2) { - if (randVal == GET_GLOBAL(83 + idx2)) - flag = true; - } - - if (!flag) - ++idx; - } - - // Put the values 0 through 3 in a random ordering in global slots 87 - 90 - for (int idx = 0; idx < 4; ) { - int randVal = _madsVm->_random->getRandomNumber(3); - SET_GLOBAL(87 + idx, randVal); - - // Check whether the given value has already been used - bool flag = false; - for (int idx2 = 0; idx2 < idx; ++idx2) { - if (randVal == GET_GLOBAL(87 + idx2)) - flag = true; - } - - if (!flag) - ++idx; - } - - // Miscellaneous global settings - SET_GLOBAL(120, 501); - SET_GLOBAL(121, 0xFFFF); - SET_GLOBAL(110, 0xFFFF); - SET_GLOBAL(119, 1); - SET_GLOBAL(134, 4); - SET_GLOBAL(190, 201); - SET_GLOBAL(191, 301); - SET_GLOBAL(192, 413); - SET_GLOBAL(193, 706); - SET_GLOBAL(194, 801); - SET_GLOBAL(195, 551); - SET_GLOBAL(196, 752); - - // Fill out the globals 200 - 209 with unique random number values less than 10000 - for (int idx = 0; idx < 10; ) { - int randVal = _madsVm->_random->getRandomNumber(9999); - SET_GLOBAL(200 + idx, randVal); - - // Check whether the given value has already been used - bool flag = false; - for (int idx2 = 0; idx2 < idx; ++idx2) { - if (randVal == GET_GLOBAL(87 + idx2)) - flag = true; - } - - if (!flag) - ++idx; - } - - switch (_madsVm->globals()->_difficultyLevel) { - case 1: - // Very hard - SET_GLOBAL(35, 0); - // TODO: object set room - SET_GLOBAL(137, 5); - SET_GLOBAL(136, 0); - break; - - case 2: - // Hard - SET_GLOBAL(35, 0); - // TODO: object set room - SET_GLOBAL(136, 0xFFFF); - SET_GLOBAL(137, 6); - break; - - case 3: - // Easy - SET_GLOBAL(35, 2); - // TODO: object set room - break; - } - - _madsVm->_player._direction = 8; - _madsVm->_player._newDirection = 8; - - // TODO: unknown processing routine getting called for 'RXM' and 'ROX' -} - -/*--------------------------------------------------------------------------*/ - -const char *MadsSceneLogic::subFormatList[] = {"scene%d_enter", "scene%d_step", "scene%d_preaction", "scene%d_actions"}; - -#define OPSIZE8 0x40 ///< when this bit is set - the operand size is 8 bits -#define OPSIZE16 0x80 ///< when this bit is set - the operand size is 16 bits -#define OPMASK 0x3F ///< mask to isolate the opcode - -enum Opcodes { - OP_HALT = 0, OP_IMM = 1, OP_ZERO = 2, OP_ONE = 3, OP_MINUSONE = 4, OP_STR = 5, OP_DLOAD = 6, - OP_DSTORE = 7, OP_PAL = 8, OP_LOAD = 9, OP_GLOAD = 10, OP_STORE = 11, OP_GSTORE = 12, - OP_CALL = 13, OP_LIBCALL = 14, OP_RET = 15, OP_ALLOC = 16, OP_JUMP = 17, OP_JMPFALSE = 18, - OP_JMPTRUE = 19, OP_EQUAL = 20, OP_LESS = 21, OP_LEQUAL = 22, OP_NEQUAL = 23, OP_GEQUAL = 24, - OP_GREAT = 25, OP_PLUS = 26, OP_MINUS = 27, OP_LOR = 28, OP_MULT = 29, OP_DIV = 30, - OP_MOD = 31, OP_AND = 32, OP_OR = 33, OP_EOR = 34, OP_LAND = 35, OP_NOT = 36, OP_COMP = 37, - OP_NEG = 38, OP_DUP = 39, - TOTAL_OPCODES = 40 -}; - -const char *MadsSceneLogic::_opcodeStrings[] = { - "HALT", "IMM", "ZERO", "ONE", "MINUSONE", "STR", "DLOAD", "DSTORE", NULL, "LOAD", "GLOAD", - "STORE", "GSTORE", "CALL", "LIBCALL", "RET", "ALLOC", "JUMP", "JMPFALSE", "JMPTRUE", "EQUAL", - "LESS", "LEQUAL", "NEQUAL", "GEQUAL", "GREAT", "PLUS", "MINUS", "LOR", "MULT", "DIV", - "MOD", "AND", "OR", "EOR", "LAND", "NOT", "COMP", "NEG", "DUP" -}; - -/** - * This method sets up the data map with pointers to all the common game objects. This allows the script engine to - * convert game specific offsets for various fields in the original game's data segment into a generic data index - * that will be common across all the MADS games - -void MadsSceneLogic::initializeDataMap() { - // The unique order of these items must be maintained -} -*/ - -uint32 MadsSceneLogic::getDataValue(int dataId) { - switch (dataId) { - case 1: - return _madsVm->scene()->_abortTimersMode2; - case 2: - return _madsVm->scene()->_abortTimers; - case 3: - return _madsVm->_player._stepEnabled ? 0xffff : 0; - case 4: - return _madsVm->scene()->_nextScene; - case 5: - return _madsVm->scene()->_previousScene; - case 6: - return _madsVm->_player._playerPos.x; - case 7: - return _madsVm->_player._playerPos.y; - case 8: - return _madsVm->_player._direction; - case 9: - return _madsVm->_player._visible ? 0xffff : 0; - case 10: - return getActiveAnimationBool(); - case 11: - return getAnimationCurrentFrame(); - case 12: - return _madsVm->scene()->_action._inProgress; - case 13: - return _madsVm->globals()->_difficultyLevel; - default: - // All other data variables get stored in the hash table - return _madsVm->globals()->_dataMap[dataId]; - break; - } -} - -void MadsSceneLogic::setDataValue(int dataId, uint16 dataValue) { - switch (dataId) { - case 1: - _madsVm->scene()->_abortTimersMode2 = (AbortTimerMode)dataValue; - break; - case 2: - _madsVm->scene()->_abortTimers = dataValue; - break; - case 3: - _madsVm->_player._stepEnabled = dataValue != 0; - break; - case 4: - _madsVm->scene()->_nextScene = dataValue; - break; - case 5: - _madsVm->scene()->_previousScene = dataValue; - break; - case 6: - _madsVm->_player._playerPos.x = dataValue; - break; - case 7: - _madsVm->_player._playerPos.y = dataValue; - break; - case 8: - _madsVm->_player._direction = dataValue; - break; - case 9: - _madsVm->_player._visible = dataValue != 0; - break; - case 10: - case 11: - error("Tried to set read only data field %d", dataId); - break; - case 12: - _madsVm->scene()->_action._inProgress = dataValue != 0; - break; - case 13: - _madsVm->globals()->_difficultyLevel = dataValue; - break; - default: - // All other data variables get stored in the hash table - _madsVm->globals()->_dataMap[dataId] = dataValue; - break; - } -} - -const char *MadsSceneLogic::formAnimName(char sepChar, int16 suffixNum) { - return MADSResourceManager::getResourceName(sepChar, _sceneNumber, EXTTYPE_NONE, NULL, suffixNum); -} - -void MadsSceneLogic::getSceneSpriteSet() { - char prefix[100]; - - // Room change sound - _madsVm->_sound->playSound(5); - - // Set up sprite set prefix to use - if ((_sceneNumber <= 103) || (_sceneNumber == 111)) { - if (_madsVm->globals()->_globals[0] == SEX_FEMALE) - strcpy(prefix, "ROX"); - else - strcpy(prefix, "RXM"); - } else if (_sceneNumber <= 110) { - strcpy(prefix, "RXSW"); - _madsVm->globals()->_globals[0] = SEX_UNKNOWN; - } else if (_sceneNumber == 112) - strcpy(prefix, ""); - - _madsVm->globals()->playerSpriteChanged = true; - _madsVm->_player.loadSprites(prefix); - -// if ((_sceneNumber == 105) ((_sceneNumber == 109) && (word_84800 != 0))) -// _madsVm->globals()->playerSpriteChanged = true; - - _vm->_palette->setEntry(16, 0x38, 0xFF, 0xFF); - _vm->_palette->setEntry(17, 0x38, 0xb4, 0xb4); -} - -void MadsSceneLogic::getAnimName() { - const char *newName = MADSResourceManager::getAAName( - ((_sceneNumber <= 103) || (_sceneNumber > 111)) ? 0 : 1); - strcpy(_madsVm->scene()->_aaName, newName); -} - -/*--------------------------------------------------------------------------*/ - -uint16 MadsSceneLogic::loadSpriteSet(uint16 suffixNum, uint16 sepChar) { - assert(sepChar < 256); - const char *resName = formAnimName((char)sepChar, (int16)suffixNum); - return _madsVm->scene()->loadSceneSpriteSet(resName); -} - -uint16 MadsSceneLogic::startReversibleSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) { - M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(0); - uint8 depth = _madsVm->_rails->getDepth(Common::Point(spriteFrame->x + (spriteFrame->width() / 2), - spriteFrame->y + (spriteFrame->height() / 2))); - - return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0, - true, 100, depth - 1, 1, ANIMTYPE_REVERSIBLE, 0, 0); -} - -uint16 MadsSceneLogic::startCycledSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) { - M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(0); - uint8 depth = _madsVm->_rails->getDepth(Common::Point(spriteFrame->x + (spriteFrame->width() / 2), - spriteFrame->y + (spriteFrame->height() / 2))); - - return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0, - true, 100, depth - 1, 1, ANIMTYPE_CYCLED, 0, 0); -} - -uint16 MadsSceneLogic::startSpriteSequence3(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks) { - M4Sprite *spriteFrame = _madsVm->scene()->_spriteSlots.getSprite(srcSpriteIdx).getFrame(0); - uint8 depth = _madsVm->_rails->getDepth(Common::Point(spriteFrame->x + (spriteFrame->width() / 2), - spriteFrame->y + (spriteFrame->height() / 2))); - - return _madsVm->scene()->_sequenceList.add(srcSpriteIdx, flipped, 1, triggerCountdown, timeoutTicks, extraTicks, numTicks, 0, 0, - true, 100, depth - 1, -1, ANIMTYPE_CYCLED, 0, 0); -} - -void MadsSceneLogic::activateHotspot(int idx, bool active) { - // TODO: -} - -void MadsSceneLogic::getPlayerSpritesPrefix() { - _madsVm->_sound->playSound(5); - - char oldName[80]; - strcpy(oldName, _madsVm->_player._spritesPrefix); - - if ((_madsVm->globals()->_nextSceneId <= 103) || (_madsVm->globals()->_nextSceneId == 111)) - strcpy(_madsVm->_player._spritesPrefix, (_madsVm->globals()->_globals[0] == SEX_FEMALE) ? "ROX" : "RXM"); - else if (_madsVm->globals()->_nextSceneId <= 110) - strcpy(_madsVm->_player._spritesPrefix, "RXSM"); - else if (_madsVm->globals()->_nextSceneId == 112) - strcpy(_madsVm->_player._spritesPrefix, ""); - - if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0) - _madsVm->_player._spritesChanged = true; - - if ((_madsVm->globals()->_nextSceneId == 105) || - ((_madsVm->globals()->_nextSceneId == 109) && (_madsVm->globals()->_globals[15] != 0))) { - // TODO: unknown flag setting - _madsVm->_player._spritesChanged = true; - } - - _madsVm->_palette->setEntry(16, 40, 255, 255); - _madsVm->_palette->setEntry(17, 40, 180, 180); - -} - -void MadsSceneLogic::getPlayerSpritesPrefix2() { - _madsVm->_sound->playSound(5); - - char oldName[80]; - strcpy(oldName, _madsVm->_player._spritesPrefix); - - if ((_madsVm->globals()->_nextSceneId == 213) || (_madsVm->globals()->_nextSceneId == 216)) - strcpy(_madsVm->_player._spritesPrefix, ""); - else if (_madsVm->globals()->_globals[0] == SEX_MALE) - strcpy(_madsVm->_player._spritesPrefix, "RXM"); - else - strcpy(_madsVm->_player._spritesPrefix, "ROX"); - - // TODO: unknown flag setting for next scene Id > 212 - - if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0) - _madsVm->_player._spritesChanged = true; - -/* if ((_madsVm->globals()->_nextSceneId == 203) && (_madsVm->globals()->_nextSceneId == 204) && - (_madsVm->globals()->_globals[0x22] == 0)) - // TODO: unknown flag set -*/ - _madsVm->_palette->setEntry(16, 40, 255, 255); - _madsVm->_palette->setEntry(17, 40, 180, 180); -} - - -/*--------------------------------------------------------------------------*/ - -/** - * Loads the MADS.DAT file and loads the script data for the correct game/language - */ -void MadsSceneLogic::initializeScripts() { - Common::File f; - if (!f.open("mads.dat")) { - warning("Could not locate mads.dat file"); - return; - } - - // Validate that the file being read is a valid mads.dat file - char header[4]; - f.read(&header[0], 4); - if (strncmp(header, "MADS", 4) != 0) { - warning("Invalid mads.dat file"); - return; - } - - // Get a list of the offsets of game blocks - uint32 v; - Common::Array offsets; - while ((v = f.readUint32LE()) != 0) - offsets.push_back(v); - - // Check the header of each block in turn - _scriptsData = NULL; - _scriptsSize = 0; - - for (uint i = 0; i < offsets.size(); ++i) { - // Get the block header - f.seek(offsets[i]); - byte gameId = f.readByte(); - byte language = f.readByte(); - f.readByte(); // Language currently unused - - // If this block isn't for the current game, skip it - if (_madsVm->getGameType() != (gameId + 2)) - continue; - if ((language != 1) || (_madsVm->getLanguage() != Common::EN_ANY)) - continue; - - // Found script block for the given game and language. - _scriptsSize = (i < (offsets.size() - 1)) ? offsets[i + 1] - offsets[i] : f.size() - offsets[i]; - break; - } - - if (!_scriptsSize) { - warning("Could not find appropriate scripts block for game in mads.dat file"); - f.close(); - return; - } - - // Load up the list of subroutines into a hash map - uint32 blockOffset = f.pos() - 3; - uint32 subsStart = 0; - for (;;) { - // Get next entry - Common::String subName; - char c; - while ((c = (char)f.readByte()) != '\0') - subName += c; - if (subName.empty()) - // Reached end of subroutine list - break; - - // Read in the offset of the routine - uint32 offset = f.readUint32LE(); - if (_subroutines.empty()) { - // The first subroutine offset is used to reduce the amount of data to later load in. In essence, - // the subroutine index will not be separately loaded, since it's contents will be in the hash map - subsStart = offset; - _scriptsSize -= offset; - } - - _subroutines[subName] = offset - subsStart; - _subroutineOffsets.push_back(offset - subsStart); - } - - // Read in the remaining data - f.seek(blockOffset + subsStart, SEEK_SET); - _scriptsData = (byte *)malloc(_scriptsSize); - f.read(_scriptsData, _scriptsSize); - - f.close(); -} - -void MadsSceneLogic::selectScene(int sceneNum) { - assert(sceneNum == 101); - _sceneNumber = sceneNum; - - Common::fill(&_spriteIndexes[0], &_spriteIndexes[50], 0); - - // If debugging is turned on, show a debug warning if any of the scene methods aren't present - if (gDebugLevel > 0) { - for (int i = 0; i < 4; ++i) { - char buffer[20]; - sprintf(buffer, subFormatList[i], sceneNum); - Common::HashMap::iterator it = _subroutines.find(Common::String(buffer)); - if (it == _subroutines.end()) - debugC(1, kDebugScript, "Scene method %s not found", buffer); - } - } -} - -void MadsSceneLogic::setupScene() { - // FIXME: This is the hardcoded logic for Rex scene 101 only - const char *animName = formAnimName('A', -1); - warning("anim - %s", animName); - -// sub_1e754(animName, 3); - - if ((_sceneNumber >= 101) && (_sceneNumber <= 112)) - getPlayerSpritesPrefix(); - else - getPlayerSpritesPrefix2(); - - getAnimName(); -} - -/** - * Handles the logic when a scene is entered - */ -void MadsSceneLogic::doEnterScene() { - char buffer[20]; - sprintf(buffer, subFormatList[SUBFORMAT_ENTER], _sceneNumber); - execute(Common::String(buffer)); -} - -/** - * Handles the script execution which is called regularly every frame - */ -void MadsSceneLogic::doSceneStep() { - char buffer[20]; - sprintf(buffer, subFormatList[SUBFORMAT_STEP], _sceneNumber); - execute(Common::String(buffer)); -} - -/** - * Handles and preactions before an action is started - */ -void MadsSceneLogic::doPreactions() { - char buffer[20]; - sprintf(buffer, subFormatList[SUBFORMAT_PREACTIONS], _sceneNumber); - execute(Common::String(buffer)); -} - -/** - * Handles any action that has been selected - */ -void MadsSceneLogic::doAction() { - char buffer[20]; - sprintf(buffer, subFormatList[SUBFORMAT_ACTIONS], _sceneNumber); - execute(Common::String(buffer)); -} - -/** - * Executes the script with the specified name - */ -void MadsSceneLogic::execute(const Common::String &scriptName) { - Common::HashMap::iterator it = _subroutines.find(scriptName); - if (it != _subroutines.end()) - execute(it->_value); -} - -#define UNUSED_VAL 0xEAEAEAEA -/** - * Executes the script at the specified offset - */ -void MadsSceneLogic::execute(uint32 subOffset) { - Common::Array locals; - Common::Stack stack; - char opcodeBuffer[100]; - uint32 scriptOffset = subOffset; - uint32 param; - - debugC(1, kDebugScript, "executing script at %xh", subOffset); - - bool done = false; - while (!done) { - param = UNUSED_VAL; - byte opcode = _scriptsData[scriptOffset++]; - sprintf(opcodeBuffer, "%.4x[%.2d] - %s", scriptOffset - 1, stack.size(), _opcodeStrings[opcode & OPMASK]); - - switch (opcode & OPMASK) { - case OP_HALT: // end of program - case OP_RET: - done = true; - break; - - case OP_IMM: // Loads immediate value onto stack - param = getParam(scriptOffset, opcode); - stack.push(ScriptVar(param)); - break; - - case OP_ZERO: // loads zero onto stack - stack.push(ScriptVar((uint32)0)); - break; - - case OP_ONE: // loads one onto stack - stack.push(ScriptVar(1)); - break; - - case OP_MINUSONE: // loads minus one (0xffff) onto stack - stack.push(ScriptVar(0xffff)); - break; - - case OP_DLOAD: { // Gets data variable - param = getParam(scriptOffset, opcode); - uint16 v = getDataValue(param); - stack.push(ScriptVar(v)); - break; - } - - case OP_DSTORE: { // Stores data variable - param = getParam(scriptOffset, opcode); - ScriptVar v = stack.pop(); - setDataValue(param, v.isInt() ? v.get() : 0); - break; - } - - case OP_LOAD: // loads local variable onto stack - param = getParam(scriptOffset, opcode); - stack.push(locals[param]); - break; - - case OP_STORE: // Pops a value and stores it in a local - // Get the local index and expand the locals store if necessary - param = getParam(scriptOffset, opcode); - while (param >= locals.size()) - locals.push_back(ScriptVar()); - - locals[param] = stack.pop(); - break; - - case OP_GLOAD: // loads global variable onto stack - param = getParam(scriptOffset, opcode); - assert(param < TOTAL_NUM_VARIABLES); - stack.push(_madsVm->globals()->_globals[param]); - break; - - case OP_GSTORE: // pops stack and stores in global variable - param = getParam(scriptOffset, opcode); - assert(param < TOTAL_NUM_VARIABLES); - _madsVm->globals()->_globals[param] = stack.pop().get(); - break; - - case OP_CALL: // procedure call - param = getParam(scriptOffset, opcode); - assert(param < _subroutineOffsets.size()); - execute(_subroutineOffsets[param]); - break; - - case OP_LIBCALL: // library procedure or function call - param = getParam(scriptOffset, opcode); - callSubroutine(param, stack); - break; - - case OP_JUMP: // unconditional jump - param = subOffset + getParam(scriptOffset, opcode); - scriptOffset = param; - break; - - case OP_JMPFALSE: // conditional jump - param = subOffset + getParam(scriptOffset, opcode); - if (stack.pop().get() == 0) - // Condition satisfied - do the jump - scriptOffset = param; - break; - - case OP_JMPTRUE: // conditional jump - param = subOffset + getParam(scriptOffset, opcode); - if (stack.pop().get() != 0) - // Condition satisfied - do the jump - scriptOffset = param; - break; - - case OP_EQUAL: // tests top two items on stack for equality - case OP_LESS: // tests top two items on stack - case OP_LEQUAL: // tests top two items on stack - case OP_NEQUAL: // tests top two items on stack - case OP_GEQUAL: // tests top two items on stack - case OP_GREAT: // tests top two items on stack - case OP_LOR: // logical or of top two items on stack and replaces with result - case OP_LAND: // logical ands top two items on stack and replaces with result - { - uint32 param2 = stack.pop().get(); - uint32 param1 = stack.pop().get(); - - // Do the comparison - uint32 tmp = 0; - switch (opcode) { - case OP_EQUAL: tmp = (param1 == param2); break; - case OP_LESS: tmp = (param1 < param2); break; - case OP_LEQUAL: tmp = (param1 <= param2); break; - case OP_NEQUAL: tmp = (param1 != param2); break; - case OP_GEQUAL: tmp = (param1 >= param2); break; - case OP_GREAT: tmp = (param1 > param2); break; - - case OP_LOR: tmp = (param1 || param2); break; - case OP_LAND: tmp = (param1 && param2); break; - } - - stack.push(ScriptVar(tmp)); - } - break; - - case OP_PLUS: // adds top two items on stack and replaces with result - case OP_MINUS: // subs top two items on stack and replaces with result - case OP_MULT: // multiplies top two items on stack and replaces with result - case OP_DIV: // divides top two items on stack and replaces with result - case OP_MOD: // divides top two items on stack and replaces with modulus - case OP_AND: // bitwise ands top two items on stack and replaces with result - case OP_OR: // bitwise ors top two items on stack and replaces with result - case OP_EOR: // bitwise exclusive ors top two items on stack and replaces with result - { - uint32 param2 = stack.pop().get(); - uint32 param1 = stack.pop().get(); - - // replace other operand with result of operation - switch (opcode) { - case OP_PLUS: param1 += param2; break; - case OP_MINUS: param1 -= param2; break; - case OP_MULT: param1 *= param2; break; - case OP_DIV: param1 /= param2; break; - case OP_MOD: param1 %= param2; break; - case OP_AND: param1 &= param2; break; - case OP_OR: param1 |= param2; break; - case OP_EOR: param1 ^= param2; break; - } - - stack.push(ScriptVar(param1)); - } - break; - - case OP_NOT: // logical nots top item on stack - param = stack.pop().get(); - stack.push(ScriptVar((uint32)(!param) & 0xffff)); - break; - - case OP_COMP: // complements top item on stack - param = stack.pop().get(); - stack.push(ScriptVar((~param) & 0xffff)); - break; - - case OP_NEG: // negates top item on stack - param = stack.pop().get(); - stack.push(ScriptVar(((uint32)-(int32)param) & 0xffff)); - break; - - case OP_DUP: // duplicates top item on stack - stack.push(stack.top()); - break; - - default: - error("execute() - Unknown opcode"); - } - - // check for stack size - assert(stack.size() < 100); - - if (gDebugLevel > 0) { - if (param != UNUSED_VAL) - sprintf(opcodeBuffer + strlen(opcodeBuffer), "\t%u", param); - debugC(2, kDebugScript, "%s", opcodeBuffer); - } - } - - debugC(1, kDebugScript, "finished executing script"); - - // make sure stack is unwound - assert(stack.size() == 0); -} - -uint32 MadsSceneLogic::getParam(uint32 &scriptOffset, int opcode) { - switch (opcode & (~OPMASK)) { - case OPSIZE8: - return _scriptsData[scriptOffset++]; - case OPSIZE16: { - uint16 v = READ_LE_UINT16(&_scriptsData[scriptOffset]); - scriptOffset += sizeof(uint16); - return v; - } - default: { - uint32 v = READ_LE_UINT32(&_scriptsData[scriptOffset]); - scriptOffset += sizeof(uint32); - return v; - } - } -} - -/** - * Support method for extracting the required number of parameters needed for a library routine call - */ -void MadsSceneLogic::getCallParameters(int numParams, Common::Stack &stack, ScriptVar *callParams) { - assert(numParams <= MAX_CALL_PARAMS); - for (int i = 0; i < numParams; ++i, ++callParams) - *callParams = stack.pop(); -} - -#define EXTRACT_PARAMS(n) getCallParameters(n, stack, p) - -void MadsSceneLogic::callSubroutine(int subIndex, Common::Stack &stack) { - ScriptVar p[MAX_CALL_PARAMS]; - - switch (subIndex) { - case 1: { - // dialog_show - EXTRACT_PARAMS(1); - Dialog *dlg = new Dialog(_vm, p[0].getStr(), "TODO: Proper Title"); - _vm->_viewManager->addView(dlg); - _vm->_viewManager->moveToFront(dlg); - break; - } - - case 2: - // SequenceList_remove - EXTRACT_PARAMS(1); - _madsVm->scene()->_sequenceList.remove(p[0]); - break; - - case 3: - case 6: - case 20: { - // 3: start_reversible_sprite_sequence - // 6: start_cycled_sprite_sequence - // 20: start_sprite_sequence3 - EXTRACT_PARAMS(6); - int idx; - if (subIndex == 3) - idx = startReversibleSpriteSequence(p[0], p[1] != 0, p[2], p[3], p[4], p[5]); - else if (subIndex == 6) - idx = startCycledSpriteSequence(p[0], p[1], p[2], p[3], p[4], p[5]); - else - idx = startSpriteSequence3(p[0], p[1] != 0, p[2], p[3], p[4], p[5]); - stack.push(ScriptVar(idx)); - break; - } - - case 4: - // SequenceList_setAnimRange - EXTRACT_PARAMS(3); - _madsVm->scene()->_sequenceList.setAnimRange(p[0], p[1], p[2]); - break; - - case 5: - // SequenceList_addSubEntry - EXTRACT_PARAMS(4); - stack.push(ScriptVar(_madsVm->scene()->_sequenceList.addSubEntry(p[0], (SequenceSubEntryMode)p[1].get(), p[2], p[3]))); - break; - - case 7: { - // quotes_get_pointer - EXTRACT_PARAMS(1); - const char *quoteStr = _madsVm->globals()->getQuote(p[0]); - stack.push(ScriptVar(quoteStr)); - break; - } - - case 8: { - // KernelMessageList_add - EXTRACT_PARAMS(8); - int msgIndex = _madsVm->scene()->_kernelMessages.add(Common::Point(p[0], p[1]), p[2], - p[3], p[4], p[5] | (p[6] << 16), p[7].getStr()); - stack.push(ScriptVar(msgIndex)); - break; - } - - case 9: - // SequenceList_unk3 - EXTRACT_PARAMS(1); - // TODO: Implement unk3 method -// stack.push(ScriptVar(_madsVm->scene()->_sequenceList.unk3(p[0]))); - break; - - case 10: - // start_sound - EXTRACT_PARAMS(1); - _madsVm->_sound->playSound(p[0]); - break; - - case 11: - // SceneLogic_formAnimName - EXTRACT_PARAMS(2); - stack.push(ScriptVar(formAnimName((char)p[0], p[1]))); - break; - - case 12: - // SpriteList_addSprites - EXTRACT_PARAMS(2); - stack.push(ScriptVar(_madsVm->scene()->_spriteSlots.addSprites(p[0].getStr(), false, p[1]))); - break; - - case 13: - // hotspot_activate - EXTRACT_PARAMS(2); - // TODO: Implement setActive version that takes in a hotspot Id -// _madsVm->scene()->getSceneResources().hotspots->setActive(p[0], p[1] != 0); - break; - - case 14: { - // DynamicHotspots_add - EXTRACT_PARAMS(7); - int idx = _madsVm->scene()->_dynamicHotspots.add(p[0], p[1], p[2], - Common::Rect(p[6], p[5], p[6] + p[4], p[5] + p[3])); - stack.push(ScriptVar(idx)); - break; - } - - case 15: - // SequenceList_setDepth - EXTRACT_PARAMS(2); - _madsVm->scene()->_sequenceList.setDepth(p[0], p[1]); - break; - - case 16: { - // quotes_load - // Quotes loading can take an arbitrary number of quote Ids, terminated by a 0 - int firstId = -1; - int quoteId; - while ((quoteId = stack.pop()) != 0) { - if (firstId == -1) - firstId = quoteId; - _madsVm->globals()->loadQuote(quoteId); - } - - if (firstId != -1) - stack.push(ScriptVar(_madsVm->globals()->getQuote(firstId))); - break; - } - - case 17: { - // form_resource_name - EXTRACT_PARAMS(4); - const char *suffix = NULL; - if (p[4].isInt()) { - // If integer provided for suffix, it must be a value of 0 (NULL) - uint32 vTemp = p[4] | stack.pop(); - assert(!vTemp); - } else - suffix = p[4].getStr(); - - stack.push(ScriptVar(MADSResourceManager::getResourceName((char)p[1], p[0], (ExtensionType)p[3].get(), - suffix, (int16)p[2]))); - break; - } - - case 18: - // MadsScene_loadAnimation - EXTRACT_PARAMS(3); - _madsVm->scene()->loadAnimation(p[1].getStr(), p[0]); - break; - - case 19: { - // Action_isAction - int verbId = stack.pop(); - int objectNameId = (verbId == 0) ? 0 : stack.pop().get(); - int indirectObjectId = (objectNameId == 0) ? 0 : stack.pop().get(); - - stack.push(ScriptVar(_madsVm->scene()->_action.isAction(verbId, objectNameId, indirectObjectId))); - break; - } - - case 21: - // DynamicHotspots_remove - EXTRACT_PARAMS(1); - _madsVm->scene()->_dynamicHotspots.remove(p[0]); - break; - - case 22: { - // object_is_present - EXTRACT_PARAMS(1); - const MadsObject *obj = _madsVm->globals()->getObject(p[0]); - stack.push(ScriptVar((obj->_roomNumber == _madsVm->scene()->_currentScene))); - break; - } - - case 23: - // inventory_add - EXTRACT_PARAMS(1); - _madsVm->scene()->getInterface()->addObjectToInventory(p[0]); - break; - - case 24: { - // dialog_picture_show - EXTRACT_PARAMS(3); - int messageId = p[0] | (p[1] << 16); - int objectNum = p[2]; - warning("TODO: Implement dialog with picture. MessageId=%d, objectNum=%d", messageId, objectNum); - break; - } - - case 25: { - // object_is_in_inventory - EXTRACT_PARAMS(1); - const MadsObject *obj = _madsVm->globals()->getObject(p[0]); - stack.push(ScriptVar(obj->isInInventory())); - break; - } - - case 26: { - // object_set_room - EXTRACT_PARAMS(2); - MadsObject *obj = _madsVm->globals()->getObject(p[0]); - obj->setRoom(p[1]); - break; - } - - case 27: { - // object_get_id_from_desc - EXTRACT_PARAMS(1); - stack.push(_madsVm->globals()->getObjectIndex(p[0])); - break; - } - - case 28: { - // object_get_folder - EXTRACT_PARAMS(1); - stack.push(_madsVm->globals()->getObjectFolder(p[0])); - break; - } - - case 29: - // inventory_remove - EXTRACT_PARAMS(1); - _madsVm->scene()->getInterface()->addObjectToInventory(p[0]); - break; - - case 30: - // image_inter_list_call - EXTRACT_PARAMS(1); - warning("TODO: image_inter_list_call"); - break; - - case 31: - // dialog_flags_show - warning("todo: dialog_flags_show"); - break; - - default: - error("Unknown subroutine %d called", subIndex); - break; - } -} - -#undef EXTRACT_PARAMS - -} diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h deleted file mode 100644 index 4f0b0d5ba2..0000000000 --- a/engines/m4/mads_logic.h +++ /dev/null @@ -1,117 +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. - * - * The MADS game logic is all hard-coded into the games, although for Rex at least - * it seems to use only a fairly basic set of instructions and function calls, so it should be - * possible - */ - -#ifndef M4_MADS_LOGIC_H -#define M4_MADS_LOGIC_H - -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/stack.h" -#include "m4/mads_views.h" - -namespace M4 { - -union ScriptVarValue { - const char *strValue; - uint32 intValue; -}; - -/** - * Specifies a script variable that either be a 32-bit unsigned integer or a string pointer - */ -class ScriptVar { -private: - ScriptVarValue _value; - bool _isInt; -public: - ScriptVar(uint32 v = 0) { _value.intValue = v; _isInt = true; } - ScriptVar(const char *s) { _value.strValue = s; _isInt = false; } - - void set(uint32 v) { _value.intValue = v; _isInt = true; } - void set(const char *s) { _value.strValue = s; _isInt = false; } - const char *getStr() const { assert(!_isInt); return _value.strValue; } - uint32 get() const { assert(_isInt); return _value.intValue; } - bool isInt() const { return _isInt; } - - operator int() { return get(); } -}; - -class MadsSceneLogic { -private: - // Library interface methods - uint16 loadSpriteSet(uint16 suffixNum, uint16 sepChar); - uint16 startReversibleSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks); - uint16 startCycledSpriteSequence(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks); - uint16 startSpriteSequence3(uint16 srcSpriteIdx, bool flipped, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks); - void activateHotspot(int idx, bool active); - void getPlayerSpritesPrefix(); - void getPlayerSpritesPrefix2(); -private: - int _sceneNumber; - int16 _spriteIndexes[50]; - byte *_scriptsData; - int _scriptsSize; - Common::HashMap _subroutines; - Common::Array _subroutineOffsets; - - enum SubFormatIndex {SUBFORMAT_ENTER, SUBFORMAT_STEP, SUBFORMAT_PREACTIONS, SUBFORMAT_ACTIONS}; - static const char *subFormatList[]; - static const char *_opcodeStrings[]; - - // Support functions - const char *formAnimName(char sepChar, int16 suffixNum); - void getSceneSpriteSet(); - void getAnimName(); - - uint32 getDataValue(int dataId); - void setDataValue(int dataId, uint16 dataValue); - void getCallParameters(int numParams, Common::Stack &stack, ScriptVar *callParams); -public: - MadsSceneLogic() { _scriptsData = NULL; } - ~MadsSceneLogic() { delete _scriptsData; } - - void initializeScripts(); - void selectScene(int sceneNum); - - void setupScene(); - void doEnterScene(); - void doPreactions(); - void doAction(); - void doSceneStep(); - - void execute(const Common::String &scriptName); - void execute(uint32 scriptOffset); - uint32 getParam(uint32 &scriptOffset, int opcode); - void callSubroutine(int subIndex, Common::Stack &stack); -}; - -class MadsGameLogic { -public: - static void initializeGlobals(); -}; - -} - -#endif diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp deleted file mode 100644 index ae16b00616..0000000000 --- a/engines/m4/mads_menus.cpp +++ /dev/null @@ -1,1173 +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/textconsole.h" - -#include "m4/mads_menus.h" -#include "m4/m4.h" - -namespace M4 { - -#define REX_MENUSCREEN 990 -#define PHANTOM_MENUSCREEN 920 -#define DRAGON_MENUSCREEN 922 - -#define DRAGON_MENU_BUTTON_W = 45 -#define DRAGON_MENU_BUTTON_H = 11 - -RexMainMenuView::RexMainMenuView(MadsM4Engine *vm): - View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())) { - - _screenType = VIEWID_MAINMENU; - _screenFlags.get = SCREVENT_ALL; - - _delayTimeout = 0; - _menuItem = NULL; - _menuItemIndex = 0; - _frameIndex = 0; - _highlightedIndex = -1; - _skipFlag = false; - - // Load the background for the Rex Nebular game - _bgSurface = new M4Surface(); - _bgSurface->loadBackground(REX_MENUSCREEN, &_bgPalData); - _vm->_palette->addRange(_bgPalData); - _bgSurface->translate(_bgPalData); - - int row = (height() - MADS_SURFACE_HEIGHT) / 2; - _bgSurface->copyTo(this, 0, row); - - // Add in the bounding lines for the background - setColor(2); - hLine(0, width() - 1, row - 1); - hLine(0, width() - 1, height() - row + 1); - - // Set up the menu item pos list - _menuItemPosList[0] = Common::Point(12, 68); - _menuItemPosList[1] = Common::Point(12, 87); - _menuItemPosList[2] = Common::Point(12, 107); - _menuItemPosList[3] = Common::Point(184, 75); - _menuItemPosList[4] = Common::Point(245, 75); - _menuItemPosList[5] = Common::Point(184, 99); -} - -RexMainMenuView::~RexMainMenuView() { - delete _menuItem; - - _vm->_palette->deleteRange(_bgPalData); - - delete _bgPalData; - delete _bgSurface; - - for (uint i = 0; i < _itemPalData.size(); ++i) { - _vm->_palette->deleteRange(_itemPalData[i]); - delete _itemPalData[i]; - } -} - -bool RexMainMenuView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - // Handle keypresses - these can be done at any time, even when the menu items are being drawn - if (eventType == KEVENT_KEY) { - switch (param) { - case Common::KEYCODE_ESCAPE: - case Common::KEYCODE_F6: - handleAction(EXIT); - break; - - case Common::KEYCODE_F1: - handleAction(START_GAME); - break; - - case Common::KEYCODE_F2: - handleAction(RESUME_GAME); - break; - - case Common::KEYCODE_F3: - handleAction(SHOW_INTRO); - break; - - case Common::KEYCODE_F4: - handleAction(CREDITS); - break; - - case Common::KEYCODE_F5: - handleAction(QUOTES); - break; - - case Common::KEYCODE_s: - // Goodness knows why, but Rex has a key to restart the menuitem animations - - // Delete the current menu items - delete _menuItem; - - _vm->_palette->deleteRange(_bgPalData); - delete _bgPalData; - for (uint i = 0; i < _itemPalData.size(); ++i) { - _vm->_palette->deleteRange(_itemPalData[i]); - delete _itemPalData[i]; - } - _itemPalData.clear(); - - // Reload the background surface, and restart the animation - _bgSurface->loadBackground(REX_MENUSCREEN, &_bgPalData); - _vm->_palette->addRange(_bgPalData); - _bgSurface->translate(_bgPalData); - - _menuItemIndex = 0; - _skipFlag = false; - _menuItem = NULL; - _vm->_mouse->cursorOff(); - break; - - default: - // Any other key skips the menu animation - _skipFlag = true; - return false; - } - - return true; - } - - int row = (height() - MADS_SURFACE_HEIGHT) / 2; - int menuIndex; - - switch (eventType) { - case MEVENT_LEFT_CLICK: - case MEVENT_LEFT_DRAG: - if (_vm->_mouse->getCursorOn()) { - menuIndex = getHighlightedItem(x, y); - if (menuIndex != _highlightedIndex) { - _bgSurface->copyTo(this, 0, row); - - _highlightedIndex = menuIndex; - if (_highlightedIndex != -1) { - M4Sprite *spr = _menuItem->getFrame(_highlightedIndex); - const Common::Point &pt = _menuItemPosList[_highlightedIndex]; - spr->copyTo(this, pt.x, row + pt.y, spr->getTransparencyIndex()); - } - } - } else { - // Skip the menu animation - _skipFlag = true; - } - return true; - - case MEVENT_LEFT_RELEASE: - if (_highlightedIndex != -1) - handleAction((MadsGameAction) _highlightedIndex); - return true; - - default: - break; - } - - return false; -} - -void RexMainMenuView::updateState() { - char resName[20]; - Common::SeekableReadStream *data; - int row = (height() - MADS_SURFACE_HEIGHT) / 2; - int itemSize; - - uint32 currTime = g_system->getMillis(); - if (currTime < _delayTimeout) - return; - _delayTimeout = currTime + MADS_MENU_ANIM_DELAY; - - // Rex Nebular handling to cycle through the animated display of the menu items - if (_menuItemIndex == 7) - return; - - // If the user has chosen to skip the menu animation, show the menu immediately - if (_skipFlag && !_vm->_mouse->getCursorOn()) { - // Clear any pending animation - _bgSurface->copyTo(this, 0, row); - // Quickly loop through all the menuitems to display each's final frame - while (_menuItemIndex < 7) { - - if (_menuItem) { - // Draw the final frame of the menuitem - M4Sprite *spr = _menuItem->getFrame(0); - itemSize = _menuItem->getFrame(0)->height(); - spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, - _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2), - spr->getTransparencyIndex()); - - delete _menuItem; - copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0, - spr->getTransparencyIndex()); - } - - // Get the next sprite set - sprintf(resName, "RM%dA%d.SS", REX_MENUSCREEN, ++_menuItemIndex); - data = _vm->res()->get(resName); - _menuItem = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - RGBList *palData = _menuItem->getRgbList(); - _vm->_palette->addRange(palData); - _menuItem->translate(palData, true); - _itemPalData.push_back(palData); - } - - _vm->_mouse->cursorOn(); - return; - } - - if ((_menuItemIndex == 0) || (_frameIndex == 0)) { - // Get the next menu item - if (_menuItem) { - delete _menuItem; - - // Copy over the current display surface area to the background, so the final frame - // of the previous menuitem should be kept on the screen - copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0); - } - - // Get the next menuitem resource - sprintf(resName, "RM%dA%d.SS", REX_MENUSCREEN, ++_menuItemIndex); - data = _vm->res()->get(resName); - _menuItem = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - RGBList *palData = _menuItem->getRgbList(); - _vm->_palette->addRange(palData); - _menuItem->translate(palData, true); - _itemPalData.push_back(palData); - - _frameIndex = _menuItem->getCount() - 1; - - // If the final resource is now loaded, which contains the highlighted versions of - // each menuitem, then the startup animation is complete - if (_menuItemIndex == 7) { - _vm->_mouse->cursorOn(); - return; - } - } else { - --_frameIndex; - } - - // Move to the next menuitem frame - - itemSize = _menuItem->getFrame(0)->height(); - - _bgSurface->copyTo(this, 0, row); - M4Sprite *spr = _menuItem->getFrame(_frameIndex); - spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, _menuItemPosList[_menuItemIndex - 1].y + - row + (itemSize / 2) - (spr->height() / 2), spr->getTransparencyIndex()); -} - -int RexMainMenuView::getHighlightedItem(int x, int y) { - y -= (height() - MADS_SURFACE_HEIGHT) / 2; - - for (int index = 0; index < 6; ++index) { - const Common::Point &pt = _menuItemPosList[index]; - M4Sprite *spr = _menuItem->getFrame(index); - - if ((x >= pt.x) && (y >= pt.y) && (x < (pt.x + spr->width())) && (y < (pt.y + spr->height()))) - return index; - } - - return -1; -} - -void RexMainMenuView::handleAction(MadsGameAction action) { - MadsEngine *vm = (MadsEngine *)_vm; - vm->_mouse->cursorOff(); - vm->_viewManager->deleteView(this); - - switch (action) { - case START_GAME: - case RESUME_GAME: - // Load a sample starting scene - note that, currently, calling loadScene automatically - // removes this menu screen from being displayed - vm->_mouse->cursorOn(); - vm->startScene(101); - return; - - case SHOW_INTRO: - vm->_viewManager->showAnimView("@rexopen"); - break; - - case CREDITS: - vm->_viewManager->showTextView("credits"); - return; - - case QUOTES: - vm->_viewManager->showTextView("quotes"); - return; - - case EXIT: - { - // When the Exit action is done from the menu, show one of two possible advertisements - - // Activate the scene display with the specified scene - bool altAdvert = vm->_random->getRandomNumber(1000) >= 500; - vm->startScene(altAdvert ? 995 : 996); - vm->_viewManager->addView(vm->_scene); - - vm->_viewManager->refreshAll(); - vm->delay(10000); - - vm->_events->quitFlag = true; - return; - } - break; - default: - break; - } -} - -//-------------------------------------------------------------------------- - -MadsMainMenuView::MadsMainMenuView(MadsM4Engine *vm): - View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())) { - -} - -bool MadsMainMenuView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - return false; -} - -void MadsMainMenuView::updateState() { - // TODO: Implement me -} - -//-------------------------------------------------------------------------- - -DragonMainMenuView::DragonMainMenuView(MadsM4Engine *vm): - View(vm, Common::Rect(0, 0, vm->_screen->width(), vm->_screen->height())) { - - _screenType = VIEWID_MAINMENU; - _screenFlags.get = SCREVENT_ALL; - - _delayTimeout = 0; - _menuItem = NULL; - _menuItemIndex = 0; - _frameIndex = 0; - _highlightedIndex = -1; - _skipFlag = false; - - // Load the background for the Dragonsphere game - this->loadBackground(942, &_bgPalData); - _vm->_palette->addRange(_bgPalData); - this->translate(_bgPalData); - - // Set up the menu item pos list - _menuItemPosList[0] = Common::Point(46, 187); - _menuItemPosList[1] = Common::Point(92, 187); - _menuItemPosList[2] = Common::Point(138, 187); - _menuItemPosList[3] = Common::Point(184, 187); - _menuItemPosList[4] = Common::Point(230, 187); - _menuItemPosList[5] = Common::Point(276, 187); -} - -DragonMainMenuView::~DragonMainMenuView() { - //if (_menuItem) - // delete _menuItem; - - _vm->_palette->deleteRange(_bgPalData); - - delete _bgPalData; - - for (uint i = 0; i < _itemPalData.size(); ++i) { - _vm->_palette->deleteRange(_itemPalData[i]); - delete _itemPalData[i]; - } -} - -bool DragonMainMenuView::onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { - char resName[20]; - Common::SeekableReadStream *data; - - // Handle keypresses - these can be done at any time, even when the menu items are being drawn - if (eventType == KEVENT_KEY) { - switch (param) { - case Common::KEYCODE_ESCAPE: - case Common::KEYCODE_F6: - handleAction(EXIT); - break; - - case Common::KEYCODE_F1: - handleAction(START_GAME); - break; - - case Common::KEYCODE_F2: - handleAction(RESUME_GAME); - break; - - case Common::KEYCODE_F3: - handleAction(SHOW_INTRO); - break; - - case Common::KEYCODE_F4: - handleAction(CREDITS); - break; - - default: - // Any other key skips the menu animation - _skipFlag = true; - return false; - } - - return true; - } - - int menuIndex; - - switch (eventType) { - case MEVENT_LEFT_CLICK: - case MEVENT_LEFT_DRAG: - if (_vm->_mouse->getCursorOn()) { - menuIndex = getHighlightedItem(x, y); - if (menuIndex != _highlightedIndex) { - - _highlightedIndex = menuIndex; - if (_highlightedIndex != -1) { - sprintf(resName, "MAIN%d.SS", menuIndex); - data = _vm->res()->get(resName); - _menuItem = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - M4Sprite *spr = _menuItem->getFrame(1); - spr->copyTo(this, spr->xOffset - 25, spr->yOffset - spr->height()); - } - } - } else { - // Skip the menu animation - _skipFlag = true; - } - return true; - - case MEVENT_LEFT_RELEASE: - if (_highlightedIndex != -1) - handleAction((MadsGameAction) _highlightedIndex); - return true; - - default: - break; - } - - return false; -} - -void DragonMainMenuView::updateState() { - char resName[20]; - Common::SeekableReadStream *data; - RGBList *palData; - M4Sprite *spr; - - if (_menuItemIndex == 6) - return; - - while (_menuItemIndex < 6) { - sprintf(resName, "MAIN%d.SS", _menuItemIndex); - data = _vm->res()->get(resName); - _menuItem = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - palData = _menuItem->getRgbList(); - _vm->_palette->addRange(palData); - _menuItem->translate(palData, true); - _itemPalData.push_back(palData); - - spr = _menuItem->getFrame(0); - spr->copyTo(this, spr->xOffset - 25, spr->yOffset - spr->height()); - - if (_menuItemIndex != 5) - delete _menuItem; - _menuItemIndex++; - } - - // Sphere - sprintf(resName, "RM920X0.SS"); - data = _vm->res()->get(resName); - _menuItem = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - palData = _menuItem->getRgbList(); - _vm->_palette->addRange(palData); - _menuItem->translate(palData, true); - _itemPalData.push_back(palData); - - spr = _menuItem->getFrame(0); // empty sphere - spr->copyTo(this, spr->xOffset - 75, spr->yOffset - spr->height()); - spr = _menuItem->getFrame(1); // dragon inside sphere - spr->copyTo(this, spr->xOffset - 75, spr->yOffset - spr->height()); - - // Dragonsphere letters - sprintf(resName, "RM920X3.SS"); - data = _vm->res()->get(resName); - _menuItem = new SpriteAsset(_vm, data, data->size(), resName); - _vm->res()->toss(resName); - - // Slot it into available palette space - palData = _menuItem->getRgbList(); - _vm->_palette->addRange(palData); - _menuItem->translate(palData, true); - _itemPalData.push_back(palData); - - spr = _menuItem->getFrame(1); - spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), spr->getTransparencyIndex()); - - _vm->_mouse->cursorOn(); -} - -int DragonMainMenuView::getHighlightedItem(int x, int y) { - y -= (height() - MADS_SURFACE_HEIGHT) / 2; - - for (int index = 0; index < 6; ++index) { - const Common::Point &pt = _menuItemPosList[index]; - M4Sprite *spr = _menuItem->getFrame(0); - - if ((x >= pt.x - 25) && (y >= pt.y - spr->height()) && (x < (pt.x - 25 + spr->width())) && (y < (pt.y))) { - debugCN(kDebugGraphics, "x = %d, y = %d, index = %d\n", x, y, index); - return index; - } - } - - return -1; -} - -void DragonMainMenuView::handleAction(MadsGameAction action) { - MadsM4Engine *vm = _vm; - vm->_mouse->cursorOff(); - vm->_viewManager->deleteView(this); - - switch (action) { - case START_GAME: - case RESUME_GAME: - // Load a sample starting scene - note that, currently, calling loadScene automatically - // removes this menu screen from being displayed - vm->_mouse->cursorOn(); - vm->_viewManager->addView(vm->_scene); - vm->_scene->loadScene(101); - return; - - case SHOW_INTRO: - vm->_viewManager->showAnimView("@dragon"); - break; - - case CREDITS: - vm->_viewManager->showTextView("credits"); - return; - - case EXIT: - vm->_events->quitFlag = true; - return; - - default: - break; - } -} - - -/*-------------------------------------------------------------------------- - * RexDialogView is the base class for the different full-screen dialogs - * in at least Rex Nebular - *-------------------------------------------------------------------------- - */ - -RexDialogView::RexDialogView(): View(_madsVm, Common::Rect(0, 0, _madsVm->_screen->width(), _madsVm->_screen->height())), - MadsView(this) { - _screenType = VIEWID_MENU; - - // Initialize class variables - _priorSceneId = _madsVm->_scene->getCurrentScene(); - _dialogType = DIALOG_NONE; - - // Load necessary quotes - _madsVm->globals()->loadQuoteRange(1, 48); - - initializeLines(); - initializeGraphics(); -} - -void RexDialogView::initializeLines() { - // Set up a list of blank entries for use in the various dialogs - for (int i = 0; i < DIALOG_LINES_SIZE; ++i) { - DialogTextEntry rec; - rec.in_use = false; - _dialogText.push_back(rec); - } - _totalTextEntries = 0; - - // Set up a default sprite slot entry for a full screen refresh - _spriteSlots.startIndex = 1; - _spriteSlots[0].spriteType = FULL_SCREEN_REFRESH; - _spriteSlots[0].seqIndex = -1; -} - -void RexDialogView::initializeGraphics() { - // Set needed palette entries - _madsVm->_palette->blockRange(0, 16); - _madsVm->_palette->setEntry(10, 0, 255, 0); - _madsVm->_palette->setEntry(11, 0, 180, 0); - _madsVm->_palette->setEntry(12, 255, 255, 0); - _madsVm->_palette->setEntry(13, 180, 180, 0); - _madsVm->_palette->setEntry(14, 255, 255, 180); - _madsVm->_palette->setEntry(15, 180, 180, 180); - - // Load an appropriate background and menu sprites - loadBackground(); - loadMenuSprites(); - - // Set the current cursor - _madsVm->_mouse->setCursorNum(CURSOR_ARROW); -} - - -RexDialogView::~RexDialogView() { - _madsVm->_palette->deleteRange(_bgPalData); - delete _bgPalData; - delete _backgroundSurface; -} - -void RexDialogView::loadBackground() { - int bgIndex = _madsVm->globals()->sceneNumber / 100; - int screenId = 0; - - switch (bgIndex) { - case 1: - case 2: - screenId = 921; - break; - case 3: - case 4: - screenId = 922; - break; - case 5: - case 6: - case 7: - screenId = 923; - break; - case 8: - screenId = 924; - break; - case 9: - screenId = 920; - break; - default: - error("Unknown scene number"); - } - - _backgroundSurface = new M4Surface(width(), MADS_SURFACE_HEIGHT); - _backgroundSurface->loadBackground(screenId, &_bgPalData); - _vm->_palette->addRange(_bgPalData); - _backgroundSurface->translate(_bgPalData); -} - -void RexDialogView::loadMenuSprites() { - const char *SPRITES_NAME = "*MENU.SS"; - - _spriteSlots.addSprites(SPRITES_NAME); -} - - -void RexDialogView::updateState() { -} - -void RexDialogView::onRefresh(RectList *rects, M4Surface *destSurface) { - // Draw the framed base area - fillRect(this->bounds(), _madsVm->_palette->BLACK); - setColor(2); - hLine(0, width(), MADS_Y_OFFSET - 2); - hLine(0, width(), MADS_Y_OFFSET + MADS_SURFACE_HEIGHT + 2); - - // Add in the loaded background vertically centered - _backgroundSurface->copyTo(this, 0, (height() - MADS_SURFACE_HEIGHT) / 2); - - // Check whether any of the dialog text entries need to be refreshed - refreshText(); - - // Handle the drawing of the various Mads elements - refresh(); - - View::onRefresh(rects, destSurface); -} - -/** - * Handles item selection within dialogs - */ -bool RexDialogView::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - static bool word_7F28C = false; - int word_7FED2 = 0; - //int word_8502A = 0; - - // If it's a keypress, handle it immediately - if (eventType == KEVENT_KEY) { - switch (param1) { - case Common::KEYCODE_q | (Common::KBD_CTRL << 24): - case Common::KEYCODE_q | (Common::KBD_ALT << 24): - _madsVm->quitGame(); - return true; - case Common::KEYCODE_RETURN: - _enterFlag = true; - _selectedLine = 0; - break; - case Common::KEYCODE_ESCAPE: - _selectedLine = 0; - break; - default: - return false; - } - } - - // Mark all the dialog text entries as not being seelcted - for (uint i = 0; i < _dialogText.size(); ++i) - _dialogText[i].state = STATE_DESELECTED; - - // Check if the mouse is over a registered screen object - int idx = _screenObjects.scan(x, y, LAYER_GUI); - - if (word_7F28C) { - if (y < _screenObjects[2].bounds.top) { - if (eventType != MEVENT_LEFT_RELEASE) - _dialogText[1].state = STATE_SELECTED; - idx = 19; - } - - if (y > _screenObjects[8].bounds.bottom) { - if (eventType != MEVENT_LEFT_RELEASE) - _dialogText[7].state = STATE_SELECTED; - idx = 20; - } - } - - int objIndex = -1; - if ((idx > 0) && ((eventType == MEVENT_LEFT_HOLD) || (eventType == MEVENT_LEFT_DRAG) || - (eventType == MEVENT_LEFT_RELEASE))) { - objIndex = _screenObjects[idx].index; - - if ((_dialogType == DIALOG_SAVE) || (_dialogType == DIALOG_RESTORE)) { - if ((objIndex > 7) && (objIndex <= 14)) - _dialogText[objIndex].state = STATE_SELECTED; - } - - if (word_7FED2) - word_7F28C = (objIndex > 0) && (objIndex <= 7); - - if (_screenObjects[idx].category == 1) - _dialogText[objIndex].state = STATE_SELECTED; - } else { - idx = -1; - } - - if (idx == 0) - idx = -1; - - if (_dialogType == DIALOG_ERROR) { - if (idx == 1) - idx = -1; - } - - if (eventType == MEVENT_LEFT_RELEASE) { - if (!word_7F28C || (objIndex <= 18)) - _selectedLine = objIndex; - - //word_8502A = -1; - } - - return true; -} - -void RexDialogView::setFrame(int frameNumber, int depth) { - int slotIndex = _spriteSlots.getIndex(); - _spriteSlots[slotIndex].spriteType = FOREGROUND_SPRITE; - _spriteSlots[slotIndex].seqIndex = 1; - _spriteSlots[slotIndex].spriteListIndex = 0; //_menuSpritesIndex; - _spriteSlots[slotIndex].frameNumber = frameNumber; - - M4Sprite *spr = _spriteSlots.getSprite(0).getFrame(frameNumber - 1); - _spriteSlots[slotIndex].xp = spr->x; - _spriteSlots[slotIndex].yp = spr->y; - _spriteSlots[slotIndex].depth = depth; - _spriteSlots[slotIndex].scale = 100; -} - -void RexDialogView::initVars() { - _v8502C = -1; - _selectedLine = -1; - _lineIndex = 0; - _enterFlag = false; - _textLines.clear(); -} - -void RexDialogView::addLine(const char *msg_p, Font *font, MadsTextAlignment alignment, int left, int top) { - DialogTextEntry *rec = NULL; - - if (_lineIndex < _totalTextEntries) { - if (strcmp(msg_p, _dialogText[_lineIndex].text) == 0) { - rec = &_dialogText[_lineIndex]; - if (rec->textDisplay_index != 0) { - MadsTextDisplayEntry &tdEntry = _textDisplay[rec->textDisplay_index]; - if (tdEntry.active) { - if (_textLines.size() < 20) { - // Add entry to line list - _textLines.push_back(tdEntry.msg); - tdEntry.msg = _textLines[_textLines.size() - 1].c_str(); - } - } - } - } - } else { - if (_lineIndex < DIALOG_LINES_SIZE) { - rec = &_dialogText[_lineIndex]; - _totalTextEntries = _lineIndex + 1; - } - } - - // Handling for if a line needs to be added - if (rec) { - strcpy(rec->text, msg_p); - rec->font = font; - rec->state = STATE_DESELECTED; - rec->pos.y = top; - rec->widthAdjust = -1; - rec->in_use = true; - rec->textDisplay_index = -1; - - switch (alignment) { - case ALIGN_CENTER: - // Center text - rec->pos.x = (width() - font->getWidth(rec->text)) / 2 + left; - break; - - case ALIGN_CHAR_CENTER: { - // Text is center aligned on the '@' character within the string - char *p = strchr(rec->text, '@'); - - if (p) { - // '@' string handling - // Get length of string up to the '@' character - *p = '\0'; - int strWidth = font->getWidth(rec->text, rec->widthAdjust); - // Remove the character from the string. strcpy isn't used here because it's unsafe for - // copying within the same string - while ((*p = *(p + 1)) != '\0') ++p; - - rec->pos.x = (width() / 2) - strWidth; - } else { - rec->pos.x = left; - } - break; - } - - case RIGHT_ALIGN: - // Right align (moving left from given passed left) - rec->pos.x = left - font->getWidth(rec->text); - break; - - default: - break; - } - } - - ++_lineIndex; -} - -/** - * Adds a line consisting of either a single quote, or the combination of two quote Ids - */ -void RexDialogView::addQuote(Font *font, MadsTextAlignment alignment, int left, int top, int id1, int id2) { - char buffer[80]; - - // Copy the first quote string into the buffer - const char *quoteStr = _madsVm->globals()->getQuote(id1); - strcpy(buffer, quoteStr); - - // Handle the optional second quote Id - if (id2 != 0) { - quoteStr = _madsVm->globals()->getQuote(id2); - strcat(buffer, " "); - strcat(buffer, quoteStr); - } - - // Add in the generated line - addLine(buffer, font, alignment, left, top); -} - -/** - * Sets any previously created dialog text entries as clickable items - */ -void RexDialogView::setClickableLines() { - _screenObjects.clear(); - - for (int i = 0; i < DIALOG_LINES_SIZE; ++i) { - if (_dialogText[i].in_use) { - // Add an entry for the line - _screenObjects.add(Common::Rect(_dialogText[i].pos.x, _dialogText[i].pos.y, - _dialogText[i].pos.x + _dialogText[i].font->getWidth(_dialogText[i].text, _dialogText[i].widthAdjust), - _dialogText[i].pos.y + _dialogText[i].font->getHeight()), 19, i, 1); - } - } - - if ((_madsVm->globals()->dialogType == DIALOG_SAVE) || (_madsVm->globals()->dialogType == DIALOG_RESTORE)) { - // Extra entries for the scroller areas of the Save and Restor dialogs - _screenObjects.add(Common::Rect(293, 26, 312, 75), LAYER_GUI, 50, 2); - _screenObjects.add(Common::Rect(293, 78, 312, 127), LAYER_GUI, 51, 2); - } -} - -/** - * Handles creating text display objects for each dialog line initially, and when the selected state - * of any entry changes - */ -void RexDialogView::refreshText() { - for (uint i = 0; i < _dialogText.size(); ++i) { - if (!_dialogText[i].in_use) - continue; - - // Get the item's colors - uint color; - if (_dialogText[i].state == STATE_DESELECTED) - color = 0xB0A; - else if (_dialogText[i].state == STATE_SELECTED) - color = 0xD0C; - else - color = 0xF0E; - - // If there's an associated text display entry, check to see if it's color needs to change - if (_dialogText[i].textDisplay_index >= 0) { - MadsTextDisplayEntry &tdEntry = _textDisplay[_dialogText[i].textDisplay_index]; - - if ((tdEntry.color1 == (color & 0xff)) && (tdEntry.color2 == (color >> 8))) - // It's still the same, so no further action needed - continue; - - // Flag the currently assigned text display to be expired, so it can be re-created - _textDisplay.expire(_dialogText[i].textDisplay_index); - _dialogText[i].textDisplay_index = -1; - } - - // Create a new text display entry for the dialog text line - _dialogText[i].textDisplay_index = _textDisplay.add(_dialogText[i].pos.x, _dialogText[i].pos.y, - color, _dialogText[i].widthAdjust, _dialogText[i].text, _dialogText[i].font); - } -} - -/*-------------------------------------------------------------------------- - * RexGameMenuDialog is the main game dialog for the game - *-------------------------------------------------------------------------- - */ - -RexGameMenuDialog::RexGameMenuDialog(): RexDialogView() { - _dialogType = DIALOG_GAME_MENU; - setFrame(1, 2); - initVars(); - - _vm->_font->setFont(FONT_CONVERSATION_MADS); - addLines(); - setClickableLines(); -} - -void RexGameMenuDialog::addLines() { - // Add the title - int top = MADS_Y_OFFSET - 2 - ((((_vm->_font->current()->getHeight() + 2) * 6) >> 1) - 78); - - addQuote(_vm->_font->current(), ALIGN_CENTER, 0, top, 10); - - // Loop for adding the option lines of the dialog - top += 6; - for (int idx = 0; idx < 5; ++idx) { - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CENTER, 0, top, 11 + idx); - } -} - -bool RexGameMenuDialog::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - // Call the parent event handler to handle line selection - bool handled = RexDialogView::onEvent(eventType, param1, x, y, captureEvents); - - if (_selectedLine > 0) { - switch (_selectedLine) { - case 1: - // Save Game - _madsVm->globals()->dialogType = DIALOG_SAVE; - break; - case 2: - // Restore Game - _madsVm->globals()->dialogType = DIALOG_RESTORE; - break; - case 3: - // Game Play Options - _madsVm->globals()->dialogType = DIALOG_OPTIONS; - break; - case 4: - // Resume Current Game - _madsVm->globals()->dialogType = DIALOG_NONE; - break; - case 5: - // Exit From Game - _madsVm->quitGame(); - break; - default: - // TODO: Extra logic for such as resuming scene if necessary - _madsVm->globals()->dialogType = DIALOG_NONE; - break; - } - - // Close this dialog - _madsVm->_viewManager->deleteView(this); - } - - return handled; -} - -/*-------------------------------------------------------------------------- - * RexOptionsDialog is the game options dialog for Rex Nebular - *-------------------------------------------------------------------------- - */ - -RexOptionsDialog::RexOptionsDialog(): RexDialogView() { - _dialogType = DIALOG_OPTIONS; - _tempConfig = _madsVm->globals()->_config; - - setFrame(2, 2); - initVars(); - - _vm->_font->setFont(FONT_CONVERSATION_MADS); - addLines(); - setClickableLines(); -} - -void RexOptionsDialog::reload() { - for (int i = 0; i < DIALOG_LINES_SIZE; ++i) - _dialogText[i].in_use = false; - _totalTextEntries = 0; - _textDisplay.clear(); - _screenObjects.clear(); - - initVars(); - - _vm->_font->setFont(FONT_CONVERSATION_MADS); - addLines(); - setClickableLines(); -} - -void RexOptionsDialog::addLines() { - // Add the title - int top = MADS_Y_OFFSET - 2 - ((((_vm->_font->current()->getHeight() + 1) * 9 + 12) >> 1) - 78); - - addQuote(_vm->_font->current(), ALIGN_CENTER, 0, top, 16); - - // Music state line - top += _vm->_font->current()->getHeight() + 1 + 6; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 17, _tempConfig.musicFlag ? 24 : 25); - - // Sound state line - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 18, _tempConfig.soundFlag ? 26 : 27); - - // Interface easy state line - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 19, _tempConfig.easyMouse ? 29 : 28); - - // Inventory sppinng state line - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 20, _tempConfig.invObjectsStill ? 31 : 30); - - // Text window state line - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 21, _tempConfig.textWindowStill ? 33 : 32); - - // Screen fade state line - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 22, _tempConfig.screenFades + 34); - - // Storyline mode line - top += _vm->_font->current()->getHeight() + 1; - addQuote(_vm->_font->current(), ALIGN_CHAR_CENTER, 0, top, 23, (_tempConfig.storyMode == 1) ? 37 : 38); - - // Add Done and Cancel button texts - top += _vm->_font->current()->getHeight() + 1 + 6; - addQuote(_vm->_font->current(), ALIGN_CENTER, -54, top, 1, 0); - addQuote(_vm->_font->current(), ALIGN_CENTER, 54, top, 2, 0); -} - -bool RexOptionsDialog::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - // Call the parent event handler to handle line selection - bool handled = RexDialogView::onEvent(eventType, param1, x, y, captureEvents); - - if (_selectedLine > 0) { - switch (_selectedLine) { - case 0: - // Enter or Escape - _selectedLine = _enterFlag ? 8 : 9; - return true; - case 1: - // Music line - _tempConfig.musicFlag = !_tempConfig.musicFlag; - break; - case 2: - // Sound line - _tempConfig.soundFlag = !_tempConfig.soundFlag; - break; - case 3: - // Interface line - _tempConfig.easyMouse = !_tempConfig.easyMouse; - break; - case 4: - // Inventory line - _tempConfig.invObjectsStill = !_tempConfig.invObjectsStill; - break; - case 5: - // Text window line - _tempConfig.textWindowStill = !_tempConfig.textWindowStill; - break; - case 6: - // Screen fades line - if (++_tempConfig.screenFades > 2) - _tempConfig.screenFades = 0; - break; - case 7: - // Story mode line - if (_tempConfig.storyMode == 2) - _tempConfig.storyMode = 1; - else if (_tempConfig.storyMode == 1) - _tempConfig.storyMode = 2; - break; - case 8: - case 9: - // Done and Cancel buttons - // TODO: Proper re-loading of settings if Cancel button clicked - _madsVm->globals()->_config = _tempConfig; - - // Closing the dialog, so return to the game menu - _madsVm->globals()->dialogType = DIALOG_GAME_MENU; - _madsVm->_viewManager->deleteView(this); - return true; - } - - // Update the option selections - reload(); - } - - return handled; -} - -} diff --git a/engines/m4/mads_menus.h b/engines/m4/mads_menus.h deleted file mode 100644 index 4d3ea5da39..0000000000 --- a/engines/m4/mads_menus.h +++ /dev/null @@ -1,179 +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. - * - */ - -#ifndef M4_MADS_MENUS_H -#define M4_MADS_MENUS_H - -#include "common/str-array.h" -#include "m4/viewmgr.h" -#include "m4/mads_views.h" -#include "m4/font.h" - -namespace M4 { - -#define MADS_MENU_ANIM_DELAY 70 - -enum MadsGameAction {START_GAME, RESUME_GAME, SHOW_INTRO, CREDITS, QUOTES, EXIT}; - -enum MadsLayers {LAYER_GUI = 19}; - -class RexMainMenuView : public View { -private: - Common::Point _menuItemPosList[6]; -private: - M4Surface *_bgSurface; - RGBList *_bgPalData; - int _menuItemIndex; - int _frameIndex; - bool _skipFlag; - SpriteAsset *_menuItem; - Common::Array _itemPalData; - uint32 _delayTimeout; - int _highlightedIndex; - - int getHighlightedItem(int x, int y); - void handleAction(MadsGameAction action); -public: - RexMainMenuView(MadsM4Engine *vm); - ~RexMainMenuView(); - - bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); - void updateState(); -}; - -class DragonMainMenuView : public View { -private: - Common::Point _menuItemPosList[6]; -private: - //M4Surface *_bgSurface; - RGBList *_bgPalData; - int _menuItemIndex; - int _frameIndex; - bool _skipFlag; - SpriteAsset *_menuItem; - Common::Array _itemPalData; - uint32 _delayTimeout; - int _highlightedIndex; - - int getHighlightedItem(int x, int y); - void handleAction(MadsGameAction action); -public: - DragonMainMenuView(MadsM4Engine *vm); - ~DragonMainMenuView(); - - bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); - void updateState(); -}; - -class MadsMainMenuView : public View { -public: - MadsMainMenuView(MadsM4Engine *vm); - - bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents); - void updateState(); -}; - -enum DialogTextState {STATE_DESELECTED = 0, STATE_SELECTED = 1, STATE_UNKNOWN = 2}; - -class DialogTextEntry { -public: - bool in_use; - DialogTextState state; - Common::Point pos; - char text[80]; - Font *font; - int widthAdjust; - - int textDisplay_index; - - DialogTextEntry() { in_use = false; } -}; - -#define DIALOG_LINES_SIZE 20 - -enum MadsTextAlignment { ALIGN_CENTER = -1, ALIGN_CHAR_CENTER = -2, RIGHT_ALIGN = -3 }; - - -class RexDialogView : public View, public MadsView { -private: - int _priorSceneId; - - void initializeLines(); - void initializeGraphics(); - void loadBackground(); - void loadMenuSprites(); -protected: - MadsDialogType _dialogType; - M4Surface *_backgroundSurface; - RGBList *_bgPalData; - SpriteAsset *_menuSprites; - - Common::Array _dialogText; - Common::StringArray _textLines; - int _totalTextEntries; - int _dialogSelectedLine; - Common::StringArray _saveList; - - int _v8502C; - int _selectedLine; - int _lineIndex; - bool _enterFlag; - - void setFrame(int frameNumber, int depth); - void initVars(); - void addLine(const char *msg_p, Font *font, MadsTextAlignment alignment, int left, int top); - void addQuote(Font *font, MadsTextAlignment alignment, int left, int top, int id1, int id2 = 0); - void setClickableLines(); - void refreshText(); -public: - RexDialogView(); - ~RexDialogView(); - - virtual void updateState(); - virtual void onRefresh(RectList *rects, M4Surface *destSurface); - virtual bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - -class RexGameMenuDialog : public RexDialogView { -private: - void addLines(); -public: - RexGameMenuDialog(); - - virtual bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - -class RexOptionsDialog : public RexDialogView { -private: - MadsConfigData _tempConfig; - - void reload(); - void addLines(); -public: - RexOptionsDialog(); - - virtual bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - -} - -#endif diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp deleted file mode 100644 index 73480088ee..0000000000 --- a/engines/m4/mads_player.cpp +++ /dev/null @@ -1,789 +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 "m4/m4.h" -#include "m4/mads_player.h" -#include "m4/mads_scene.h" - -namespace M4 { - -const int MadsPlayer::_directionListIndexes[32] = { - 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0 -}; - -MadsPlayer::MadsPlayer() { - _playerPos = Common::Point(160, 78); - _ticksAmount = 3; - _forceRefresh = true; - _stepEnabled = true; - _visible = true; - _yScale = 0; - _moving = false; - - _spriteListStart = 0; - //TODO:unknown vars - _special = 0; - _next = 0; - _unk4 = false; - - _spritesChanged = true; - - _direction = 0; - _newDirection = 0; - _priorTimer = 0; - _priorVisible = false; - _visible3 = false; - _spriteListIdx = 0; - _currentScale = 0; - strcpy(_spritesPrefix, ""); - for (int idx = 0; idx < 8; ++idx) - _spriteSetsPresent[idx] = false; - _frameNum = 0; - _frameOffset = 0; - _unk1 = 0; - _frameCount = 0; - _frameListIndex = 0; - _actionIndex = 0; - _routeCount = 0; - - resetActionList(); -} - -/** - * Loads the sprite set for the player - */ -bool MadsPlayer::loadSprites(const char *prefix) { - const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' }; - char setName[80]; - bool result = true; - - if (prefix) - strcpy(_spritesPrefix, prefix); - - _spriteSetCount = 0; - int prefixLen = strlen(_spritesPrefix); - - if (prefixLen == 0) { - // No player sprites at at all - for (int idx = 0; idx < 8; ++idx) - _spriteSetsPresent[idx] = false; - } else { - strcpy(setName, "*"); - strcat(setName, _spritesPrefix); - strcat(setName, "_0.SS"); - - char *digitP = strchr(setName, '_') + 1; - - for (int idx = 0; idx < 8; ++idx) { - *digitP = suffixList[idx]; - _spriteSetsPresent[idx] = true; - - int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO); - if (setIndex < 0) { - if (idx < 5) - break; - _spriteSetsPresent[idx] = false; - } else { - ++_spriteSetCount; - } - - if (idx == 0) - _spriteListStart = setIndex; - } - - result = 0; - // TODO: Unknown flag - _spritesChanged = false; - } - - return result; -} - -/** - * Called each frame to update the display of the player - */ -void MadsPlayer::update() { - if (_forceRefresh || (_visible != _priorVisible)) { - // If there's an existing player sprite visible, flag it for expiry - int slotIndex = getSpriteSlot(); - if (slotIndex >= 0) - _madsVm->scene()->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE; - - // Figure out the depth for the sprite - int newDepth = 1; - int yp = MIN(_playerPos.y, (int16)155); - - for (int idx = 1; idx < 15; ++idx) { - if (_madsVm->scene()->getSceneResources()._depthBands[newDepth] >= yp) - newDepth = idx + 1; - } - _currentDepth = newDepth; - - // Get the scale - int newScale = getScale(_playerPos.y); - _currentScale = MIN(newScale, 100); - - if (_visible) { - // Player sprite needs to be rendered - MadsSpriteSlot slot; - slot.spriteType = FOREGROUND_SPRITE; - slot.seqIndex = PLAYER_SEQ_INDEX; - slot.spriteListIndex = _spriteListStart + _spriteListIdx; - slot.frameNumber = _frameOffset + _frameNum; - slot.xp = _playerPos.x; - slot.yp = _playerPos.y + (_yScale * newScale) / 100; - slot.depth = newDepth; - slot.scale = newScale; - - if (slotIndex >= 0) { - // Check if the existing player slot has the same details, and can be re-used - MadsSpriteSlot &s2 = _madsVm->scene()->_spriteSlots[slotIndex]; - bool equal = (s2.seqIndex == slot.seqIndex) && (s2.spriteListIndex == slot.spriteListIndex) - && (s2.frameNumber == slot.frameNumber) && (s2.xp == slot.xp) && (s2.yp == slot.yp) - && (s2.depth == slot.depth) && (s2.scale == slot.scale); - - if (equal) - // Undo the prior expiry of the player sprite - s2.spriteType = SPRITE_ZERO; - else - slotIndex = -1; - } - - if (slotIndex < 0) { - // New slot needed, so allocate one and copy the slot data - slotIndex = _madsVm->scene()->_spriteSlots.getIndex(); - _madsVm->scene()->_spriteSlots[slotIndex] = slot; - } - - // TODO: Meaning of _v844c0 block - - } - } - - _visible3 = _priorVisible = _visible; - _forceRefresh = false; -} - -/** - * Updates the animation frame for the player - */ -void MadsPlayer::updateFrame() { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - - if (!spriteSet._charInfo->_numEntries) { - _frameNum = 1; - } else { - _frameListIndex = _actionList[_actionIndex]; - - if (!_visible) { - _unk2 = 0; - } else { - _unk2 = _actionList2[_actionIndex]; - - if (_actionIndex > 0) - --_actionIndex; - } - - // Set the player frame number - int frameIndex = ABS(_frameListIndex); - _frameNum = (_frameListIndex <= 0) ? spriteSet._charInfo->_frameList[frameIndex] : - spriteSet._charInfo->_frameList2[frameIndex]; - - // Set next waiting period in ticks - if (frameIndex == 0) - setTicksAmount(); - else - _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksList[frameIndex]; - } -} - -void MadsPlayer::setupFrame() { - resetActionList(); - _frameOffset = 0; - _spriteListIdx = _directionListIndexes[_direction]; - if (!_spriteSetsPresent[_spriteListIdx]) { - // Direction isn't present, so use alternate direction, with entries flipped - _spriteListIdx -= 4; - _frameOffset = 0x8000; - } - - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - _unk1 = MAX(spriteSet._charInfo->_unk1, 100); - setTicksAmount(); - - _frameCount = spriteSet._charInfo->_totalFrames; - if (_frameCount == 0) - _frameCount = spriteSet.getCount(); - - _yScale = spriteSet._charInfo->_yScale; - - if ((_frameNum <= 0) || (_frameNum > _frameCount)) - _frameNum = 1; - _forceRefresh = true; -} - -void MadsPlayer::step() { - if (_visible && _stepEnabled && !_moving && (_direction == _newDirection) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) { - if (_actionIndex == 0) { - int randVal = _vm->_random->getRandomNumber(29999); - - if (GET_GLOBAL(0) == SEX_MALE) { - switch (_direction) { - case 1: - case 3: - case 7: - case 9: - if (randVal < 200) { - queueAction(-1, 0); - queueAction(1, 0); - } - break; - - case 2: - if (randVal < 500) { - for (int i = 0; i < 10; ++i) - queueAction((randVal < 250) ? 1 : 2, 0); - } else if (randVal < 750) { - for (int i = 0; i < 5; ++i) - queueAction(1, 0); - queueAction(0, 0); - for (int i = 0; i < 5; ++i) - queueAction(2, 0); - } - break; - - case 4: - case 6: - if (randVal < 500) { - for (int i = 0; i < 10; ++i) - queueAction(1, 0); - } - break; - - case 5: - case 8: - if (randVal < 200) { - queueAction(-1, 0); - queueAction(1, 0); - } - break; - } - } - } - - SET_GLOBAL32(2, GET_GLOBAL32(2) + 6); - } - - if (GET_GLOBAL(138) == 1) { - uint32 diff = _madsVm->_currentTimer - GET_GLOBAL32(142); - if (diff > 60) { - SET_GLOBAL32(144, GET_GLOBAL32(144) + 1); - } else { - SET_GLOBAL32(144, GET_GLOBAL32(144) + diff); - } - - SET_GLOBAL32(142, _madsVm->_currentTimer); - } -} - -void MadsPlayer::nextFrame() { - if (_madsVm->_currentTimer >= (_priorTimer + _ticksAmount)) { - _priorTimer = _madsVm->_currentTimer; - - if (_moving) - move(); - else - idle(); - - // Post update logic - if (_moving) { - ++_frameNum; - if (_frameNum > _frameCount) - _frameNum = 1; - _forceRefresh = true; - } else if (!_forceRefresh) { - idle(); - } - - // Final update - update(); - } -} - -void MadsPlayer::setDest(int destX, int destY, int facing) { - resetActionList(); - setTicksAmount(); - _moving = true; - _destFacing = facing; - - _madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 2, - _playerPos, _madsVm->scene()->_depthSurface); - _madsVm->scene()->getSceneResources().setRouteNode(_madsVm->scene()->getSceneResources()._nodes.size() - 1, - Common::Point(destX, destY), _madsVm->scene()->_depthSurface); - - bool v = _madsVm->scene()->getDepthHighBit(Common::Point(destX, destY)); - setupRoute(v); - _next = 0; - - if (_routeCount > 0) { - Common::Point srcPos = _playerPos; - for (int routeCtr = _routeCount - 1; (routeCtr >= 0) && (_next == 0); --routeCtr) { - int idx = _routeIndexes[routeCtr]; - const Common::Point &pt = _madsVm->scene()->getSceneResources()._nodes[idx].pt; - - _next = scanPath(_madsVm->scene()->_depthSurface, srcPos, pt); - srcPos = pt; - } - } -} - - -int MadsPlayer::getScale(int yp) { - MadsSceneResources &r = _madsVm->scene()->getSceneResources(); - - int scale = (r.bandsRange() == 0) ? r._maxScale : (yp - r._yBandsStart) * r.scaleRange() / r.bandsRange() - + r._minScale; - - return MIN(scale, 100); -} - -/** - * Scans through the scene's sprite slot list to find any sprite displaying the player - */ -int MadsPlayer::getSpriteSlot() { - MadsSpriteSlots &slots = _madsVm->scene()->_spriteSlots; - for (int i = 0; i < slots.startIndex; ++i) { - if ((slots[i].seqIndex == PLAYER_SEQ_INDEX) && (slots[i].spriteType >= SPRITE_ZERO)) - return i; - } - return -1; -} - -void MadsPlayer::setTicksAmount() { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount; - if (_madsVm->_player._ticksAmount == 0) - _madsVm->_player._ticksAmount = 6; -} - -void MadsPlayer::resetActionList() { - _actionList[0] = 0; - _actionList2[0] = 0; - _actionIndex = 0; - _unk2 = 0; - _unk3 = 0; -} - -int MadsPlayer::queueAction(int action1, int action2) { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - - if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) { - ++_actionIndex; - _actionList[_actionIndex] = action1; - _actionList2[_actionIndex] = action2; - return false; - } - - return true; -} - -void MadsPlayer::idle() { - if (_direction != _newDirection) { - // The direction has changed, so reset for new direction - dirChanged(); - return; - } - - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); - assert(spriteSet._charInfo); - if (spriteSet._charInfo->_numEntries == 0) - // No entries, so exit immediately - return; - - int frameIndex = ABS(_frameListIndex); - int direction = (_frameListIndex < 0) ? -1 : 1; - - if (frameIndex >= spriteSet._charInfo->_numEntries) - // Reset back to the start of the list - _frameListIndex = 0; - else { - _frameNum += direction; - _forceRefresh = true; - - if (spriteSet._charInfo->_frameList2[frameIndex] < _frameNum) { - _unk3 = _unk2; - updateFrame(); - } - if (spriteSet._charInfo->_frameList[frameIndex] < _frameNum) { - _unk3 = _unk2; - updateFrame(); - } - } -} - -void MadsPlayer::move() { - bool routeFlag = false; - - if (_moving) { - int idx = _routeCount; - while (!_v844C0 && (_destPos.x == _playerPos.x) && (_destPos.y == _playerPos.y)) { - if (idx != 0) { - --idx; - SceneNode &node = _madsVm->scene()->getSceneResources()._nodes[_routeIndexes[idx]]; - _destPos = node.pt; - routeFlag = true; - } else if (_v844BE == idx) { - // End of walking path - _routeCount = 0; - _moving = false; - turnToDestFacing(); - routeFlag = true; - idx = _routeCount; - } else { - _v844C0 = _v844BE; - _v844BC = true; - _v844BE = 0; - _stepEnabled = true; - routeFlag = false; - } - - if (!_moving) - break; - } - _routeCount = idx; - } - - if (routeFlag && _moving) - startMovement(); - - if (_newDirection != _direction) - dirChanged(); - else if (!_moving) - updateFrame(); - - int var1 = _unk1; - if (_unk4 && (_hypotenuse > 0)) { - int v1 = -(_currentScale - 100) * (_posDiff.x - 1) / _hypotenuse + _currentScale; - var1 = MAX(1, 10000 / (v1 * _currentScale * var1)); - } - - if (!_moving || (_direction != _newDirection)) - return; - - Common::Point newPos = _playerPos; - - if (_v8452E < var1) { - do { - if (_v8452C < _posDiff.x) - _v8452C += _posDiff.y; - if (_v8452C >= _posDiff.x) { - if ((_posChange.y > 0) || (_v844C0 != 0)) - newPos.y += _yDirection; - --_posChange.y; - _v8452C -= _posDiff.x; - } - - if (_v8452C < _posDiff.x) { - if ((_posChange.x > 0) || (_v844C0 != 0)) - newPos.x += _xDirection; - --_posChange.x; - } - - if ((_v844BC == 0) && (_v844C0 == 0) && (_v844BE == 0)) { - routeFlag = _madsVm->scene()->getDepthHighBit(newPos); - - if (_special == 0) - _special = _madsVm->scene()->getDepthHighBits(newPos); - } - - _v8452E += _v84530; - - } while ((_v8452E < var1) && !routeFlag && ((_posChange.x > 0) || (_posChange.y > 0) || (_v844C0 != 0))); - } - - _v8452E -= var1; - - if (routeFlag) - moveComplete(); - else { - if (!_v844C0) { - // If the move is complete, make sure the position is exactly on the given destination - if (_posChange.x == 0) - newPos.x = _destPos.x; - if (_posChange.y == 0) - newPos.y = _destPos.y; - } - - _playerPos = newPos; - } -} - -void MadsPlayer::dirChanged() { - int dirIndex = 0, dirIndex2 = 0; - int newDir = 0, newDir2 = 0; - - if (_direction != _newDirection) { - // Find the index for the given direction in the player direction list - int tempDir = _direction; - do { - ++dirIndex; - newDir += tempDir; - tempDir = _directionListIndexes[tempDir + 10]; - } while (tempDir != _newDirection); - } - - - if (_direction != _newDirection) { - // Find the index for the given direction in the player direction list - int tempDir = _direction; - do { - ++dirIndex2; - newDir2 += tempDir; - tempDir = _directionListIndexes[tempDir + 20]; - } while (tempDir != _newDirection); - } - - int diff = dirIndex - dirIndex2; - if (diff == 0) - diff = newDir - newDir2; - - _direction = (diff >= 0) ? _directionListIndexes[_direction + 20] : _directionListIndexes[_direction + 10]; - setupFrame(); - if ((_direction == _newDirection) && !_moving) - updateFrame(); - - _priorTimer += 1; -} - -void MadsPlayer::moveComplete() { - reset(); - //todo: Unknown flag -} - -void MadsPlayer::reset() { - _destPos = _playerPos; - _destFacing = 5; - _newDirection = _direction; - - _madsVm->scene()->_action._startWalkFlag = false; - _madsVm->scene()->_action._walkFlag = false; - _moving = false; - _v844BC = false; - _v844C0 = false; - _v844BE = 0; - _next = 0; - _routeCount = 0; -} - -/** - * Scans along an edge connecting two points within the depths/walk surface, and returns the information of the first - * pixel high nibble encountered with a non-zero value - */ -int MadsPlayer::scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos) { - // For compressed depth surfaces, always return 0 - if (_madsVm->scene()->getSceneResources()._depthStyle != 2) - return 0; - - int yDiff = destPos.y - srcPos.y; - int yAmount = MADS_SURFACE_WIDTH; - - if (yDiff < 0) { - yDiff = -yDiff; - yAmount = -yAmount; - } - - int xDiff = destPos.x - srcPos.y; - int xDirection = 1; - int xAmount = 0; - if (xDiff < 0) { - xDiff = -xDiff; - xDirection = -xDirection; - xAmount = MIN(yDiff, xDiff); - } - - ++xDiff; - ++yDiff; - - const byte *srcP = depthSurface->getBasePtr(srcPos.x, srcPos.y); - int index = xAmount; - - // Outer horizontal movement loop - for (int yIndex = 0; yIndex < yDiff; ++yIndex) { - index += yDiff; - int v = (*srcP & 0x7F) >> 4; - if (v) - return v; - - // Inner loop for handling vertical movement - while (index >= xDiff) { - index -= xDiff; - - v = (*srcP & 0x7F) >> 4; - if (v) - return v; - - srcP += yAmount; - } - - srcP += xDirection; - } - - return 0; -} - -/** - * Starts a player moving to a given destination - */ -void MadsPlayer::startMovement() { - int xDiff = _destPos.x - _playerPos.x; - int yDiff = _destPos.y - _playerPos.y; - int srcScale = getScale(_playerPos.y); - int destScale = getScale(_destPos.y); - - // Sets the X direction - if (xDiff > 0) - _xDirection = 1; - else if (xDiff < 0) - _xDirection = -1; - else - _xDirection = 0; - - // Sets the Y direction - if (yDiff > 0) - _yDirection = 1; - else if (yDiff < 0) - _yDirection = -1; - else - _yDirection = 0; - - xDiff = ABS(xDiff); - yDiff = ABS(yDiff); - int scaleDiff = ABS(srcScale - destScale); - - int xAmt100 = xDiff * 100; - int yAmt100 = yDiff * 100; - int xAmt33 = xDiff * 33; - - int scaleAmount = (_unk4 ? scaleDiff * 3 : 0) + 100 * yDiff / 100; - int scaleAmount100 = scaleAmount * 100; - - // Figure out direction that will need to be moved in - int majorDir; - if (xDiff == 0) - majorDir = 1; - else if (yDiff == 0) - majorDir = 3; - else { - if ((scaleAmount < xDiff) && ((xAmt33 / scaleAmount) >= 141)) - majorDir = 3; - else if (yDiff <= xDiff) - majorDir = 2; - else if ((scaleAmount100 / xDiff) >= 141) - majorDir = 1; - else - majorDir = 2; - } - - switch (majorDir) { - case 1: - _newDirection = (_yDirection <= 0) ? 8 : 2; - break; - case 2: { - _newDirection = ((_yDirection <= 0) ? 9 : 3) - ((_xDirection <= 0) ? 2 : 0); - break; - } - case 3: - _newDirection = (_xDirection <= 0) ? 4 : 6; - break; - default: - break; - } - - _hypotenuse = SqrtF16(xAmt100 * xAmt100 + yAmt100 * yAmt100); - _posDiff.x = xDiff + 1; - _posDiff.y = yDiff + 1; - _posChange.x = xDiff; - _posChange.y = yDiff; - - int majorChange = MAX(xDiff, yDiff); - _v84530 = (majorChange == 0) ? 0 : _hypotenuse / majorChange; - - if (_playerPos.x > _destPos.x) - _v8452C = MAX(_posChange.x, _posChange.y); - else - _v8452C = 0; - - _hypotenuse /= 100; - _v8452E = -_v84530; -} - -void MadsPlayer::turnToDestFacing() { - if (_destFacing != 5) - _newDirection = _destFacing; -} - -void MadsPlayer::setupRoute(bool bitFlag) { - // Reset the flag set of nodes in use - SceneNodeList &nodes = _madsVm->scene()->getSceneResources()._nodes; - for (uint i = 0; i < nodes.size(); ++i) - nodes[i].active = false; - - // Start constructing route node list - _routeLength = 0x3FFF; - _routeCount = 0; - - setupRouteNode(_tempRoute, nodes.size() - 1, bitFlag ? 0xC000 : 0x8000, 0); -} - -void MadsPlayer::setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength) { - SceneNodeList &nodes = _madsVm->scene()->getSceneResources()._nodes; - SceneNode ¤tNode = nodes[nodeIndex]; - currentNode.active = true; - - *routeIndexP++ = nodeIndex; - - int subIndex = nodes.size() - 2; - int indexVal = nodes[nodeIndex].indexes[subIndex]; - if (indexVal & flags) { - routeLength += indexVal & 0x3FFF; - if (routeLength < _routeLength) { - // Found a new shorter route to destination, so set up the route with the found one - Common::copy(_tempRoute, routeIndexP, _routeIndexes); - _routeCount = routeIndexP - _tempRoute; - _routeLength = indexVal & 0x3FFF; - } - } else { - for (int idx = nodes.size() - 2; idx > 0; --idx) { - int nodePos = idx - 1; - if (!nodes[nodePos].active && ((currentNode.indexes[nodePos] & flags) != 0)) - setupRouteNode(routeIndexP, nodePos, 0x8000, indexVal & 0x3fff); - } - } - - currentNode.active = false; -} - -} // End of namespace M4 diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h deleted file mode 100644 index bbeefaf3d5..0000000000 --- a/engines/m4/mads_player.h +++ /dev/null @@ -1,113 +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. - * - */ - -#ifndef M4_MADS_PLAYER_H -#define M4_MADS_PLAYER_H - -#include "common/scummsys.h" -#include "m4/mads_scene.h" - -namespace M4 { - -#define PLAYER_SEQ_INDEX -2 - -class MadsPlayer { -private: - int getScale(int yp); - int getSpriteSlot(); - void setTicksAmount(); - void resetActionList(); - int queueAction(int v0, int v1); - void idle(); - void move(); - void dirChanged(); - void reset(); - int scanPath(M4Surface *depthSurface, const Common::Point &srcPos, const Common::Point &destPos); - void startMovement(); - void setupRouteNode(int *routeIndexP, int nodeIndex, int flags, int routeLength); -public: - char _spritesPrefix[16]; - int _spriteSetCount; - bool _spriteSetsPresent[8]; - Common::Point _playerPos; - Common::Point _destPos; - Common::Point _posChange; - Common::Point _posDiff; - int _hypotenuse; - uint32 _priorTimer; - uint _ticksAmount; - int16 _direction, _newDirection; - bool _stepEnabled; - bool _visible, _priorVisible; - bool _visible3; - bool _forceRefresh; - int16 _currentScale; - int16 _yScale; - int16 _currentDepth; - int16 _spriteListStart, _spriteListIdx; - bool _spritesChanged; - uint16 _frameOffset, _frameNum; - bool _moving; - int _unk1; - int _frameCount; - int _frameListIndex; - int _actionIndex; - int _actionList[12]; - int _actionList2[12]; - int _unk2; - int _unk3; - int _xDirection, _yDirection; - int _destFacing; - int _special; - int _next; - int _routeCount; - int _routeOffset; - int _tempRoute[MAX_ROUTE_NODES]; - int _routeIndexes[MAX_ROUTE_NODES]; - bool _unk4; - bool _v844BC; - int _v844BE; - bool _v844C0; - int _v8452E; - int _v8452C; - int _v84530; - int _routeLength; - - static const int _directionListIndexes[32]; -public: - MadsPlayer(); - - bool loadSprites(const char *prefix); - void update(); - void updateFrame(); - void setupFrame(); - void step(); - void nextFrame(); - void setDest(int destX, int destY, int facing); - void turnToDestFacing(); - void setupRoute(bool bitFlag); - void moveComplete(); -}; - -} // End of namespace M4 - -#endif 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 diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h deleted file mode 100644 index 9835de4daf..0000000000 --- a/engines/m4/mads_scene.h +++ /dev/null @@ -1,195 +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. - * - */ - -#ifndef M4_MADS_SCENE_H -#define M4_MADS_SCENE_H - -#include "m4/scene.h" -#include "m4/mads_logic.h" -#include "m4/mads_views.h" - -namespace M4 { - -#define INTERFACE_HEIGHT 106 -class MadsInterfaceView; - -#define DEPTH_BANDS_SIZE 15 -#define MAX_ROUTE_NODES 22 - -enum ScreenCategory {CAT_NONE = 0, CAT_ACTION = 1, CAT_INV_LIST = 2, CAT_INV_VOCAB, CAT_HOTSPOT = 4, - CAT_INV_ANIM = 6, CAT_6, CAT_INV_SCROLLER = 7, CAT_12 = 12}; - -class SceneNode { -public: - Common::Point pt; - int indexes[MAX_ROUTE_NODES]; - - bool active; - - SceneNode() { - active = false; - } - - void load(Common::SeekableReadStream *stream); -}; - -typedef Common::Array SceneNodeList; - -class MadsSceneResources: public SceneResources { -private: - int getRouteFlags(const Common::Point &src, const Common::Point &dest, M4Surface *depthSurface); -public: - int _sceneId; - int _artFileNum; - int _depthStyle; - int _width; - int _height; - SceneNodeList _nodes; - Common::Array _setNames; - int _yBandsStart, _yBandsEnd; - int _maxScale, _minScale; - int _depthBands[DEPTH_BANDS_SIZE]; - - MadsSceneResources() {} - ~MadsSceneResources() {} - void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface); - int bandsRange() const { return _yBandsEnd - _yBandsStart; } - int scaleRange() const { return _maxScale - _minScale; } - void setRouteNode(int nodeIndex, const Common::Point &pt, M4Surface *depthSurface); -}; - -class MadsScene : public Scene, public MadsView { -private: - MadsEngine *_vm; - MadsSceneResources _sceneResources; - Animation *_activeAnimation; - - MadsSceneLogic _sceneLogic; - SpriteAsset *_playerSprites; - int _mouseMsgIndex; - int _highlightedHotspot; - - void drawElements(); - void loadScene2(const char *aaName, int sceneNumber); - void loadSceneTemporary(); - void loadSceneHotspots(int sceneNumber); - void clearAction(); - void appendActionVocab(int vocabId, bool capitalise); - void setAction(); - void checkStartWalk(); - void doPreactions(); - void doSceneStep(); - void doAction(); -public: - char _aaName[100]; - bool _showMousePos; - Common::Point _destPos; - int _destFacing; - Common::Point _customDest; -public: - MadsScene(MadsEngine *vm); - virtual ~MadsScene(); - void initialize() { - _sceneLogic.initializeScripts(); - } - - // Methods that differ between engines - virtual void loadScene(int sceneNumber); - virtual void leaveScene(); - virtual void loadSceneCodes(int sceneNumber, int index = 0); - virtual void show(); - virtual void mouseMove(int x, int y); - virtual void leftClick(int x, int y); - virtual void rightClick(int x, int y); - virtual void setAction(int action, int objectId = -1); - virtual void update(); - - virtual void updateState(); - - int loadSceneSpriteSet(const char *setName); - void showMADSV2TextBox(char *text, int x, int y, char *faceName); - void loadAnimation(const Common::String &animName, int abortTimers); - Animation *activeAnimation() const { return _activeAnimation; } - void freeAnimation(); - - MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; } - MadsSceneResources &getSceneResources() { return _sceneResources; } - bool getDepthHighBit(const Common::Point &pt); - bool getDepthHighBits(const Common::Point &pt); -}; - -#define CHEAT_SEQUENCE_MAX 8 - -class IntegerList : public Common::Array { -public: - int indexOf(int v) { - for (uint i = 0; i < size(); ++i) - if (operator [](i) == v) - return i; - return -1; - } -}; - -enum InterfaceFontMode {ITEM_NORMAL, ITEM_HIGHLIGHTED, ITEM_SELECTED}; - -enum InterfaceObjects {ACTIONS_START = 0, SCROLL_UP = 10, SCROLL_SCROLLER = 11, SCROLL_DOWN = 12, - INVLIST_START = 13, VOCAB_START = 18}; - -class MadsInterfaceView : public GameInterfaceView { -private: - IntegerList _inventoryList; - RectList _screenObjects; - int _highlightedElement; - int _topIndex; - uint32 _nextScrollerTicks; - int _cheatKeyCtr; - - // Object display fields - int _selectedObject; - SpriteAsset *_objectSprites; - RGBList *_objectPalData; - int _objectFrameNumber; - - void setFontMode(InterfaceFontMode newMode); - bool handleCheatKey(int32 keycode); - bool handleKeypress(int32 keycode); - void leaveScene(); -public: - MadsInterfaceView(MadsM4Engine *vm); - ~MadsInterfaceView(); - - virtual void initialize(); - virtual void setSelectedObject(int objectNumber); - virtual void addObjectToInventory(int objectNumber); - int getSelectedObject() { return _selectedObject; } - int getInventoryObject(int objectIndex) { return _inventoryList[objectIndex]; } - - void onRefresh(RectList *rects, M4Surface *destSurface); - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - -extern int getActiveAnimationBool(); -extern int getAnimationCurrentFrame(); - -} // End of namespace M4 - -#endif diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp deleted file mode 100644 index c1d88d5741..0000000000 --- a/engines/m4/mads_views.cpp +++ /dev/null @@ -1,1632 +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 "m4/m4_views.h" -#include "m4/animation.h" -#include "m4/dialogs.h" -#include "m4/events.h" -#include "m4/font.h" -#include "m4/globals.h" -#include "m4/mads_menus.h" -#include "m4/m4.h" -#include "m4/staticres.h" - -#include "common/algorithm.h" -#include "common/textconsole.h" - -namespace M4 { - -MadsAction::MadsAction(MadsView &owner): _owner(owner) { - clear(); - _currentAction = kVerbNone; - _startWalkFlag = false; - _statusTextIndex = -1; - _selectedAction = 0; - _inProgress = false; -} - -void MadsAction::clear() { - _v83338 = 1; - _actionMode = ACTMODE_NONE; - _actionMode2 = ACTMODE2_0; - _v86F42 = 0; - _v86F4E = 0; - _articleNumber = 0; - _lookFlag = false; - _v86F4A = 0; - _statusText[0] = '\0'; - _selectedRow = -1; - _hotspotId = -1; - _v86F3A = -1; - _v86F4C = -1; - _action.verbId = -1; - _action.objectNameId = -1; - _action.indirectObjectId = -1; - _textChanged = true; - _walkFlag = false; -} - -void MadsAction::appendVocab(int vocabId, bool capitalise) { - char *s = _statusText + strlen(_statusText); - const char *vocabStr = _madsVm->globals()->getVocab(vocabId); - strcpy(s, vocabStr); - if (capitalise) - *s = toupper(*s); - - strcat(s, " "); -} - -void MadsAction::set() { - int hotspotCount = _madsVm->scene()->getSceneResources().hotspots->size(); - bool flag = false; // FIXME: unused - strcpy(_statusText, ""); - - _currentAction = -1; - _action.objectNameId = -1; - _action.indirectObjectId = -1; - - if (_actionMode == ACTMODE_TALK) { - // Handle showing the conversation selection. Rex at least doesn't actually seem to use this - if (_selectedRow >= 0) { - const char *desc = _madsVm->_converse[_selectedRow].desc; - if (desc) - strcpy(_statusText, desc); - } - } else if (_lookFlag && (_selectedRow == 0)) { - // Two 'look' actions in succession, so the action becomes 'Look around' - strcpy(_statusText, lookAroundStr); - } else { - if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) { - // Use/to action - int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject(); - MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject); - - _action.objectNameId = objEntry->_descId; - _currentAction = objEntry->_vocabList[_selectedRow].vocabId; - - // Set up the status text stirng - strcpy(_statusText, useStr); - appendVocab(_action.objectNameId); - strcpy(_statusText, toStr); - appendVocab(_currentAction); - } else { - // Handling for if an action has been selected - if (_selectedRow >= 0) { - if (_actionMode == ACTMODE_VERB) { - // Standard verb action - _currentAction = verbList[_selectedRow].verb; - } else { - // Selected action on an inventory object - int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject(); - MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject); - - _currentAction = objEntry->_vocabList[_selectedRow].vocabId; - } - - appendVocab(_currentAction, true); - - if (_currentAction == kVerbLook) { - // Add in the word 'add' - strcat(_statusText, atStr); - strcat(_statusText, " "); - } - } - - // Handling for if a hotspot has been selected/highlighted - if ((_hotspotId >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) { - flag = true; - - strcat(_statusText, englishMADSArticleList[_articleNumber]); - strcat(_statusText, " "); - } - - if (_hotspotId >= 0) { - if (_selectedRow < 0) { - int verbId; - - if (_hotspotId < hotspotCount) { - // Get the verb Id from the hotspot - verbId = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getVerbID(); - } else { - // Get the verb Id from the scene object - verbId = (*_madsVm->scene()->getSceneResources().dynamicHotspots)[_hotspotId - hotspotCount].getVerbID(); - } - - if (verbId > 0) { - // Set the specified action - _currentAction = verbId; - appendVocab(_currentAction, true); - } else { - // Default to a standard 'walk to' - _currentAction = kVerbWalkTo; - strcat(_statusText, walkToStr); - } - } - - if ((_actionMode2 == ACTMODE2_2) || (_actionMode2 == ACTMODE2_5)) { - // Get name from given inventory object - int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_hotspotId); - _action.objectNameId = _madsVm->globals()->getObject(objectId)->_descId; - } else if (_hotspotId < hotspotCount) { - // Get name from scene hotspot - _action.objectNameId = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getVocabID(); - } else { - // Get name from temporary scene hotspot - _action.objectNameId = (*_madsVm->scene()->getSceneResources().dynamicHotspots)[_hotspotId].getVocabID(); - } - appendVocab(_action.objectNameId); - } - } - - if ((_hotspotId >= 0) && (_articleNumber > 0) && !flag) { - if (_articleNumber == -1) { - if (_v86F3A >= 0) { - int articleNum = 0; - - if ((_v86F42 == 2) || (_v86F42 == 5)) { - int objectId = _madsVm->scene()->getInterface()->getInventoryObject(_hotspotId); - articleNum = _madsVm->globals()->getObject(objectId)->_article; - } else if (_v86F3A < hotspotCount) { - articleNum = (*_madsVm->scene()->getSceneResources().hotspots)[_hotspotId].getArticle(); - } else { - - } - } - - } else if ((_articleNumber == kVerbLook) || (_vm->getGameType() != GType_RexNebular) || - (strcmp(_madsVm->globals()->getVocab(_action.indirectObjectId), fenceStr) != 0)) { - // Write out the article - strcat(_statusText, englishMADSArticleList[_articleNumber]); - } else { - // Special case for a 'fence' entry in Rex Nebular - strcat(_statusText, overStr); - } - - strcat(_statusText, " "); - } - - // Append object description if necessary - if (_v86F3A >= 0) - appendVocab(_action.indirectObjectId); - - // Remove any trailing space character - int statusLen = strlen(_statusText); - if ((statusLen > 0) && (_statusText[statusLen - 1] == ' ')) - _statusText[statusLen - 1] = '\0'; - } - - _textChanged = true; -} - -void MadsAction::refresh() { - // Exit immediately if nothing has changed - if (!_textChanged) - return; - - // Remove any old copy of the status text - if (_statusTextIndex >= 0) { - _owner._textDisplay.expire(_statusTextIndex); - _statusTextIndex = -1; - } - - if (_statusText[0] != '\0') { - if ((_owner._screenObjects._v832EC == 0) || (_owner._screenObjects._v832EC == 2)) { - Font *font = _madsVm->_font->getFont(FONT_MAIN_MADS); - int textSpacing = -1; - - int strWidth = font->getWidth(_statusText); - if (strWidth > 320) { - // Too large to fit, so fall back on interface font - font = _madsVm->_font->getFont(FONT_INTERFACE_MADS); - strWidth = font->getWidth(_statusText, 0); - textSpacing = 0; - } - - // Add a new text display entry to display the status text at the bottom of the screen area - uint colors = (_vm->getGameType() == GType_DragonSphere) ? 0x0300 : 0x0003; - - _statusTextIndex = _owner._textDisplay.add(160 - (strWidth / 2), - MADS_SURFACE_HEIGHT + _owner._posAdjust.y - 13, colors, textSpacing, _statusText, font); - } - } - - _textChanged = false; -} - -void MadsAction::startAction() { - _madsVm->_player.moveComplete(); - - _inProgress = true; - _v8453A = ABORTMODE_0; - _savedFields.selectedRow = _selectedRow; - _savedFields.articleNumber = _articleNumber; - _savedFields.actionMode = _actionMode; - _savedFields.actionMode2 = _actionMode2; - _savedFields.lookFlag = _lookFlag; - int savedHotspotId = _hotspotId; - int savedV86F3A = _v86F3A; - int savedV86F42 = _v86F42; - - // Copy the action to be active - _activeAction = _action; - strcpy(_dialogTitle, _statusText); - - if ((_savedFields.actionMode2 == ACTMODE2_4) && (savedV86F42 == 0)) - _v8453A = ABORTMODE_1; - - _startWalkFlag = false; - int hotspotId = -1; - HotSpotList &dynHotspots = *_madsVm->scene()->getSceneResources().dynamicHotspots; - HotSpotList &hotspots = *_madsVm->scene()->getSceneResources().hotspots; - - if (!_savedFields.lookFlag && (_madsVm->scene()->_screenObjects._v832EC != 1)) { - if (_savedFields.actionMode2 == ACTMODE2_4) - hotspotId = savedHotspotId; - else if (savedV86F42 == 4) - hotspotId = savedV86F3A; - - if (hotspotId >= hotspots.size()) { - HotSpot &hs = dynHotspots[hotspotId - hotspots.size()]; - if ((hs.getFeetX() == -1) || (hs.getFeetX() == -3)) { - if (_v86F4A && ((hs.getFeetX() == -3) || (_savedFields.selectedRow < 0))) { - _startWalkFlag = true; - _madsVm->scene()->_destPos = _madsVm->scene()->_customDest; - } - } else if ((hs.getFeetX() >= 0) && ((_savedFields.actionMode == ACTMODE_NONE) || (hs.getCursor() < 2))) { - _startWalkFlag = true; - _madsVm->scene()->_destPos.x = hs.getFeetX(); - _madsVm->scene()->_destPos.y = hs.getFeetY(); - } - _madsVm->scene()->_destFacing = hs.getFacing(); - hotspotId = -1; - } - } - - if (hotspotId >= 0) { - HotSpot &hs = hotspots[hotspotId]; - if ((hs.getFeetX() == -1) || (hs.getFeetX() == -3)) { - if (_v86F4A && ((hs.getFeetX() == -3) || (_savedFields.selectedRow < 0))) { - _startWalkFlag = true; - _madsVm->scene()->_destPos = _madsVm->scene()->_customDest; - } - } else if ((hs.getFeetX() >= 0) && ((_savedFields.actionMode == ACTMODE_NONE) || (hs.getCursor() < 2))) { - _startWalkFlag = true; - _madsVm->scene()->_destPos.x = hs.getFeetX(); - _madsVm->scene()->_destPos.y = hs.getFeetY(); - } - _madsVm->scene()->_destFacing = hs.getFacing(); - } - - _walkFlag = _startWalkFlag; -} - -void MadsAction::checkAction() { - if (isAction(kVerbLookAt) || isAction(kVerbThrow)) - _startWalkFlag = 0; -} - -bool MadsAction::isAction(int verbId, int objectNameId, int indirectObjectId) { - if (_activeAction.verbId != verbId) - return false; - if ((objectNameId != 0) && (_activeAction.objectNameId != objectNameId)) - return false; - if ((indirectObjectId != 0) && (_activeAction.indirectObjectId != indirectObjectId)) - return false; - return true; -} - -//-------------------------------------------------------------------------- - -bool MadsSpriteSlot::operator==(const SpriteSlotSubset &other) const { - return (spriteListIndex == other.spriteListIndex) && (frameNumber == other.frameNumber) && - (xp == other.xp) && (yp == other.yp) && (depth == other.depth) && (scale == other.scale); -} - -void MadsSpriteSlot::copy(const SpriteSlotSubset &other) { - spriteListIndex = other.spriteListIndex; - frameNumber = other.frameNumber; - xp = other.xp; - yp = other.yp; - depth = other.depth; - scale = other.scale; -} - -//-------------------------------------------------------------------------- - -MadsSpriteSlots::MadsSpriteSlots(MadsView &owner): _owner(owner) { - for (int i = 0; i < SPRITE_SLOTS_SIZE; ++i) { - MadsSpriteSlot rec; - _entries.push_back(rec); - } - - startIndex = 0; -} - -MadsSpriteSlots::~MadsSpriteSlots() { - for (uint i = 0; i < _sprites.size(); ++i) - delete _sprites[i]; -} - -void MadsSpriteSlots::clear() { - _owner._textDisplay.clear(); - for (uint i = 0; i < _sprites.size(); ++i) - delete _sprites[i]; - _sprites.clear(); - - // Reset the sprite slots list back to a single entry for a full screen refresh - startIndex = 1; - _entries[0].spriteType = FULL_SCREEN_REFRESH; - _entries[0].seqIndex = -1; -} - -int MadsSpriteSlots::getIndex() { - if (startIndex == SPRITE_SLOTS_SIZE) - error("Run out of sprite slots"); - - return startIndex++; -} - -int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors, int flags) { - // If errors are suppressed, first check if the resource exists - if (suppressErrors) { - if (!_vm->res()->resourceExists(resName)) - return -1; - } - - // Append on a '.SS' suffix if the resource doesn't already have an extension - char buffer[100]; - strncpy(buffer, resName, 95); - buffer[95] = '\0'; - if (!strchr(buffer, '.')) - strcat(buffer, ".SS"); - - // Get the sprite set - Common::SeekableReadStream *data = _vm->res()->get(buffer); - SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), buffer, false, flags); - spriteSet->translate(_madsVm->_palette); - assert(spriteSet != NULL); - - _sprites.push_back(spriteSet); - _vm->res()->toss(buffer); - - return _sprites.size() - 1; -} - -int MadsSpriteSlots::addSprites(SpriteAsset *spriteSet) { - _sprites.push_back(spriteSet); - - return _sprites.size() - 1; -} - -void MadsSpriteSlots::deleteSprites(int listIndex) { - if (listIndex < 0) - return; - - delete _sprites[listIndex]; - _sprites[listIndex] = NULL; - if (listIndex == ((int)_sprites.size() - 1)) - _sprites.remove_at(listIndex); -} - -/* - * Deletes the sprite slot with the given timer entry - */ -void MadsSpriteSlots::deleteTimer(int seqIndex) { - for (int idx = 0; idx < startIndex; ++idx) { - if (_entries[idx].seqIndex == seqIndex) - _entries[idx].spriteType = EXPIRED_SPRITE; - } -} - -class DepthEntry { -public: - int depth; - int index; - - DepthEntry(int depthAmt, int indexVal) { depth = depthAmt; index = indexVal; } -}; - -bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) { - return entry1.depth < entry2.depth; -} - -typedef Common::List DepthList; - -void MadsSpriteSlots::drawBackground() { - // Draw all active sprites onto the background surface - for (int i = 0; i < startIndex; ++i) { - MadsSpriteSlot &slot = _entries[i]; - - if (slot.spriteType >= 0) { - _owner._dirtyAreas[i].active = false; - } else { - _owner._dirtyAreas[i].textActive = true; - _owner._dirtyAreas.setSpriteSlot(i, slot); - - if (slot.spriteType == BACKGROUND_SPRITE) { - SpriteAsset &spriteSet = getSprite(slot.spriteListIndex); - M4Sprite *frame = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); - int xp = slot.xp; - int yp = slot.yp; - - if (_entries[i].scale != -1) { - // Adjust position based on frame size - xp -= frame->width() / 2; - yp -= frame->height() / 2; - } - - if (slot.depth > 1) { - // Draw the frame with depth processing - _owner._bgSurface->copyFrom(frame, xp, yp, slot.depth, _owner._depthSurface, 100, - frame->getTransparencyIndex()); - } else { - // No depth, so simply draw the image - frame->copyTo(_owner._bgSurface, xp, yp, frame->getTransparencyIndex()); - } - } - } - } - - // Flag any remaining dirty areas as inactive - for (uint i = startIndex; i < DIRTY_AREAS_TEXT_DISPLAY_IDX; ++i) - _owner._dirtyAreas[i].active = false; -} - -void MadsSpriteSlots::drawForeground(M4Surface *viewport) { - DepthList depthList; - - // Get a list of sprite object depths for active objects - for (int i = 0; i < startIndex; ++i) { - if (_entries[i].spriteType >= SPRITE_ZERO) { - DepthEntry rec(16 - _entries[i].depth, i); - depthList.push_back(rec); - } - } - - // Sort the list in order of the depth - Common::sort(depthList.begin(), depthList.end(), sortHelper); - - // Loop through each of the objects - DepthList::iterator i; - for (i = depthList.begin(); i != depthList.end(); ++i) { - DepthEntry &de = *i; - MadsSpriteSlot &slot = _entries[de.index]; - assert(slot.spriteListIndex < (int)_sprites.size()); - SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex]; - - // Get the sprite frame - int frameNumber = slot.frameNumber & 0x7fff; - bool flipped = (slot.frameNumber & 0x8000) != 0; - M4Sprite *sprite = spriteSet.getFrame(frameNumber - 1); - - M4Surface *spr = sprite; - if (flipped) { - // Create a flipped copy of the sprite temporarily - spr = sprite->flipHorizontal(); - } - - if ((slot.scale < 100) && (slot.scale != -1)) { - // Minimalised drawing - viewport->copyFrom(spr, slot.xp, slot.yp, slot.depth, _owner._depthSurface, slot.scale, - sprite->getTransparencyIndex()); - } else { - int xp, yp; - - if (slot.scale == -1) { - xp = slot.xp - _owner._posAdjust.x; - yp = slot.yp - _owner._posAdjust.y; - } else { - xp = slot.xp - (spr->width() / 2) - _owner._posAdjust.x; - yp = slot.yp - spr->height() - _owner._posAdjust.y + 1; - } - - if (slot.depth > 1) { - // Draw the frame with depth processing - viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, sprite->getTransparencyIndex()); - } else { - // No depth, so simply draw the image - spr->copyTo(viewport, xp, yp, sprite->getTransparencyIndex()); - } - } - - // Free sprite if it was a flipped one - if (flipped) - delete spr; - } -} - -void MadsSpriteSlots::setDirtyAreas() { - for (int i = 0; i < startIndex; ++i) { - if (_entries[i].spriteType >= 0) { - _owner._dirtyAreas.setSpriteSlot(i, _entries[i]); - - _owner._dirtyAreas[i].textActive = (_entries[i].spriteType <= 0) ? 0 : 1; - _entries[i].spriteType = 0; - } - } -} - -/** - * Flags the entire screen to be redrawn during the next drawing cycle - */ -void MadsSpriteSlots::fullRefresh() { - int idx = getIndex(); - - _entries[idx].spriteType = FULL_SCREEN_REFRESH; - _entries[idx].seqIndex = -1; -} - -/** - * Removes any sprite slots that are no longer needed - */ -void MadsSpriteSlots::cleanUp() { - // Delete any entries that aren't needed - int idx = 0; - while (idx < startIndex) { - if (_entries[idx].spriteType < 0) { - _entries.remove_at(idx); - --startIndex; - } else { - ++idx; - } - } - - // Original engine sprite slot list was a fixed array, so to keep the engine similiar, for - // now I'm adding in new entries to make up the original fixed total again - while (_entries.size() < SPRITE_SLOTS_SIZE) { - MadsSpriteSlot rec; - _entries.push_back(rec); - } -} - -//-------------------------------------------------------------------------- - -MadsTextDisplay::MadsTextDisplay(MadsView &owner): _owner(owner) { - for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) { - MadsTextDisplayEntry rec; - rec.active = false; - rec.expire = 0; - _entries.push_back(rec); - } -} - -void MadsTextDisplay::clear() { - for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) - _entries[i].active = false; -} - -int MadsTextDisplay::add(int xp, int yp, uint fontColor, int charSpacing, const char *msg, Font *font) { - int usedSlot = -1; - - for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) { - if (!_entries[idx].active) { - usedSlot = idx; - - _entries[idx].bounds.left = xp; - _entries[idx].bounds.top = yp; - _entries[idx].font = font; - _entries[idx].msg = msg; - _entries[idx].bounds.setWidth(font->getWidth(msg, charSpacing)); - _entries[idx].bounds.setHeight(font->getHeight()); - _entries[idx].color1 = fontColor & 0xff; - _entries[idx].color2 = fontColor >> 8; - _entries[idx].spacing = charSpacing; - _entries[idx].expire = 1; - _entries[idx].active = true; - break; - } - } - - return usedSlot; -} - -void MadsTextDisplay::setDirtyAreas() { - // Determine dirty areas for active text areas - for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) { - if ((_entries[idx].expire >= 0) || !_entries[idx].active) - _owner._dirtyAreas[dirtyIdx].active = false; - else { - _owner._dirtyAreas[dirtyIdx].textActive = true; - _owner._dirtyAreas.setTextDisplay(dirtyIdx, _entries[idx]); - } - } -} - -void MadsTextDisplay::setDirtyAreas2() { - // Determine dirty areas for active text areas - for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) { - if (_entries[idx].active && (_entries[idx].expire >= 0)) { - _owner._dirtyAreas.setTextDisplay(dirtyIdx, _entries[idx]); - _owner._dirtyAreas[dirtyIdx].textActive = (_entries[idx].expire <= 0) ? 0 : 1; - } - } -} - -void MadsTextDisplay::draw(M4Surface *view) { - for (uint idx = 0; idx < _entries.size(); ++idx) { - if (_entries[idx].active && (_entries[idx].expire >= 0)) { - _entries[idx].font->setColors(_entries[idx].color1, _entries[idx].color2, 0); - _entries[idx].font->writeString(view, _entries[idx].msg, - _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(), - _entries[idx].spacing); - } - } -} - -/** - * Deactivates any text display entries that are finished - */ -void MadsTextDisplay::cleanUp() { - for (uint idx = 0; idx < _entries.size(); ++idx) { - if (_entries[idx].expire < 0) { - _entries[idx].active = false; - _entries[idx].expire = 0; - } - } -} - -//-------------------------------------------------------------------------- - -MadsKernelMessageList::MadsKernelMessageList(MadsView &owner): _owner(owner) { - for (int i = 0; i < TIMED_TEXT_SIZE; ++i) { - MadsKernelMessageEntry rec; - _entries.push_back(rec); - } - - _owner._textSpacing = -1; - _talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS); - word_8469E = 0; -} - -void MadsKernelMessageList::clear() { - for (uint i = 0; i < _entries.size(); ++i) - _entries[i].flags = 0; - - _owner._textSpacing = -1; - _talkFont = _vm->_font->getFont(FONT_CONVERSATION_MADS); -} - -int MadsKernelMessageList::add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg) { - // Find a free slot - uint idx = 0; - while ((idx < _entries.size()) && ((_entries[idx].flags & KMSG_ACTIVE) != 0)) - ++idx; - if (idx == _entries.size()) { - if (abortTimers == 0) - return -1; - - error("MadsKernelList overflow"); - } - - MadsKernelMessageEntry &rec = _entries[idx]; - strcpy(rec.msg, msg); - rec.flags = flags | KMSG_ACTIVE; - rec.color1 = fontColor & 0xff; - rec.color2 = fontColor >> 8; - rec.position = pt; - rec.textDisplayIndex = -1; - rec.timeout = timeout; - rec.frameTimer = _madsVm->_currentTimer; - rec.abortTimers = abortTimers; - rec.abortMode = _owner._abortTimersMode2; - - for (int i = 0; i < 3; ++i) - rec.actionNouns[i] = _madsVm->globals()->actionNouns[i]; - - if (flags & KMSG_PLAYER_TIMEOUT) - rec.frameTimer = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer; - - return idx; -} - -int MadsKernelMessageList::addQuote(int quoteId, int abortTimers, uint32 timeout) { - const char *quoteStr = _madsVm->globals()->getQuote(quoteId); - return add(Common::Point(0, 0), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr); -} - -void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quoted) { - if (msgIndex < 0) - return; - - _entries[msgIndex].flags |= quoted ? (KMSG_SCROLL | KMSG_QUOTED) : KMSG_SCROLL; - _entries[msgIndex].msgOffset = 0; - _entries[msgIndex].numTicks = numTicks; - _entries[msgIndex].frameTimer2 = _madsVm->_currentTimer; - - const char *msgP = _entries[msgIndex].msg; - _entries[msgIndex].asciiChar = *msgP; - _entries[msgIndex].asciiChar2 = *(msgP + 1); - - if (_entries[msgIndex].flags & KMSG_PLAYER_TIMEOUT) - _entries[msgIndex].frameTimer2 = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer; - - _entries[msgIndex].frameTimer = _entries[msgIndex].frameTimer2; -} - -void MadsKernelMessageList::setSeqIndex(int msgIndex, int seqIndex) { - if (msgIndex >= 0) { - _entries[msgIndex].flags |= KMSG_SEQ_ENTRY; - _entries[msgIndex].sequenceIndex = seqIndex; - } -} - -void MadsKernelMessageList::remove(int msgIndex) { - MadsKernelMessageEntry &rec = _entries[msgIndex]; - - if (rec.flags & KMSG_ACTIVE) { - if (rec.flags & KMSG_SCROLL) { - *(rec.msg + rec.msgOffset) = rec.asciiChar; - *(rec.msg + rec.msgOffset + 1) = rec.asciiChar2; - } - - if (rec.textDisplayIndex >= 0) - _owner._textDisplay.expire(rec.textDisplayIndex); - - rec.flags &= ~KMSG_ACTIVE; - } -} - -void MadsKernelMessageList::reset() { - for (uint i = 0; i < _entries.size(); ++i) - remove(i); - - // sub_20454 -} - -void MadsKernelMessageList::update() { - uint32 currentTimer = _madsVm->_currentTimer; - - for (uint i = 0; i < _entries.size(); ++i) { - if (((_entries[i].flags & KMSG_ACTIVE) != 0) && (currentTimer >= _entries[i].frameTimer)) - processText(i); - } -} - -void MadsKernelMessageList::processText(int msgIndex) { - MadsKernelMessageEntry &msg = _entries[msgIndex]; - uint32 currentTimer = _madsVm->_currentTimer; - bool flag = false; - - if ((msg.flags & KMSG_EXPIRE) != 0) { - _owner._textDisplay.expire(msg.textDisplayIndex); - msg.flags &= !KMSG_ACTIVE; - return; - } - - if ((msg.flags & KMSG_SCROLL) == 0) { - msg.timeout -= 3; - } - - if (msg.flags & KMSG_SEQ_ENTRY) { - MadsSequenceEntry &seqEntry = _owner._sequenceList[msg.sequenceIndex]; - if (seqEntry.doneFlag || !seqEntry.active) - msg.timeout = 0; - } - - if ((msg.timeout <= 0) && (_owner._abortTimers == 0)) { - msg.flags |= KMSG_EXPIRE; - if (msg.abortTimers != 0) { - _owner._abortTimers = msg.abortTimers; - _owner._abortTimersMode = msg.abortMode; - - if (_owner._abortTimersMode != ABORTMODE_1) { - for (int i = 0; i < 3; ++i) - _madsVm->globals()->actionNouns[i] = msg.actionNouns[i]; - } - } - } - - msg.frameTimer = currentTimer + 3; - int x1 = 0, y1 = 0; - - if (msg.flags & KMSG_SEQ_ENTRY) { - MadsSequenceEntry &seqEntry = _owner._sequenceList[msg.sequenceIndex]; - if (!seqEntry.nonFixed) { - SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex); - M4Sprite *frame = spriteSet.getFrame(seqEntry.frameIndex - 1); - x1 = frame->bounds().left; - y1 = frame->bounds().top; - } else { - x1 = seqEntry.msgPos.x; - y1 = seqEntry.msgPos.y; - } - } - - if (msg.flags & KMSG_PLAYER_TIMEOUT) { - if (word_8469E != 0) { - // TODO: Figure out various flags - } else { - x1 = 160; - y1 = 78; - } - } - - x1 += msg.position.x; - y1 += msg.position.y; - - if ((msg.flags & KMSG_SCROLL) && (msg.frameTimer >= currentTimer)) { - msg.msg[msg.msgOffset] = msg.asciiChar; - char *msgP = &msg.msg[++msg.msgOffset]; - *msgP = msg.asciiChar2; - - msg.asciiChar = *msgP; - msg.asciiChar2 = *(msgP + 1); - - if (!msg.asciiChar) { - // End of message - *msgP = '\0'; - msg.flags &= ~KMSG_SCROLL; - } else if (msg.flags & KMSG_QUOTED) { - *msgP = '"'; - *(msgP + 1) = '\0'; - } - - msg.frameTimer = msg.frameTimer2 = currentTimer + msg.numTicks; - flag = true; - } - - int strWidth = _talkFont->getWidth(msg.msg, _owner._textSpacing); - - if (msg.flags & (KMSG_RIGHT_ALIGN | KMSG_CENTER_ALIGN)) { - x1 -= (msg.flags & KMSG_CENTER_ALIGN) ? strWidth / 2 : strWidth; - } - - // Make sure text appears entirely on-screen - int x2 = x1 + strWidth; - if (x2 > MADS_SURFACE_WIDTH) - x1 -= x2 - MADS_SURFACE_WIDTH; - if (x1 > (MADS_SURFACE_WIDTH - 1)) - x1 = MADS_SURFACE_WIDTH - 1; - if (x1 < 0) - x1 = 0; - - if (y1 > (MADS_SURFACE_HEIGHT - 1)) - y1 = MADS_SURFACE_HEIGHT - 1; - if (y1 < 0) - y1 = 0; - - if (msg.textDisplayIndex >= 0) { - MadsTextDisplayEntry textEntry = _owner._textDisplay[msg.textDisplayIndex]; - - if (flag || (textEntry.bounds.left != x1) || (textEntry.bounds.top != y1)) { - // Mark the associated text entry as deleted, so it can be re-created - _owner._textDisplay.expire(msg.textDisplayIndex); - msg.textDisplayIndex = -1; - } - } - - if (msg.textDisplayIndex < 0) { - // Need to create a new text display entry for this message - int idx = _owner._textDisplay.add(x1, y1, msg.color1 | (msg.color2 << 8), _owner._textSpacing, msg.msg, _talkFont); - if (idx >= 0) - msg.textDisplayIndex = idx; - } -} - -//-------------------------------------------------------------------------- - -ScreenObjects::ScreenObjects(MadsView &owner): _owner(owner) { - _v832EC = 0; - _v7FECA = 0; - _v7FED6 = 0; - _v8332A = 0; - _yp = 0; - _v8333C = 0; - _selectedObject = 0; - _category = 0; - _objectIndex = 0; -} - -/** - * Clears the entries list - */ -void ScreenObjects::clear() { - _entries.clear(); -} - -/** - * Adds a new entry to the list of screen objects - */ -void ScreenObjects::add(const Common::Rect &bounds, int layer, int idx, int category) { - ScreenObjectEntry rec; - rec.bounds = bounds; - rec.layer = layer; - rec.index = idx; - rec.category = category; - rec.active = true; - - _entries.push_back(rec); -} - -/** - * Scans the list for an element that contains the given mode. The result will be 1 based for a match, - * with 0 indicating no entry was found - */ -int ScreenObjects::scan(int xp, int yp, int layer) { - for (uint i = 0; i < _entries.size(); ++i) { - if (_entries[i].active && _entries[i].bounds.contains(xp, yp) && (_entries[i].layer == layer)) - return i + 1; - } - - // Entry not found - return 0; -} - -int ScreenObjects::scanBackwards(int xp, int yp, int layer) { - for (int i = (int)_entries.size() - 1; i >= 0; --i) { - if (_entries[i].active && _entries[i].bounds.contains(xp, yp) && (_entries[i].layer == layer)) - return i + 1; - } - - // Entry not found - return 0; -} - -void ScreenObjects::setActive(int category, int idx, bool active) { - for (uint i = 0; i < _entries.size(); ++i) { - if (_entries[i].active && (_entries[i].category == category) && (_entries[i].index == idx)) - _entries[i].active = active; - } -} - -void ScreenObjects::check(bool scanFlag, bool mouseClick) { - if (!mouseClick || _v832EC) - _v7FECA = 0; - - if (!_v7FED6 && !_v8332A && !_yp && (_v8333C != 0)) { - if (scanFlag) { - _category = CAT_NONE; - _selectedObject = scanBackwards(_madsVm->_mouse->currentPos().x, _madsVm->_mouse->currentPos().y, - LAYER_GUI); - - if (_selectedObject > 0) { - ScreenObjectEntry &obj = _entries[_selectedObject]; - _category = obj.category & 7; - _objectIndex = obj.index; - } - - // TODO: Other stuff related to the user interface - } - } - - _owner._action.refresh(); -} - -/*--------------------------------------------------------------------------*/ - -MadsDynamicHotspots::MadsDynamicHotspots(MadsView &owner): _owner(owner) { - for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) { - DynamicHotspot rec; - rec.active = false; - _entries.push_back(rec); - } - _changed = true; - _count = 0; -} - -int MadsDynamicHotspots::add(int descId, int field14, int seqIndex, const Common::Rect &bounds) { - // Find a free slot - uint idx = 0; - while ((idx < _entries.size()) && _entries[idx].active) - ++idx; - if (idx == _entries.size()) - error("MadsDynamicHotspots overflow"); - - _entries[idx].active = true; - _entries[idx].descId = descId; - _entries[idx].seqIndex = seqIndex; - _entries[idx].bounds = bounds; - _entries[idx].pos.x = -3; - _entries[idx].pos.y = 0; - _entries[idx].facing = 5; - _entries[idx].field_14 = field14; - _entries[idx].articleNumber = 6; - _entries[idx].field_17 = 0; - - ++_count; - _changed = true; - - if (seqIndex >= 0) - _owner._sequenceList[seqIndex].dynamicHotspotIndex = idx; - - return idx; -} - -int MadsDynamicHotspots::setPosition(int index, int xp, int yp, int facing) { - if (index >= 0) { - _entries[index].pos.x = xp; - _entries[index].pos.y = yp; - _entries[index].facing = facing; - } - - return index; -} - -int MadsDynamicHotspots::set17(int index, int v) { - if (index >= 0) - _entries[index].field_17 = v; - - return index; -} - -void MadsDynamicHotspots::remove(int index) { - if (_entries[index].active) { - if (_entries[index].seqIndex >= 0) - _owner._sequenceList[_entries[index].seqIndex].dynamicHotspotIndex = -1; - _entries[index].active = false; - - --_count; - _changed = true; - } -} - -void MadsDynamicHotspots::reset() { - for (uint i = 0; i < _entries.size(); ++i) - _entries[i].active = false; - - _count = 0; - _changed = false; -} - -/*--------------------------------------------------------------------------*/ - -void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) { - if (bounds.left % 2) { - --bounds.left; - ++width; - } - - if (bounds.left < 0) - bounds.left = 0; - else if (bounds.left > maxWidth) - bounds.left = maxWidth; - int right = bounds.left + width; - if (right < 0) - right = 0; - if (right > maxWidth) - right = maxWidth; - - bounds.right = right; - bounds2.left = bounds.width() / 2; - bounds2.right = bounds.left + (bounds.width() + 1) / 2 - 1; - - if (bounds.top < 0) - bounds.top = 0; - else if (bounds.top > maxHeight) - bounds.top = maxHeight; - int bottom = bounds.top + height; - if (bottom < 0) - bottom = 0; - if (bottom > maxHeight) - bottom = maxHeight; - - bounds.bottom = bottom; - bounds2.top = bounds.height() / 2; - bounds2.bottom = bounds.top + (bounds.height() + 1) / 2 - 1; - - active = true; -} - -/*--------------------------------------------------------------------------*/ - -MadsDirtyAreas::MadsDirtyAreas(MadsView &owner): _owner(owner) { - for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) { - MadsDirtyArea rec; - rec.active = false; - _entries.push_back(rec); - } -} - -void MadsDirtyAreas::setSpriteSlot(int dirtyIdx, const MadsSpriteSlot &spriteSlot) { - int width, height; - MadsDirtyArea &dirtyArea = _entries[dirtyIdx]; - - if (spriteSlot.spriteType == FULL_SCREEN_REFRESH) { - // Special entry to refresh the entire screen - dirtyArea.bounds.left = 0; - dirtyArea.bounds.top = 0; - width = MADS_SURFACE_WIDTH; - height = MADS_SURFACE_HEIGHT; - } else { - // Standard sprite slots - dirtyArea.bounds.left = spriteSlot.xp - _owner._posAdjust.x; - dirtyArea.bounds.top = spriteSlot.yp - _owner._posAdjust.y; - - SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(spriteSlot.spriteListIndex); - M4Sprite *frame = spriteSet.getFrame(((spriteSlot.frameNumber & 0x7fff) - 1) & 0x7f); - - if (spriteSlot.scale == -1) { - width = frame->width(); - height = frame->height(); - } else { - width = frame->width() * spriteSlot.scale / 100; - height = frame->height() * spriteSlot.scale / 100; - - dirtyArea.bounds.left -= width / 2; - dirtyArea.bounds.top += -(height - 1); - } - } - - dirtyArea.setArea(width, height, MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT); -} - -void MadsDirtyAreas::setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &textDisplay) { - MadsDirtyArea &dirtyArea = _entries[dirtyIdx]; - dirtyArea.bounds.left = textDisplay.bounds.left; - dirtyArea.bounds.top = textDisplay.bounds.top; - - dirtyArea.setArea(textDisplay.bounds.width(), textDisplay.bounds.height(), MADS_SURFACE_WIDTH, MADS_SURFACE_HEIGHT); -} - -/** - * Merge together any designated dirty areas that overlap - * @param startIndex 1-based starting dirty area starting index - * @param count Number of entries to process - */ -void MadsDirtyAreas::merge(int startIndex, int count) { -return;//***DEBUG*** - if (startIndex >= count) - return; - - for (int outerCtr = startIndex - 1, idx = 0; idx < count; ++outerCtr, ++idx) { - if (!_entries[outerCtr].active) - continue; - - for (int innerCtr = outerCtr + 1; innerCtr < count; ++innerCtr) { - if (!_entries[innerCtr].active || !intersects(outerCtr, innerCtr)) - continue; - - if (_entries[outerCtr].textActive && _entries[innerCtr].textActive) - mergeAreas(outerCtr, innerCtr); - } - } -} - -/** - * Returns true if two dirty areas intersect - */ -bool MadsDirtyAreas::intersects(int idx1, int idx2) { - return _entries[idx1].bounds2.intersects(_entries[idx2].bounds2); -} - -void MadsDirtyAreas::mergeAreas(int idx1, int idx2) { - MadsDirtyArea &da1 = _entries[idx1]; - MadsDirtyArea &da2 = _entries[idx2]; - - da1.bounds.extend(da2.bounds); - - da1.bounds2.left = da1.bounds.width() / 2; - da1.bounds2.right = da1.bounds.left + (da1.bounds.width() + 1) / 2 - 1; - da1.bounds2.top = da1.bounds.height() / 2; - da1.bounds2.bottom = da1.bounds.top + (da1.bounds.height() + 1) / 2 - 1; - - da2.active = false; - da1.textActive = true; -} - -void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust) { - for (uint i = 0; i < _entries.size(); ++i) { - const Common::Rect &srcBounds = _entries[i].bounds; - - Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, - srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); - - if (_entries[i].active && _entries[i].bounds.isValidRect()) - src->copyTo(dest, bounds, _entries[i].bounds.left, _entries[i].bounds.top); - } -} - -void MadsDirtyAreas::clear() { - for (uint i = 0; i < _entries.size(); ++i) - _entries[i].active = false; -} - -/*--------------------------------------------------------------------------*/ - -MadsSequenceList::MadsSequenceList(MadsView &owner): _owner(owner) { - for (int i = 0; i < TIMER_LIST_SIZE; ++i) { - MadsSequenceEntry rec; - rec.active = 0; - rec.dynamicHotspotIndex = -1; - _entries.push_back(rec); - } -} - -void MadsSequenceList::clear() { - for (uint i = 0; i < _entries.size(); ++i) { - _entries[i].active = 0; - _entries[i].dynamicHotspotIndex = -1; - } -} - -bool MadsSequenceList::addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal) { - if (_entries[index].entries.count >= TIMER_ENTRY_SUBSET_MAX) - return true; - - int subIndex = _entries[index].entries.count++; - _entries[index].entries.mode[subIndex] = mode; - _entries[index].entries.frameIndex[subIndex] = frameIndex; - _entries[index].entries.abortVal[subIndex] = abortVal; - - return false; -} - -int MadsSequenceList::add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, int extraTicks, int numTicks, - int msgX, int msgY, bool nonFixed, char scale, uint8 depth, int frameInc, SpriteAnimType animType, int numSprites, - int frameStart) { - - // Find a free slot - uint seqIndex = 0; - while ((seqIndex < _entries.size()) && (_entries[seqIndex].active)) - ++seqIndex; - if (seqIndex == _entries.size()) - error("TimerList full"); - - if (frameStart <= 0) - frameStart = 1; - if (numSprites == 0) - numSprites = _madsVm->scene()->_spriteSlots.getSprite(spriteListIndex).getCount(); - if (frameStart == numSprites) - frameInc = 0; - - // Set the list entry fields - _entries[seqIndex].active = true; - _entries[seqIndex].spriteListIndex = spriteListIndex; - _entries[seqIndex].flipped = flipped; - _entries[seqIndex].frameIndex = frameIndex; - _entries[seqIndex].frameStart = frameStart; - _entries[seqIndex].numSprites = numSprites; - _entries[seqIndex].animType = animType; - _entries[seqIndex].frameInc = frameInc; - _entries[seqIndex].depth = depth; - _entries[seqIndex].scale = scale; - _entries[seqIndex].nonFixed = nonFixed; - _entries[seqIndex].msgPos.x = msgX; - _entries[seqIndex].msgPos.y = msgY; - _entries[seqIndex].numTicks = numTicks; - _entries[seqIndex].extraTicks = extraTicks; - - _entries[seqIndex].timeout = _madsVm->_currentTimer + delayTicks; - - _entries[seqIndex].triggerCountdown = triggerCountdown; - _entries[seqIndex].doneFlag = false; - _entries[seqIndex].field_13 = 0; - _entries[seqIndex].dynamicHotspotIndex = -1; - _entries[seqIndex].entries.count = 0; - _entries[seqIndex].abortMode = _owner._abortTimersMode2; - - for (int i = 0; i < 3; ++i) - _entries[seqIndex].actionNouns[i] = _madsVm->globals()->actionNouns[i]; - - return seqIndex; -} - -void MadsSequenceList::remove(int seqIndex) { - if (_entries[seqIndex].active) { - if (_entries[seqIndex].dynamicHotspotIndex >= 0) - _owner._dynamicHotspots.remove(_entries[seqIndex].dynamicHotspotIndex); - } - - _entries[seqIndex].active = false; - _owner._spriteSlots.deleteTimer(seqIndex); -} - -void MadsSequenceList::setSpriteSlot(int seqIndex, MadsSpriteSlot &spriteSlot) { - MadsSequenceEntry &timerEntry = _entries[seqIndex]; - SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(timerEntry.spriteListIndex); - - spriteSlot.spriteType = spriteSet.isBackground() ? BACKGROUND_SPRITE : FOREGROUND_SPRITE; - spriteSlot.seqIndex = seqIndex; - spriteSlot.spriteListIndex = timerEntry.spriteListIndex; - spriteSlot.frameNumber = (timerEntry.flipped ? 0x8000 : 0) | timerEntry.frameIndex; - spriteSlot.depth = timerEntry.depth; - spriteSlot.scale = timerEntry.scale; - - if (!timerEntry.nonFixed) { - spriteSlot.xp = timerEntry.msgPos.x; - spriteSlot.yp = timerEntry.msgPos.y; - } else { - spriteSlot.xp = spriteSet.getFrame(timerEntry.frameIndex - 1)->x; - spriteSlot.yp = spriteSet.getFrame(timerEntry.frameIndex - 1)->y; - } -} - -bool MadsSequenceList::loadSprites(int seqIndex) { - MadsSequenceEntry &seqEntry = _entries[seqIndex]; - int slotIndex; - bool result = false; - int idx = -1; - - _owner._spriteSlots.deleteTimer(seqIndex); - if (seqEntry.doneFlag) { - remove(seqIndex); - return false; - } - - if (seqEntry.spriteListIndex == -1) { - // Doesn't have an associated sprite anymore, so mark as done - seqEntry.doneFlag = true; - } else if ((slotIndex = _owner._spriteSlots.getIndex()) >= 0) { - MadsSpriteSlot &spriteSlot = _owner._spriteSlots[slotIndex]; - setSpriteSlot(seqIndex, spriteSlot); - - int x2 = 0, y2 = 0; - - if ((seqEntry.field_13 != 0) || (seqEntry.dynamicHotspotIndex >= 0)) { - SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex); - M4Sprite *frame = spriteSet.getFrame(seqEntry.frameIndex - 1); - int width = frame->width() * seqEntry.scale / 200; - int height = frame->height() * seqEntry.scale / 100; - - warning("frame size %d x %d", width, height); - - // TODO: Missing stuff here, and I'm not certain about the dynamic hotspot stuff below - - if (seqEntry.dynamicHotspotIndex >= 0) { - DynamicHotspot &dynHotspot = _owner._dynamicHotspots[seqEntry.dynamicHotspotIndex]; - - dynHotspot.bounds.left = MAX(x2 - width, 0); - dynHotspot.bounds.right = MAX(x2 - width, 319) - dynHotspot.bounds.left + 1; - dynHotspot.bounds.top = MAX(y2 - height, 0); - dynHotspot.bounds.bottom = MIN(y2, 155) - dynHotspot.bounds.top; - - _owner._dynamicHotspots._changed = true; - } - } - - // Frame adjustments - if (seqEntry.frameStart != seqEntry.numSprites) - seqEntry.frameIndex += seqEntry.frameInc; - - if (seqEntry.frameIndex >= seqEntry.frameStart) { - if (seqEntry.frameIndex > seqEntry.numSprites) { - result = true; - if (seqEntry.animType == ANIMTYPE_CYCLED) { - // Reset back to the starting frame (cyclic) - seqEntry.frameIndex = seqEntry.frameStart; - } else { - // Switch into reverse mode - seqEntry.frameIndex = seqEntry.numSprites - 1; - seqEntry.frameInc = -1; - } - } - } else { - // Currently in reverse mode and moved past starting frame - result = true; - - if (seqEntry.animType == ANIMTYPE_CYCLED) - { - // Switch back to forward direction again - seqEntry.frameIndex = seqEntry.frameStart + 1; - seqEntry.frameInc = 1; - } else { - // Otherwise reset back to last sprite for further reverse animating - seqEntry.frameIndex = seqEntry.numSprites; - } - } - - if (result && (seqEntry.triggerCountdown != 0)) { - if (--seqEntry.triggerCountdown == 0) - seqEntry.doneFlag = true; - } - } else { - // Out of sprite display slots, so mark entry as done - seqEntry.doneFlag = true; - } - - if (seqEntry.entries.count > 0) { - for (int i = 0; i <= seqEntry.entries.count; ++i) { - switch (seqEntry.entries.mode[i]) { - case SM_0: - case SM_1: - if (((seqEntry.entries.mode[i] == SM_0) && seqEntry.doneFlag) || - ((seqEntry.entries.mode[i] == SM_1) && result)) - idx = i; - break; - - case SM_FRAME_INDEX: { - int v = seqEntry.entries.frameIndex[i]; - if ((v == seqEntry.frameIndex) || (v == 0)) - idx = i; - } - - default: - break; - } - } - } - - if (idx >= 0) { - _owner._abortTimers = seqEntry.entries.abortVal[idx]; - _owner._abortTimersMode = seqEntry.abortMode; - } - - return result; -} - -/** - * Handles counting down entries in the timer list for action - */ -void MadsSequenceList::tick() { - for (uint idx = 0; idx < _entries.size(); ++idx) { - if ((_owner._abortTimers2 == 0) && (_owner._abortTimers != 0)) - break; - - MadsSequenceEntry &seqEntry = _entries[idx]; - uint32 currentTimer = _madsVm->_currentTimer; - - if (!seqEntry.active || (currentTimer < seqEntry.timeout)) - continue; - - // Set the next timeout for the timer entry - seqEntry.timeout = currentTimer + seqEntry.numTicks; - - // Action the sprite - if (loadSprites(idx)) { - seqEntry.timeout += seqEntry.extraTicks; - } - } -} - -void MadsSequenceList::delay(uint32 v1, uint32 v2) { - for (uint idx = 0; idx < _entries.size(); ++idx) { - if (_entries[idx].active) { - _entries[idx].timeout += v1 - v2; - } - } -} - -void MadsSequenceList::setAnimRange(int seqIndex, int startVal, int endVal) { - MadsSequenceEntry &seqEntry = _entries[seqIndex]; - SpriteAsset &spriteSet = _owner._spriteSlots.getSprite(seqEntry.spriteListIndex); - int numSprites = spriteSet.getCount(); - int tempStart = startVal, tempEnd = endVal; - - switch (startVal) { - case -2: - tempStart = numSprites; - break; - case -1: - tempStart = 1; - break; - } - - switch (endVal) { - case -2: - case 0: - tempEnd = numSprites; - break; - case -1: - tempEnd = 1; - break; - default: - tempEnd = numSprites; - break; - } - - seqEntry.frameStart = tempStart; - seqEntry.numSprites = tempEnd; - - seqEntry.frameIndex = (seqEntry.frameInc < 0) ? tempStart : tempEnd; -} - -void MadsSequenceList::scan() { - for (uint i = 0; i < _entries.size(); ++i) { - if (!_entries[i].active && (_entries[i].spriteListIndex != -1)) { - int idx = _owner._spriteSlots.getIndex(); - setSpriteSlot(i, _owner._spriteSlots[idx]); - } - } -} - -/** - * Sets the depth of the specified entry in the sequence list - */ -void MadsSequenceList::setDepth(int seqIndex, int depth) { - _entries[seqIndex].depth = depth; -} - -//-------------------------------------------------------------------------- - -Animation::Animation(MadsM4Engine *vm): _vm(vm) { -} - -Animation::~Animation() { -} - -//-------------------------------------------------------------------------- - -MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceList(*this), - _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this), - _screenObjects(*this), _action(*this) { - - _textSpacing = -1; - _newTimeout = 0; - _abortTimers = 0; - _abortTimers2 = 0; - _abortTimersMode = ABORTMODE_0; - _abortTimersMode2 = ABORTMODE_0; - - _depthSurface = NULL; - _bgSurface = NULL; - _viewport = NULL; - _sceneAnimation = new MadsAnimation(_vm, this); -} - -MadsView::~MadsView() { - delete _sceneAnimation; - delete _viewport; -} - -void MadsView::refresh() { - if (!_viewport) - setViewport(_view->bounds()); - - // Draw any sprites - _dirtyAreas.clear(); - _spriteSlots.drawBackground(); - - // Process dirty areas - _textDisplay.setDirtyAreas(); - - // Merge any identified dirty areas - _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); - - // Copy dirty areas to the main display surface - _dirtyAreas.copy(_viewport, _bgSurface, _posAdjust); - - // Handle dirty areas for foreground objects - _spriteSlots.setDirtyAreas(); - _textDisplay.setDirtyAreas2(); - _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); - - // Draw foreground sprites - _spriteSlots.drawForeground(_viewport); - - // Draw text elements onto the view - _textDisplay.draw(_viewport); - - // Remove any sprite slots that are no longer needed - _spriteSlots.cleanUp(); - - // Deactivate any text display entries that are no longer needed - _textDisplay.cleanUp(); -} - -void MadsView::update() { - _sequenceList.tick(); - _kernelMessages.update(); -} - -void MadsView::clearLists() { - _textDisplay.clear(); - _kernelMessages.clear(); - _spriteSlots.clear(); -} - -void MadsView::setViewport(const Common::Rect &bounds) { - delete _viewport; - _viewport = new M4Surface(bounds.width(), bounds.height(), _view->getBasePtr(bounds.left, bounds.top), - _view->getPitch()); -} - -} // End of namespace M4 diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h deleted file mode 100644 index 41caaa2ded..0000000000 --- a/engines/m4/mads_views.h +++ /dev/null @@ -1,494 +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. - * - */ - -#ifndef M4_MADS_VIEWS_H -#define M4_MADS_VIEWS_H - -#include "m4/gui.h" -#include "m4/viewmgr.h" -#include "common/rect.h" -#include "common/list.h" -#include "common/ptr.h" - -namespace M4 { - -class MadsView; - -enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6}; -enum MadsActionMode2 {ACTMODE2_0 = 0, ACTMODE2_2 = 2, ACTMODE2_4 = 4, ACTMODE2_5 = 5}; -enum AbortTimerMode {ABORTMODE_0 = 0, ABORTMODE_1 = 1, ABORTMODE_2 = 2}; - -struct ActionDetails { - int verbId; - int objectNameId; - int indirectObjectId; -}; - -struct MadsActionSavedFields { - int articleNumber; - int actionMode; - int actionMode2; - bool lookFlag; - int selectedRow; -}; - -class MadsAction { -private: - MadsView &_owner; - char _statusText[100]; - char _dialogTitle[100]; - - void appendVocab(int vocabId, bool capitalise = false); -public: - ActionDetails _action, _activeAction; - int _currentAction; - int8 _flags1, _flags2; - MadsActionMode _actionMode; - MadsActionMode2 _actionMode2; - int _articleNumber; - bool _lookFlag; - int _selectedRow; - bool _textChanged; - int _selectedAction; - bool _startWalkFlag; - int _statusTextIndex; - int _hotspotId; - MadsActionSavedFields _savedFields; - bool _walkFlag; - - // Unknown fields - int16 _v86F3A; - int16 _v86F42; - int16 _v86F4E; - bool _v86F4A; - int16 _v86F4C; - int _v83338; - bool _inProgress; - AbortTimerMode _v8453A; - -public: - MadsAction(MadsView &owner); - - void clear(); - void set(); - const char *statusText() const { return _statusText; } - void refresh(); - void startAction(); - void checkAction(); - bool isAction(int verbId, int objectNameId = 0, int indirectObjectId = 0); -}; - -class SpriteSlotSubset { -public: - int spriteListIndex; - int frameNumber; - int xp; - int yp; - int depth; - int scale; -}; - -class MadsSpriteSlot { -public: - int spriteType; - int seqIndex; - int spriteListIndex; - int frameNumber; - int xp; - int yp; - int depth; - int scale; - - MadsSpriteSlot() { } - - bool operator==(const SpriteSlotSubset &other) const; - void copy(const SpriteSlotSubset &other); -}; - -#define SPRITE_SLOTS_SIZE 50 - -enum SpriteIdSpecial { - BACKGROUND_SPRITE = -4, FULL_SCREEN_REFRESH = -2, EXPIRED_SPRITE = -1, SPRITE_ZERO = 0, FOREGROUND_SPRITE = 1 -}; - -class MadsSpriteSlots { -private: - MadsView &_owner; - Common::Array _entries; - Common::Array _sprites; -public: - int startIndex; - - MadsSpriteSlots(MadsView &owner); - ~MadsSpriteSlots(); - - MadsSpriteSlot &operator[](int idx) { - assert(idx < SPRITE_SLOTS_SIZE); - return _entries[idx]; - } - SpriteAsset &getSprite(int idx) { - assert(idx < (int)_sprites.size()); - return *_sprites[idx]; - } - - int getIndex(); - int addSprites(const char *resName, bool suppressErrors = false, int flags = 0); - int addSprites(SpriteAsset *spriteSet); - void deleteSprites(int listIndex); - void clear(); - void deleteTimer(int seqIndex); - - void drawBackground(); - void drawForeground(M4Surface *viewport); - void setDirtyAreas(); - void fullRefresh(); - void cleanUp(); -}; - -class MadsTextDisplayEntry { -public: - bool active; - int expire; - int spacing; - Common::Rect bounds; - uint8 color1; - uint8 color2; - Font *font; - const char *msg; - - MadsTextDisplayEntry() { active = false; } -}; - -#define TEXT_DISPLAY_SIZE 40 - -class MadsTextDisplay { -private: - MadsView &_owner; - Common::Array _entries; -public: - MadsTextDisplay(MadsView &owner); - - MadsTextDisplayEntry &operator[](int idx) { - assert(idx < TEXT_DISPLAY_SIZE); - return _entries[idx]; - } - - void expire(int idx) { - assert(idx < TEXT_DISPLAY_SIZE); - _entries[idx].expire = -1; - } - - int add(int xp, int yp, uint fontColor, int charSpacing, const char *msg, Font *font); - void clear(); - void draw(M4Surface *view); - void setDirtyAreas(); - void setDirtyAreas2(); - void cleanUp(); -}; - -#define TIMED_TEXT_SIZE 10 -#define INDEFINITE_TIMEOUT 9999999 - -enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10, - KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80}; - -class MadsKernelMessageEntry { -public: - uint8 flags; - int sequenceIndex; - char asciiChar; - char asciiChar2; - int color1; - int color2; - Common::Point position; - int textDisplayIndex; - int msgOffset; - int numTicks; - uint32 frameTimer2; - uint32 frameTimer; - uint32 timeout; - int abortTimers; - AbortTimerMode abortMode; - uint16 actionNouns[3]; - char msg[100]; - - MadsKernelMessageEntry() { - flags = 0; - } -}; - -class MadsKernelMessageList { -private: - MadsView &_owner; - Common::Array _entries; - Font *_talkFont; -public: - int word_8469E; -public: - MadsKernelMessageList(MadsView &owner); - - void clear(); - int add(const Common::Point &pt, uint fontColor, uint8 flags, uint8 abortTimers, uint32 timeout, const char *msg); - int addQuote(int quoteId, int abortTimers, uint32 timeout); - void scrollMessage(int msgIndex, int numTicks, bool quoted); - void setSeqIndex(int msgIndex, int seqIndex); - void remove(int msgIndex); - void reset(); - void update(); - void processText(int msgIndex); -}; - -class ScreenObjectEntry { -public: - Common::Rect bounds; - int category; - int index; - int layer; - bool active; - - ScreenObjectEntry() { active = false; } -}; - -class ScreenObjects { -private: - MadsView &_owner; - Common::Array _entries; -public: - int _v832EC; - int _v7FECA; - int _v7FED6; - int _v8332A; - int _yp; - int _v8333C; - int _selectedObject; - int _category; - int _objectIndex; - - ScreenObjects(MadsView &owner); - ScreenObjectEntry &operator[](uint idx) { - assert(idx <= _entries.size()); - return _entries[idx - 1]; - } - - void clear(); - void add(const Common::Rect &bounds, int layer, int idx, int category); - void draw(View *view); - int scan(int xp, int yp, int layer); - int scanBackwards(int xp, int yp, int layer); - void setActive(int category, int idx, bool active); - void check(bool scanFlag, bool mouseClick); -}; - -class DynamicHotspot { -public: - bool active; - int seqIndex; - Common::Rect bounds; - Common::Point pos; - int facing; - int descId; - int field_14; - int articleNumber; - int field_17; - - DynamicHotspot() { active = false; } -}; - -#define DYNAMIC_HOTSPOTS_SIZE 8 - -class MadsDynamicHotspots { -private: - MadsView &_owner; - Common::Array _entries; - int _count; -public: - bool _changed; -public: - MadsDynamicHotspots(MadsView &owner); - - DynamicHotspot &operator[](uint idx) { return _entries[idx]; } - int add(int descId, int field14, int seqIndex, const Common::Rect &bounds); - int setPosition(int index, int xp, int yp, int facing); - int set17(int index, int v); - void remove(int index); - void reset(); - void refresh() { - // TODO - } -}; - -class MadsDirtyArea { -public: - Common::Rect bounds; - Common::Rect bounds2; - bool textActive; - bool active; - - MadsDirtyArea() { active = false; } - void setArea(int width, int height, int maxWidth, int maxHeight); -}; - -#define DIRTY_AREAS_SIZE 90 -#define DIRTY_AREAS_TEXT_DISPLAY_IDX 50 - -class MadsDirtyAreas { -private: - MadsView &_owner; - Common::Array _entries; -public: - MadsDirtyAreas(MadsView &owner); - - MadsDirtyArea &operator[](uint idx) { - assert(idx < _entries.size()); - return _entries[idx]; - } - - void setSpriteSlot(int dirtyIdx, const MadsSpriteSlot &spriteSlot); - void setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &textDisplay); - void merge(int startIndex, int count); - bool intersects(int idx1, int idx2); - void mergeAreas(int idx1, int idx2); - void copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust); - void clear(); -}; - -enum SpriteAnimType {ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2}; - -enum SequenceSubEntryMode {SM_0 = 0, SM_1 = 1, SM_FRAME_INDEX = 2}; - -#define TIMER_ENTRY_SUBSET_MAX 5 - -struct MadsSequenceSubEntries { - int count; - SequenceSubEntryMode mode[TIMER_ENTRY_SUBSET_MAX]; - int16 frameIndex[TIMER_ENTRY_SUBSET_MAX]; - int8 abortVal[TIMER_ENTRY_SUBSET_MAX]; -}; - -struct MadsSequenceEntry { - int8 active; - int8 spriteListIndex; - bool flipped; - - int frameIndex; - int frameStart; - int numSprites; - - SpriteAnimType animType; - int frameInc; - - int depth; - int scale; - int dynamicHotspotIndex; - - bool nonFixed; - int field_13; - - Common::Point msgPos; - int triggerCountdown; - bool doneFlag; - MadsSequenceSubEntries entries; - AbortTimerMode abortMode; - - uint16 actionNouns[3]; - int numTicks; - int extraTicks; - uint32 timeout; -}; - -#define TIMER_LIST_SIZE 30 - -class MadsSequenceList { -private: - MadsView &_owner; - Common::Array _entries; -public: - MadsSequenceList(MadsView &owner); - - MadsSequenceEntry &operator[](int index) { return _entries[index]; } - void clear(); - bool addSubEntry(int index, SequenceSubEntryMode mode, int frameIndex, int abortVal); - int add(int spriteListIndex, bool flipped, int frameIndex, int triggerCountdown, int delayTicks, - int extraTicks, int numTicks, int msgX, int msgY, bool nonFixed, char scale, uint8 depth, - int frameInc, SpriteAnimType animType, int numSprites, int frameStart); - void remove(int seqIndex); - void setSpriteSlot(int seqIndex, MadsSpriteSlot &spriteSlot); - bool loadSprites(int seqIndex); - void tick(); - void delay(uint32 v1, uint32 v2); - void setAnimRange(int seqIndex, int startVal, int endVal); - void scan(); - void setDepth(int seqIndex, int depth); -}; - -class Animation { -protected: - MadsM4Engine *_vm; -public: - Animation(MadsM4Engine *vm); - virtual ~Animation(); - virtual void initialize(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) = 0; - virtual void load(const Common::String &filename, int v0) = 0; - virtual void update() = 0; - virtual void setCurrentFrame(int frameNumber) = 0; - virtual int getCurrentFrame() = 0; -}; - - -class MadsView { -private: - View *_view; -public: - Animation *_sceneAnimation; - MadsSpriteSlots _spriteSlots; - MadsTextDisplay _textDisplay; - MadsKernelMessageList _kernelMessages; - ScreenObjects _screenObjects; - MadsDynamicHotspots _dynamicHotspots; - MadsSequenceList _sequenceList; - MadsDirtyAreas _dirtyAreas; - MadsAction _action; - - int _textSpacing; - uint32 _newTimeout; - int _abortTimers; - int8 _abortTimers2; - AbortTimerMode _abortTimersMode; - AbortTimerMode _abortTimersMode2; - Common::Point _posAdjust; - - M4Surface *_depthSurface; - M4Surface *_bgSurface; - M4Surface *_viewport; -public: - MadsView(View *view); - ~MadsView(); - - void refresh(); - void update(); - void clearLists(); - void setViewport(const Common::Rect &bounds); -}; - -} - -#endif diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp deleted file mode 100644 index bfe77828da..0000000000 --- a/engines/m4/midi.cpp +++ /dev/null @@ -1,256 +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. - * - */ - -// FIXME: This is cribbed together from the SAGA music player. It needs cleanup -// and testing. - -#include "m4/m4.h" -#include "m4/midi.h" -#include "audio/midiparser.h" -#include "common/config-manager.h" -#include "common/memstream.h" -#include "common/textconsole.h" - -namespace M4 { - -MidiPlayer::MidiPlayer(MadsM4Engine *vm) : _vm(vm), _isGM(false) { - - MidiPlayer::createDriver(); - - int ret = _driver->open(); - if (ret == 0) { - _driver->setTimerCallback(this, &timerCallback); - } -} - -void MidiPlayer::send(uint32 b) { - if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) { - b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8; - } - - Audio::MidiPlayer::send(b); -} - -void MidiPlayer::playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene) { - Common::StackLock lock(_mutex); - - stop(); - - char fullname[144]; - _vm->res()->changeExtension(fullname, name, "HMP"); - - Common::SeekableReadStream *midiFile = _vm->res()->get(fullname); - byte *hmpData = new byte[midiFile->size()]; - uint32 smfSize; - - midiFile->read(hmpData, midiFile->size()); - _midiData = convertHMPtoSMF(hmpData, midiFile->size(), smfSize); - delete[] hmpData; - _vm->res()->toss(fullname); - _vm->res()->purge(); - - if (_midiData) { - _parser = MidiParser::createParser_SMF(); - _parser->setMidiDriver(this); - _parser->setTimerRate(_driver->getBaseTempo()); - - _parser->loadMusic(_midiData, smfSize); - _parser->property(MidiParser::mpAutoLoop, loop); - } - - setVolume(255); - - _isPlaying = true; -} - -// This function will convert HMP music into type 1 SMF, which our SMF parser -// will be able to handle. It is based on Hans de Goede's HMP 2 MIDI file -// converter, which in turn is "based on the conversion algorithms found in -// d1x, d2x-xl and jjffe". Hans's original code is licensed under the LGPL. -// -// TODO: It would probably be nicer to write a MIDI parser class to deal with -// HMP data directly. Though the multi-track nature of HMP makes that tricky. - -byte *MidiPlayer::convertHMPtoSMF(byte *data, uint32 inSize, uint32 &outSize) { - Common::MemoryReadStream readS(data, inSize); - Common::MemoryWriteStreamDynamic writeS; - - byte buf[8]; - - readS.read(buf, sizeof(buf)); - if (memcmp(buf, "HMIMIDIP", 8) != 0) { - warning("convertHMPtoSMF: Invalid HMP header"); - return NULL; - } - - // Read the number of tracks. Note that all the tracks are still part - // of the same song, just like in type 1 SMF files. - - readS.seek(0x30); - - uint32 numTracks = readS.readUint32LE(); - - // The first track starts on offset 0x300. It's currently unknown what - // the skipped data is for. - - readS.seek(0x300); - - // For some reason, we skip the first track entirely. - - byte a = readS.readByte(); - byte b = readS.readByte(); - byte c = readS.readByte(); - - while (a != 0xFF || b != 0x2F || c != 0x00) { - a = b; - b = c; - c = readS.readByte(); - } - - // The beginning of the MIDI header - static const byte midiHeader1[] = { 'M', 'T', 'h', 'd', 0, 0, 0, 6, 0, 1 }; - // The last 2 bytes of the midi header and track 0 - static const byte midiHeader2[] = { 0, 0xC0, 'M', 'T', 'r', 'k', 0, 0, 0, 0x0B, 0, 0xFF, 0x51, 0x03, 0x18, 0x80, 0, 0, 0xFF, 0x2F, 0 }; - - - // Write the MIDI header - writeS.write(midiHeader1, sizeof(midiHeader1)); - - // Write the number of tracks - writeS.writeUint16BE(numTracks); - - // Write the rest of the MIDI header and track 0. - writeS.write(midiHeader2, sizeof(midiHeader2)); - - // Read and convert all the tracks - for (uint i = 1; i < numTracks; i++) { - if (readS.readUint32LE() != i) { - warning("convertHMPtoSMF: Invalid HMP track number"); - delete[] writeS.getData(); - return NULL; - } - - uint32 trackLength = readS.readUint32LE() - 12; - readS.readUint32LE(); // Unused? - - // Write the track header - writeS.write("MTrk", 4); - - // This is where we will write the length of the track. - uint32 trackLengthPos = writeS.pos(); - writeS.writeUint32LE(0); - - // In the original, this is cleared once at the beginning of - // the function, but surely the last command does not carry - // over to the next track? - - byte lastCmd = 0; - - // Now we can finally convert the track - int32 endPos = readS.pos() + trackLength; - while (readS.pos() < endPos) { - // Convert the VLQ - byte vlq[4]; - int j = -1; - - do { - j++; - vlq[j] = readS.readByte(); - } while (!(vlq[j] & 0x80)); - - for (int k = 0; k <= j; k++) { - a = vlq[j - k] & 0x7F; - if (k != j) - a |= 0x80; - writeS.writeByte(a); - } - - a = readS.readByte(); - - if (a == 0xFF) { - // META event - b = readS.readByte(); - c = readS.readByte(); - - writeS.writeByte(a); - writeS.writeByte(b); - writeS.writeByte(c); - - if (c > 0) { - byte *metaBuf = new byte[c]; - readS.read(metaBuf, c); - writeS.write(metaBuf, c); - delete[] metaBuf; - } - - if (b == 0x2F) { - if (c != 0x00) { - warning("convertHMPtoSMF: End of track with non-zero size"); - delete[] writeS.getData(); - return NULL; - } - break; - } - } else { - if (a != lastCmd) - writeS.writeByte(a); - - switch (a & 0xF0) { - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - case 0xE0: - b = readS.readByte(); - c = readS.readByte(); - writeS.writeByte(b); - writeS.writeByte(c); - break; - case 0xC0: - case 0xD0: - b = readS.readByte(); - writeS.writeByte(b); - break; - default: - warning("convertHMPtoSMF: Invalid HMP command %02X", a); - delete[] writeS.getData(); - return NULL; - } - - lastCmd = a; - } - } - - if (readS.pos() != endPos) { - warning("convertHMPtoSMF: Invalid track length"); - delete[] writeS.getData(); - return NULL; - } - - WRITE_BE_UINT32(writeS.getData() + trackLengthPos, writeS.pos() - trackLengthPos - 4); - } - - outSize = writeS.size(); - return writeS.getData(); -} - -} // End of namespace M4 diff --git a/engines/m4/midi.h b/engines/m4/midi.h deleted file mode 100644 index 817150fd81..0000000000 --- a/engines/m4/midi.h +++ /dev/null @@ -1,59 +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. - * - */ - -// Music class - -#ifndef M4_MIDI_H -#define M4_MIDI_H - -#include "audio/midiplayer.h" - -namespace M4 { - -class MidiPlayer : public Audio::MidiPlayer { -public: - MidiPlayer(MadsM4Engine *vm); - - void playMusic(const char *name, int32 vol, bool loop, int32 trigger, int32 scene); - - void setGM(bool isGM) { _isGM = isGM; } - - // MidiDriver_BASE interface implementation - virtual void send(uint32 b); - -protected: - MadsM4Engine *_vm; - - bool _isGM; - - bool _randomLoop; - - byte *_musicData; - uint16 *_buf; - size_t _musicDataSize; - - byte *convertHMPtoSMF(byte *data, uint32 inSize, uint32 &outSize); -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/module.mk b/engines/m4/module.mk deleted file mode 100644 index f60757ba3b..0000000000 --- a/engines/m4/module.mk +++ /dev/null @@ -1,49 +0,0 @@ -MODULE := engines/m4 - -MODULE_OBJS = \ - actor.o \ - animation.o \ - assets.o \ - compression.o \ - console.o \ - converse.o \ - detection.o \ - dialogs.o \ - events.o \ - font.o \ - globals.o \ - graphics.o \ - gui.o \ - hotspot.o \ - m4.o \ - m4_menus.o \ - m4_scene.o \ - m4_views.o \ - mads_anim.o \ - mads_logic.o \ - mads_menus.o \ - mads_player.o \ - mads_scene.o \ - mads_views.o \ - midi.o \ - rails.o \ - resource.o \ - saveload.o \ - scene.o \ - script.o \ - sound.o \ - sprite.o \ - staticres.o \ - viewmgr.o \ - woodscript.o \ - ws_machine.o \ - ws_sequence.o - - -# This module can be built as a plugin -ifeq ($(ENABLE_M4), DYNAMIC_PLUGIN) -PLUGIN := 1 -endif - -# Include common rules -include $(srcdir)/rules.mk diff --git a/engines/m4/rails.cpp b/engines/m4/rails.cpp deleted file mode 100644 index f51d81c8f4..0000000000 --- a/engines/m4/rails.cpp +++ /dev/null @@ -1,358 +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. - * - */ - -/* - TODO: - - rewrite functions (GetShortestPath etc.) -*/ - -#include "graphics/primitives.h" -#include "common/list.h" -#include "common/rect.h" -#include "common/util.h" - -#include "m4/rails.h" -#include "m4/m4.h" - -namespace M4 { - -#define TOP_EDGE 1 << 0 -#define LEFT_EDGE 1 << 1 -#define BOTTOM_EDGE 1 << 2 -#define RIGHT_EDGE 1 << 3 - - -Rails::Rails() { -} - - -Rails::~Rails() { - clearRails(); -} - - -void Rails::clearRails() { - uint32 i; - Common::List::iterator j; - RailNode *tempNode; - - for (i = 0; i < _nodes.size(); i++) { - tempNode = _nodes[i]; - _nodes.remove_at(i); - delete tempNode; - } - - _edges.clear(); - - for (j = _noWalkRects.begin(); j != _noWalkRects.end(); ++j) - delete (*j); - _noWalkRects.clear(); -} - -static void checkPoint(int x, int y, int color, void *data) { - IsWalkableData *isWalkableData = (IsWalkableData*)data; - if (!isWalkableData->result) - return; - else { - M4Surface *codes = isWalkableData->codes; - if (x >= 0 && x < codes->width() && y >= 0 && y < codes->height()) { - isWalkableData->result = !((*((uint8*)codes->getBasePtr(x, y))) & 0x10); - } else { - isWalkableData->result = false; - } - } -} - -bool Rails::isLineWalkable(int x0, int y0, int x1, int y1) { - IsWalkableData isWalkableData; - isWalkableData.codes = _walkCodes; - isWalkableData.result = true; - Graphics::drawLine(x0, y0, x1, y1, 0, &checkPoint, &isWalkableData); - return isWalkableData.result; -} - -uint8 Rails::getDepth(const Common::Point &pt) { - // TODO: Check based on sceneResources - const byte *b = _walkCodes->getBasePtr(pt.x, pt.y); - return *b & 0xf; -} - -// helper function -uint8 getEndCode(int32 x, int32 y, Common::Rect rect) { - uint8 endCode = 0; - endCode = (x < rect.left) ? LEFT_EDGE : endCode; - endCode = (x > rect.right) ? RIGHT_EDGE : endCode; - endCode = (y < rect.top) ? endCode | TOP_EDGE : endCode; - endCode = (y > rect.bottom) ? endCode | BOTTOM_EDGE : endCode; - return endCode; -} - -bool Rails::lineCrossesRect(int32 x1, int32 y1, int32 x2, int32 y2, Common::Rect rect) { - int32 mX, mY; - int32 pX1 = x1, pX2 = x2, pY1 = y1, pY2 = y2; - uint8 endCode1, endCode2, midCode; - - if (rect.left > rect.right || rect.top > rect.bottom) - return false; - - // Cohen-Sutherland line clipping algorithm - - endCode1 = getEndCode(pX1, pY1, rect); - endCode2 = getEndCode(pX2, pY2, rect); - - if (!endCode1 || !endCode2) // if both endcodes are zero - return true; // point is inside the rectangle, therefore the line intersects - - while (true) { - if (endCode1 & endCode2) // if both endcodes have a common bitset - return false; // line is completely off one edge - - // calculate midpoint - mX = (pX1 + pX2)>>1; - mY = (pY1 + pY2)>>1; - - // avoid round-off error: make sure that the midpoint isn't the same as one of the - // two endpoints - if (((mX == pX1) && (mY == pY1)) || ((mX == pX2) && (mY == pY2))) - return false; - - midCode = getEndCode(mX, mY, rect); - - if (!midCode) { - return true; - } else if (midCode & endCode1) { - // the midCode and an end point form a line segment completely off one edge, so - // remove that half of the line segment - pX1 = mX; - pY1 = mY; - endCode1 = midCode; - } else { - pX2 = mX; - pY2 = mY; - endCode2 = midCode; - } - } -} - - -bool Rails::linePassesThroughRect(int32 x1, int32 y1, int32 x2, int32 y2) { - if (_noWalkRects.empty()) - return false; - - bool intersected = false; - Common::List::iterator i; - - for (i = _noWalkRects.begin(); i != _noWalkRects.end(); ++i) { - intersected = lineCrossesRect(x1, y1, x2, y2, Common::Rect((*i)->x1, (*i)->y1, (*i)->x2, (*i)->y2)); - if (intersected) - break; - } - - return intersected; -} - -long SqrtF16(long n) { - uint32 r = 0, s; - uint32 v = (uint32)n; - - for (int i = 15; i >= 0; --i) { - s = r + (1L << i * 2); - r >>= 1; - if (s <= v) { - v -= s; - r |= (1L << i * 2); - } - } - - return (long)r; -} - -void Rails::createEdge(int32 node1, int32 node2) { - uint32 index; - int32 x1, y1, x2, y2; - bool valid; - long deltaX, deltaY, distance; - - if ((node1 < 0) || (node1 >= MAXRAILNODES) || (node2 < 0) || (node2 >= MAXRAILNODES)) - return; - - if (node1 == node2) - return; - - if (node2 < node1) - SWAP(node1, node2); // ensure node1 < node2 - - // Find the table entry i.e. tableWidth * node1 + node2 and then subtract - // n(n+1)/2, since only the upper triangle of the table is stored - index = (MAXRAILNODES-1) * node1 + node2 - 1 - (node1*(node1+1)>>1); - if (index > _edges.size() - 1) - _edges.resize(index + 1); - _edges.insert_at(index, 0); - valid = true; - - if (_nodes.size() <= (uint32)node1 || _nodes.size() <= (uint32)node2) - return; - - x1 = _nodes[node1]->x; - y1 = _nodes[node1]->y; - x2 = _nodes[node2]->x; - y2 = _nodes[node2]->y; - - // Make sure that the algorithm is symmetric - if (x2 < x1) { - SWAP(x1, x2); - SWAP(y1, y2); - } - - valid = isLineWalkable(_nodes[node1]->x, _nodes[node1]->y, - _nodes[node2]->x, _nodes[node2]->y); - debugCN(kDebugCore, "test code says: %d\n", valid); - - // Check if the line passes through a forbidden rectangle - if (valid) { - if (linePassesThroughRect(x1, y1, x2, y2)) { - valid = false; - } - } - - if (valid) { - deltaX = ABS(((long)(x2 - x1)) << 16); - deltaY = ABS(((long)(y2 - y1)) << 16); - if ((deltaX >= 0x800000) || (deltaY >= 0x800000)) { - deltaX >>= 16; - deltaY >>= 16; - distance = (long)(SqrtF16(deltaX * deltaX + deltaY * deltaY) << 16); - } else { - distance = SqrtF16(FixedMul(deltaX, deltaX) + FixedMul(deltaY, deltaY)) << 8; - } - _edges.insert_at(index, distance >> 16); - } - - debugCN(kDebugCore, "node1 = %d, node2 = %d, valid = %d\n", node1, node2, valid); - -} - - -void Rails::restoreNodeEdges(int32 nodeID) { - for (int32 i = 0; i < MAXRAILNODES; i++) { - createEdge(i, nodeID); - } -} - -void Rails::restoreEdgeList() { - int32 j; - for (int32 i = 0; i < MAXRAILNODES; i++) { - for (j = i + 1; j < MAXRAILNODES; j++) { - createEdge(i, j); - } - } -} - -int32 Rails::addRailNode(int32 x, int32 y, bool restoreEdges) { - uint32 i = _nodes.size(); - if (i >= MAXRAILNODES) - return -1; - - RailNode *newNode = new RailNode(); - newNode->nodeID = i; - newNode->x = x; - newNode->y = y; - _nodes.insert_at(i, newNode); - if (restoreEdges) { - for (uint32 j=0; j<_nodes.size(); j++) - createEdge(i, j); - } - return i; -} - -bool Rails::removeRailNode(int32 nodeID, bool restoreEdges) { - if (nodeID < 0 || nodeID >= MAXRAILNODES) - return false; - - if (_nodes.empty() || _edges.empty()) - return false; - - RailNode *tempNode = _nodes[nodeID]; - _nodes.remove_at(nodeID); - delete tempNode; - - if (restoreEdges) { - restoreNodeEdges(nodeID); - } - return true; -} - -int16 Rails::getEdgeLength(int32 node1, int32 node2) { - int32 index; - if (_edges.empty() || node1 == node2) - return 0; - if (node2 < node1) - SWAP(node1, node2); - // Find the table entry i.e. tableWidth * node1 + node2 and then subtract - // n(n+1)/2, since only the upper triangle of the table is stored - index = (MAXRAILNODES-1)*node1 + node2 - 1 - (node1*(node1+1)>>1); - return _edges[index]; -} - -void Rails::disposePath(RailNode *pathStart) { - RailNode *tempNode = pathStart; - while (tempNode) { - pathStart = pathStart->shortPath; - delete tempNode; - tempNode = pathStart; - } -} - -/* -static RailNode* duplicatePath(RailNode *pathStart) { - RailNode *newNode = NULL; - RailNode *firstNode = NULL; - RailNode *prevNode = NULL; - // A valid path is assumed - RailNode *pathNode = pathStart; - - while (pathNode) { - newNode = new RailNode(); - newNode->x = pathNode->x; - newNode->y = pathNode->y; - newNode->shortPath = NULL; - - if (!firstNode) - firstNode = newNode; - else - prevNode->shortPath = newNode; - - prevNode = newNode; - // Get the next node - pathNode = pathNode->shortPath; - } - - return firstNode; -} -*/ - -bool Rails::getShortestPath(int32 origID, int32 destID, RailNode **shortPath) { - // TODO - return true; -} - -} // End of namespace M4 diff --git a/engines/m4/rails.h b/engines/m4/rails.h deleted file mode 100644 index 80bb55e9de..0000000000 --- a/engines/m4/rails.h +++ /dev/null @@ -1,97 +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. - * - */ - -#ifndef M4_RAILS_H -#define M4_RAILS_H - -#include "m4/graphics.h" -#include "common/list.h" -#include "common/array.h" -#include "common/rect.h" - -// TODO: This needs cleaning up - -namespace M4 { - -#define MAXRAILNODES 32 -#define PATH_END 0xffff - -struct RailNode { - uint8 nodeID; - int32 x, y; - RailNode *shortPath; - int32 pathWeight; -}; - -struct NoWalkRect { - int32 x1, y1, x2, y2; - int32 alternateWalkToNode; - int32 walkAroundNode1; - int32 walkAroundNode2; - int32 walkAroundNode3; - int32 walkAroundNode4; -}; - -struct PathNode { - PathNode *next; - int8 nodeID; -}; - -struct IsWalkableData { - M4Surface *codes; - bool result; -}; - -class Rails { -public: - Rails(); - ~Rails(); - - void setCodeSurface(M4Surface *surface) { _walkCodes = surface; } - void clearRails(); - int32 addRailNode(int32 x, int32 y, bool restoreEdges); - uint8 getDepth(const Common::Point &pt); - -private: - Common::Array _nodes; - Common::Array _edges; - Common::List _noWalkRects; - M4Surface *_walkCodes; - - bool lineCrossesRect(int32 x1, int32 y1, int32 x2, int32 y2, Common::Rect rect); - bool linePassesThroughRect(int32 x1, int32 y1, int32 x2, int32 y2); - void createEdge(int32 node1, int32 node2); - bool removeRailNode(int32 nodeID, bool restoreEdges); - int16 getEdgeLength(int32 node1, int32 node2); - - void restoreNodeEdges(int32 nodeID); - void restoreEdgeList(); - void disposePath(RailNode *pathStart); - bool getShortestPath(int32 origID, int32 destID, RailNode **shortPath); - bool isLineWalkable(int x0, int y0, int x1, int y1); -}; - -long SqrtF16(long n); - -} // End of namespace M4 - -#endif diff --git a/engines/m4/resource.cpp b/engines/m4/resource.cpp deleted file mode 100644 index f5b2050052..0000000000 --- a/engines/m4/resource.cpp +++ /dev/null @@ -1,530 +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 "m4/m4.h" -#include "m4/resource.h" -#include "m4/events.h" - -#include "common/substream.h" -#include "common/textconsole.h" - -namespace M4 { - -FileSystem::FileSystem(const char *hashFilename) { - - for (int i = 0; i < 10; i++) { - _hagEntries[i].filename[0] = '\0'; - _hagEntries[i].fileIndex = 0; // Was -1 - _hagEntries[i].hagFile = 0; - } - - Common::File hashFile; - uint32 hashSize; - - hashFile.open(hashFilename); - - if (!hashFile.isOpen()) { - debugCN(kDebugCore, "FileSystem::FileSystem: error opening hash %s\n", hashFilename); - } - - hashSize = hashFile.readUint32LE(); - - //debugCN(kDebugCore, "FileSystem::FileSystem: hashSize = %d\n", hashSize); - - /* load file records and add them to the hash list */ - for (uint i = 0; i < hashSize; i++) { - HashFileEntry entry; - hashFile.read(entry.filename, kM4MaxFilenameSize); - str_lower(entry.filename); - entry.hagfile = hashFile.readByte(); - hashFile.readByte(); - entry.offset = hashFile.readUint32LE(); - entry.size = hashFile.readUint32LE(); - hashFile.readUint32LE(); - - if (entry.filename[0]) { - /* - debugCN(kDebugCore, " filename: %s\n", entry.filename); - debugCN(kDebugCore, " hagfile: %d\n", entry.hagfile); - debugCN(kDebugCore, " disks: %d\n", entry.disks); - debugCN(kDebugCore, " offset: %08X\n", entry.offset); - debugCN(kDebugCore, " size: %d\n", entry.size); - debugCN(kDebugCore, " next: %08X\n", entry.next); - */ - _fileEntries[entry.filename] = entry; - } - - } - - /* load hagfile records and update the list */ - while (!hashFile.eos()) { - HashHagEntry entry; - hashFile.read(entry.filename, kM4MaxFilenameSize); - entry.fileIndex = hashFile.readByte(); - if (hashFile.eos()) - break; - - changeExtension(_hagEntries[entry.fileIndex].filename, entry.filename, "HAG"); - _hagEntries[entry.fileIndex].fileIndex = entry.fileIndex; - - _hagEntries[entry.fileIndex].hagFile = new Common::File(); - _hagEntries[entry.fileIndex].hagFile->open(_hagEntries[entry.fileIndex].filename); - - if (!_hagEntries[entry.fileIndex].hagFile->isOpen()) { - debugCN(kDebugCore, "FileSystem::FileSystem: error opening hag %s\n", _hagEntries[entry.fileIndex].filename); - } - - } - - hashFile.close(); - -} - -FileSystem::~FileSystem() { - - for (int i = 0; i < 10; i++) { - if (_hagEntries[i].hagFile) - delete _hagEntries[i].hagFile; - } - -} - -Common::SeekableReadStream *FileSystem::loadFile(const char *resourceName, bool preloadFlag) { - const HashFileEntry *hfe = getHashFileEntry(resourceName); - Common::SeekableReadStream *result = NULL; - - if (hfe) { - //debugCN(kDebugCore, "FileSystem::loadFile() success opening %s\n", filename); - HashHagEntry *hagEntry = &_hagEntries[hfe->hagfile]; - - if (preloadFlag) { - // Creates a MemoryReadStream object that contains all of the resource in memory - hagEntry->hagFile->seek(hfe->offset); - result = _hagEntries[hfe->hagfile].hagFile->readStream(hfe->size); - } - else - // Creates a SeekableSubReadStream, which will read the data in from disk as the - // caller reads in data - result = new Common::SeekableSubReadStream(hagEntry->hagFile, hfe->offset, - hfe->offset + hfe->size); - - } else { - debugCN(kDebugCore, "FileSystem::loadFile() error opening %s\n", resourceName); - } - - return result; -} - -const FileSystem::HashFileEntry *FileSystem::getHashFileEntry(const char *filename) { - char resourceName[20]; - strcpy(resourceName, filename); - str_lower(resourceName); - - FileHashMap::const_iterator entry = _fileEntries.find(filename); - if (entry != _fileEntries.end()) - return &(entry->_value); - else - return NULL; -} - -void FileSystem::changeExtension(char *destName, const char *sourceName, const char *extension) { - if (sourceName != destName) - strcpy(destName, sourceName); - char *dot = strrchr(destName, '.'); - if (dot != NULL) - *dot = 0; - - strcat(destName, "."); - strcat(destName, extension); - - str_upper(destName); -} - -//-------------------------------------------------------------------------- - -ResourceManager::~ResourceManager() { - ResourceIterator i; - for (i = _resources.begin(); i != _resources.end(); ++i) { - Resource *r = (*i).get(); - delete r->stream; - } -} - -Common::SeekableReadStream *ResourceManager::get(const char *resourceName, bool preloadFlag) { - char lowerName[kM4MaxFilenameSize]; - - strcpy(lowerName, resourceName); - str_lower(lowerName); - - // Check whether the resource is already loaded - ResourceIterator i; - for (i = _resources.begin(); i != _resources.end(); ++i) { - Resource *r = (*i).get(); - if (!strcmp(r->name, resourceName)) { - // Just in case resource was marked to be purged, reactive it again - r->flags &= ~kResourcePurge; - - // Return the existing copy of the resource - r->stream->seek(0, SEEK_SET); - return r->stream; - } - } - - // the resource wasn't found in the list, load it from disk - Resource *newRes = new Resource(); - strncpy(newRes->name, resourceName, 63); - newRes->name[63] = '\0'; - newRes->flags = 0; - newRes->stream = loadResource(resourceName, preloadFlag); - - _resources.push_back(ResourceList::value_type(newRes)); - return newRes->stream; -} - -void ResourceManager::toss(const char *resourceName) { - ResourceIterator i; - for (i = _resources.begin(); i != _resources.end(); ++i) { - Resource *r = (*i).get(); - - if (!strcmp(r->name, resourceName)) { - r->flags |= kResourcePurge; - //debugCN(kDebugCore, "M4ResourceManager::toss: mark resource %s to be purged\n", resourceName); - } - } -} - -void ResourceManager::purge() { - ResourceIterator i = _resources.begin(); - while (i != _resources.end()) { - Resource *r = (*i).get(); - - if (r->flags & kResourcePurge) { - delete r->stream; - i = _resources.erase(i); - } else { - ++i; - } - } -} - -void ResourceManager::dump() { - _vm->_events->getConsole()->DebugPrintf("Scene resources:\n"); - - int index = 0; - ResourceIterator i; - for (i = _resources.begin(); i != _resources.end(); ++i) { - Resource *r = (*i).get(); - - if (!(r->flags & kResourcePurge)) { - _vm->_events->getConsole()->DebugPrintf( - "Resource #%i, name: %s, handle pointer: %p, size: %d, flags: %02X\n", - index++, r->name, r->buffer, r->stream->size(), r->flags); - } - } -} - -//-------------------------------------------------------------------------- - -const char *madsConcatString = "MADSCONCAT"; - -ResourceType MADSResourceManager::getResourceType(const char *resourceName) { - if (!strncmp(resourceName, "RM", 2)) { - // Room resource - return RESTYPE_ROOM; - } else if (!strncmp(resourceName, "SC", 2)) { - // SC resource - return RESTYPE_SC; - } else if (strstr(resourceName, ".TXT")) { - // Text resource - return RESTYPE_TEXT; - } else if (strstr(resourceName, ".QUO")) { - // QUO resource - return RESTYPE_QUO; - } else if (*resourceName == 'I') { - // I resource - return RESTYPE_I; - } else if (!strncmp(resourceName, "OB", 2)) { - // OB resource - return RESTYPE_OB; - } else if (!strncmp(resourceName, "FONT", 4)) { - // FONT resource - return RESTYPE_FONT; - } else if (!strncmp(resourceName, "SOUND", 5)) { - // SOUND resource - return RESTYPE_SOUND; - } else if (!strncmp(resourceName, "SPCHC", 5)) { - // SPEECH resource - return RESTYPE_SPEECH; - } - - // Check for a known extension - const char *extPos = strchr(resourceName, '.'); - if (extPos) { - ++extPos; - if (!strcmp(extPos, "FL") || !strcmp(extPos, "LBM") || !strcmp(extPos, "ANM") || - !strcmp(extPos, "AA") || !strcmp(extPos, "SS")) { - return RESTYPE_HAS_EXT; - } - } - - return RESTYPE_NO_EXT; -} - -const char *MADSResourceManager::getResourceFilename(const char *resourceName) { - static char outputFilename[64]; - - ResourceType resType = getResourceType(resourceName); - - strcpy(outputFilename, "GLOBAL.HAG"); - - if ((resType == RESTYPE_ROOM) || (resType == RESTYPE_SC)) { - int value = atoi(resourceName + 2); - int hagFileNum = (resType == RESTYPE_ROOM) ? value / 100 : value; - - if (hagFileNum > 0) - sprintf(outputFilename, "SECTION%d.HAG", hagFileNum); - } - - if (resType == RESTYPE_SPEECH) - strcpy(outputFilename, "SPEECH.HAG"); - - return outputFilename; -} - -/** - * Forms a resource name based on the passed specifiers - */ -const char *MADSResourceManager::getResourceName(char asciiCh, int prefix, ExtensionType extType, - const char *suffix, int index) { - static char resourceName[100]; - - if (prefix <= 0) - strcpy(resourceName, "*"); - else { - if (prefix < 100) - strcpy(resourceName, "*SC"); - else - strcpy(resourceName, "*RM"); - sprintf(resourceName + 3, "%.3d", prefix); - } - - // Append the specified ascii prefix character - char asciiStr[2]; - asciiStr[0] = asciiCh; - asciiStr[1] = '\0'; - strcat(resourceName, asciiStr); - - // Add in the index specified - if (index >= 0) - sprintf(resourceName + strlen(resourceName), "%d", index); - - // Add in any suffix - if (suffix) - strcat(resourceName, suffix); - - // Handle extension types - switch (extType) { - case EXTTYPE_SS: - strcat(resourceName, ".SS"); - break; - case EXTTYPE_AA: - strcat(resourceName, ".AA"); - break; - case EXTTYPE_DAT: - strcat(resourceName, ".DAT"); - break; - case EXTTYPE_HH: - strcat(resourceName, ".HH"); - break; - case EXTTYPE_ART: - strcat(resourceName, ".ART"); - break; - case EXTTYPE_INT: - strcat(resourceName, ".INT"); - break; - default: - break; - } - - return &resourceName[0]; -} - -/** - * Another variation for forming resource names - */ -const char *MADSResourceManager::getResourceName(ResourcePrefixType prefixType, int idx, const char *extension) { - static char resourceName[100]; - - strcpy(resourceName, "*"); - - if (extension) { - switch (prefixType) { - case RESPREFIX_GL: - strcat(resourceName, "GL000"); - break; - case RESPREFIX_SC: - case RESPREFIX_RM: - strcat(resourceName, (prefixType == RESPREFIX_SC) ? "SC" : "RM"); - sprintf(resourceName + 3, "%.3d", idx); - break; - default: - break; - } - - strcat(resourceName, extension); - } - - return &resourceName[0]; -} - -/** - * Forms an AA resource name based on the given passed index - */ -const char *MADSResourceManager::getAAName(int index) { - return getResourceName('I', 0, EXTTYPE_AA, NULL, index); -} - -Common::SeekableReadStream *MADSResourceManager::loadResource(const char *resourceName, bool loadFlag) { - Common::File hagFile; - uint32 offset = 0, size = 0; - - // If the first character is a '@' then look for an external file - - if (*resourceName == '@') { - ++resourceName; - - hagFile.open(resourceName); - if (loadFlag) - return hagFile.readStream(hagFile.size()); - else - return new Common::SeekableSubReadStream(&hagFile, 0, hagFile.size()); - } - - // If the first character is the wildcard (resource indicator), skip over it - if (*resourceName == '*') - ++resourceName; - - char resName[20]; - strcpy(resName, resourceName); - str_upper(resName); - - hagFile.open(getResourceFilename(resName)); - - // Validate hag file header - char headerBuffer[16]; - if ((hagFile.read(headerBuffer, 16) != 16) || (strncmp(headerBuffer, madsConcatString, 10) != 0)) - error("Invalid HAG file opened"); - - int numEntries = hagFile.readUint16LE(); - - int resIndex = -1; - while (++resIndex < numEntries) { - // Read in the details of the next resource - char resourceBuffer[14]; - offset = hagFile.readUint32LE(); - size = hagFile.readUint32LE(); - hagFile.read(resourceBuffer, 14); - - if (!strcmp(resName, resourceBuffer)) - break; - } - - if (resIndex == numEntries) - error("Invalid resource '%s' specified", resourceName); - - // Get the resource, either loading it in it's entirely or getting a stream reference - - if (loadFlag) { - hagFile.seek(offset); - return hagFile.readStream(size); - } else { - return new Common::SeekableSubReadStream(&hagFile, offset, offset + size); - } -} - -bool MADSResourceManager::resourceExists(const char *resourceName) { - Common::File hagFile; - - // If the first character is the wildcard (resource indicator), skip over it - if (*resourceName == '*') - ++resourceName; - - char resName[20]; - strcpy(resName, resourceName); - str_upper(resName); - - hagFile.open(getResourceFilename(resName)); - - // Validate hag file header - char headerBuffer[16]; - if ((hagFile.read(headerBuffer, 16) != 16) || (strncmp(headerBuffer, madsConcatString, 10) != 0)) - error("Invalid HAG file opened"); - - int numEntries = hagFile.readUint16LE(); - - int resIndex = -1; - while (++resIndex < numEntries) { - // Read in the details of the next resource - char resourceBuffer[14]; - hagFile.readUint32LE(); // offset - hagFile.readUint32LE(); // size - hagFile.read(resourceBuffer, 14); - - if (!strcmp(resName, resourceBuffer)) - break; - } - - if (resIndex == numEntries) - return false; - else - return true; -} - -//-------------------------------------------------------------------------- - -M4ResourceManager::M4ResourceManager(MadsM4Engine *vm): ResourceManager(vm) { - _hfs = new FileSystem(_vm->getGameFile(kFileTypeHash)); -} - -M4ResourceManager::~M4ResourceManager() { -} - -Common::SeekableReadStream *M4ResourceManager::loadResource(const char *resourceName, bool preloadFlag) { - //debugCN(kDebugCore, "M4ResourceManager::loadResource() loading resource %s\n", resourceName); - Common::SeekableReadStream* result = NULL; - if (_hfs) { - // actually load the resource - result = _hfs->loadFile(resourceName, preloadFlag); - if (!result) { - error("M4ResourceManager::loadResource() Resource %s not found", resourceName); - } - } else { - error("M4ResourceManager::loadResource() No FileSystem attached"); - } - return result; -} - -bool M4ResourceManager::resourceExists(const char *resourceName) { - return (_hfs->getHashFileEntry(resourceName) != NULL); -} - -} // End of namespace M4 diff --git a/engines/m4/resource.h b/engines/m4/resource.h deleted file mode 100644 index c13c293544..0000000000 --- a/engines/m4/resource.h +++ /dev/null @@ -1,147 +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. - * - */ - -#ifndef M4_RESOURCE_H -#define M4_RESOURCE_H - -#include "common/scummsys.h" -#include "common/stream.h" -#include "common/endian.h" -#include "common/file.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/list.h" -#include "common/ptr.h" - -/* - TODO: - - change array to HashMap if it turns out to be slow -*/ - -namespace M4 { - -#define MAX_RESOURCES 128 -#define kM4MaxFilenameSize 33 - -enum { - kResourcePurge = 1 << 1 -}; - - -class FileSystem { -public: - struct HashHagEntry { - char filename[kM4MaxFilenameSize]; - byte fileIndex; - Common::File *hagFile; - }; - - struct HashFileEntry { - char filename[kM4MaxFilenameSize]; - byte hagfile; - uint32 offset, size; - }; - - FileSystem(const char *hashFilename); - ~FileSystem(); - - Common::SeekableReadStream *loadFile(const char *resourceName, bool preloadFlag); - static void changeExtension(char *destName, const char *sourceName, const char *extension); - const HashFileEntry *getHashFileEntry(const char *filename); - -private: - typedef Common::HashMap FileHashMap; - - HashHagEntry _hagEntries[10]; // GLOBAL.HAG and SECTION1.HAG to SECTION9.HAG - FileHashMap _fileEntries; -}; - -struct Resource { - char name[64]; - Common::SeekableReadStream *stream; - uint8 *buffer; - uint8 flags; -}; - -class ResourceManager { -protected: - typedef Common::List > ResourceList; - typedef ResourceList::iterator ResourceIterator; - ResourceList _resources; - MadsM4Engine *_vm; - - virtual Common::SeekableReadStream *loadResource(const char *resourceName, bool loadFlag) = 0; -public: - ResourceManager(MadsM4Engine *vm): _vm(vm) {} - virtual ~ResourceManager(); - - Common::SeekableReadStream *get(const char *resourceName, bool loadFlag = true); - void toss(const char *resourceName); - void purge(); - void dump(); - virtual bool resourceExists(const char *resourceName) = 0; - - Common::SeekableReadStream *openFile(const char *resourceName) { return get(resourceName, false); } - void changeExtension(char *destName, const char *sourceName, const char *extension) { - FileSystem::changeExtension(destName, sourceName, extension); - } -}; - -enum ResourceType {RESTYPE_ROOM, RESTYPE_SC, RESTYPE_TEXT, RESTYPE_QUO, RESTYPE_I, - RESTYPE_OB, RESTYPE_FONT, RESTYPE_SOUND, RESTYPE_SPEECH, RESTYPE_HAS_EXT, RESTYPE_NO_EXT}; - -enum ExtensionType {EXTTYPE_SS = 1, EXTTYPE_AA = 2, EXTTYPE_DAT = 3, EXTTYPE_HH = 4, EXTTYPE_ART = 5, - EXTTYPE_INT = 6, EXTTYPE_NONE = -1}; - -enum ResourcePrefixType {RESPREFIX_GL = 1, RESPREFIX_SC = 2, RESPREFIX_RM = 3}; - -class MADSResourceManager : public ResourceManager { -private: - ResourceType getResourceType(const char *resourceName); - const char *getResourceFilename(const char *resourceName); -protected: - Common::SeekableReadStream *loadResource(const char *resourceName, bool loadFlag); -public: - MADSResourceManager(MadsM4Engine *vm): ResourceManager(vm) {} - bool resourceExists(const char *resourceName); - - static const char *getResourceName(char asciiCh, int prefix, ExtensionType extType, const char *suffix, int index); - static const char *getResourceName(ResourcePrefixType prefixType, int idx, const char *extension); - static const char *getAAName(int index); -}; - -class M4ResourceManager : public ResourceManager { -protected: - Common::SeekableReadStream *loadResource(const char *resourceName, bool loadFlag); -public: - M4ResourceManager(MadsM4Engine *vm); - ~M4ResourceManager(); - bool resourceExists(const char *resourceName); - -private: - FileSystem *_hfs; -}; - -} // End of namespace M4 - - -#endif diff --git a/engines/m4/saveload.cpp b/engines/m4/saveload.cpp deleted file mode 100644 index a7615fa4b6..0000000000 --- a/engines/m4/saveload.cpp +++ /dev/null @@ -1,166 +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/file.h" -#include "common/savefile.h" - -#include "m4/m4.h" -#include "m4/saveload.h" -#include "m4/sprite.h" - -namespace M4 { - -const char *orionSavesList = "saves.dir"; - -SaveLoad::SaveLoad(MadsM4Engine *vm) : _vm(vm) { - // For Orion Burger, check the existance of a 'saves.dir' file to determine whether to - // act exactly like the original. Otherwise, we'll use the ScummVM standard, where we'll - // keep all the data for a savegame in a single file - - Common::File file; - _emulateOriginal = file.exists(orionSavesList); -} - -const char *SaveLoad::generateSaveName(int slotNumber) { - static char buffer[15]; - - sprintf(buffer, _emulateOriginal ? "burg%.3d.sav" : "burger.%.3d", slotNumber); - return buffer; -} - -bool SaveLoad::hasSaves() { - // Return true if a savegame file exists for the first slot - - if (_emulateOriginal) { - Common::File f; - return f.exists(generateSaveName(1)); - - } else { - Common::ReadStream *f = _vm->saveManager()->openForLoading(generateSaveName(1)); - if (f == NULL) - return false; - - delete f; - return true; - } -} - -SaveGameList *SaveLoad::getSaves() { - SaveGameList *result = new SaveGameList(); - char saveName[MAX_SAVEGAME_NAME]; - Common::ReadStream *f = NULL; - - if (_emulateOriginal) { - Common::File *saveFile = new Common::File(); - saveFile->open(orionSavesList); - f = saveFile; - } - - for (int slotNumber = 1; slotNumber <= 99; ++slotNumber) { - if (_emulateOriginal) { - // Read in savegame name from save directory - bool isPresent = (f->readByte() != 0); - f->read(&saveName[0], MAX_SAVEGAME_NAME); - - if (isPresent) - result->push_back(Common::String(saveName)); - else { - result->push_back(Common::String()); - } - - } else { - // Read in savegame name from savegame files directly - Common::ReadStream *saveFile = _vm->saveManager()->openForLoading( - generateSaveName(slotNumber)); - if (!saveFile) { - // No savegame prsent at that slot - result->push_back(Common::String()); - } else { - // Skip over byte offset - uint32 offset = saveFile->readUint32LE(); - assert(offset < 0x100); - - // Read in savegame name - saveFile->read(&saveName[0], MAX_SAVEGAME_NAME); - result->push_back(Common::String(saveName)); - - delete saveFile; - } - } - } - - if (_emulateOriginal) - delete f; - - return result; -} - -M4Surface *SaveLoad::getThumbnail(int slotNumber) { - Common::SeekableReadStream *saveFile; - uint32 dataOffset; - - if (_emulateOriginal) { - // Get savegame file from original game folder - Common::File *f = new Common::File(); - if (!f->open(generateSaveName(slotNumber))) { - delete f; - return NULL; - } - - saveFile = f; - } else { - // Open up savegame for access via savefile manager - saveFile = _vm->saveManager()->openForLoading(generateSaveName(slotNumber)); - } - if (!saveFile) - return NULL; - - dataOffset = saveFile->readUint32LE(); - assert(dataOffset < 0x100); - saveFile->seek(dataOffset, SEEK_CUR); - - // Read in the sprite data - - saveFile->seek(16, SEEK_CUR); - int width = saveFile->readUint32LE(); - int height = saveFile->readUint32LE(); - saveFile->seek(21, SEEK_CUR); - saveFile->readUint32LE(); // sprite data size - - M4Sprite *result = new M4Sprite(saveFile, 0, 0, width, height); - delete saveFile; - - return result; -} - -bool SaveLoad::load(int slotNumber) { - // TODO: Currently it's hardcoded to return a failure - return false; -} - -bool SaveLoad::save(int slotNumber, Common::String saveName) { - // TODO: Currently it's hardcoded to return a failure - return false; -} - - -} // End of namespace M4 diff --git a/engines/m4/saveload.h b/engines/m4/saveload.h deleted file mode 100644 index 9b76054e65..0000000000 --- a/engines/m4/saveload.h +++ /dev/null @@ -1,54 +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. - * - */ - -#ifndef M4_SAVELOAD_H -#define M4_SAVELOAD_H - -#include "m4/graphics.h" -#include "common/ptr.h" - -#define MAX_SAVEGAME_NAME 80 - -namespace M4 { - -typedef Common::List SaveGameList; -typedef SaveGameList::iterator SaveGameIterator; - -class SaveLoad { -private: - MadsM4Engine *_vm; - bool _emulateOriginal; - - const char *generateSaveName(int slotNumber); -public: - SaveLoad(MadsM4Engine *vm); - - bool hasSaves(); - SaveGameList *getSaves(); - M4Surface *getThumbnail(int slotNumber); - bool load(int slotNumber); - bool save(int slotNumber, Common::String saveName); -}; - -} - -#endif diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp deleted file mode 100644 index be49dcb13f..0000000000 --- a/engines/m4/scene.cpp +++ /dev/null @@ -1,208 +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 "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" - -namespace M4 { - -Scene::Scene(MadsM4Engine *vm, SceneResources *res): View(vm, Common::Rect(0, 0, vm->_screen->width(), - vm->_screen->height())), _sceneResources(res) { - _screenType = VIEWID_SCENE; - - _sceneResources->hotspots = new HotSpotList(); - _sceneResources->dynamicHotspots = new HotSpotList(); - _backgroundSurface = new M4Surface(); - _walkSurface = new M4Surface(); - _palData = NULL; - _interfacePal = NULL; - _interfaceSurface = NULL; - _vm->_rails->setCodeSurface(_walkSurface); - _currentScene = -1; -} - -Scene::~Scene() { - leaveScene(); - _vm->_scene = NULL; -} - -void Scene::loadScene(int sceneNumber) { - _previousScene = _currentScene; - _currentScene = sceneNumber; - _nextScene = sceneNumber; -} - -void Scene::leaveScene() { - if (_palData) { - _vm->_palette->deleteRange(_palData); - delete _palData; - _palData = NULL; - } - if (_interfacePal) { - _vm->_palette->deleteRange(_interfacePal); - delete _interfacePal; - _interfacePal = NULL; - } -} - -void Scene::show() { - _vm->_viewManager->addView(this); -} - -void Scene::showInterface() { - _vm->_viewManager->addView(_interfaceSurface); -} - -void Scene::hideInterface() { - _vm->_viewManager->deleteView(_interfaceSurface); -} - -void Scene::showSprites() { - // TODO: This is all experimental code, it needs heavy restructuring - // and cleanup - - // taken from set_walker_scaling() in adv_walk.cpp. A proper implementation will need - // to store these in global variables - int minScaling = FixedDiv(_sceneResources->backScale << 16, 100 << 16); - int maxScaling = FixedDiv(_sceneResources->frontScale << 16, 100 << 16); - int scaler; - - _vm->_actor->setWalkerDirection(kFacingSouthEast); - //_vm->_actor->setWalkerPalette(); - - // taken from set_walker_scaling() in adv_walk.cpp - if (_sceneResources->frontY == _sceneResources->backY) - scaler = 0; - else - scaler = FixedDiv(maxScaling - minScaling, - (_sceneResources->frontY << 16) - (_sceneResources->backY << 16)); - - // FIXME: For now, we (incorrectly) scale the walker to 50% of the scene's max scaling - _vm->_actor->setWalkerScaling(scaler / 2); - // Test code to display the protagonist - _vm->_actor->placeWalkerSpriteAt(0, 320, 200); - - // Test code to display scene sprites - // TODO -} - -// Test function, shows all scene hotspots -void Scene::showHotSpots() { - int i = 0; - HotSpot *currentHotSpot; - - // hotspots (green) - for (i = 0; i < _sceneResources->hotspots->size(); i++) { - currentHotSpot = _sceneResources->hotspots->get(i); - _backgroundSurface->frameRect(currentHotSpot->getRect(), _vm->_palette->GREEN); - } - - // Dynamic hotspots (red) - for (i = 0; i < _sceneResources->dynamicHotspots->size(); i++) { - currentHotSpot = _sceneResources->dynamicHotspots->get(i); - _backgroundSurface->frameRect(currentHotSpot->getRect(), _vm->_palette->RED); - } -} - -/** - * Debug function that shows the walkable areas by copying them over the current background surface - */ -void Scene::showCodes() { - if (_vm->isM4()) { - // Show the walk areas for the M4 engine in black and white - const byte *srcP = (const byte *)_walkSurface->getBasePtr(0, 0); - byte *destP = _backgroundSurface->getBasePtr(0, 0); - - for (int i = 0; i < _walkSurface->width() * _walkSurface->height(); i++) - destP[i] = (srcP[i] & 0x10) ? 0xFF : 0; - - byte colors[256 * 3]; - memset(colors, 0, sizeof(colors)); - colors[255 * 3 + 0] = 255; - colors[255 * 3 + 1] = 255; - colors[255 * 3 + 2] = 255; - _vm->_palette->setPalette(colors, 0, 256); - } else { - // MADS handling - - // copy the walk data to the background, in whatever current palette is active - _walkSurface->copyTo(_backgroundSurface); - - // Show all the scene's walk nodes - SceneNodeList &nodeList = _madsVm->scene()->getSceneResources()._nodes; - _backgroundSurface->setColor(_madsVm->_palette->WHITE); - for (uint i = 0; i < nodeList.size() - 2; ++i) { - // Draw a little cross at the node's position - _backgroundSurface->hLine(nodeList[i].pt.x - 2, nodeList[i].pt.x + 2, nodeList[i].pt.y); - _backgroundSurface->vLine(nodeList[i].pt.x, nodeList[i].pt.y - 2, nodeList[i].pt.y + 2); - } - - ((MadsScene *)this)->_spriteSlots.fullRefresh(); - } -} - -void Scene::playIntro() { - -} - -void Scene::onRefresh(RectList *rects, M4Surface *destSurface) { - update(); - View::onRefresh(rects, destSurface); -} - -bool Scene::onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents) { - //if (_vm->getGameType() != GType_Burger) - // return false; - - // If the game is currently paused, don't do any scene processing - if (_vm->_kernel->paused) - return false; - - switch (eventType) { - case MEVENT_LEFT_CLICK: - leftClick(x, y); - break; - case MEVENT_RIGHT_CLICK: - rightClick(x, y); - break; - case MEVENT_MOVE: - mouseMove(x, y); - break; - default: - return false; - } - - return true; -} - -} // End of namespace M4 diff --git a/engines/m4/scene.h b/engines/m4/scene.h deleted file mode 100644 index 5086cc0db0..0000000000 --- a/engines/m4/scene.h +++ /dev/null @@ -1,120 +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. - * - */ - -#ifndef M4_SCENE_H -#define M4_SCENE_H - -class View; - -#include "m4/assets.h" -#include "m4/font.h" -#include "m4/hotspot.h" -#include "m4/graphics.h" -#include "m4/viewmgr.h" -#include "m4/gui.h" -#include "m4/m4_views.h" -#include "common/array.h" - -namespace M4 { - -#define MAX_CHK_FILENAME_SIZE 144 - -enum MADSVerbs { - kVerbNone = 0, - kVerbLook = 3, - kVerbTake = 4, - kVerbPush = 5, - kVerbOpen = 6, - kVerbPut = 7, - kVerbTalkTo = 8, - kVerbGive = 9, - kVerbPull = 10, - kVerbClose = 11, - kVerbThrow = 12, - kVerbWalkTo = 13, - kVerbLookAt = 209 -}; - -class SceneResources { -public: - char artBase[MAX_CHK_FILENAME_SIZE]; - char pictureBase[MAX_CHK_FILENAME_SIZE]; - HotSpotList *hotspots; - HotSpotList *dynamicHotspots; - int32 frontY, backY; - int32 frontScale, backScale; - int16 depthTable[16]; - int32 railNodeCount; // # of rails -}; - -class M4Engine; -class MadsEngine; -class InterfaceView; - -class Scene : public View { -private: - HotSpotList _sceneHotspots; -protected: - GameInterfaceView *_interfaceSurface; - M4Surface *_backgroundSurface; - M4Surface *_walkSurface; - RGBList *_palData; - RGBList *_interfacePal; - SceneResources *_sceneResources; -public: - int _currentScene; - int _previousScene; - int _nextScene; -public: - Scene(MadsM4Engine *vm, SceneResources *res); - virtual ~Scene(); - - // Methods that differ between engines - virtual void loadScene(int sceneNumber); - virtual void leaveScene(); - virtual void loadSceneCodes(int sceneNumber, int index = 0) = 0; - virtual void show(); - virtual void mouseMove(int x, int y) = 0; - virtual void leftClick(int x, int y) = 0; - virtual void rightClick(int x, int y) = 0; - virtual void update() = 0; - virtual void showHotSpots(); - - // TODO: perhaps move playIntro() someplace else? - void playIntro(); - void showSprites(); - void showCodes(); - int getCurrentScene() { return _currentScene; } - M4Surface *getBackgroundSurface() const { return _backgroundSurface; } - void showInterface(); - void hideInterface(); - GameInterfaceView *getInterface() { return _interfaceSurface; } - SceneResources &getSceneResources() { return *_sceneResources; } - M4Surface *getWalkSurface() const { return _walkSurface; } - - void onRefresh(RectList *rects, M4Surface *destSurface); - bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents); -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/script.cpp b/engines/m4/script.cpp deleted file mode 100644 index 026c025f45..0000000000 --- a/engines/m4/script.cpp +++ /dev/null @@ -1,1389 +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/m4.h" -#include "m4/script.h" -#include "m4/resource.h" - -namespace M4 { - -enum OpcodeType { - opRet = 0, - opCall, - opCallKernel, - opPush, - opPush0, - opPush1, - opPushNeg1, - opPop, - opMov, - opAdd, - opSub, - opInc, - opDec, - opCmp, - opJmp, - opJmpByTable, - opJz, - opJnz, - opJe, - opJne, - opJl, - opJle, - opJg, - opJge, - opXor, - opShl, - opShr, - - opDebug, - - opInvalid -}; - -const char *opcodeNames[] = { - "opRet", - "opCall", - "opCallKernel", - "opPush", - "opPush0", - "opPush1", - "opPushNeg1", - "opPop", - "opMov", - "opAdd", - "opSub", - "opInc", - "opDec", - "opCmp", - "opJmp", - "opJmpByTable", - "opJz", - "opJnz", - "opJe", - "opJne", - "opJl", - "opJle", - "opJg", - "opJge", - "opXor", - "opShl", - "opShr", - "opDebug", - "opInvalid" -}; - -StringTable::StringTable() : _stringsData(NULL) { -} - -StringTable::~StringTable() { - delete[] _stringsData; -} - -void StringTable::load(Common::File *fd) { - int stringSize = fd->readUint32LE(); - int stringCount = fd->readUint32LE(); - _stringsData = new char[stringSize]; - fd->read(_stringsData, stringSize); - char *stringPtr = _stringsData; - for (int i = 0; i < stringCount; i++) { - _strings.push_back((const char*)stringPtr); - stringPtr += strlen(stringPtr) + 1; - } -} - -SeriesStreamBreakList::~SeriesStreamBreakList() { -} - -void SeriesStreamBreakList::load(Common::File *fd) { - uint32 count = fd->readUint32LE(); - debugCN(kDebugScript, "SeriesStreamBreakList::load() count = %d\n", count); - for (uint32 i = 0; i < count; i++) { - SeriesStreamBreakItem *item = new SeriesStreamBreakItem(); - item->frameNum = fd->readUint32LE(); - item->digiName = _inter->loadGlobalString(fd); - item->digiChannel = fd->readUint32LE(); - item->digiVolume = fd->readUint32LE(); - item->trigger = fd->readUint32LE(); - item->flags = fd->readUint32LE(); - item->variable.type = kGameVar; - item->variable.value = fd->readUint32LE(); - item->value = fd->readUint32LE(); - _items.push_back(item); - - debugCN(kDebugScript, "%02d: frameNum = %d; digiName = %s; digiChannel = %d; digiVolume = %d; trigger = %d; flags = %d; variable = %d; value = %d\n", - i, item->frameNum, item->digiName, item->digiChannel, item->digiVolume, item->trigger, item->flags, item->variable.value, item->value); - - } -} - -SaidArray::~SaidArray() { -} - -void SaidArray::load(Common::File *fd) { - uint32 count = fd->readUint32LE(); - debugCN(kDebugScript, "SaidArray::load() count = %d\n", count); - for (uint32 i = 0; i < count; i++) { - SaidArrayItem *item = new SaidArrayItem(); - item->itemName = _inter->loadGlobalString(fd); - item->digiNameLook = _inter->loadGlobalString(fd); - item->digiNameTake = _inter->loadGlobalString(fd); - item->digiNameGear = _inter->loadGlobalString(fd); - _items.push_back(item); - - debugCN(kDebugScript, "itemName = %s; digiNameLook = %s; digiNameTake = %s; digiNameGear = %s\n", - item->itemName, item->digiNameLook, item->digiNameTake, item->digiNameGear); - - } -} - -ParserArray::~ParserArray() { -} - -void ParserArray::load(Common::File *fd) { - uint32 count = fd->readUint32LE(); - debugCN(kDebugScript, "ParserArray::load() count = %d\n", count); - for (uint32 i = 0; i < count; i++) { - ParserArrayItem *item = new ParserArrayItem(); - item->w0 = _inter->loadGlobalString(fd); - item->w1 = _inter->loadGlobalString(fd); - item->trigger = fd->readUint32LE(); - item->testVariable.type = kGameVar; - item->testVariable.value = fd->readUint32LE(); - item->testValue = fd->readUint32LE(); - item->variable.type = kGameVar; - item->variable.value = fd->readUint32LE(); - item->value = fd->readUint32LE(); - _items.push_back(item); - - debugCN(kDebugScript, "w0 = %s; w1 = %s; trigger = %d; testVariable = %d; testValue = %d; variable = %d; value = %d\n", - item->w0, item->w1, item->trigger, item->testVariable.value, item->testValue, item->variable.value, item->value); - - } -} - -ScriptFunction::ScriptFunction(ScriptInterpreter *inter) : _inter(inter) { -} - -ScriptFunction::~ScriptFunction() { - delete _code; -} - -void ScriptFunction::load(Common::File *fd) { - debugCN(kDebugScript, "ScriptFunction::load()\n"); - uint32 size = fd->readUint32LE(); - debugCN(kDebugScript, "ScriptFunction::load() size = %d\n", size); - _code = fd->readStream(size); -} - -void ScriptFunction::jumpAbsolute(uint32 ofs) { - _code->seek(ofs); -} - -void ScriptFunction::jumpRelative(int32 ofs) { - _code->seek(ofs, SEEK_CUR); -} - -byte ScriptFunction::readByte() { - return _code->readByte(); -} - -uint32 ScriptFunction::readUint32() { - return _code->readUint32LE(); -} - - -ScriptInterpreter::ScriptInterpreter(MadsM4Engine *vm) : _scriptFile(NULL), _vm(vm) { - initScriptKernel(); - _dataCache = new ScriptDataCache(this); - _runningFunction = NULL; -} - -ScriptInterpreter::~ScriptInterpreter() { - close(); - delete _dataCache; -} - -void ScriptInterpreter::open(const char *filename) { - if (_scriptFile) - close(); - _scriptFile = new Common::File(); - _scriptFile->open(filename); - if (!_scriptFile->isOpen()) - error("ScriptInterpreter::open() Error opening %s", filename); - - _scriptFile->readUint32LE(); // skip magic for now - uint32 version = _scriptFile->readUint32LE(); - if (version != kScriptFileVersion) { - error("ScriptInterpreter::open() DAT file version mismatch; requested %li, got %i", kScriptFileVersion, version); - } - - int functionCount = _scriptFile->readUint32LE(); - debugCN(kDebugScript, "functionCount = %d\n", functionCount); - for (int i = 0; i < functionCount; i++) { - uint32 offset = _scriptFile->readUint32LE(); - debugCN(kDebugScript, "func(%d) offset = %08X\n", i, offset); - uint32 len = _scriptFile->readUint32LE(); - if (len > 0) { - char *funcName = new char[len + 1]; - _scriptFile->read(funcName, len); - funcName[len] = '\0'; - debugCN(kDebugScript, "func(%d) name = %s\n", i, funcName); - _functionNames[Common::String(funcName)] = _functions.size(); - // DEBUG - _scriptFunctionNames.push_back(Common::String(funcName)); - delete[] funcName; - } - _functions.push_back(new ScriptFunctionEntry(offset)); - } - - int dataCount = _scriptFile->readUint32LE(); - debugCN(kDebugScript, "dataCount = %d\n", dataCount); - for (int i = 0; i < dataCount; i++) { - uint32 offset = _scriptFile->readUint32LE(); - ScriptDataType type = (ScriptDataType)_scriptFile->readUint32LE(); - debugCN(kDebugScript, "data(%d) offset = %08X; type = %d\n", i, offset, type); - _data.push_back(new ScriptDataEntry(offset, type)); - } - - _globalVarCount = _scriptFile->readUint32LE(); - debugCN(kDebugScript, "_globalVarCount = %d\n", _globalVarCount); - - uint32 stringOfs = _scriptFile->readUint32LE(); - _scriptFile->seek(stringOfs); - _constStrings.load(_scriptFile); - - for (int i = 0; i < ARRAYSIZE(_globalVars); i++) { - _globalVars[i].type = kInteger; - _globalVars[i].value = 0; - } - - memset(_logicGlobals, 0, sizeof(_logicGlobals)); - - memset(_registers, 0, sizeof(_registers)); - memset(_stack, 0, sizeof(_stack)); - _stackPtr = 0; - -} - -void ScriptInterpreter::close() { - delete _scriptFile; -} - -void ScriptInterpreter::initScriptKernel() { - -#include "m4/scripttab.h" - - _kernelFunctions = kernelFunctions; - _kernelFunctionsMax = ARRAYSIZE(kernelFunctions) + 1; - - _kernelVars = kernelVars; - _kernelVarsMax = ARRAYSIZE(kernelVars) + 1; - -} - - -ScriptFunction *ScriptInterpreter::loadFunction(uint32 index) { - //GONE WHILE DEBUGGING assert(index < _functions.size()); - if (index >= _functions.size()) return NULL; - ScriptFunction *scriptFunction; - scriptFunction = _functions[index]->func; - if (!scriptFunction) { - scriptFunction = new ScriptFunction(this); - _scriptFile->seek(_functions[index]->offset); - scriptFunction->load(_scriptFile); - _functions[index]->func = scriptFunction; - } - return scriptFunction; -} - -ScriptFunction *ScriptInterpreter::loadFunction(const Common::String &name) { - FunctionNameMap::iterator iter = _functionNames.find(name); - if (iter == _functionNames.end()) { - debugCN(kDebugScript, "ScriptInterpreter::loadFunction() Function '%s' not found!\n", name.c_str()); - return NULL; - } - uint32 funcIndex = (*iter)._value; - debugCN(kDebugScript, "ScriptInterpreter::loadFunction() index('%s') = %d\n", name.c_str(), funcIndex); - return loadFunction(funcIndex); -} - -void ScriptInterpreter::unloadFunctions() { - for (uint32 i = 0; i < _functions.size(); i++) { - if (_functions[i]->func) { - delete _functions[i]->func; - _functions[i]->func = NULL; - } - } -} - -int ScriptInterpreter::runFunction(ScriptFunction *scriptFunction) { - bool done = false; - - int oldLocalStackPtr = _localStackPtr; - ScriptFunction *oldRunningFunction = _runningFunction; - - // TODO: Also initialize _localStackPtr - - _runningFunction = scriptFunction; - _runningFunction->jumpAbsolute(0); - while (!done) { - byte opcode = _runningFunction->readByte(); - done = !execOpcode(opcode); - } - - _localStackPtr = oldLocalStackPtr; - _runningFunction = oldRunningFunction; - - return 0; -} - -void ScriptInterpreter::push(const ScriptValue &value) { - if (_stackPtr == ARRAYSIZE(_stack)) - error("ScriptInterpreter::push() Stack overflow"); - _stack[_stackPtr++] = value; -} - -void ScriptInterpreter::pop(ScriptValue &value) { - if (_stackPtr == 0) - error("ScriptInterpreter::pop() Stack underflow"); - value = _stack[_stackPtr--]; -} - -void ScriptInterpreter::dumpStack() { - debugCN(kDebugScript, "ScriptInterpreter::dumpStack()\n"); - for (int i = 0; i < _stackPtr; i++) { - debugCN(kDebugScript, "%03d. type = %02d; value = %d\n", i, _stack[i].type, _stack[i].value); - } -} - -void ScriptInterpreter::dumpRegisters() { - debugCN(kDebugScript, "ScriptInterpreter::dumpRegisters()\n"); - for (int i = 0; i < ARRAYSIZE(_registers); i++) { - debugCN(kDebugScript, "%03d. type = %02d; value = %d\n", i, _registers[i].type, _registers[i].value); - } -} - -void ScriptInterpreter::dumpGlobalVars() { - debugCN(kDebugScript, "ScriptInterpreter::dumpGlobalVars()\n"); - for (int i = 0; i < ARRAYSIZE(_globalVars); i++) { - if (_globalVars[i].type != -1) - debugCN(kDebugScript, "%03d. type = %02d; value = %d\n", i, _globalVars[i].type, _globalVars[i].value); - } -} - -int ScriptInterpreter::toInteger(const ScriptValue &value) { - - switch (value.type) { - - case kInteger: - return value.value; - - default: - debugCN(kDebugScript, "ScriptInterpreter::toInteger() Invalid type %d!\n", value.type); - return 0; - - } - -} - -const char *ScriptInterpreter::toString(const ScriptValue &value) { - - switch (value.type) { - - case kInteger: - return NULL; - - case kConstString: - return _constStrings[value.value]; - - default: - debugCN(kDebugScript, "ScriptInterpreter::toString() Invalid type %d!\n", value.type); - return NULL; - - } - -} - -const char *ScriptInterpreter::loadGlobalString(Common::File *fd) { - uint32 index = fd->readUint32LE(); - if (index != 0xFFFFFFFF) - return getGlobalString(index); - else - return NULL; -} - -void ScriptInterpreter::test() { -} - -void ScriptInterpreter::loadValue(ScriptValue &value) { - - value.type = (ScriptValueType)_runningFunction->readByte(); - - switch (value.type) { - - case kGameVar: - case kInteger: - case kConstString: - case kDataRef: - case kLogicVar: - case kLogicVarRef: - case kKernelVar: - value.value = _runningFunction->readUint32(); - break; - - case kRegister: - value.value = _runningFunction->readByte(); - break; - - default: - debugCN(kDebugScript, "ScriptInterpreter::loadValue() Invalid value type %d!\n", value.type); - - } - -} - -void ScriptInterpreter::copyValue(ScriptValue &destValue, ScriptValue &sourceValue) { - - if (sourceValue.type == -1) { - debugCN(kDebugScript, "ScriptInterpreter::copyValue() Trying to read uninitialized value!\n"); - } - - switch (destValue.type) { - - case kGameVar: - _globalVars[destValue.value] = sourceValue; - break; - - case kRegister: - _registers[destValue.value] = sourceValue; - break; - - case kLogicVar: - // TODO: Move to own method - if (sourceValue.type == kInteger) { - _logicGlobals[destValue.value] = sourceValue.value; - } else { - debugCN(kDebugScript, "ScriptInterpreter::copyValue() Invalid source value type %d!\n", sourceValue.type); - } - break; - - case kKernelVar: - setKernelVar(destValue.value, sourceValue); - break; - - default: - debugCN(kDebugScript, "ScriptInterpreter::copyValue() Invalid dest value type %d!\n", destValue.type); - - } - -} - -void ScriptInterpreter::derefValue(ScriptValue &value) { - - switch (value.type) { - - case kGameVar: - value = _globalVars[value.value]; - break; - - case kInteger: - case kConstString: - case kDataRef: - case kLogicVarRef: - // These need no dereferencing - break; - - case kRegister: - value = _registers[value.value]; - break; - - case kLogicVar: - // TODO: Move to own method - value = _logicGlobals[value.value]; - break; - - case kKernelVar: - getKernelVar(value.value, value); - break; - - default: - debugCN(kDebugScript, "ScriptInterpreter::derefValue() Invalid value type %d!\n", value.type); - - } - -} - -void ScriptInterpreter::callKernelFunction(uint32 index) { - - debugCN(kDebugScript, "ScriptInterpreter::callKernelFunction() index = %d\n", index); - - if (index > _kernelFunctionsMax) { - debugCN(kDebugScript, "ScriptInterpreter::callKernelFunction() Invalid kernel functionindex (%d)\n", index); - return; - } - - debugCN(kDebugScript, "ScriptInterpreter::callKernelFunction() name = %s\n", _kernelFunctions[index].desc); - - int args = (this->*(_kernelFunctions[index].proc))(); - // Now remove values from the stack if the function used any - if (args > 4) - _stackPtr -= args - 4; - - debugCN(kDebugScript, "-------------\n"); - -} - -ScriptValue ScriptInterpreter::getArg(uint32 index) { - if (index < 4) { - return _registers[index]; - } else { - index -= 4; - return _stack[_stackPtr - index - 1]; - } -} - -void ScriptInterpreter::dumpArgs(uint32 count) { - debugCN(kDebugScript, "ScriptInterpreter::dumpArgs() "); - for (uint32 i = 0; i < count; i++) { - ScriptValue argValue = getArg(i); - if (argValue.type == kConstString) { - debugCN(kDebugScript, "'%s'", toString(argValue)); - } else { - debugCN(kDebugScript, "%d", argValue.value); - } - if (i + 1 < count) - debugCN(kDebugScript, ", "); - } - debugCN(kDebugScript, "\n"); -} - -void ScriptInterpreter::callFunction(uint32 index) { - // NOTE: This is a temporary hack for script functions not yet in the m4.dat - if (index == 0xFFFFFFFF) - return; - debugCN(kDebugScript, "ScriptInterpreter::callFunction() index = %d [%s]\n", index, _scriptFunctionNames[index].c_str()); - ScriptFunction *subFunction = loadFunction(index); - if (!subFunction) { - // This *should* never happen since the linker checks this - debugCN(kDebugScript, "ScriptInterpreter::callFunction() Function %d could not be loaded!\n", index); - return; - } - runFunction(subFunction); -} - -bool ScriptInterpreter::execOpcode(byte opcode) { - - debugCN(kDebugScript, "opcode = %d (%s)\n", opcode, opcodeNames[opcode]); - - ScriptValue value1, value2, value3; - uint32 temp; - - /* TODO: Put all opcodes into separate functions and into an array - (but only after all needed opcodes are known and frozen) - */ - - switch (opcode) { - - case opRet: - return false; - - case opPush: - loadValue(value1); - derefValue(value1); - push(value1); - return true; - - case opPush0: - push(ScriptValue(0)); - return true; - - case opPush1: - push(ScriptValue(1)); - return true; - - case opPushNeg1: - push(ScriptValue(-1)); - return true; - - case opPop: - loadValue(value1); - pop(value2); - copyValue(value1, value2); - return true; - - case opMov: - loadValue(value1); - loadValue(value2); - derefValue(value2); - copyValue(value1, value2); - return true; - - // Possibly join all jump variants into one opcode - - case opJmp: - temp = _runningFunction->readUint32(); - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - return true; - - case opJl: - temp = _runningFunction->readUint32(); - if (_cmpFlags < 0) { - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - } - return true; - - case opJle: - temp = _runningFunction->readUint32(); - if (_cmpFlags <= 0) { - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - } - return true; - - case opJg: - temp = _runningFunction->readUint32(); - if (_cmpFlags > 0) { - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - } - return true; - - case opJge: - temp = _runningFunction->readUint32(); - if (_cmpFlags >= 0) { - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - } - return true; - - case opJz: - temp = _runningFunction->readUint32(); - if (_cmpFlags == 0) { - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - } - return true; - - case opJnz: - temp = _runningFunction->readUint32(); - if (_cmpFlags != 0) { - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - } - return true; - - case opJmpByTable: - temp = _runningFunction->readUint32(); - debugCN(kDebugScript, "-> index = %d\n", _registers[0].value); - _runningFunction->jumpRelative(_registers[0].value * 4); - temp = _runningFunction->readUint32(); - debugCN(kDebugScript, "-> ofs = %08X\n", temp); - _runningFunction->jumpAbsolute(temp); - return true; - - case opCmp: - loadValue(value1); - loadValue(value2); - derefValue(value1); - derefValue(value2); - if (value1.type != kInteger || value2.type != kInteger) - warning("ScriptInterpreter::execOpcode() Trying to compare non-integer values (%d, %d, line %d)", value1.type, value2.type, _lineNum); - _cmpFlags = value1.value - value2.value; - debugCN(kDebugScript, "-> cmp %d, %d\n", value1.value, value2.value); - debugCN(kDebugScript, "-> _cmpFlags = %d\n", _cmpFlags); - return true; - - case opCall: - temp = _runningFunction->readUint32(); - callFunction(temp); - return true; - - case opCallKernel: - temp = _runningFunction->readUint32(); - callKernelFunction(temp); - return true; - - case opInc: - loadValue(value1); - value2 = value1; - derefValue(value2); - value2.value++; - copyValue(value1, value2); - return true; - - case opDec: - loadValue(value1); - value2 = value1; - derefValue(value2); - value2.value--; - copyValue(value1, value2); - return true; - - case opAdd: - loadValue(value1); - value3 = value1; - loadValue(value2); - derefValue(value3); - derefValue(value2); - value3.value += value2.value; - copyValue(value1, value3); - return true; - - case opSub: - loadValue(value1); - value3 = value1; - loadValue(value2); - derefValue(value3); - derefValue(value2); - value3.value -= value2.value; - copyValue(value1, value3); - return true; - - case opDebug: - _lineNum = (int)_runningFunction->readUint32(); - return true; - - default: - debugCN(kDebugScript, "Invalid opcode %d!\n", opcode); - return false; - - } - -} - -// Kernel functions - -#define STRING(arg) (toString(getArg(arg))) -#define INTEGER(arg) (toInteger(getArg(arg))) -#define DATA(arg, T) (toData(getArg(arg))) -#define RETURN(value) (_registers[0] = (value)) - -int ScriptInterpreter::o1_handleStreamBreak() { - return 0; -} - -int ScriptInterpreter::o1_handlePlayBreak() { - return 0; -} - -int ScriptInterpreter::o1_dispatchTriggerOnSoundState() { - return 0; -} - -int ScriptInterpreter::o1_getTicks() { - return 0; -} - -int ScriptInterpreter::o1_setSoundVolume() { - return 0; -} - -int ScriptInterpreter::o1_getSoundStatus() { - return 0; -} - -int ScriptInterpreter::o1_getSoundDuration() { - return 0; -} - -int ScriptInterpreter::o1_setSeriesFrameRate() { - return 0; -} - -int ScriptInterpreter::o1_terminateMachine() { - return 0; -} - -int ScriptInterpreter::o1_sendWoodScriptMessage() { - return 0; -} - -int ScriptInterpreter::o1_runConversation() { - return 0; -} - -int ScriptInterpreter::o1_exportConversationValue() { - return 0; -} - -int ScriptInterpreter::o1_exportConversationPointer() { - return 0; -} - -int ScriptInterpreter::o1_playBreakSeries() { - return 0; -} - -int ScriptInterpreter::o1_hideWalker() { - return 0; -} - -int ScriptInterpreter::o1_showWalker() { - return 0; -} - -int ScriptInterpreter::o1_walk() { - return 0; -} - -int ScriptInterpreter::o1_overrideCrunchTime() { - return 0; -} - -int ScriptInterpreter::o1_addBlockingRect() { - return 0; -} - -int ScriptInterpreter::o1_setPlayerCommandsAllowed() { - return 0; -} - -int ScriptInterpreter::o1_getPlayerCommandsAllowed() { - return 0; -} - -int ScriptInterpreter::o1_setPlayerFacingAngle() { - return 0; -} - -int ScriptInterpreter::o1_disablePlayerFadeToBlack() { - return 0; -} - -int ScriptInterpreter::o1_enablePlayer() { - return 0; -} - -int ScriptInterpreter::o1_disablePlayer() { - return 0; -} - -int ScriptInterpreter::o1_freshenSentence() { - return 0; -} - -int ScriptInterpreter::o1_playerGiveItem() { - return 0; -} - -int ScriptInterpreter::o1_moveObject() { - return 0; -} - -int ScriptInterpreter::o1_setStopSoundsBetweenRooms() { - return 0; -} - -int ScriptInterpreter::o1_backupPalette() { - return 0; -} - -int ScriptInterpreter::o1_unloadWilburWalker() { - return 0; -} - -int ScriptInterpreter::o1_wilburTalk() { - return 0; -} - -int ScriptInterpreter::o1_wilburFinishedTalking() { - return 0; -} - -int ScriptInterpreter::o1_preloadSound() { - const char *name = STRING(0); - int room = INTEGER(1); - debugCN(kDebugScript, "name = %s; room = %d\n", name, room); - return 2; -} - -int ScriptInterpreter::o1_unloadSound() { - const char *name = STRING(0); - int room = INTEGER(1); - debugCN(kDebugScript, "name = %s; room = %d\n", name, room); - return 2; -} - -int ScriptInterpreter::o1_playSound() { - const char *name = STRING(0); - int channel = INTEGER(1); - int volume = INTEGER(2); - int trigger = INTEGER(3); - int room = INTEGER(4); - debugCN(kDebugScript, "name = %s; channel = %d; volume = %d; trigger = %d; room = %d\n", - name, channel, volume, trigger, room); - - Common::String soundName = Common::String(name) + ".raw"; - _vm->_sound->playVoice(soundName.c_str(), 100); - - // HACK until fixed - _vm->_kernel->sendTrigger(trigger); - - return 5; -} - -int ScriptInterpreter::o1_playLoopingSound() { - const char *name = STRING(0); - int channel = INTEGER(1); - int volume = INTEGER(2); - int trigger = INTEGER(3); - int room = INTEGER(4); - debugCN(kDebugScript, "name = %s; channel = %d; volume = %d; trigger = %d; room = %d\n", - name, channel, volume, trigger, room); - - // HACK until fixed - _vm->_kernel->sendTrigger(trigger); - - return 5; -} - -int ScriptInterpreter::o1_stopSound() { - int channel = INTEGER(0); - debugCN(kDebugScript, "channel = %d\n", channel); - return 1; -} - -int ScriptInterpreter::o1_fadeSetStart() { - // skip arg 0: palette ptr - int percent = INTEGER(1); - debugCN(kDebugScript, "percent = %d\n", percent); - return 2; -} - -int ScriptInterpreter::o1_fadeInit() { - // skip arg 0: palette ptr - int first = INTEGER(1); - int last = INTEGER(2); - int percent = INTEGER(3); - int ticks = INTEGER(4); - int trigger = INTEGER(5); - debugCN(kDebugScript, "first = %d; last = %d; percent = %d; ticks = %d; trigger = %d\n", - first, last, percent, ticks, trigger); - - // HACK until palette fading is implemented - _vm->_kernel->sendTrigger(trigger); - - return 6; -} - -int ScriptInterpreter::o1_fadeToBlack() { - return 0; -} - -int ScriptInterpreter::o1_initPaletteCycle() { - int first = INTEGER(0); - int last = INTEGER(1); - int delay = INTEGER(2); - int ticks = INTEGER(3); - int trigger = INTEGER(4); - debugCN(kDebugScript, "first = %d; last = %d; delay = %d; ticks = %d; trigger = %d\n", - first, last, delay, ticks, trigger); - - // HACK until palette cycling is implemented - _vm->_kernel->sendTrigger(trigger); - - return 5; -} - -int ScriptInterpreter::o1_stopPaletteCycle() { - return 0; -} - -int ScriptInterpreter::o1_hasPlayerSaid() { - const char *words[3]; - for (int i = 0; i < 3; i++) - words[i] = STRING(i); - debugCN(kDebugScript, "'%s', '%s', '%s'\n", words[0], words[1], words[2]); - - int result = _vm->_player->said(words[0], words[1], words[2]); - - debugCN(kDebugScript, " -> '%d'\n", result); - - RETURN(result); - return 3; -} - -int ScriptInterpreter::o1_hasPlayerSaidAny() { - const char *words[10]; - for (int i = 0; i < 10; i++) - words[i] = STRING(i); - - debugCN(kDebugScript, "'%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s'\n", - words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]); - - int result = _vm->_player->saidAny(words[0], words[1], words[2], words[3], words[4], words[5], words[6], words[7], words[8], words[9]); - debugCN(kDebugScript, " -> '%d'\n", result); - - RETURN(result); - return 10; -} - -int ScriptInterpreter::o1_updatePlayerInfo() { - // skip arg 0: player info struct - return 1; -} - -int ScriptInterpreter::o1_playerHotspotWalkOverride() { - int x1 = INTEGER(0); - int y1 = INTEGER(1); - int x2 = INTEGER(2); - int y2 = INTEGER(3); - debugCN(kDebugScript, "(%d, %d); (%d, %d)\n", x1, y1, x2, y2); - return 4; -} - -int ScriptInterpreter::o1_playerHasItem() { - const char *name = STRING(0); - debugCN(kDebugScript, "item = '%s'\n", name); - // TODO - RETURN(0); - return 1; -} - -int ScriptInterpreter::o1_setWalkerLocation() { - // skip arg 0: walker - int x = INTEGER(1); - int y = INTEGER(2); - debugCN(kDebugScript, "x = %d; y = %d\n", x, y); - return 3; -} - -int ScriptInterpreter::o1_setWalkerFacing() { - // skip arg 0: walker - int facing = INTEGER(1); - debugCN(kDebugScript, "facing = %d\n", facing); - return 2; -} - -int ScriptInterpreter::o1_setHotspot() { - // skip arg 0: hotspot list - const char *name = STRING(1); - int value = INTEGER(2); - debugCN(kDebugScript, "name = '%s' -> %d\n", name, value); - - _vm->_scene->getSceneResources().hotspots->setActive(name, (value != 0)); - - return 2; -} - -int ScriptInterpreter::o1_loadConversation() { - const char *name = STRING(0); - //int trigger = INTEGER(1); - //int flag = INTEGER(2); - - // TODO; just to show something - _m4Vm->_converse->startConversation(name); - - return 3; -} - -int ScriptInterpreter::o1_playSeries() { - const char *name = STRING(0); - int layer = INTEGER(1); - int flags = INTEGER(2); - int trigger = INTEGER(3); - int frameRate = INTEGER(4); - int loopCount = INTEGER(5); - int scale = INTEGER(6); - int x = INTEGER(7); - int y = INTEGER(8); - int firstFrame = INTEGER(9); - int lastFrame = INTEGER(10); - - debugCN(kDebugScript, "name = %s; layer = %04X; flags = %08X; trigger = %d; frameRate = %d; loopCount = %d; scale = %d; x = %d; y = %d: firstFrame = %d; lastFrame = %d\n", - name, layer, flags, trigger, frameRate, loopCount, scale, x, y, firstFrame, lastFrame); - - // TODO: Return the machine to the script - _vm->_ws->playSeries(name, layer, flags, trigger, frameRate, loopCount, scale, x, y, firstFrame, lastFrame); - - return 11; -} - -int ScriptInterpreter::o1_showSeries() { - const char *name = STRING(0); - int layer = INTEGER(1); - int flags = INTEGER(2); - int trigger = INTEGER(3); - int duration = INTEGER(4); - int frameIndex = INTEGER(5); - int scale = INTEGER(6); - int x = INTEGER(7); - int y = INTEGER(8); - - debugCN(kDebugScript, "name = %s; layer = %04X; flags = %08X; trigger = %d; duration = %d; frameIndex = %d; scale = %d; x = %d; y = %d\n", - name, layer, flags, trigger, duration, frameIndex, scale, x, y); - - // TODO: Return the machine to the script - _vm->_ws->showSeries(name, layer, flags, trigger, duration, frameIndex, scale, x, y); - - return 9; -} - -int ScriptInterpreter::o1_loadSeries() { - const char *name = STRING(0); - int hash = INTEGER(1); - // skip arg 3: palette ptr - - debugCN(kDebugScript, "name = %s; hash = %d\n", name, hash); - - int result = _vm->_ws->loadSeries(name, hash, NULL); - - RETURN(result); - return 3; -} - -int ScriptInterpreter::o1_unloadSeries() { - return 0; -} - -int ScriptInterpreter::o1_preloadBreakSeries() { - //const SeriesStreamBreakList& seriesStreamBreakList = DATA(0, SeriesStreamBreakList); - return 1; -} - -int ScriptInterpreter::o1_unloadBreakSeries() { - //const SeriesStreamBreakList& seriesStreamBreakList = DATA(0, SeriesStreamBreakList); - return 1; -} - -int ScriptInterpreter::o1_startBreakSeries() { - //const SeriesStreamBreakList& seriesStreamBreakList = DATA(0, SeriesStreamBreakList); - return 1; -} - -int ScriptInterpreter::o1_globalTriggerProc() { - int value1 = INTEGER(0); - int value2 = INTEGER(1); - int value3 = INTEGER(2); - debugCN(kDebugScript, "%d; %d; %d\n", value1, value2, value3); - return 3; -} - -int ScriptInterpreter::o1_triggerTimerProc() { - int value1 = INTEGER(0); - int value2 = INTEGER(1); - int value3 = INTEGER(2); - debugCN(kDebugScript, "%d; %d; %d\n", value1, value2, value3); - return 3; -} - -int ScriptInterpreter::o1_dispatchTrigger() { - int trigger = INTEGER(0); - debugCN(kDebugScript, "trigger = %d\n", trigger); - - _vm->_kernel->sendTrigger(trigger); - //g_system->delayMillis(5000); - - return 1; -} - -int ScriptInterpreter::o1_getRangedRandomValue() { - int minValue = INTEGER(0); - int maxValue = INTEGER(1); - RETURN(_vm->imath_ranged_rand(minValue, maxValue)); - return 2; -} - -int ScriptInterpreter::o1_wilburSaid() { - const SaidArray& saidArray = DATA(0, SaidArray); - - int result = 0; - - // NOTE: The "Common::String soundName" stuff is just temporary until playVoice is fixed. - - for (int i = 0; i < saidArray.size(); i++) { - SaidArrayItem *item = saidArray[i]; - - if (_vm->_player->said("LOOK AT", item->itemName) && item->digiNameLook) { - debugCN(kDebugScript, " -> LOOK AT: '%s'\n", item->digiNameLook); - Common::String soundName = Common::String(item->digiNameLook) + ".raw"; - _vm->_sound->playVoice(soundName.c_str(), 100); - result = 1; - break; - } - - if (_vm->_player->said("TAKE", item->itemName) && item->digiNameTake) { - debugCN(kDebugScript, " -> TAKE: '%s'\n", item->digiNameTake); - Common::String soundName = Common::String(item->digiNameTake) + ".raw"; - _vm->_sound->playVoice(soundName.c_str(), 100); - result = 1; - break; - } - - if (_vm->_player->said("GEAR", item->itemName) && item->digiNameGear) { - debugCN(kDebugScript, " -> GEAR: '%s'\n", item->digiNameGear); - Common::String soundName = Common::String(item->digiNameGear) + ".raw"; - _vm->_sound->playVoice(soundName.c_str(), 100); - result = 1; - break; - } - - /* - debugCN(kDebugScript, "##### itemName = '%s'; digiNameLook = %s; digiNameTake = %s; digiNameGear = %s\n", - item->itemName, item->digiNameLook, item->digiNameTake, item->digiNameGear); - */ - } - debugCN(kDebugScript, " -> '%d'\n", result); - - RETURN(result); - return 1; -} - -int ScriptInterpreter::o1_wilburParse() { - //const ParserArray& parserArray = DATA(0, ParserArray); - RETURN(0); - return 1; -} - -int ScriptInterpreter::o1_wilburSpeech() { - const char *name = STRING(0); - int trigger = INTEGER(1); - int room = INTEGER(2); - int flag = INTEGER(3); - int volume = INTEGER(4); - int slot = INTEGER(5); - - debugCN(kDebugScript, "%s; %d; %d; %d; %d; %d\n", name, trigger, room, flag, volume, slot); - //g_system->delayMillis(5000); - - KernelTriggerType oldTriggerMode = _vm->_kernel->triggerMode; - - // TODO - Common::String soundName = Common::String(name) + ".raw"; - _vm->_sound->playVoice(soundName.c_str(), 100); - - _vm->_kernel->triggerMode = oldTriggerMode; - - return 6; -} - -// Kernel vars - -void ScriptInterpreter::getKernelVar(int index, ScriptValue &value) { - - debugCN(kDebugScript, "ScriptInterpreter::getKernelVar() index = %d\n", index); - - if (index > _kernelVarsMax) { - debugCN(kDebugScript, "ScriptInterpreter::getKernelVar() Invalid kernel var index %d!\n", index); - return; - } - - debugCN(kDebugScript, "ScriptInterpreter::getKernelVar() name = %s\n", _kernelVars[index].desc); - - ScriptKernelVariable var = _kernelVars[index].var; - - switch (var) { - - case kKernelTrigger: - value = _vm->_kernel->trigger; - break; - - case kKernelTriggerMode: - value = (int)_vm->_kernel->triggerMode; - break; - - case kKernelContinueHandlingTrigger: - value = (int)_vm->_kernel->daemonTriggerAvailable; - break; - - case kGameVersion: - // TODO - value = 0; - break; - - case kGameLanguage: - // TODO - value = 0; - break; - - case kGameNewRoom: - // TODO - value = 0; - break; - - case kPlayerCommandReady: - value = (int)_vm->_player->commandReady; - break; - - default: - debugCN(kDebugScript, "ScriptInterpreter::getKernelVar() Invalid kernel var %d!\n", var); - //g_system->delayMillis(2000); - - } - -} - -void ScriptInterpreter::setKernelVar(int index, const ScriptValue &value) { - - debugCN(kDebugScript, "ScriptInterpreter::setKernelVar() index = %d\n", index); - - if (index > _kernelVarsMax) { - debugCN(kDebugScript, "ScriptInterpreter::setKernelVar() Invalid kernel var index %d!\n", index); - return; - } - - debugCN(kDebugScript, "ScriptInterpreter::setKernelVar() name = %s\n", _kernelVars[index].desc); - - ScriptKernelVariable var = _kernelVars[index].var; - - switch (var) { - - case kKernelTrigger: - _vm->_kernel->trigger = toInteger(value); - debugCN(kDebugScript, "kKernelTrigger -> %d\n", toInteger(value)); - break; - - case kKernelTriggerMode: - _vm->_kernel->triggerMode = (KernelTriggerType)toInteger(value); - debugCN(kDebugScript, "kKernelTrigger -> %d\n", toInteger(value)); - break; - - case kKernelContinueHandlingTrigger: - _vm->_kernel->daemonTriggerAvailable = (toInteger(value) != 0); - debugCN(kDebugScript, "kKernelContinueHandlingTrigger -> %d\n", toInteger(value)); - break; - - case kGameNewRoom: - _vm->_kernel->newRoom = toInteger(value); - debugCN(kDebugScript, "kGameNewRoom -> %d\n", toInteger(value)); - break; - - case kPlayerCommandReady: - // TODO - debugCN(kDebugScript, "kPlayerCommandReady -> %d\n", toInteger(value)); - break; - - default: - debugCN(kDebugScript, "ScriptInterpreter::setKernelVar() Invalid kernel var %d!\n", var); - //g_system->delayMillis(2000); - - } - -} - -} // End of namespace M4 diff --git a/engines/m4/script.h b/engines/m4/script.h deleted file mode 100644 index 22f07fd062..0000000000 --- a/engines/m4/script.h +++ /dev/null @@ -1,463 +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. - * - */ - -#ifndef M4_SCRIPT_H -#define M4_SCRIPT_H - -#include "common/file.h" -#include "common/stream.h" -#include "common/hashmap.h" -#include "common/str.h" -#include "common/stack.h" - -#include "m4/woodscript.h" - -namespace M4 { - -const unsigned long kScriptFileMagic = 0x5845344D; -const unsigned long kScriptFileVersion = 1; - -enum ScriptValueType { - kInteger, - kConstString, - kLogicVar, - kLogicVarRef, - kGameVar, - kKernelVar, - kDataRef, - kRegister, - kStackVar -}; - -enum ScriptDataType { - kStreamBreakSeries, - kStreamPlaySeries, - kSaidArray, - kParserArray, - kSpeechArray, - kCreditsArray, - kInvObj, - kMineRoom, - kButtonItem -}; - -class ScriptInterpreter; - -class StringTable { -public: - StringTable(); - ~StringTable(); - void load(Common::File *fd); - int size() { return _strings.size(); } - const char *operator[](uint32 index) const { - assert(index < _strings.size() ); - return _strings[index]; - } -protected: - Common::Array _strings; - char *_stringsData; -}; - -struct ScriptValue { - - ScriptValueType type; - - union { - int value; - }; - - ScriptValue() : type(kInteger), value(0) {} - ScriptValue(ScriptValueType itype, int ivalue) : type(itype), value(ivalue) {} - - ScriptValue(const int intValue) : type(kInteger), value(intValue) {} - - ScriptValue& operator=(const int intValue) { - type = kInteger; - value = intValue; - return *this; - } - -}; - -class ScriptDataItem { -public: - ScriptDataItem() : _inter(NULL) {} - ScriptDataItem(ScriptInterpreter *inter) : _inter(inter) {} - virtual ~ScriptDataItem() {} - virtual void load(Common::File *fd) = 0; - static int type() { return -1; } -protected: - ScriptInterpreter *_inter; -}; - -class ScriptDataCache { -public: - ScriptDataCache(ScriptInterpreter *inter) : _inter(inter) { - } - ~ScriptDataCache() { - clear(); - } - - // WORKAROUND: The old prototype for this function was: - // template T *load(Common::File *fd, uint32 ofs); - // that caused a parser error in g++ 3.3.6 used by our - // "motoezx" target of our buildbot. The actual parser - // error happended, when calling the function like this: - // "T *result = _dataCache->load(_scriptFile, _data[value.value]->offset);" - // in ScriptInterpreter::toData. To work around this - // we moved the return value as parameter instead. - template - void load(Common::File *fd, uint32 ofs, T *&item) { - if (_cache.contains(ofs)) { - item = (T*)(_cache[ofs]); - } else { - item = new T(_inter); - fd->seek(ofs + 4); // "+4" skips the data size - item->load(fd); - _cache[ofs] = item; - } - } - void clear() { - // TODO: Free all cached items - } -protected: - typedef Common::HashMap CacheMap; - CacheMap _cache; - ScriptInterpreter *_inter; -}; - -struct SeriesStreamBreakItem { - int frameNum; - const char *digiName; - int digiChannel; - int digiVolume; - int trigger; - int flags; - ScriptValue variable; - int value; -}; - -class SeriesStreamBreakList : public ScriptDataItem { -public: - SeriesStreamBreakList(ScriptInterpreter *inter) : ScriptDataItem(inter) {} - ~SeriesStreamBreakList(); - void load(Common::File *fd); - int size() const { return _items.size(); } - SeriesStreamBreakItem *operator[](int index) const { return _items[index]; } - static int type() { return 0; } -protected: - Common::Array _items; -}; - -struct SaidArrayItem { - const char *itemName; - const char *digiNameLook; - const char *digiNameTake; - const char *digiNameGear; -}; - -class SaidArray : public ScriptDataItem { -public: - SaidArray(ScriptInterpreter *inter) : ScriptDataItem(inter) {} - ~SaidArray(); - void load(Common::File *fd); - int size() const { return _items.size(); } - SaidArrayItem *operator[](int index) const { return _items[index]; } - static int type() { return 2; } -protected: - Common::Array _items; -}; - -struct ParserArrayItem { - const char *w0; - const char *w1; - int trigger; - ScriptValue testVariable; - int testValue; - ScriptValue variable; - int value; -}; - -class ParserArray : public ScriptDataItem { -public: - ParserArray(ScriptInterpreter *inter) : ScriptDataItem(inter) {} - ~ParserArray(); - void load(Common::File *fd); - int size() const { return _items.size(); } - ParserArrayItem *operator[](int index) const { return _items[index]; } - static int type() { return 3; } -protected: - Common::Array _items; -}; - -class ScriptFunction { -public: - ScriptFunction(ScriptInterpreter *inter); - ~ScriptFunction(); - void load(Common::File *fd); - void jumpAbsolute(uint32 ofs); - void jumpRelative(int32 ofs); - byte readByte(); - uint32 readUint32(); -protected: - ScriptInterpreter *_inter; - Common::SeekableReadStream *_code; -}; - -struct ScriptFunctionEntry { - uint32 offset; - ScriptFunction *func; - ScriptFunctionEntry(uint32 funcOffset) : offset(funcOffset), func(NULL) { - } -}; - -struct ScriptDataEntry { - uint32 offset; - ScriptDataType type; - ScriptDataEntry(uint32 dataOffset, ScriptDataType dataType) : offset(dataOffset), type(dataType) { - } -}; - -enum ScriptKernelVariable { - kGameLanguage, - kGameVersion, - kGameCurrentRoom, - kGameNewRoom, - kGamePreviousRoom, - kGameNewSection, - kKernelTrigger, - kKernelTriggerMode, - kKernelFirstFade, - kKernelSuppressFadeUp, - kKernelContinueHandlingTrigger, - kKernelUseDebugMonitor, - kPlayerPosX, - kPlayerPosY, - kPlayerFacing, - kPlayerScale, - kPlayerDepth, - kPlayerWalkX, - kPlayerWalkY, - kPlayerReadyToWalk, - kPlayerNeedToWalk, - kPlayerCommandReady, - kPlayerWalkerInThisScene, - kPlayerVerb, - kWalkerInitialized, - kCallDaemonEveryLoop, - kConvCurrentTalker, - kConvCurrentNode, - kConvCurrentEntry, - kConvSoundToPlay, - kInterfaceVisible -}; - -class ScriptInterpreter { -public: - ScriptInterpreter(MadsM4Engine *vm); - ~ScriptInterpreter(); - /* Opens a M4 program file */ - void open(const char *filename); - void close(); - /* Loads a function via the index. Creates the function object if it's not already loaded. */ - ScriptFunction *loadFunction(uint32 index); - /* Loads a function via the exported name. */ - ScriptFunction *loadFunction(const Common::String &name); - /* Unload all loaded functions. - This should be called before entering a new room to free unused functions. */ - void unloadFunctions(); - //TODO void unloadData(); - /* Executes a function. */ - int runFunction(ScriptFunction *scriptFunction); - - void push(const ScriptValue &value); - void pop(ScriptValue &value); - void dumpStack(); - void dumpRegisters(); - void dumpGlobalVars(); - - int toInteger(const ScriptValue &value); - - const char *toString(const ScriptValue &value); - - // Is this ok? - template - const T& toData(const ScriptValue &value) { - debugCN(kDebugScript, "ScriptInterpreter::toData() index = %d; type = %d; max = %d\n", value.value, _data[value.value]->type, _data.size()); - assert((uint32)value.value < _data.size()); - T *result = 0; - _dataCache->load(_scriptFile, _data[value.value]->offset, result); - return *result; - } - - const char *getGlobalString(int index) const { - return _constStrings[index]; - } - - const char *loadGlobalString(Common::File *fd); - - void test(); - -protected: - - MadsM4Engine *_vm; - - typedef Common::HashMap FunctionNameMap; - Common::File *_scriptFile; - /* An array of offset/ScriptFunction* pairs for each script function */ - Common::Array _functions; - - // DEBUG only - Common::Array _scriptFunctionNames; - - Common::Array _data; - /* Maps function name -> index of function in _functions array */ - FunctionNameMap _functionNames; - StringTable _constStrings; - /* The currently running function */ - ScriptFunction *_runningFunction; - int _localStackPtr; - - ScriptValue _registers[8]; - - ScriptValue _stack[512]; - int _stackPtr; - - int _globalVarCount; - ScriptValue _globalVars[1024]; - - int _logicGlobals[512]; - - int _cmpFlags; - - ScriptDataCache *_dataCache; - - int _lineNum; - - typedef int (ScriptInterpreter::*KernelFunction)(); - struct KernelFunctionEntry { - KernelFunction proc; - const char *desc; - }; - const KernelFunctionEntry *_kernelFunctions; - uint16 _kernelFunctionsMax; - - struct KernelVariableEntry { - ScriptKernelVariable var; - const char *desc; - }; - const KernelVariableEntry *_kernelVars; - int16 _kernelVarsMax; - - void initScriptKernel(); - - void loadValue(ScriptValue &value); - void writeValue(ScriptValue &value); - void copyValue(ScriptValue &destValue, ScriptValue &sourceValue); - void derefValue(ScriptValue &value); - - void callKernelFunction(uint32 index); - ScriptValue getArg(uint32 index); - void dumpArgs(uint32 count); - - void callFunction(uint32 index); - - bool execOpcode(byte opcode); - - // Kernel functions - int o1_handleStreamBreak(); - int o1_handlePlayBreak(); - int o1_dispatchTriggerOnSoundState(); - int o1_getRangedRandomValue(); - int o1_getTicks(); - int o1_preloadSound(); - int o1_unloadSound(); - int o1_stopSound(); - int o1_playSound(); - int o1_playLoopingSound(); - int o1_setSoundVolume(); - int o1_getSoundStatus(); - int o1_getSoundDuration(); - int o1_loadSeries(); - int o1_unloadSeries(); - int o1_showSeries(); - int o1_playSeries(); - int o1_setSeriesFrameRate(); - int o1_playBreakSeries(); - int o1_preloadBreakSeries(); - int o1_unloadBreakSeries(); - int o1_startBreakSeries(); - int o1_dispatchTrigger(); - int o1_terminateMachine(); - int o1_sendWoodScriptMessage(); - int o1_runConversation(); - int o1_loadConversation(); - int o1_exportConversationValue(); - int o1_exportConversationPointer(); - int o1_fadeInit(); - int o1_fadeSetStart(); - int o1_fadeToBlack(); - int o1_initPaletteCycle(); - int o1_stopPaletteCycle(); - int o1_setHotspot(); - int o1_hideWalker(); - int o1_showWalker(); - int o1_setWalkerLocation(); - int o1_setWalkerFacing(); - int o1_walk(); - int o1_overrideCrunchTime(); - int o1_addBlockingRect(); - int o1_triggerTimerProc(); - int o1_setPlayerCommandsAllowed(); - int o1_getPlayerCommandsAllowed(); - int o1_updatePlayerInfo(); - int o1_hasPlayerSaid(); - int o1_hasPlayerSaidAny(); - int o1_playerHotspotWalkOverride(); - int o1_setPlayerFacingAngle(); - int o1_disablePlayerFadeToBlack(); - int o1_enablePlayer(); - int o1_disablePlayer(); - int o1_freshenSentence(); - int o1_playerHasItem(); - int o1_playerGiveItem(); - int o1_moveObject(); - int o1_setStopSoundsBetweenRooms(); - int o1_backupPalette(); - int o1_unloadWilburWalker(); - int o1_globalTriggerProc(); - int o1_wilburSpeech(); - int o1_wilburSaid(); - int o1_wilburParse(); - int o1_wilburTalk(); - int o1_wilburFinishedTalking(); - //int (); - - // Kernel vars - void getKernelVar(int index, ScriptValue &value); - void setKernelVar(int index, const ScriptValue &value); - -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/scripttab.h b/engines/m4/scripttab.h deleted file mode 100644 index 3264ae743c..0000000000 --- a/engines/m4/scripttab.h +++ /dev/null @@ -1,135 +0,0 @@ -/* This file has been autogenerated by the linker. - Do not edit it or merge it with script.cpp! */ -#define FUNCTION(x) { &ScriptInterpreter::x, #x } - static KernelFunctionEntry kernelFunctions[] = { - /* 000 */ - FUNCTION(o1_handleStreamBreak), - FUNCTION(o1_handlePlayBreak), - FUNCTION(o1_dispatchTriggerOnSoundState), - FUNCTION(o1_getRangedRandomValue), - /* 004 */ - FUNCTION(o1_getTicks), - FUNCTION(o1_preloadSound), - FUNCTION(o1_unloadSound), - FUNCTION(o1_stopSound), - /* 008 */ - FUNCTION(o1_playSound), - FUNCTION(o1_playLoopingSound), - FUNCTION(o1_setSoundVolume), - FUNCTION(o1_getSoundStatus), - /* 012 */ - FUNCTION(o1_getSoundDuration), - FUNCTION(o1_loadSeries), - FUNCTION(o1_unloadSeries), - FUNCTION(o1_showSeries), - /* 016 */ - FUNCTION(o1_playSeries), - FUNCTION(o1_setSeriesFrameRate), - FUNCTION(o1_playBreakSeries), - FUNCTION(o1_preloadBreakSeries), - /* 020 */ - FUNCTION(o1_unloadBreakSeries), - FUNCTION(o1_startBreakSeries), - FUNCTION(o1_dispatchTrigger), - FUNCTION(o1_terminateMachine), - /* 024 */ - FUNCTION(o1_sendWoodScriptMessage), - FUNCTION(o1_runConversation), - FUNCTION(o1_runConversation), - FUNCTION(o1_loadConversation), - /* 028 */ - FUNCTION(o1_exportConversationValue), - FUNCTION(o1_exportConversationPointer), - FUNCTION(o1_runConversation), - FUNCTION(o1_fadeInit), - /* 032 */ - FUNCTION(o1_fadeSetStart), - FUNCTION(o1_fadeToBlack), - FUNCTION(o1_initPaletteCycle), - FUNCTION(o1_stopPaletteCycle), - /* 036 */ - FUNCTION(o1_setHotspot), - FUNCTION(o1_hideWalker), - FUNCTION(o1_showWalker), - FUNCTION(o1_setWalkerLocation), - /* 040 */ - FUNCTION(o1_setWalkerFacing), - FUNCTION(o1_walk), - FUNCTION(o1_overrideCrunchTime), - FUNCTION(o1_addBlockingRect), - /* 044 */ - FUNCTION(o1_triggerTimerProc), - FUNCTION(o1_setPlayerCommandsAllowed), - FUNCTION(o1_getPlayerCommandsAllowed), - FUNCTION(o1_updatePlayerInfo), - /* 048 */ - FUNCTION(o1_hasPlayerSaid), - FUNCTION(o1_hasPlayerSaidAny), - FUNCTION(o1_playerHotspotWalkOverride), - FUNCTION(o1_setPlayerFacingAngle), - /* 052 */ - FUNCTION(o1_disablePlayerFadeToBlack), - FUNCTION(o1_enablePlayer), - FUNCTION(o1_disablePlayer), - FUNCTION(o1_freshenSentence), - /* 056 */ - FUNCTION(o1_playerHasItem), - FUNCTION(o1_playerGiveItem), - FUNCTION(o1_moveObject), - FUNCTION(o1_setStopSoundsBetweenRooms), - /* 060 */ - FUNCTION(o1_backupPalette), - FUNCTION(o1_unloadWilburWalker), - FUNCTION(o1_globalTriggerProc), - FUNCTION(o1_wilburSpeech), - /* 064 */ - FUNCTION(o1_wilburParse), - FUNCTION(o1_wilburSaid), - FUNCTION(o1_wilburTalk), - FUNCTION(o1_wilburFinishedTalking) - }; -#undef FUNCTION - -#define VARIABLE(x) { x, #x } - static KernelVariableEntry kernelVars[] = { - /* 000 */ - VARIABLE(kGameLanguage), - VARIABLE(kGameVersion), - VARIABLE(kGameCurrentRoom), - VARIABLE(kGameNewRoom), - /* 004 */ - VARIABLE(kGamePreviousRoom), - VARIABLE(kGameNewSection), - VARIABLE(kKernelTrigger), - VARIABLE(kKernelTriggerMode), - /* 008 */ - VARIABLE(kKernelFirstFade), - VARIABLE(kKernelSuppressFadeUp), - VARIABLE(kKernelContinueHandlingTrigger), - VARIABLE(kKernelUseDebugMonitor), - /* 012 */ - VARIABLE(kPlayerPosX), - VARIABLE(kPlayerPosY), - VARIABLE(kPlayerFacing), - VARIABLE(kPlayerScale), - /* 016 */ - VARIABLE(kPlayerDepth), - VARIABLE(kPlayerWalkX), - VARIABLE(kPlayerWalkY), - VARIABLE(kPlayerReadyToWalk), - /* 020 */ - VARIABLE(kPlayerNeedToWalk), - VARIABLE(kPlayerCommandReady), - VARIABLE(kPlayerWalkerInThisScene), - VARIABLE(kPlayerVerb), - /* 024 */ - VARIABLE(kWalkerInitialized), - VARIABLE(kCallDaemonEveryLoop), - VARIABLE(kConvCurrentTalker), - VARIABLE(kConvCurrentNode), - /* 028 */ - VARIABLE(kConvCurrentEntry), - VARIABLE(kConvSoundToPlay), - VARIABLE(kInterfaceVisible) - }; -#undef VARIABLE diff --git a/engines/m4/sound.cpp b/engines/m4/sound.cpp deleted file mode 100644 index 76eae8a661..0000000000 --- a/engines/m4/sound.cpp +++ /dev/null @@ -1,276 +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 "m4/m4.h" -#include "m4/sound.h" -#include "m4/compression.h" - -#include "common/stream.h" -#include "common/textconsole.h" - -#include "audio/audiostream.h" -#include "audio/mixer.h" -#include "audio/decoders/raw.h" - -namespace M4 { - -Sound::Sound(MadsM4Engine *vm, Audio::Mixer *mixer, int volume) : - _vm(vm), _mixer(mixer) { - - for (int i = 0; i < SOUND_HANDLES; i++) - _handles[i].type = kFreeHandle; - - _dsrFileLoaded = false; - - setVolume(volume); -} - -Sound::~Sound() { - unloadDSRFile(); -} - -SndHandle *Sound::getHandle() { - for (int i = 0; i < SOUND_HANDLES; i++) { - if (_handles[i].type == kFreeHandle) - return &_handles[i]; - - if (!_mixer->isSoundHandleActive(_handles[i].handle)) { - _handles[i].type = kFreeHandle; - return &_handles[i]; - } - } - - error("Sound::getHandle(): Too many sound handles"); - return NULL; // for compilers that don't support NORETURN -} - -bool Sound::isHandleActive(SndHandle *handle) { - return (_mixer->isSoundHandleActive(handle->handle)); -} - -void Sound::playSound(const char *soundName, int volume, bool loop, int channel) { - Common::SeekableReadStream *soundStream = _vm->res()->get(soundName); - SndHandle *handle; - if (channel < 0) { - handle = getHandle(); - } else { - if (_handles[channel].type == kFreeHandle) { - handle = &_handles[channel]; - } else { - warning("Attempted to play a sound on a channel that isn't free"); - return; - } - } - - int bufferSize = soundStream->size(); - byte *buffer = new byte[bufferSize]; - soundStream->read(buffer, bufferSize); - _vm->res()->toss(soundName); - - handle->type = kEffectHandle; - - _vm->res()->toss(soundName); - - // Sound format is 8bit mono, unsigned, 11025kHz - Audio::AudioStream *stream = Audio::makeLoopingAudioStream( - Audio::makeRawStream(buffer, bufferSize, 11025, Audio::FLAG_UNSIGNED), - loop ? 0 : 1); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle->handle, stream, -1, volume); -} - -void Sound::playSound(int soundNum) { - warning("TODO: playSound(%d)", soundNum); -} - -void Sound::pauseSound() { - for (int i = 0; i < SOUND_HANDLES; i++) { - if (_handles[i].type == kEffectHandle) - _mixer->pauseHandle(_handles[i].handle, true); - } -} - -void Sound::resumeSound() { - for (int i = 0; i < SOUND_HANDLES; i++) { - if (_handles[i].type == kEffectHandle) - _mixer->pauseHandle(_handles[i].handle, false); - } -} - -void Sound::stopSound(int channel) { - if (channel >= 0) { - if (_handles[channel].type == kEffectHandle) { - _mixer->stopHandle(_handles[channel].handle); - _handles[channel].type = kFreeHandle; - return; - } else { - warning("Attempted to stop a sound on a channel that is already free"); - return; - } - } - - for (int i = 0; i < SOUND_HANDLES; i++) { - if (_handles[i].type == kEffectHandle) { - _mixer->stopHandle(_handles[i].handle); - _handles[i].type = kFreeHandle; - } - } -} - -void Sound::playVoice(const char *soundName, int volume) { - Common::SeekableReadStream *soundStream = _vm->res()->get(soundName); - SndHandle *handle = getHandle(); - byte *buffer; - - buffer = (byte *)malloc(soundStream->size()); - soundStream->read(buffer, soundStream->size()); - - handle->type = kEffectHandle; - - _vm->res()->toss(soundName); - - // Voice format is 8bit mono, unsigned, 11025kHz - Audio::AudioStream *stream = Audio::makeRawStream(buffer, soundStream->size(), 11025, Audio::FLAG_UNSIGNED); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle->handle, stream, -1, volume); -} - -void Sound::pauseVoice() { - for (int i = 0; i < SOUND_HANDLES; i++) - if (_handles[i].type == kVoiceHandle) - _mixer->pauseHandle(_handles[i].handle, true); -} - -void Sound::resumeVoice() { - for (int i = 0; i < SOUND_HANDLES; i++) - if (_handles[i].type == kVoiceHandle) - _mixer->pauseHandle(_handles[i].handle, false); -} - -void Sound::stopVoice() { - for (int i = 0; i < SOUND_HANDLES; i++) - if (_handles[i].type == kVoiceHandle) { - _mixer->stopHandle(_handles[i].handle); - _handles[i].type = kFreeHandle; - } -} - -void Sound::stopAll() { - stopVoice(); - stopSound(); -} - -void Sound::setVolume(int volume) { - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume); -} - -void Sound::loadDSRFile(const char *fileName) { - if (_dsrFileLoaded) - unloadDSRFile(); - - Common::SeekableReadStream *fileStream = _vm->res()->get(fileName); - - sprintf(_dsrFile.fileName, "%s", fileName); - - // Read header - _dsrFile.entryCount = fileStream->readUint16LE(); - //warning(kDebugSound, "DSR has %i entries\n", _dsrFile.entryCount); - - for (int i = 0; i < _dsrFile.entryCount; i++) { - DSREntry newEntry; - newEntry.frequency = fileStream->readUint16LE(); - newEntry.channels = fileStream->readUint32LE(); - newEntry.compSize = fileStream->readUint32LE(); - newEntry.uncompSize = fileStream->readUint32LE(); - newEntry.offset = fileStream->readUint32LE(); - _dsrFile.dsrEntries.push_back(newEntry); - - /* - warning(kDebugSound, "%i: ", i); - warning(kDebugSound, "frequency: %i ", newEntry->frequency); - warning(kDebugSound, "channels: %i ", newEntry->channels); - warning(kDebugSound, "comp: %i ", newEntry.compSize); - warning(kDebugSound, "uncomp: %i ", newEntry.uncompSize); - warning(kDebugSound, "offset: %i ", newEntry->offset); - warning(kDebugSound, "\n"); - */ - } - - _vm->res()->toss(fileName); - - _dsrFileLoaded = true; -} - -void Sound::unloadDSRFile() { - if (!_dsrFileLoaded) - return; - - _dsrFile.dsrEntries.clear(); - - _dsrFile.entryCount = 0; - strcpy(_dsrFile.fileName, ""); - _dsrFileLoaded = false; -} - -void Sound::playDSRSound(int soundIndex, int volume, bool loop) { - if (!_dsrFileLoaded) { - warning("DSR file not loaded, not playing sound"); - return; - } - - if (soundIndex < 0 || soundIndex > _dsrFile.entryCount - 1) { - warning("Invalid sound index: %i, not playing sound", soundIndex); - return; - } - - SndHandle *handle = getHandle(); - - handle->type = kEffectHandle; - - // Get sound data - FabDecompressor fab; - byte *compData = new byte[_dsrFile.dsrEntries[soundIndex].compSize]; - byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex].uncompSize]; - Common::SeekableReadStream *fileStream = _vm->res()->get(_dsrFile.fileName); - fileStream->seek(_dsrFile.dsrEntries[soundIndex].offset, SEEK_SET); - fileStream->read(compData, _dsrFile.dsrEntries[soundIndex].compSize); - _vm->res()->toss(_dsrFile.fileName); - - fab.decompress(compData, _dsrFile.dsrEntries[soundIndex].compSize, - buffer, _dsrFile.dsrEntries[soundIndex].uncompSize); - - // Play sound - Audio::AudioStream *stream = Audio::makeLoopingAudioStream( - Audio::makeRawStream(buffer, - _dsrFile.dsrEntries[soundIndex].uncompSize, - _dsrFile.dsrEntries[soundIndex].frequency, Audio::FLAG_UNSIGNED), - loop ? 0 : 1); - _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle->handle, stream, -1, volume); - - /* - // Dump the sound file - FILE *destFile = fopen("sound.raw", "wb"); - fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile); - fclose(destFile); - */ -} - -} // End of namespace M4 diff --git a/engines/m4/sound.h b/engines/m4/sound.h deleted file mode 100644 index 99a2292d83..0000000000 --- a/engines/m4/sound.h +++ /dev/null @@ -1,110 +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. - * - */ - -// Sound class - -#ifndef M4_SOUND_H -#define M4_SOUND_H - -#include "common/file.h" -#include "common/array.h" -#include "audio/mixer.h" -#include "audio/decoders/mp3.h" -#include "audio/decoders/vorbis.h" -#include "audio/decoders/flac.h" - -namespace M4 { - -#define SOUND_HANDLES 10 - -enum SOUND_FLAGS { - SOUND_LOOP = 1 -}; - -enum sndHandleType { - kFreeHandle, - kEffectHandle, - kVoiceHandle -}; - -struct SndHandle { - Audio::SoundHandle handle; - sndHandleType type; -}; - -struct DSREntry { - int16 frequency; - int channels; - int32 compSize; - int32 uncompSize; - int32 offset; -}; - -struct DSRFile { - char fileName[20]; - int entryCount; - Common::Array dsrEntries; -}; - -class MadsM4Engine; - -class Sound { -public: - - Sound(MadsM4Engine *vm, Audio::Mixer *mixer, int volume); - ~Sound(); - - void playSound(const char *soundName, int volume, bool loop, int channel = -1); - void playSound(int soundNum); - void pauseSound(); - void resumeSound(); - void stopSound(int channel = -1); - - void playVoice(const char *soundName, int volume); - void pauseVoice(); - void resumeVoice(); - void stopVoice(); - - void stopAll(); - - void setVolume(int volume); - - bool isHandleActive(SndHandle *handle); - SndHandle *getHandle(); - - void loadDSRFile(const char *fileName); - void unloadDSRFile(); - void playDSRSound(int soundIndex, int volume, bool loop); - - private: - - MadsM4Engine *_vm; - Audio::Mixer *_mixer; - SndHandle _handles[SOUND_HANDLES]; - - DSRFile _dsrFile; - bool _dsrFileLoaded; -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp deleted file mode 100644 index d0741732f3..0000000000 --- a/engines/m4/sprite.cpp +++ /dev/null @@ -1,207 +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/rect.h" -#include "common/textconsole.h" - -#include "m4/globals.h" -#include "m4/graphics.h" -#include "m4/m4.h" -#include "m4/resource.h" -#include "m4/sprite.h" - -namespace M4 { - -enum { - kEndOfLine = 0, - kEndOfSprite = 1, - kMarker = 2 -}; - -M4Sprite::M4Sprite(Common::SeekableReadStream* source, int xOfs, int yOfs, int widthVal, int heightVal, bool decodeRle, uint8 encodingVal) - : M4Surface(widthVal, heightVal), encoding(encodingVal) { - - if (_vm->isM4()) { - if (decodeRle) { - loadRle(source); - } else { - // Raw sprite data, load directly - byte *dst = getBasePtr(); - source->read(dst, widthVal * heightVal); - } - } else { - loadMadsSprite(source); - } - - x = xOffset = xOfs; - y = yOffset = yOfs; - -} - -void M4Sprite::loadRle(Common::SeekableReadStream* rleData) { - byte *dst = getBasePtr(); - while (1) { - byte len = rleData->readByte(); - if (len == 0) { - len = rleData->readByte(); - if (len <= kMarker) { - if (len == kEndOfSprite) - break; - } else { - while (len--) { - *dst++ = rleData->readByte(); - } - } - } else { - byte value = rleData->readByte(); - while (len--) - *dst++ = value; - } - } -} - -void M4Sprite::loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int destY) { - int lineNum = 0; - byte *dst = getBasePtr(destX, destY); - while (1) { - byte len = rleData->readByte(); - if (len == 0) { - len = rleData->readByte(); - if (len <= kMarker) { - if (len == kEndOfLine) { - dst = getBasePtr(destX, destY + lineNum); - lineNum++; - } else if (len == kEndOfSprite) - break; - } else { - while (len--) { - byte pixel = rleData->readByte(); - if (pixel == 0) - dst++; - else - *dst++ = pixel; - /* NOTE: The change below behaved differently than the old code, - so I put the old code back in again above. - If the pixel value is 0, nothing should be written to the - output buffer, since 0 means transparent. */ - //*dst++ = (pixel == 0xFD) ? 0 : pixel; - } - } - } else { - byte value = rleData->readByte(); - if (value == 0) - dst += len; - else - while (len--) - *dst++ = value; - } - } -} - -// TODO: The sprite outlines (pixel value 0xFD) are not shown -void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { - bool spriteEnd = false; - - // Set entire sprite contents to transparent pixels - fillRect(bounds(), TRANSPARENT_COLOR_INDEX); - - // Major line loop - for (int yp = 0; yp < h; ++yp) { - byte *destP = getBasePtr(0, yp); - bool newLine = false; - byte cmd = source->readByte(); - int x2 = 0; - - if (cmd == 0xfc) { - // End of entire sprite - spriteEnd = true; - break; - } else if (cmd == 0xff) { - // The entire line is empty - newLine = true; - } else if (cmd == 0xFD) { - // Lines contains only run lenghs of pixels - while (x2 < w) { - cmd = source->readByte(); - if (cmd == 0xff) { - // End of line reached - newLine = true; - break; - } - - byte v = source->readByte(); - while (cmd-- > 0) { - if (x2 < w) - *destP++ = (v == 0xFD) ? TRANSPARENT_COLOR_INDEX : v; - ++x2; - } - } - } else { - // Line intermixes run lengths with individual pixels - while (x2 < w) { - cmd = source->readByte(); - if (cmd == 0xff) { - // End of line reached - newLine = true; - break; - } - - if (cmd == 0xFE) { - // Handle repeated sequence - cmd = source->readByte(); - byte v = source->readByte(); - while (cmd-- > 0) { - if (x2 < w) { - *destP++ = (v == 0xFD) ? TRANSPARENT_COLOR_INDEX : v; - } - ++x2; - } - } else { - // Handle writing out single pixel - *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOR_INDEX : cmd; - ++x2; - } - } - } - - // Check if we need to scan forward to find the end of the line - if (!newLine) { - do { - if (source->eos()) { - warning("M4Sprite::loadMadsSprite: unexpected end of data"); - break; - } - } while (source->readByte() != 0xff); - } - } - - if (!spriteEnd) { - byte v = source->readByte(); - assert(v == 0xFC); - } -} - -byte M4Sprite::getTransparencyIndex() const { - return TRANSPARENT_COLOR_INDEX; -} - -} // End of namespace M4 diff --git a/engines/m4/sprite.h b/engines/m4/sprite.h deleted file mode 100644 index af49d8cbaf..0000000000 --- a/engines/m4/sprite.h +++ /dev/null @@ -1,121 +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. - * - */ - -#ifndef M4_SPRITE_H -#define M4_SPRITE_H - -#include "common/util.h" -#include "common/endian.h" -#include "common/stream.h" -#include "m4/graphics.h" - -/* - TODO: - - change DrawRequestX and RendCell -*/ - -namespace M4 { - -typedef struct -{ - int32 x; // x position relative to GrBuff(0, 0) - int32 y; // y position relative to GrBuff(0, 0) - int32 scale_x; // x scale factor (can be negative for reverse draw) - int32 scale_y; // y scale factor (can't be negative) - uint8* depth_map; // depth code array for destination (doesn't care if srcDepth is 0) - BGR8 *Pal; // palette for shadow draw (doesn't care if SHADOW bit is not set in Src.encoding) - uint8* ICT; // Inverse Color Table (doesn't care if SHADOW bit is not set in Src.encoding) - uint8 depth; // depth code for source (0 if no depth processing) -} DrawRequestX; - -typedef struct -{ - uint32 Pack; - uint32 Stream; - long hot_x; - long hot_y; - uint32 Width; - uint32 Height; - uint32 Comp; - uint32 Reserved[8]; - uint8* data; -} RendCell; - -#define SS_HEADER_NUM_FIELDS 14 -struct SpriteSeriesHeader { - uint32 header; - uint32 size; - uint32 packing; - uint32 frameRate; - uint32 pixSpeed; - uint32 maxWidth; - uint32 maxHeight; - uint32 reserved3; - uint32 reserved4; - uint32 reserved5; - uint32 reserved6; - uint32 reserved7; - uint32 reserved8; - uint32 count; -}; - -#define SF_HEADER_NUM_FIELDS 15 -struct SpriteFrameHeader { - uint32 pack; - uint32 stream; - uint32 x; - uint32 y; - uint32 width; - uint32 height; - uint32 comp; - uint32 reserved1; - uint32 reserved2; - uint32 reserved3; - uint32 reserved4; - uint32 reserved5; - uint32 reserved6; - uint32 reserved7; - uint32 reserved8; -}; - -class M4Sprite : public M4Surface { -public: - int x, y; - int xOffset, yOffset; - uint8 encoding; - - M4Sprite(MadsM4Engine *vm): M4Surface() {} - M4Sprite(MadsM4Engine *vm, int widthVal, int heightVal): M4Surface(widthVal, heightVal), xOffset(0), yOffset(0) {} - // Loads a sprite from the given stream, and optionally decompresses the RLE-encoded data - M4Sprite(Common::SeekableReadStream* source, int xOfs, int yOfs, int widthVal, int heightVal, bool decodeRle = true, uint8 encodingVal = 0); - // Loads an RLE compressed sprite; the surface must have been created before - void loadRle(Common::SeekableReadStream* rleData); - void loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int destY); - void loadMadsSprite(Common::SeekableReadStream* source); - - byte getTransparencyIndex() const; -protected: -}; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/staticres.cpp b/engines/m4/staticres.cpp deleted file mode 100644 index 520c0ad58e..0000000000 --- a/engines/m4/staticres.cpp +++ /dev/null @@ -1,61 +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 "m4/staticres.h" - -namespace M4 { - -const char *englishMADSArticleList[9] = { - NULL, "with", "to", "at", "from", "on", "in", "under", "behind" -}; - -const char *cheatingEnabledDesc[3] = { - "CHEATING ENABLED", - "(For your convenience).", - NULL -}; - -const char *atStr = "at"; -const char *lookAroundStr = "Look around"; -const char *toStr = "to "; -const char *useStr = "Use "; -const char *walkToStr = "Walk to "; -const char *fenceStr = "fence"; -const char *overStr = "over"; - -const char *GameReleaseInfoStr = "ScummVM rev: 8.43 14-Sept-92"; -const char *GameReleaseTitleStr = "GAME RELASE VERSION INFO"; - -VerbInit verbList[10] = { - {kVerbLook, 2, 0}, - {kVerbTake, 2, 0}, - {kVerbPush, 2, 0}, - {kVerbOpen, 2, 0}, - {kVerbPut, 1, -1}, - {kVerbTalkTo, 2, 0}, - {kVerbGive, 1, 2}, - {kVerbPull, 2, 0}, - {kVerbClose, 2, 0}, - {kVerbThrow, 1, 3} -}; - -} // End of namespace M4 diff --git a/engines/m4/staticres.h b/engines/m4/staticres.h deleted file mode 100644 index e3ead3398b..0000000000 --- a/engines/m4/staticres.h +++ /dev/null @@ -1,56 +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. - * - */ - -#ifndef M4_STATICRES_H -#define M4_STATICRES_H - -#include "common/scummsys.h" -#include "m4/m4.h" - -namespace M4 { - -extern const char *englishMADSArticleList[9]; - -extern const char *cheatingEnabledDesc[3]; - -extern const char *atStr; -extern const char *lookAroundStr; -extern const char *toStr; -extern const char *useStr; -extern const char *walkToStr; -extern const char *fenceStr; -extern const char *overStr; - -extern const char *GameReleaseInfoStr; -extern const char *GameReleaseTitleStr; - -struct VerbInit { - int verb; - int8 flag1; - int8 flag2; -}; - -extern VerbInit verbList[10]; - -} // End of namespace M4 - -#endif diff --git a/engines/m4/viewmgr.cpp b/engines/m4/viewmgr.cpp deleted file mode 100644 index 8eb40f0f17..0000000000 --- a/engines/m4/viewmgr.cpp +++ /dev/null @@ -1,444 +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. - * - */ - -// TODO: Views have a _coords rect, so I'm not sure if x/y is needed in the onRefresh - -#include "m4/m4.h" -#include "m4/viewmgr.h" -#include "m4/mads_anim.h" - -namespace M4 { - -void returnToMainMenuFn(MadsM4Engine *vm) { - vm->_palette->resetColorCounts(); - vm->_palette->setMadsSystemPalette(); - - vm->loadMenu(MAIN_MENU); -} - -RectList::RectList() { -} - -RectList::~RectList() { -} - -void RectList::addRect(int x1, int y1, int x2, int y2) { - addRect(Common::Rect(x1, y1, x2, y2)); -} - -void RectList::addRect(const Common::Rect &rect) { - /* TODO: - Implement the following: - - Don't add the Rect if it's contained in any Rect in the list - - Split up the Rect if it intersects any Rect in the list - and add the resulting partial Rects instead - */ - push_back(rect); -} - -int RectList::find(const Common::Point &pt) { - for (uint idx = 0; idx < size(); ++idx) { - if (this->operator [](idx).contains(pt.x, pt.y)) - return idx; - } - return -1; -} - -//-------------------------------------------------------------------------- - -HotkeyList::HotkeyList(View *owner) : _view(owner) { -} - -HotkeyList::~HotkeyList() { - for (uint32 i = 0; i < _hotkeys.size(); i++) - delete _hotkeys[i]; -} - -void HotkeyList::add(uint32 key, Hotkey::Callback callback) { - _hotkeys.push_back(new Hotkey(key, callback)); -} - -void HotkeyList::remove(uint32 key) { - for (uint32 i = 0; i < _hotkeys.size(); i++) { - if (_hotkeys[i]->key == key) { - delete _hotkeys[i]; - _hotkeys.remove_at(i); - break; - } - } -} - -bool HotkeyList::call(uint32 key) { - for (uint32 i = 0; i < _hotkeys.size(); i++) { - if (_hotkeys[i]->key == key) { - if (_hotkeys[i]->callback) - (_hotkeys[i]->callback)(_vm, _view, key); - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- - -// View constructor - -View::View(MadsM4Engine *vm, const Common::Rect &viewBounds, bool transparent) - : M4Surface(viewBounds.width(), viewBounds.height()), _hotkeys(this), _vm(vm) { - SCREEN_FLAGS_DEFAULT; - _coords = viewBounds; - _transparent = transparent; -} - -View::View(MadsM4Engine *vm, int x, int y, bool transparent) - : M4Surface(), _hotkeys(this), _vm(vm) { - SCREEN_FLAGS_DEFAULT; - _coords.left = x; - _coords.top = y; - _coords.right = _vm->_screen->width(); - _coords.bottom = _vm->_screen->height(); - _transparent = transparent; -} - -void View::getCoordinates(Common::Rect &rect) { - rect = _coords; -} - -void View::extract(int *status) { -} - -void View::show() { - _screenFlags.visible = true; - _vm->_viewManager->moveToFront(this); - _vm->_viewManager->restore(_coords); -} - -void View::hide() { - _screenFlags.visible = false; - _vm->_viewManager->restore(_coords); -} - -void View::moveToBack() { - _vm->_viewManager->moveToBack(this); -} - -void View::moveAbsolute(int x, int y) { - // TODO: Handle clipping and offscreen - Common::Rect oldCoords = _coords; - _coords.moveTo(x, y); - _vm->_viewManager->restore(oldCoords); - _vm->_viewManager->restore(_coords); -} - -void View::moveRelative(int x, int y) { - // TODO: Handle clipping and offscreen - Common::Rect oldCoords = _coords; - _coords.translate(x, y); - _vm->_viewManager->restore(oldCoords); - _vm->_viewManager->restore(_coords); -} - -void View::resize(int newWidth, int newHeight) { - Common::Rect oldCoords = _coords; - if (newWidth >= 0) - _coords.setWidth(newWidth); - if (newHeight >= 0) - _coords.setHeight(newHeight); - _vm->_viewManager->restore(oldCoords); - _vm->_viewManager->restore(_coords); -} - -void View::restore(int x1, int y1, int x2, int y2) { - _vm->_viewManager->restore(_coords.left + x1, _coords.top + y1, _coords.left + x2, _coords.top + y2); -} - -void View::onRefresh(RectList *rects, M4Surface *destSurface) { - assert(destSurface); - - if (rects == NULL) - // No rect list specified, so copy entire surface - copyTo(destSurface, _coords.left, _coords.top, _transparent ? 0 : -1); - else { - // Loop through the set of specified rectangles - RectList::iterator i; - for (i = rects->begin(); i != rects->end(); ++i) { - Common::Rect &destRect = *i; - Common::Rect srcBounds(destRect.left - _coords.left, destRect.top - _coords.top, - destRect.right - _coords.left, destRect.bottom - _coords.top); - copyTo(destSurface, srcBounds, destRect.left, destRect.top, _transparent ? 0 : -1); - } - } -} - -//-------------------------------------------------------------------------- - -ViewManager::ViewManager(MadsM4Engine *vm): _systemHotkeys(HotkeyList(NULL)), _vm(vm) { - _captureScreen = NULL; - _captureEvents = false; -} - -ViewManager::~ViewManager() { - // Delete any remaining active views - ListIterator i; - for (i = _views.begin(); i != _views.end(); ++i) - delete (*i); -} - -void ViewManager::addView(View *view) { - _views.push_back(view); - moveToFront(view); -} - -// Warning: After calling this method, the passed view object will no longer be valid - -void ViewManager::deleteView(View *view) { - _views.remove(view); - delete view; -} - -void ViewManager::handleEvents(const Common::Event &event) { -} - -void ViewManager::handleKeyboardEvents(uint32 keycode) { - Common::Point mousePos = _vm->_mouse->currentPos(); - View *view; - bool blockedFlag; - bool foundFlag; - bool handledFlag; - - // Scan view list for one which accepts or blocks keyboard events. If one is found, - // then the event is passed to it - - view = NULL; - handledFlag = false; - foundFlag = false; - blockedFlag = false; - - // Loop from the front to back view - ListIterator i; - for (i = _views.reverse_begin(); (i != _views.end()) && !foundFlag; --i) { - view = *i; - if (!view->isVisible()) continue; - - if (view->screenFlags().blocks & SCREVENT_KEY) - blockedFlag = true; - if (view->screenFlags().get & SCREVENT_KEY) { - foundFlag = true; - handledFlag = (view->onEvent)(KEVENT_KEY, keycode, mousePos.x, mousePos.y, _captureEvents); - if (_captureEvents) - _captureScreen = view; - } - } - - // Scan view list for one with a hotkey list, aborting if a view is found that either - // blocks keyboard events, or has a hotkey list that includes the keycode - - blockedFlag = false; - for (i = _views.reverse_begin(); (i != _views.end()) && !foundFlag && !blockedFlag; --i) { - view = *i; - if (!view->isVisible()) continue; - - if (view->screenFlags().blocks & SCREVENT_KEY) - blockedFlag = true; - if (view->screenFlags().get & SCREVENT_KEY) { - if (view->hotkeys().call(keycode)) { - handledFlag = true; - _captureEvents = false; - //_vm->_dialogs->keyMouseCollision(); // TODO - } - } - } - - // Final check: if no view handled or blocked the key, check against the system hotkey list - - if (!handledFlag && !blockedFlag) { - handledFlag = _systemHotkeys.call(keycode); - if (handledFlag) { - _captureEvents = false; - //_vm->_dialogs->keyMouseCollision(); // TODO - } - } -} - -void ViewManager::handleMouseEvents(M4EventType event) { - Common::Point mousePos = _vm->_mouse->currentPos(); - ListIterator i; - View *view; - bool blockedFlag; - bool foundFlag; - - // If a window sets the _captureEvents flag to true, it will receive all events until - // it sets it to false, even if it's not the top window - if (_captureEvents) { - assert(_captureScreen); - if (_captureScreen->screenFlags().get & SCREVENT_MOUSE) - (_captureScreen->onEvent)(event, 0, mousePos.x, mousePos.y, _captureEvents); - - } else { - blockedFlag = false; - foundFlag = false; - view = NULL; - - // Loop from the front to back view - for (i = _views.reverse_begin(); (i != _views.end()) && !foundFlag && !blockedFlag; --i) { - view = *i; - if (!view->isVisible()) continue; - - if (view->screenFlags().blocks & SCREVENT_MOUSE) - blockedFlag = true; - if ((view->screenFlags().get & SCREVENT_MOUSE) && view->isInside(mousePos.x, mousePos.y)) - foundFlag = true; - } - - if (foundFlag) - view->onEvent(event, 0, mousePos.x, mousePos.y, _captureEvents); - else - _captureEvents = false; - if (_captureEvents) - _captureScreen = view; - } -} - -void ViewManager::restore(int x1, int y1, int x2, int y2) { - RectList *rl = new RectList(); - Common::Rect redrawBounds(x1, y1, x2, y2); - rl->addRect(x1, y1, x2, y2); - - for (ListIterator i = _views.begin(); i != _views.end(); ++i) { - View *v = *i; - - if (v->isVisible() && v->bounds().intersects(redrawBounds)) - v->onRefresh(rl, _vm->_screen); - } - - _vm->_screen->update(); - -} - -void ViewManager::restore(const Common::Rect &rect) { - restore(rect.left, rect.top, rect.right, rect.bottom); -} - -void ViewManager::moveToFront(View *view) { - if (_views.size() < 2) - return; - - _views.remove(view); - - ListIterator i = _views.begin(); - while ((i != _views.end()) && ((*i)->layer() <= view->layer())) - ++i; - - _views.insert(i, view); -} - -void ViewManager::moveToBack(View *view) { - if (_views.size() < 2) - return; - - _views.remove(view); - - ListIterator i = _views.begin(); - while ((i != _views.end()) && ((*i)->layer() < view->layer())) - ++i; - - _views.insert(i, view); -} - -View *ViewManager::getView(int screenType) { - ListIterator i = _views.begin(); - while (i != _views.end()) { - if ((*i)->screenType() == screenType) - return *i; - ++i; - } - - return NULL; -} - -void ViewManager::updateState() { - Common::List viewList = _views; - - for (ListIterator i = viewList.begin(); i != viewList.end(); ++i) { - if (_vm->_events->quitFlag) - return; - - View *v = *i; - v->updateState(); - } -} - -void ViewManager::refreshAll() { - _vm->_screen->clear(); - - for (ListIterator i = _views.begin(); i != _views.end(); ++i) { - View *v = *i; - - if (v->isVisible()) - v->onRefresh(NULL, _vm->_screen); - } - - _vm->_screen->update(); -} - -void ViewManager::showTextView(const char *textViewName, bool returnToMainMenu) { - // Deactivate the scene if it's currently active - View *view = _vm->_viewManager->getView(VIEWID_SCENE); - if (view != NULL) - _vm->_viewManager->deleteView(view); - - // Deactivate the main menu if it's currently active - view = _vm->_viewManager->getView(VIEWID_MAINMENU); - if (view != NULL) - _vm->_viewManager->deleteView(view); - - // Activate the textview view - _vm->_font->setFont(FONT_CONVERSATION_MADS); - TextviewView *textView = new TextviewView(_vm); - _vm->_viewManager->addView(textView); - if (returnToMainMenu) - textView->setScript(textViewName, returnToMainMenuFn); - else - textView->setScript(textViewName, NULL); -} - -void ViewManager::showAnimView(const char *animViewName, bool returnToMainMenu) { - // Deactivate the scene if it's currently active - View *view = _vm->_viewManager->getView(VIEWID_SCENE); - if (view != NULL) - _vm->_viewManager->deleteView(view); - - // Deactivate the main menu if it's currently active - view = _vm->_viewManager->getView(VIEWID_MAINMENU); - if (view != NULL) - _vm->_viewManager->deleteView(view); - - // Activate the animview view - AnimviewView *animView = new AnimviewView(_vm); - _vm->_viewManager->addView(animView); - if (returnToMainMenu) - animView->setScript(animViewName, returnToMainMenuFn); - else - animView->setScript(animViewName, NULL); -} - -} // End of namespace M4 diff --git a/engines/m4/viewmgr.h b/engines/m4/viewmgr.h deleted file mode 100644 index bb4f76cfaa..0000000000 --- a/engines/m4/viewmgr.h +++ /dev/null @@ -1,204 +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. - * - */ - -#ifndef M4_VIEWMGR_H -#define M4_VIEWMGR_H - -#include "common/algorithm.h" -#include "common/array.h" -#include "common/list.h" -#include "common/events.h" -#include "common/rect.h" - -#include "m4/font.h" -#include "m4/globals.h" -#include "m4/events.h" -#include "m4/graphics.h" - -namespace M4 { - -class View; -class ViewManager; - -enum SceneTransition { - kTransitionNone = 0, - kTransitionFadeIn = 1, - kTransitionFadeIn2 = 2, - kTransitionBoxInBottomLeft = 3, - kTransitionBoxInBottomRight = 4, - kTransitionBoxInTopLeft = 5, - kTransitionBoxInTopRight = 6, - kTransitionPanLeftToRight = 7, - kTransitionPanRightToLeft = 8, - kTransitionCircleIn = 9 -}; - -enum {SCREEN_DIALOG, SCREEN_BUFFER, SCREEN_TEXT, SCREEN_TRANSPARENT}; -enum ScreenEventType {SCREVENT_NONE = 0, SCREVENT_KEY = 1, SCREVENT_MOUSE = 2, SCREVENT_ALL = 3}; -enum ScreenLayers { - LAYER_BACKGROUND = 0, LAYER_DRIFTER = 1, LAYER_INTERFACE = 1, LAYER_FLOATER = 2, - LAYER_SURFACE = 3, LAYER_MENU = 9, LAYER_DIALOG = 10, LAYER_MOUSE = 15 -}; - -enum ViewIds { - VIEWID_MAINMENU = 1, - VIEWID_SCENE = 2, - VIEWID_TEXTVIEW = 3, - VIEWID_ANIMVIEW = 4, - VIEWID_MENU = 69, - VIEWID_CONVERSATION = 48, - VIEWID_INTERFACE = 49 -}; - -struct ScreenFlags { - bool visible:1; - bool transparent:1; - bool immovable:1; - - enum ScreenEventType blocks:2; - enum ScreenEventType get:2; - - uint layer:4; -}; - -#define SCREEN_FLAGS_DEFAULT _screenFlags.layer = LAYER_DRIFTER; \ - _screenFlags.get = SCREVENT_ALL; _screenFlags.blocks = SCREVENT_NONE; \ - _screenFlags.visible = true; -#define SCREEN_FLAGS_ALERT _screenFlags.layer = LAYER_FLOATER \ - _screenFlags.get = SCREVENT_ALL; _screenFlags.blocks = SCREVENT_ALL; \ - _screenFlags.visible = true; - -class RectList : public Common::Array { -public: - RectList(); - ~RectList(); - void addRect(int x1, int y1, int x2, int y2); - void addRect(const Common::Rect &rect); - -// Common::Rect& operator [](int idx) { return _rects[idx]; } - int find(const Common::Point &pt); -}; - -struct Hotkey { -public: - typedef void (*Callback)(MadsM4Engine *vm, View *view, uint32 key); - Hotkey(uint32 keyVal, Hotkey::Callback callbackFn) : key(keyVal), callback(callbackFn) {} - uint32 key; - Hotkey::Callback callback; -}; - -class HotkeyList { -public: - HotkeyList(View *owner); - ~HotkeyList(); - void add(uint32 key, Hotkey::Callback callback); - void remove(uint32 key); - bool call(uint32 key); -private: - Common::Array _hotkeys; - View *_view; -}; - -class View : public M4Surface { -public: - View(MadsM4Engine *vm, const Common::Rect &viewBounds, bool transparent = false); - View(MadsM4Engine *vm, int x = 0, int y = 0, bool transparent = false); - virtual ~View() {} - - void getCoordinates(Common::Rect &rect); - void extract(int *status); - virtual void show(); - virtual void hide(); - void moveToFront() {} - void moveToBack(); - void moveAbsolute(int x, int y); - void moveRelative(int x, int y); - void resize(int newWidth, int newHeight); - void restore(int x1, int y1, int x2, int y2); - - Common::Rect bounds() const { return _coords; } - bool isInside(int x, int y) const { return _coords.contains(x, y); } - ScreenFlags screenFlags() const { return _screenFlags; } - int screenType() const { return _screenType; } - bool isOffscreen() const { return !_screenFlags.visible; } - bool isTransparent() const { return _screenFlags.transparent; } - bool isVisible() const { return _screenFlags.visible; } - uint layer() const { return _screenFlags.layer; } - HotkeyList &hotkeys() { return _hotkeys; } - - virtual void onRefresh(RectList *rects, M4Surface *destSurface); - virtual bool onEvent(M4EventType eventType, int32 param, int x, int y, bool &captureEvents) { return false; } - virtual void updateState() {} - -protected: - MadsM4Engine *_vm; - Common::Rect _coords; - HotkeyList _hotkeys; - int _screenType; - ScreenFlags _screenFlags; - bool _transparent; -}; - -class ViewManager { -private: - MadsM4Engine *_vm; - HotkeyList _systemHotkeys; - Common::List _views; - View *_captureScreen; - bool _captureEvents; -public: - typedef Common::List::iterator ListIterator; - - ViewManager(MadsM4Engine *vm); - ~ViewManager(); - - void addView(View *view); - void deleteView(View *view); - - void handleEvents(const Common::Event &event); - void handleKeyboardEvents(uint32 keycode); - void handleMouseEvents(M4EventType event); - void restore(int x1, int y1, int x2, int y2); - void restore(const Common::Rect &rect); - - void moveToFront(View *view); - void moveToBack(View *view); - - Common::List views() const { return _views; } - bool contains(View *key) const { - return Common::find(_views.begin(), _views.end(), key) != _views.end(); - } - bool contains(int screenType) { return getView(screenType) != NULL; } - View *getView(int screenType); - int containsViews() { return !_views.empty(); } - - void showTextView(const char *textViewName, bool returnToMainMenu = true); - void showAnimView(const char *animViewName, bool returnToMainMenu = true); - - void updateState(); - void refreshAll(); - HotkeyList &systemHotkeys() { return _systemHotkeys; } -}; - -} - -#endif diff --git a/engines/m4/woodscript.cpp b/engines/m4/woodscript.cpp deleted file mode 100644 index 42f4fbce98..0000000000 --- a/engines/m4/woodscript.cpp +++ /dev/null @@ -1,398 +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 "m4/woodscript.h" - -#include "common/memstream.h" -#include "graphics/palette.h" - -namespace M4 { - -// FIXME: Put in Engine/WoodScript class -RGB8 _mainPalette[256]; - -//Woodscript Assembler/Compiler - -int32 Bytecode::_dataFormats[] = {0, 5, 8, 12, 16}; - -Bytecode::Bytecode(WoodScript *ws, byte *code, int32 codeSize, Sequence *seq) { - _ws = ws; - _code = new Common::MemoryReadStream(code, codeSize); - _sequence = seq; -} - -Bytecode::~Bytecode() { - delete _code; -} - -int Bytecode::loadInstruction(Instruction &instruction) { - - //debugCN(kDebugScript, "Bytecode::loadInstruction() ip = %08X\n", _code->pos()); - - int32 format, data; - uint32 code, code2; - - code = _code->readUint32LE(); - - instruction.instr = (code >> 25) & 0xFF; - instruction.argp[0] = NULL; - instruction.argp[1] = NULL; - instruction.argp[2] = NULL; - instruction.argc = 0; - - // Maybe make this a for-loop? - - format = (code >> 22) & 7; - if (format) { - /* Load argument 1 */ - data = code & 0xFFFF; - decodeArgument(format, data, instruction.argp[0], instruction.argv[0]); - instruction.argc++; - /* Load argument 2 */ - format = (code >> 19) & 7; - if (format) { - code2 = _code->readUint32LE(); - data = (code2 >> 16) & 0xFFFF; - decodeArgument(format, data, instruction.argp[1], instruction.argv[1]); - instruction.argc++; - /* Load argument 3 */ - format = (code >> 16) & 7; - if (format) { - data = code2 & 0xFFFF; - decodeArgument(format, data, instruction.argp[2], instruction.argv[2]); - instruction.argc++; - } - } - } - - return 0; //FIXME check if instruction size is needed by caller - -} - -void Bytecode::jumpAbsolute(int32 ofs) { - _code->seek(ofs * 4); - //debugCN(kDebugScript, "Bytecode::jumpAbsolute() ofs = %08X\n", _code->pos()); -} - -void Bytecode::jumpRelative(int32 ofs) { - _code->seek(ofs * 4, SEEK_CUR); -} - -void Bytecode::setSequence(Sequence *seq) { - _sequence = seq; -} - -void Bytecode::setCode(byte *code, int32 codeSize) { - delete _code; - _code = new Common::MemoryReadStream(code, codeSize); -} - -Sequence *Bytecode::sequence() const { - assert(_sequence); - return _sequence; -} - -bool Bytecode::decodeArgument(int32 format, int32 data, long *&arg, long &value) { - - int32 index; - - if (format == 1) { - if (data & 0x8000) - index = _sequence->indexReg(); - else - index = data & 0x0FFF; - switch (data & 0x7000) { - case 0x0000: - arg = sequence()->getParentVarPtr(index); - value = *arg; - break; - case 0x1000: - arg = sequence()->getVarPtr(index); - value = *arg; - break; - case 0x2000: - arg = sequence()->getDataPtr(index); - value = *arg; - break; - } - } else if (format == 2) { - if (data & 0x8000) - index = _sequence->indexReg(); - else - index = data & 0x0FFF; - arg = _ws->getGlobalPtr(index); - value = *arg; - } else { - if (data & 0x8000) { - value = -(data & 0x7FFF) << (_dataFormats[format - 3]); - } else { - value = (data & 0x7FFF) << (_dataFormats[format - 3]); - } - arg = &value; - } - - return true; -} - -WoodScript::WoodScript(MadsM4Engine *vm) { - _vm = vm; - _machineId = 0; - _assets = new AssetManager(vm); - _globals = new long[256]; //FIXME Find out how many globals there should be - memset(_globals, 0, sizeof(long)); - - _backgroundSurface = NULL; - - //Common::Rect viewBounds = Common::Rect(0, 0, 640, 480); - //_surfaceView = new View(viewBounds); -} - -WoodScript::~WoodScript() { - delete _assets; - delete[] _globals; -} - -Sequence *WoodScript::createSequence(Machine *machine, int32 sequenceHash) { - Sequence *sequence = new Sequence(this, machine, sequenceHash); - _sequences.push_back(sequence); - _layers.push_back(sequence); - return sequence; -} - -void WoodScript::runSequencePrograms() { - // A lot TODO - for (Common::Array::iterator it = _sequences.begin(); it != _sequences.end(); ++it) { - Sequence *sequence = *it; - if (sequence->isActive()) { - sequence->runProgram(); - if (sequence->isTerminated() && sequence->hasEndOfSequenceRequestPending()) { - _endOfSequenceRequestList.push_back(sequence); - } - } - } -} - -void WoodScript::runEndOfSequenceRequests() { -} - -void WoodScript::runTimerSequenceRequests() { -} - -Machine *WoodScript::createMachine(int32 machineHash, Sequence *parentSeq, - int32 dataHash, int32 dataRowIndex, int callbackHandler, const char *machineName) { - - //debugCN(kDebugScript, "WoodScript::createMachine(%d)\n", machineHash); - - Machine *machine = new Machine(this, machineHash, parentSeq, dataHash, dataRowIndex, callbackHandler, machineName, _machineId); - _machineId++; - - _machines.push_back(machine); - - // goto first state for initialization - machine->enterState(); - - return machine; -} - -int32 WoodScript::loadSeries(const char* seriesName, int32 hash, RGB8* palette) { - return _assets->addSpriteAsset(seriesName, hash, palette); -} - -void WoodScript::unloadSeries(int32 hash) { - _assets->clearAssets(kAssetTypeCELS, hash, hash); -} - -void WoodScript::setSeriesFramerate(Machine *machine, int32 frameRate) { -} - -Machine *WoodScript::playSeries(const char *seriesName, long layer, uint32 flags, int32 triggerNum, - int32 frameRate, int32 loopCount, int32 s, int32 x, int32 y, - int32 firstFrame, int32 lastFrame) { - - //debugCN(kDebugScript, "WoodScript::playSeries(%s)\n", seriesName); - - RGB8 *palette = NULL; - if (flags & SERIES_LOAD_PALETTE) - palette = &_mainPalette[0]; - - int32 spriteHash = _assets->addSpriteAsset(seriesName, -1, palette); - - _globals[kGlobTemp1] = (long)spriteHash << 24; - _globals[kGlobTemp2] = layer << 16; - _globals[kGlobTemp3] = _vm->_kernel->createTrigger(triggerNum); - _globals[kGlobTemp4] = frameRate << 16; - _globals[kGlobTemp5] = loopCount << 16; - _globals[kGlobTemp6] = (s << 16) / 100; - _globals[kGlobTemp7] = x << 16; - _globals[kGlobTemp8] = y << 16; - _globals[kGlobTemp9] = firstFrame << 16; - _globals[kGlobTemp10] = lastFrame << 16; - _globals[kGlobTemp11] = (flags & SERIES_PINGPONG) ? 0x10000 : 0; - _globals[kGlobTemp12] = (flags & SERIES_BACKWARD) ? 0x10000 : 0; - _globals[kGlobTemp13] = (flags & SERIES_RANDOM) ? 0x10000 : 0; - _globals[kGlobTemp14] = (flags & SERIES_STICK) ? 0x10000 : 0; - _globals[kGlobTemp15] = (flags & SERIES_LOOP_TRIGGER) ? 0x10000 : 0; - _globals[kGlobTemp16] = (flags & SERIES_HORZ_FLIP) ? 0x10000 : 0; - - return createMachine(0, NULL, -1, -1, kCallbackTriggerDispatch, seriesName); - -} - -Machine *WoodScript::showSeries(const char *seriesName, long layer, uint32 flags, int32 triggerNum, - int32 duration, int32 index, int32 s, int32 x, int32 y) { - - RGB8 *palette = NULL; - if (flags & SERIES_LOAD_PALETTE) - palette = &_mainPalette[0]; - - int32 spriteHash = _assets->addSpriteAsset(seriesName, -1, palette); - - _globals[kGlobTemp1] = spriteHash << 24; - _globals[kGlobTemp2] = layer << 16; - _globals[kGlobTemp3] = _vm->_kernel->createTrigger(triggerNum); - _globals[kGlobTemp4] = duration << 16; - _globals[kGlobTemp5] = index << 16; - _globals[kGlobTemp6] = (s << 16) / 100; - _globals[kGlobTemp7] = x << 16; - _globals[kGlobTemp8] = y << 16; - _globals[kGlobTemp14] = (flags & SERIES_STICK) ? 0x10000 : 0; - _globals[kGlobTemp16] = (flags & SERIES_HORZ_FLIP) ? 0x10000 : 0; - - return createMachine(1, NULL, -1, -1, kCallbackTriggerDispatch, seriesName); - -} - -Machine *WoodScript::streamSeries(const char *seriesName, int32 frameRate, long layer, int32 triggerNum) { - //debugCN(kDebugScript, "WoodScript::streamSeries(%s)\n", seriesName); - _globals[kGlobTemp1] = frameRate << 16; - /* FIXME: Single frames from a stream series will be decompressed on-the-fly, contrary to - "normal" sprite series, to save some memory, and since no random access to single - frames is needed, this is ok. - */ - _globals[kGlobTemp4] = 0; // The actual stream is opened in the Sequence - _globals[kGlobTemp5] = 0;//TODO: kernel_trigger_create(triggerNum); // trigger - _globals[kGlobTemp6] = layer << 16; // layer - return createMachine(6, NULL, -1, -1, kCallbackTriggerDispatch, seriesName); -} - -void WoodScript::update() { - // TODO: Don't show hidden sequences etc. - - // TODO: For now, prevent any engine action if a menu is being displayed - eventually this should be - // changed to a proper check of the engine paused variable, which the menus should set while active - if (_vm->_viewManager->getView(VIEWID_MENU) != NULL) - return; - - //TODO: Include _pauseTime - uint32 clockTime = g_system->getMillis() / 60; // FIXME: g_system - _globals[kGlobTimeDelta] = clockTime - _globals[kGlobTime]; - _globals[kGlobTime] += _globals[kGlobTimeDelta]; - - runSequencePrograms(); - - if (_backgroundSurface) { - // FIXME: For now, copy the whole surface. Later, copy only the rectangles that need updating. - _backgroundSurface->copyTo(_surfaceView); - } else { - // "This should never happen." - _surfaceView->fillRect(Common::Rect(0, 0, 640, 480), 0); - } - - { - // FIXME: This should be done when a new palette is set - byte palette[768]; - g_system->getPaletteManager()->grabPalette(palette, 0, 256); - for (int i = 0; i < 256; i++) { - _mainPalette[i].r = palette[i * 3 + 0]; - _mainPalette[i].g = palette[i * 3 + 1]; - _mainPalette[i].b = palette[i * 3 + 2]; - } - } - - for (Common::Array::iterator it = _layers.begin(); it != _layers.end(); ++it) { - Sequence *sequence = *it; - - // TODO: Use correct clipRect etc. - Common::Rect clipRect = Common::Rect(0, 0, 640, 480); - Common::Rect updateRect; - - sequence->draw(_surfaceView, clipRect, updateRect); - - } - - // Handle end-of-sequence requests - if (_endOfSequenceRequestList.size() > 0) { - for (Common::Array::iterator it = _endOfSequenceRequestList.begin(); it != _endOfSequenceRequestList.end(); ++it) { - Sequence *sequence = *it; - - EndOfSequenceRequestItem endOfSequenceRequestItem = sequence->getEndOfSequenceRequestItem(); - sequence->getMachine()->execBlock(endOfSequenceRequestItem.codeOffset, endOfSequenceRequestItem.count); - } - _endOfSequenceRequestList.clear(); - } - -} - -void WoodScript::clear() { - - for (Common::Array::iterator it = _sequences.begin(); it != _sequences.end(); ++it) - delete *it; - _sequences.clear(); - - for (Common::Array::iterator it = _machines.begin(); it != _machines.end(); ++it) - delete *it; - _machines.clear(); - - _layers.clear(); - _endOfSequenceRequestList.clear(); - -} - -void WoodScript::setDepthTable(int16 *depthTable) { - _depthTable = depthTable; -} - -long *WoodScript::getGlobalPtr(int index) { - return &_globals[index]; -} - -long WoodScript::getGlobal(int index) { - return _globals[index]; -} - -void WoodScript::setGlobal(int index, long value) { - _globals[index] = value; -} - -void WoodScript::setBackgroundSurface(M4Surface *backgroundSurface) { - _backgroundSurface = backgroundSurface; -} - -void WoodScript::setSurfaceView(View *view) { - _surfaceView = view; -} - -RGB8 *WoodScript::getMainPalette() const { - return _mainPalette; -} - -} diff --git a/engines/m4/woodscript.h b/engines/m4/woodscript.h deleted file mode 100644 index 95033b9179..0000000000 --- a/engines/m4/woodscript.h +++ /dev/null @@ -1,348 +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. - * - */ - -#ifndef M4_WOODSCRIPT_H -#define M4_WOODSCRIPT_H - -#include "common/scummsys.h" -#include "common/util.h" -#include "common/str.h" -#include "common/array.h" -#include "common/stream.h" -#include "graphics/surface.h" - -#include "m4/globals.h" -#include "m4/assets.h" -#include "m4/resource.h" -#include "m4/sprite.h" -#include "m4/m4.h" -#include "m4/graphics.h" -#include "m4/viewmgr.h" - -namespace M4 { - -class MadsM4Engine; -class WoodScript; -class Machine; -class Sequence; -class AssetManager; -class View; - -struct Instruction { - int32 instr; - long *argp[3]; - long argv[3]; - int argc; - // Helper method; many opcode functions can get either a defined value or a random value - long getValue() { - if (argc == 3) - return _vm->imath_ranged_rand16(argv[1], argv[2]); - else - return argv[1]; - } -}; - -class Bytecode { -public: - Bytecode(WoodScript *ws, byte *code, int32 codeSize, Sequence *seq); - ~Bytecode(); - int loadInstruction(Instruction &instruction); - void jumpAbsolute(int32 ofs); - void jumpRelative(int32 ofs); - void setSequence(Sequence *sequence); - void setCode(byte *code, int32 codeSize); - Sequence *sequence() const; - uint32 pos() const { return _code->pos() / 4; } -protected: - WoodScript *_ws; - Common::SeekableReadStream *_code; - Sequence *_sequence; - static int32 _dataFormats[]; - bool decodeArgument(int32 format, int32 data, long *&arg, long &value); -}; - -struct EndOfSequenceRequestItem { - int32 codeOffset, count; - EndOfSequenceRequestItem() : codeOffset(-1) {} - bool isValid() const { return codeOffset >= 0; } -}; - -typedef Common::Array EndOfSequenceRequestList; - -class Sequence { -public: - Sequence(WoodScript *ws, Machine *machine, int32 sequenceHash); - ~Sequence(); - - void pause(); - void resume(); - void issueEndOfSequenceRequest(int32 codeOffset, int32 count); - void cancelEndOfSequenceRequest(); - - bool runProgram(); - - bool changeProgram(int32 sequenceHash); - - void clearVars(); - - long *getVarPtr(int index); - long *getParentVarPtr(int index); - long *getDataPtr(int index); - - void setActive(bool active) { _active = active; } - bool isActive() const { return _active; } - - bool isTerminated() const { return _terminated; } - - void draw(M4Surface *surface, const Common::Rect &clipRect, Common::Rect &updateRect); - - bool s1_end(Instruction &instruction); - bool s1_clearVars(Instruction &instruction); - bool s1_set(Instruction &instruction); - bool s1_compare(Instruction &instruction); - bool s1_add(Instruction &instruction); - bool s1_sub(Instruction &instruction); - bool s1_mul(Instruction &instruction); - bool s1_div(Instruction &instruction); - bool s1_and(Instruction &instruction); - bool s1_or(Instruction &instruction); - bool s1_not(Instruction &instruction); - bool s1_sin(Instruction &instruction); - bool s1_cos(Instruction &instruction); - bool s1_abs(Instruction &instruction); - bool s1_min(Instruction &instruction); - bool s1_max(Instruction &instruction); - bool s1_mod(Instruction &instruction); - bool s1_floor(Instruction &instruction); - bool s1_round(Instruction &instruction); - bool s1_ceil(Instruction &instruction); - bool s1_point(Instruction &instruction); - bool s1_dist2d(Instruction &instruction); - bool s1_crunch(Instruction &instruction); - bool s1_branch(Instruction &instruction); - bool s1_setFrame(Instruction &instruction); - bool s1_sendMessage(Instruction &instruction); - bool s1_push(Instruction &instruction); - bool s1_pop(Instruction &instruction); - bool s1_jumpSub(Instruction &instruction); - bool s1_return(Instruction &instruction); - bool s1_getFrameCount(Instruction &instruction); - bool s1_getFrameRate(Instruction &instruction); - bool s1_getCelsPixSpeed(Instruction &instruction); - bool s1_setIndex(Instruction &instruction); - bool s1_setLayer(Instruction &instruction); - bool s1_setDepth(Instruction &instruction); - bool s1_setData(Instruction &instruction); - bool s1_openStream(Instruction &instruction); - bool s1_streamNextFrame(Instruction &instruction); - bool s1_closeStream(Instruction &instruction); - - int32 indexReg() const { return _indexReg; } - - EndOfSequenceRequestItem getEndOfSequenceRequestItem() const { return _endOfSequenceRequest; } - bool hasEndOfSequenceRequestPending() const { return _endOfSequenceRequest.isValid(); } - void resetEndOfSequenceRequest() { _endOfSequenceRequest.codeOffset = -1; } - - Machine *getMachine() const { return _machine; } - - -protected: - WoodScript *_ws; - Bytecode *_code; - - long *_vars; - bool _active, _terminated; - Machine *_machine; - Sequence *_parentSequence; - int32 _layer; - int32 _startTime, _switchTime; - long *_dataRow; - int32 _localVarCount; - int32 _cmpFlags; - - EndOfSequenceRequestItem _endOfSequenceRequest; - - int32 _indexReg; - - M4Sprite *_curFrame; - - int32 _sequenceHash; - - int32 _returnHashes[8]; //FIXME: Use constant instead of 8 - uint32 _returnOffsets[8]; - int32 _returnStackIndex; - - Common::SeekableReadStream *_stream; - SpriteAsset *_streamSpriteAsset; - - bool streamOpen(); - bool streamNextFrame(); - void streamClose(); - -}; - -class Machine { -public: - Machine(WoodScript *ws, int32 machineHash, Sequence *parentSeq, int32 dataHash, - int32 dataRowIndex, int callbackHandler, Common::String machineName, int32 id); - ~Machine(); - - void clearMessages(); - void clearPersistentMessages(); - void restorePersistentMessages(); - void sendMessage(uint32 messageHash, long messageValue, Machine *sender); - void resetSwitchTime(); - bool changeSequenceProgram(int32 sequenceHash); - - bool searchMessages(uint32 messageHash, uint32 messageValue, Machine *sender); - bool searchPersistentMessages(uint32 messageHash, uint32 messageValue, Machine *sender); - - void enterState(); - int32 execInstruction(); - void execBlock(int32 offset, int32 count); - int32 getState() { return _currentState; } - - int32 getId() const { return _id; } - - bool m1_gotoState(Instruction &instruction); - bool m1_jump(Instruction &instruction); - bool m1_terminate(Instruction &instruction); - bool m1_startSequence(Instruction &instruction); - bool m1_pauseSequence(Instruction &instruction); - bool m1_resumeSequence(Instruction &instruction); - bool m1_storeValue(Instruction &instruction); - bool m1_sendMessage(Instruction &instruction); - bool m1_broadcastMessage(Instruction &instruction); - bool m1_replyMessage(Instruction &instruction); - bool m1_sendSystemMessage(Instruction &instruction); - bool m1_createMachine(Instruction &instruction); - bool m1_createMachineEx(Instruction &instruction); - bool m1_clearVars(Instruction &instruction); - - void m1_onEndSequence(Instruction &instruction); - void m1_onMessage(Instruction &instruction); - void m1_switchLt(Instruction &instruction); - void m1_switchLe(Instruction &instruction); - void m1_switchEq(Instruction &instruction); - void m1_switchNe(Instruction &instruction); - void m1_switchGe(Instruction &instruction); - void m1_switchGt(Instruction &instruction); - - long *dataRow() const { return _dataRow; } - Sequence *parentSequence() const { return _parentSequence; } - Common::String name() const { return _name; } - -protected: - WoodScript *_ws; - Bytecode *_code; - - Common::String _name; - Sequence *_sequence, *_parentSequence; - byte *_mach; - int32 _machHash, _machineCodeOffset; - int32 _stateCount, _stateTableOffset; - long *_dataRow; - int32 _id, _recursionLevel, _currentState, _targetCount; - /* TODO: - m->msgReplyXM = NULL; - m->CintrMsg = CintrMsg; - _walkPath - _messages - _persistentMessages - _usedPersistentMessages - */ -}; - -class WoodScript { -public: - - WoodScript(MadsM4Engine *vm); - ~WoodScript(); - - Machine *createMachine(int32 machineHash, Sequence *parentSeq, int32 dataHash, int32 dataRowIndex, int callbackHandler, const char *machineName); - Sequence *createSequence(Machine *machine, int32 sequenceHash); - - void runSequencePrograms(); - void runEndOfSequenceRequests(); - void runTimerSequenceRequests(); - - /* Series */ - // Move to own class, e.g. SeriesPlayer - int32 loadSeries(const char* seriesName, int32 hash, RGB8* palette); - void unloadSeries(int32 hash); - void setSeriesFramerate(Machine *machine, int32 frameRate); - Machine *playSeries(const char *seriesName, long layer, uint32 flags, int32 triggerNum, - int32 frameRate, int32 loopCount, int32 s, int32 x, int32 y, - int32 firstFrame, int32 lastFrame); - Machine *showSeries(const char *seriesName, long layer, uint32 flags, int32 triggerNum, - int32 duration, int32 index, int32 s, int32 x, int32 y); - Machine *streamSeries(const char *seriesName, int32 frameRate, long layer, int32 triggerNum); - - void update(); - void clear(); - - /* Misc */ - void setDepthTable(int16 *depthTable); - - long *getGlobalPtr(int index); - long getGlobal(int index); - void setGlobal(int index, long value); - - AssetManager *assets() const { return _assets; } - - // Sets the untouched, clean surface which contains the room background - void setBackgroundSurface(M4Surface *backgroundSurface); - // Sets the view which is used for drawing - void setSurfaceView(View *view); - - RGB8 *getMainPalette() const; - - void setInverseColorTable(byte *inverseColorTable) { _inverseColorTable = inverseColorTable; } - byte *getInverseColorTable() const { return _inverseColorTable; } - -protected: - MadsM4Engine *_vm; - AssetManager *_assets; - - Common::Array _sequences, _layers; - Common::Array _machines; - int32 _machineId; - - long *_globals; - - Common::Array _endOfSequenceRequestList; - - int32 _indexReg; - - /* Misc */ - int16 *_depthTable; - byte *_inverseColorTable; - M4Surface *_backgroundSurface; - View *_surfaceView; - -}; - - -} // End of namespace M4 - - -#endif diff --git a/engines/m4/ws_machine.cpp b/engines/m4/ws_machine.cpp deleted file mode 100644 index 18a8af76a8..0000000000 --- a/engines/m4/ws_machine.cpp +++ /dev/null @@ -1,423 +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 "m4/woodscript.h" - -namespace M4 { - -bool (Machine::*machineCommandsTable[])(Instruction &instruction) = { - NULL, - NULL,//TODO: nop - &Machine::m1_gotoState, - &Machine::m1_jump, - &Machine::m1_terminate, - &Machine::m1_startSequence, - &Machine::m1_pauseSequence, - &Machine::m1_resumeSequence, - &Machine::m1_storeValue, - &Machine::m1_sendMessage, - &Machine::m1_broadcastMessage, - &Machine::m1_replyMessage, - &Machine::m1_sendSystemMessage, - &Machine::m1_createMachine, - &Machine::m1_createMachineEx, - &Machine::m1_clearVars -}; - -void (Machine::*machineConditionalsTable[])(Instruction &instruction) = { - NULL,//TODO: after - &Machine::m1_onEndSequence, - &Machine::m1_onMessage, - NULL,//TODO: on_p_msg - &Machine::m1_switchLt, - &Machine::m1_switchLe, - &Machine::m1_switchEq, - &Machine::m1_switchNe, - &Machine::m1_switchGe, - &Machine::m1_switchGt, -}; - -Machine::Machine(WoodScript *ws, int32 machineHash, Sequence *parentSeq, int32 dataHash, - int32 dataRowIndex, int callbackHandler, Common::String machineName, int32 id) { - - _ws = ws; - - _machHash = machineHash; - _name = machineName; - _id = id; - - // initialize the machine's bytecode - MachineAsset *machineAsset = _ws->assets()->getMachine(_machHash); - byte *code; - uint32 codeSize; - machineAsset->getCode(code, codeSize); - _code = new Bytecode(_ws, code, codeSize, NULL); - - // initialize the machine's data - if (dataHash >= 0) { - DataAsset *dataAsset = _ws->assets()->getData(dataHash); - _dataRow = dataAsset->getRow(dataRowIndex); - } else { - _dataRow = NULL; - } - - _recursionLevel = 0; - _currentState = 0; - _sequence = NULL; - _parentSequence = parentSeq; - _targetCount = 0; - -} - -Machine::~Machine() { - delete _code; -} - -void Machine::clearMessages() { -} - -void Machine::clearPersistentMessages() { -} - -void Machine::restorePersistentMessages() { -} - -void Machine::sendMessage(uint32 messageHash, long messageValue, Machine *sender) { -} - -void Machine::resetSwitchTime() { -} - -bool Machine::changeSequenceProgram(int32 sequenceHash) { - return _sequence->changeProgram(sequenceHash); -} - -bool Machine::searchMessages(uint32 messageHash, uint32 messageValue, Machine *sender) { - return false; -} - -bool Machine::searchPersistentMessages(uint32 messageHash, uint32 messageValue, Machine *sender) { - return false; -} - -void Machine::enterState() { - - MachineAsset *machineAsset = _ws->assets()->getMachine(_machHash); - - _code->jumpAbsolute(machineAsset->getStateOffset(_currentState)); - - int32 instruction = -1; - - _recursionLevel++; - - int32 oldId = _id; - int32 oldRecursionLevel = _recursionLevel; - - while (instruction && instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel) { - instruction = execInstruction(); - } - - if (instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel) { - _recursionLevel--; - } - -} - -int32 Machine::execInstruction() { - - //debugCN(kDebugScript, "Machine::execInstruction()\n"); - - bool done = false; - Instruction instruction; - //Sequence *sequence; - int32 machID = _id; - - _code->loadInstruction(instruction); - - if (instruction.instr >= 64) { - if (machineConditionalsTable[instruction.instr - 64] != 0) - (this->*machineConditionalsTable[instruction.instr - 64])(instruction); - /* The next line is to yield on unimplemented opcodes */ - else { - g_system->delayMillis(5000); - } - } else if (instruction.instr > 0) { - if (machineCommandsTable[instruction.instr] != 0) - done = !(this->*machineCommandsTable[instruction.instr])(instruction); - /* The next line is to yield on unimplemented opcodes */ - else { - g_system->delayMillis(5000); - } - if (done) { - if (_id == machID) { - //TODO: Cancel all requests - if (_currentState == -1) { - // TODO: Set terminated flag and delete machine in WoodScript update - } - else { - // initialize new state - enterState(); - } - } - } - } - - return instruction.instr; - -} - -void Machine::execBlock(int32 offset, int32 count) { - - // MachineAsset *machineAsset = _ws->assets()->getMachine(_machHash); - - int32 startOffset = offset, endOffset = offset + count; - - _recursionLevel++; - - int32 oldId = _id; - int32 oldRecursionLevel = _recursionLevel; - - _code->jumpAbsolute(offset); - - int32 instruction = -1; - - //debugCN(kDebugScript, "---------------------------------------\n"); - - while (instruction && instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel && - _code->pos() >= (uint32)startOffset && _code->pos() < (uint32)endOffset) { - - instruction = execInstruction(); - //g_system->delayMillis(500); - } - - //debugCN(kDebugScript, "---------------------------------------\n"); - - if (instruction == 3) { - execInstruction(); - } - - if (instruction != 4 && _id == oldId && _recursionLevel == oldRecursionLevel) { - _recursionLevel--; - } - -} - -bool Machine::m1_gotoState(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_gotoState() state = %d\n", (int32)instruction.argv[0] >> 16); - - _currentState = (int32)instruction.argv[0] >> 16; - _recursionLevel = 0; - return false; -} - -bool Machine::m1_jump(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_jump() ofs = %08X\n", (int32)instruction.argv[0] >> 16); - - _code->jumpRelative((int32)instruction.argv[0] >> 16); - return true; -} - -bool Machine::m1_terminate(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_terminate()\n"); - - _currentState = -1; - _recursionLevel = 0; - return false; -} - -bool Machine::m1_startSequence(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_startSequence() sequence hash = %d\n", (uint32)instruction.argv[0] >> 16); - - int32 sequenceHash = instruction.argv[0] >> 16; - if (_sequence == NULL) { - //debugCN(kDebugScript, "Machine::m1_startSequence() creating new sequence\n"); - _sequence = _ws->createSequence(this, sequenceHash); - _code->setSequence(_sequence); - } else { - //debugCN(kDebugScript, "Machine::m1_startSequence() using existing sequence\n"); - _sequence->changeProgram(sequenceHash); - //_code->setSequence(_sequence); - } - return true; -} - -bool Machine::m1_pauseSequence(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_pauseSequence()\n"); - - _sequence->pause(); - return true; -} - -bool Machine::m1_resumeSequence(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_resumeSequence()\n"); - - _sequence->resume(); - return true; -} - -bool Machine::m1_storeValue(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_storeValue() %p = %d (%08X)\n", (void*)instruction.argp[0], (uint32)instruction.argv[1], (uint32)instruction.argv[1]); - - *instruction.argp[0] = instruction.getValue(); - return true; -} - -bool Machine::m1_sendMessage(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_sendMessage() %p = %d (%08X)\n", (void*)instruction.argp[0], (uint32)instruction.argv[1], (uint32)instruction.argv[1]); - -#if 0 -//TODO - long messageValue; - - if (instruction.argc == 3) { - messageValue = instruction.argv[2]; - } else { - messageValue = 0; - } - //_ws->sendMessage((uint32)instruction.argv[1], messageValue, (uint32)instruction.argv[0] >> 16); - //void SendWSMessage(uint32 msgHash, long msgValue, machine *recvM, uint32 machHash, machine *sendM, int32 msgCount) { -#endif - return true; - -} - -bool Machine::m1_broadcastMessage(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_broadcastMessage() %p = %d (%08X)\n", (void*)instruction.argp[0], (uint32)instruction.argv[1], (uint32)instruction.argv[1]); - -#if 0 -//TODO - long messageValue; - - if (instruction.argc == 3) { - messageValue = instruction.argv[2]; - } else { - messageValue = 0; - } - //_ws->sendMessage((uint32)instruction.argv[1], messageValue, (uint32)instruction.argv[0] >> 16); -#endif - return true; -} - -bool Machine::m1_replyMessage(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_replyMessage() messageHash = %d; messageValue = %d\n", (uint32)instruction.argv[0], (uint32)instruction.argv[1]); -#if 0 - if (myArg2) { - msgValue = *myArg2; - } - else { - msgValue = 0; - } - SendWSMessage(*myArg1, msgValue, m->msgReplyXM, 0, m, 1); -#endif - return true; -} - -bool Machine::m1_sendSystemMessage(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_sendSystemMessage() messageValue = %d\n", (uint32)instruction.argv[0]); -#if 0 -#endif - return true; -} - -bool Machine::m1_createMachine(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_createMachine()\n"); -#if 0 -#endif - return true; -} - -bool Machine::m1_createMachineEx(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_createMachineEx()\n"); -#if 0 -#endif - return true; -} - -bool Machine::m1_clearVars(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_clearVars()\n"); - - _sequence->clearVars(); - return true; -} - - -void Machine::m1_onEndSequence(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_onEndSequence() count = %08X\n", (uint32)instruction.argv[0] >> 16); - - int32 count = instruction.argv[0] >> 16; - _sequence->issueEndOfSequenceRequest(_code->pos(), count); - _code->jumpRelative(count); -} - -void Machine::m1_onMessage(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_onEndSequence() count = %08X\n", (uint32)instruction.argv[0] >> 16); - - // TODO: Add message to list - - int32 count = instruction.argv[0] >> 16; - _code->jumpRelative(count); - -} - -void Machine::m1_switchLt(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_switchLt() %d < %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); - - if (instruction.argv[1] >= instruction.argv[2]) - _code->jumpRelative(instruction.argv[0] >> 16); -} - -void Machine::m1_switchLe(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_switchLe() %d <= %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); - - if (instruction.argv[1] > instruction.argv[2]) - _code->jumpRelative(instruction.argv[0] >> 16); -} - -void Machine::m1_switchEq(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_switchEq() %d == %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); - - if (instruction.argv[1] != instruction.argv[2]) - _code->jumpRelative(instruction.argv[0] >> 16); -} - -void Machine::m1_switchNe(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_switchNe() %d != %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); - - if (instruction.argv[1] == instruction.argv[2]) - _code->jumpRelative(instruction.argv[0] >> 16); -} - -void Machine::m1_switchGe(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_switchGe() %d >= %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); - - if (instruction.argv[1] < instruction.argv[2]) - _code->jumpRelative(instruction.argv[0] >> 16); -} - -void Machine::m1_switchGt(Instruction &instruction) { - //debugCN(kDebugScript, "Machine::m1_switchGt() %d > %d -> %08X\n", (uint32)instruction.argv[1], (uint32)instruction.argv[2], (uint32)instruction.argv[0] >> 16); - - if (instruction.argv[1] <= instruction.argv[2]) - _code->jumpRelative(instruction.argv[0] >> 16); -} - -} diff --git a/engines/m4/ws_sequence.cpp b/engines/m4/ws_sequence.cpp deleted file mode 100644 index 01776ef6ec..0000000000 --- a/engines/m4/ws_sequence.cpp +++ /dev/null @@ -1,768 +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 "m4/woodscript.h" - -namespace M4 { - -static const long sinCosTable[320] = { - 0, 1608, 3215, 4821, 6423, 8022, 9616, 11204, - 12785, 14359, 15923, 17479, 19024, 20557, 22078, 23586, - 25079, 26557, 28020, 29465, 30893, 32302, 33692, 35061, - 36409, 37736, 39039, 40319, 41575, 42806, 44011, 45189, - 46340, 47464, 48558, 49624, 50660, 51665, 52639, 53581, - 54491, 55368, 56212, 57022, 57797, 58538, 59243, 59913, - 60547, 61144, 61705, 62228, 62714, 63162, 63571, 63943, - 64276, 64571, 64826, 65043, 65220, 65358, 65457, 65516, - 65536, 65516, 65457, 65358, 65220, 65043, 64826, 64571, - 64276, 63943, 63571, 63162, 62714, 62228, 61705, 61144, - 60547, 59913, 59243, 58538, 57797, 57022, 56212, 55368, - 54491, 53581, 52639, 51665, 50660, 49624, 48558, 47464, - 46340, 45189, 44011, 42806, 41575, 40319, 39039, 37736, - 36409, 35061, 33692, 32302, 30893, 29465, 28020, 26557, - 25079, 23586, 22078, 20557, 19024, 17479, 15923, 14359, - 12785, 11204, 9616, 8022, 6423, 4821, 3215, 1608, - 0, -1608, -3215, -4821, -6423, -8022, -9616, -11204, - -12785, -14359, -15923, -17479, -19024, -20557, -22078, -23586, - -25079, -26557, -28020, -29465, -30893, -32302, -33692, -35061, - -36409, -37736, -39039, -40319, -41575, -42806, -44011, -45189, - -46340, -47464, -48558, -49624, -50660, -51665, -52639, -53581, - -54491, -55368, -56212, -57022, -57797, -58538, -59243, -59913, - -60547, -61144, -61705, -62228, -62714, -63162, -63571, -63943, - -64276, -64571, -64826, -65043, -65220, -65358, -65457, -65516, - -65536, -65516, -65457, -65358, -65220, -65043, -64826, -64571, - -64276, -63943, -63571, -63162, -62714, -62228, -61705, -61144, - -60547, -59913, -59243, -58538, -57797, -57022, -56212, -55368, - -54491, -53581, -52639, -51665, -50660, -49624, -48558, -47464, - -46340, -45189, -44011, -42806, -41575, -40319, -39039, -37736, - -36409, -35061, -33692, -32302, -30893, -29465, -28020, -26557, - -25079, -23586, -22078, -20557, -19024, -17479, -15923, -14359, - -12785, -11204, -9616, -8022, -6423, -4821, -3215, -1608, - 0, 1608, 3215, 4821, 6423, 8022, 9616, 11204, - 12785, 14359, 15923, 17479, 19024, 20557, 22078, 23586, - 25079, 26557, 28020, 29465, 30893, 32302, 33692, 35061, - 36409, 37736, 39039, 40319, 41575, 42806, 44011, 45189, - 46340, 47464, 48558, 49624, 50660, 51665, 52639, 53581, - 54491, 55368, 56212, 57022, 57797, 58538, 59243, 59913, - 60547, 61144, 61705, 62228, 62714, 63162, 63571, 63943, - 64276, 64571, 64826, 65043, 65220, 65358, 65457, 65516 -}; - -const long *sinTable = &(sinCosTable[0]); -const long *cosTable = &(sinCosTable[64]); - -// FIXME: Tables - -const int sequenceVariableCount = 33; - -enum SequenceVariables { - kSeqVarTimer = 0, - kSeqVarTag = 1, - kSeqVarLayer = 2, - kSeqVarWidth = 3, - kSeqVarHeight = 4, - kSeqVarX = 5, - kSeqVarY = 6, - kSeqVarScale = 7, - kSeqVarR = 8, - kSeqVarSpriteHash = 9, - kSeqVarSpriteFrameNumber = 10, - kSeqVarSpriteFrameCount = 11, - kSeqVarSpriteFrameRate = 12, - kSeqVarSpriteFramePixelSpeed = 13, - kSeqVarTargetS = 14, - kSeqVarTargetR = 15, - kSeqVarTargetX = 16, - kSeqVarTargetY = 17, - kSeqVarDeltaS = 18, - kSeqVarDeltaR = 19, - kSeqVarDeltaX = 20, - kSeqVarDeltaY = 21, - kSeqVarVelocity = 22, - kSeqVarTheta = 23, - kSeqVarTemp1 = 24, - kSeqVarTemp2 = 25, - kSeqVarTemp3 = 26, - kSeqVarTemp4 = 27, - kSeqVarTemp5 = 28, - kSeqVarTemp6 = 29, - kSeqVarTemp7 = 30, - kSeqVarTemp8 = 31, - kSeqVarMachineID = 32 -}; - -bool (Sequence::*sequenceCommandsTable[])(Instruction &instruction) = { - &Sequence::s1_end, - &Sequence::s1_clearVars, - &Sequence::s1_set, - &Sequence::s1_compare, - &Sequence::s1_add, - &Sequence::s1_sub, - &Sequence::s1_mul, - &Sequence::s1_div, - &Sequence::s1_and, - &Sequence::s1_or, - &Sequence::s1_not, - &Sequence::s1_sin, - &Sequence::s1_cos, - &Sequence::s1_abs, - &Sequence::s1_min, - &Sequence::s1_max, - &Sequence::s1_mod, - &Sequence::s1_floor, - &Sequence::s1_round, - &Sequence::s1_ceil, - &Sequence::s1_point, - &Sequence::s1_dist2d, - &Sequence::s1_crunch, - &Sequence::s1_branch, - &Sequence::s1_setFrame, - &Sequence::s1_sendMessage, - &Sequence::s1_push, - &Sequence::s1_pop, - &Sequence::s1_jumpSub, - &Sequence::s1_return, - &Sequence::s1_getFrameCount, - &Sequence::s1_getFrameRate, - &Sequence::s1_getCelsPixSpeed, - &Sequence::s1_setIndex, - &Sequence::s1_setLayer, - &Sequence::s1_setDepth, - &Sequence::s1_setData, - &Sequence::s1_openStream, - &Sequence::s1_streamNextFrame, - &Sequence::s1_closeStream -}; - -Sequence::Sequence(WoodScript *ws, Machine *machine, int32 sequenceHash) { - - _ws = ws; - - SequenceAsset *sequenceAsset = _ws->assets()->getSequence(sequenceHash); - - // initialize the sequence's bytecode - byte *code; - uint32 codeSize; - sequenceAsset->getCode(code, codeSize); - _code = new Bytecode(_ws, code, codeSize, this); - - _active = true; - _sequenceHash = sequenceHash; - _machine = machine; - _parentSequence = _machine->parentSequence(); - _dataRow = _machine->dataRow(); - _startTime = 0; - _switchTime = 0; - //TODO _flags = 0; - _localVarCount = sequenceAsset->localVarCount(); - _vars = new long[sequenceVariableCount + _localVarCount]; - _returnStackIndex = 0; - _layer = 0; - _terminated = false; - - clearVars(); - _vars[kSeqVarMachineID] = _machine->getId(); - -} - -Sequence::~Sequence() { - delete _code; -} - -void Sequence::pause() { - _active = false; -} - -void Sequence::resume() { - _active = true; -} - -void Sequence::issueEndOfSequenceRequest(int32 codeOffset, int32 count) { - - //debugCN(kDebugScript, "Sequence::issueEndOfSequenceRequest(%04X, %04X)\n", codeOffset, count); - //g_system->delayMillis(5000); - - _endOfSequenceRequest.codeOffset = codeOffset; - _endOfSequenceRequest.count = count; -} - -void Sequence::cancelEndOfSequenceRequest() { - _endOfSequenceRequest.codeOffset = -1; -} - -bool Sequence::runProgram() { - - bool done = true; - - //debugCN(kDebugScript, "_ws->getGlobal(kGlobTime) = %ld, _switchTime = %d\n", _ws->getGlobal(kGlobTime), _switchTime); - - if (_switchTime >= 0 && _ws->getGlobal(kGlobTime) >= _switchTime) - done = false; - - _vars[kSeqVarTimer] -= _ws->getGlobal(kGlobTimeDelta) << 16; - - while (!done) { - Instruction instruction; - _code->loadInstruction(instruction); - if (sequenceCommandsTable[instruction.instr] != 0) - done = !(this->*sequenceCommandsTable[instruction.instr])(instruction); - else { - //g_system->delayMillis(1000); - } - } - - return _terminated; -} - -void Sequence::clearVars() { - for (int i = 0; i < sequenceVariableCount + _localVarCount; i++) - _vars[i] = 0; - // set default scaling to 100% - _vars[kSeqVarScale] = 0x10000; -} - -bool Sequence::changeProgram(int32 sequenceHash) { - - SequenceAsset *sequenceAsset = _ws->assets()->getSequence(sequenceHash); - - if (sequenceAsset->localVarCount() > _localVarCount) { - //debugCN(kDebugScript, "Sequence::changeProgram(%d) sequenceAsset->localVarCount() > _localVarCount\n", sequenceHash); - return false; - } - - // Initialize the sequence's bytecode - byte *code; - uint32 codeSize; - sequenceAsset->getCode(code, codeSize); - _code->setCode(code, codeSize); - - // Reset status variables - _switchTime = 0; - _active = true; - _terminated = false; - _endOfSequenceRequest.codeOffset = -1; - - _sequenceHash = sequenceHash; - _returnStackIndex = 0; - - return true; - -} - -long *Sequence::getVarPtr(int index) { - return &_vars[index]; -} - -long *Sequence::getParentVarPtr(int index) { - return _parentSequence->getVarPtr(index); -} - -long *Sequence::getDataPtr(int index) { - return &_dataRow[index]; -} - -void Sequence::draw(M4Surface *surface, const Common::Rect &clipRect, Common::Rect &updateRect) { - - SpriteInfo info; - - info.sprite = _curFrame; - info.hotX = _curFrame->xOffset; - info.hotY = _curFrame->yOffset; - info.encoding = _curFrame->encoding; - info.inverseColorTable = _m4Vm->scene()->getInverseColorTable(); - info.palette = _ws->getMainPalette(); - info.width = _curFrame->width(); - info.height = _curFrame->height(); - int32 scaler = FixedMul(_vars[kSeqVarScale], 100 << 16) >> 16; - info.scaleX = _vars[kSeqVarWidth] < 0 ? -scaler : scaler; - info.scaleY = scaler; - surface->drawSprite(_vars[kSeqVarX] >> 16, _vars[kSeqVarY] >> 16, info, clipRect); - -} - -bool Sequence::s1_end(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_end()\n"); - - _terminated = true; - return false; -} - -bool Sequence::s1_clearVars(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_clearVars()\n"); - - clearVars(); - _vars[kSeqVarMachineID] = _machine->getId(); - return true; -} - -bool Sequence::s1_set(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_set()\n"); - - *instruction.argp[0] = instruction.getValue(); - return true; -} - -bool Sequence::s1_compare(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_compare()\n"); - - long value = instruction.getValue(); - if (instruction.argv[0] < value) - _cmpFlags = -1; - else if (instruction.argv[0] > value) - _cmpFlags = 1; - else - _cmpFlags = 0; - return true; -} - -bool Sequence::s1_add(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_add()\n"); - - *instruction.argp[0] += instruction.getValue(); - return true; -} - -bool Sequence::s1_sub(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_sub()\n"); - - *instruction.argp[0] -= instruction.getValue(); - return true; -} - -bool Sequence::s1_mul(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_mul()\n"); - - *instruction.argp[0] = FixedMul(instruction.argv[0], instruction.getValue()); - return true; -} - -bool Sequence::s1_div(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_div()\n"); - - // TODO: Catch divisor = 0 in FixedDiv - *instruction.argp[0] = FixedDiv(instruction.argv[0], instruction.getValue()); - return true; -} - -bool Sequence::s1_and(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_and()\n"); - - *instruction.argp[0] = instruction.argv[0] & instruction.getValue(); - if (*instruction.argp[0]) - _cmpFlags = 0; - else - _cmpFlags = 1; - return true; -} - -bool Sequence::s1_or(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_or()\n"); - - *instruction.argp[0] = instruction.argv[0] | instruction.getValue(); - if (*instruction.argp[0]) - _cmpFlags = 0; - else - _cmpFlags = 1; - return true; -} - -bool Sequence::s1_not(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_not()\n"); - - if (instruction.argv[0] == 0) { - *instruction.argp[0] = 0x10000; - _cmpFlags = 1; - } else { - *instruction.argp[0] = 0; - _cmpFlags = 0; - } - return true; -} - -bool Sequence::s1_sin(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_sin()\n"); - - int32 tempAngle = *instruction.argp[1] >> 16; - if (tempAngle < 0) - tempAngle = 0x0100 - ((-tempAngle) & 0xff); - else - tempAngle &= 0xff; - - // FIXME: Why use the cosTable in s1_sin() ? - // Note that sin(0) 0 and sinTable[0] = 0 but cos(0)=1, and indeed - // cosTable[0] = 65536, which is 1 considered as a fixed point. - *instruction.argp[0] = -cosTable[tempAngle]; - - return true; -} - -bool Sequence::s1_cos(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_cos()\n"); - - int32 tempAngle = *instruction.argp[1] >> 16; - if (tempAngle < 0) - tempAngle = 0x0100 - ((-tempAngle) & 0xff); - else - tempAngle &= 0xff; - - // FIXME: Why use the sinTable in s1_cos() ? - // Note that sin(0) 0 and sinTable[0] = 0 but cos(0)=1, and indeed - // cosTable[0] = 65536, which is 1 considered as a fixed point. - *instruction.argp[0] = sinTable[tempAngle]; - - return true; -} - -bool Sequence::s1_abs(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_abs()\n"); - - *instruction.argp[0] = ABS(instruction.argv[1]); - return true; -} - -bool Sequence::s1_min(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_min()\n"); - - *instruction.argp[0] = MIN(instruction.argv[1], instruction.argv[2]); - return true; -} - -bool Sequence::s1_max(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_max()\n"); - - *instruction.argp[0] = MAX(instruction.argv[1], instruction.argv[2]); - return true; -} - -bool Sequence::s1_mod(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_mod()\n"); - - *instruction.argp[0] = instruction.argv[0] % instruction.getValue(); - return true; -} - -bool Sequence::s1_floor(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_floor()\n"); - - *instruction.argp[0] = instruction.getValue() & 0xffff0000; - return true; -} - -bool Sequence::s1_round(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_round()\n"); - - if ((*instruction.argp[1] & 0xffff) >= 0x8000) - *instruction.argp[0] = (*instruction.argp[1] + 0x10000) & 0xffff0000; - else - *instruction.argp[0] = *instruction.argp[1] & 0xffff0000; - return true; -} - -bool Sequence::s1_ceil(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_ceil()\n"); - - if ((*instruction.argp[1] & 0xffff) >= 0) - *instruction.argp[0] = (*instruction.argp[1] + 0x10000) & 0xffff0000; - else - *instruction.argp[0] = *instruction.argp[1] & 0xffff0000; - return true; -} - -bool Sequence::s1_point(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_point()\n"); - // TODO - return true; -} - -bool Sequence::s1_dist2d(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_dist2d()\n"); - // TODO - return true; -} - -bool Sequence::s1_crunch(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_crunch()\n"); - - long deltaTime; - - if (instruction.argc == 2) { - deltaTime = _vm->imath_ranged_rand16(instruction.argv[0], instruction.argv[1]); - } else if (instruction.argc == 1) { - deltaTime = instruction.argv[0]; - } else { - deltaTime = 0; - } - - _startTime = _ws->getGlobal(kGlobTime); - - //debugCN(kDebugScript, "deltaTime = %ld\n", deltaTime >> 16); - //g_system->delayMillis(5000); - - if (deltaTime >= 0) { - _switchTime = _ws->getGlobal(kGlobTime) + (deltaTime >> 16); - //debugCN(kDebugScript, "_ws->getGlobal(kGlobTime) = %ld\n", _ws->getGlobal(kGlobTime)); - //g_system->delayMillis(5000); - } else { - _switchTime = -1; - } - - // TODO: Update if walking etc. - - return false; -} - -bool Sequence::s1_branch(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_branch()\n"); - - uint32 ofs = instruction.argv[1] >> 16; - switch (instruction.argv[0] >> 16) { - case 0: // jmp - _code->jumpRelative(ofs); - break; - case 1: // < - if (_cmpFlags < 0) - _code->jumpRelative(ofs); - break; - case 2: // <= - if (_cmpFlags <= 0) - _code->jumpRelative(ofs); - break; - case 3: // == - if (_cmpFlags == 0) - _code->jumpRelative(ofs); - break; - case 4: // != - if (_cmpFlags != 0) - _code->jumpRelative(ofs); - break; - case 5: // >= - if (_cmpFlags >= 0) - _code->jumpRelative(ofs); - break; - case 6: // > - if (_cmpFlags > 0) - _code->jumpRelative(ofs); - break; - } - - return true; -} - -bool Sequence::s1_setFrame(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_setFrame()\n"); - - int32 frameIndex; - if (instruction.argc == 3) { - frameIndex = _vm->imath_ranged_rand(instruction.argv[1] >> 16, instruction.argv[2] >> 16); - } else if (instruction.argc == 2) { - frameIndex = instruction.argv[1] >> 16; - } else { - frameIndex = (instruction.argv[0] & 0xFF0000) >> 16; - } - - //debugCN(kDebugScript, "Sequence::s1_setFrame() spriteHash = %d\n", (uint32)instruction.argv[0] >> 24); - //debugCN(kDebugScript, "Sequence::s1_setFrame() frameIndex = %d\n", frameIndex); - - SpriteAsset *spriteAsset = _ws->assets()->getSprite((uint32)instruction.argv[0] >> 24); - _curFrame = spriteAsset->getFrame(frameIndex); - - return true; -} - -bool Sequence::s1_sendMessage(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_sendMessage()\n"); - // TODO - return true; -} - -bool Sequence::s1_push(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_push()\n"); - // TODO - return true; -} - -bool Sequence::s1_pop(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_pop()\n"); - // TODO - return true; -} - -bool Sequence::s1_jumpSub(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_jumpSub()\n"); - - _returnHashes[_returnStackIndex] = _sequenceHash; - _returnOffsets[_returnStackIndex] = _code->pos(); - _returnStackIndex++; - - _sequenceHash = instruction.argv[0] >> 16; - - SequenceAsset *sequenceAsset = _ws->assets()->getSequence(_sequenceHash); - - // initialize the sequence's bytecode - byte *code; - uint32 codeSize; - sequenceAsset->getCode(code, codeSize); - _code->setCode(code, codeSize); - - return true; -} - -bool Sequence::s1_return(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_return()\n"); - - if (_returnStackIndex <= 0) - return s1_end(instruction); - - _returnStackIndex--; - - _sequenceHash = _returnHashes[_returnStackIndex]; - uint32 ofs = _returnOffsets[_returnStackIndex]; - - SequenceAsset *sequenceAsset = _ws->assets()->getSequence(_sequenceHash); - - // initialize the sequence's bytecode - byte *code; - uint32 codeSize; - sequenceAsset->getCode(code, codeSize); - _code->setCode(code, codeSize); - _code->jumpAbsolute(ofs); - - - return true; -} - -bool Sequence::s1_getFrameCount(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_getFrameCount()\n"); - - SpriteAsset *spriteAsset = _ws->assets()->getSprite(instruction.argv[1] >> 24); - *instruction.argp[0] = spriteAsset->getCount() << 16; - return true; -} - -bool Sequence::s1_getFrameRate(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_getFrameRate()\n"); - - SpriteAsset *spriteAsset = _ws->assets()->getSprite(instruction.argv[1] >> 24); - *instruction.argp[0] = spriteAsset->getFrameRate(); - return true; -} - -bool Sequence::s1_getCelsPixSpeed(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_getCelsPixSpeed()\n"); - // TODO - return true; -} - -bool Sequence::s1_setIndex(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_setIndex()\n"); - // TODO - return true; -} - -bool Sequence::s1_setLayer(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_setLayer()\n"); - //TODO - return true; -} - -bool Sequence::s1_setDepth(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_setDepth()\n"); - //TODO - return true; -} - -bool Sequence::s1_setData(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_setData()\n"); - //TODO - return true; -} - -bool Sequence::s1_openStream(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_openStream()\n"); - - _stream = _vm->res()->openFile(_machine->name().c_str()); - streamOpen(); - return true; -} - -bool Sequence::s1_streamNextFrame(Instruction &instruction) { - //debugCN(kDebugScript, "Sequence::s1_streamNextFrame()\n"); - - streamNextFrame(); - return true; -} - -bool Sequence::s1_closeStream(Instruction &instruction) { - debugCN(kDebugScript, "Sequence::s1_closeStream()\n"); - //TODO - return true; -} - -bool Sequence::streamOpen() { - - _streamSpriteAsset = new SpriteAsset(_vm, _stream, _stream->size(), "stream", true); - - _vars[kSeqVarSpriteFrameNumber] = -0x10000; - _vars[kSeqVarSpriteFrameCount] = _streamSpriteAsset->getCount() << 16; - _vars[kSeqVarSpriteFrameRate] = _streamSpriteAsset->getFrameRate() << 16; - - //debugCN(kDebugScript, "Sequence::streamOpen() frames = %d; max = %d x %d\n", _streamSpriteAsset->getCount(), _streamSpriteAsset->getMaxFrameWidth(), _streamSpriteAsset->getMaxFrameHeight()); - - _curFrame = new M4Sprite(_vm, _streamSpriteAsset->getMaxFrameWidth(), _streamSpriteAsset->getMaxFrameHeight()); - streamNextFrame(); - - // TODO: Just a hack to see the series with the correct palette. - _vm->_palette->setPalette(_streamSpriteAsset->getPalette(), 0, 256); - - return true; -} - -bool Sequence::streamNextFrame() { - - _vars[kSeqVarSpriteFrameNumber] += 0x10000; - - int32 frameNum = _vars[kSeqVarSpriteFrameNumber] >> 16; - if (frameNum >= _streamSpriteAsset->getCount()) { - // End reached - return false; - } - - _streamSpriteAsset->loadStreamingFrame(_curFrame, frameNum, _vars[kSeqVarX], _vars[kSeqVarY]); - - _vars[kSeqVarWidth] = _curFrame->width() << 16; - _vars[kSeqVarHeight] = _curFrame->height() << 16; - - return true; -} - -void Sequence::streamClose() { - _stream = NULL; - _vm->res()->toss(_machine->name().c_str()); - //_vm->res()->purge(); - delete _streamSpriteAsset; - delete _curFrame; - _stream = NULL; - _streamSpriteAsset = NULL; - _curFrame = NULL; -} - -} diff --git a/gui/credits.h b/gui/credits.h index 8abd4bba69..08be2e0534 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -138,12 +138,6 @@ static const char *credits[] = { "C1""Lure", "C0""Paul Gilbert", "", -"C1""M4", -"C0""Torbj\366rn Andersson", -"C0""Paul Gilbert", -"C0""Benjamin Haisch", -"C0""Filippos Karapetis", -"", "C1""MADE", "C0""Benjamin Haisch", "C0""Filippos Karapetis", -- cgit v1.2.3