[Scummvm-cvs-logs] scummvm master -> b0611f31895130dcc27bef93bf1d54dfbfc1da43
dreammaster
dreammaster at scummvm.org
Sun Nov 20 02:15:06 CET 2011
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b0611f3189 M4: Removed the M4/MADS engine from trunk
Commit: b0611f31895130dcc27bef93bf1d54dfbfc1da43
https://github.com/scummvm/scummvm/commit/b0611f31895130dcc27bef93bf1d54dfbfc1da43
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2011-11-19T17:14:10-08:00
Commit Message:
M4: Removed the M4/MADS engine from trunk
Changed paths:
R dists/engine-data/m4.dat
R dists/engine-data/mads.dat
R engines/m4/actor.cpp
R engines/m4/actor.h
R engines/m4/animation.cpp
R engines/m4/animation.h
R engines/m4/assets.cpp
R engines/m4/assets.h
R engines/m4/burger_data.h
R engines/m4/compression.cpp
R engines/m4/compression.h
R engines/m4/console.cpp
R engines/m4/console.h
R engines/m4/converse.cpp
R engines/m4/converse.h
R engines/m4/detection.cpp
R engines/m4/dialogs.cpp
R engines/m4/dialogs.h
R engines/m4/events.cpp
R engines/m4/events.h
R engines/m4/font.cpp
R engines/m4/font.h
R engines/m4/globals.cpp
R engines/m4/globals.h
R engines/m4/graphics.cpp
R engines/m4/graphics.h
R engines/m4/gui.cpp
R engines/m4/gui.h
R engines/m4/hotspot.cpp
R engines/m4/hotspot.h
R engines/m4/m4.cpp
R engines/m4/m4.h
R engines/m4/m4_menus.cpp
R engines/m4/m4_menus.h
R engines/m4/m4_scene.cpp
R engines/m4/m4_scene.h
R engines/m4/m4_views.cpp
R engines/m4/m4_views.h
R engines/m4/mads_anim.cpp
R engines/m4/mads_anim.h
R engines/m4/mads_logic.cpp
R engines/m4/mads_logic.h
R engines/m4/mads_menus.cpp
R engines/m4/mads_menus.h
R engines/m4/mads_player.cpp
R engines/m4/mads_player.h
R engines/m4/mads_scene.cpp
R engines/m4/mads_scene.h
R engines/m4/mads_views.cpp
R engines/m4/mads_views.h
R engines/m4/midi.cpp
R engines/m4/midi.h
R engines/m4/module.mk
R engines/m4/rails.cpp
R engines/m4/rails.h
R engines/m4/resource.cpp
R engines/m4/resource.h
R engines/m4/saveload.cpp
R engines/m4/saveload.h
R engines/m4/scene.cpp
R engines/m4/scene.h
R engines/m4/script.cpp
R engines/m4/script.h
R engines/m4/scripttab.h
R engines/m4/sound.cpp
R engines/m4/sound.h
R engines/m4/sprite.cpp
R engines/m4/sprite.h
R engines/m4/staticres.cpp
R engines/m4/staticres.h
R engines/m4/viewmgr.cpp
R engines/m4/viewmgr.h
R engines/m4/woodscript.cpp
R engines/m4/woodscript.h
R engines/m4/ws_machine.cpp
R engines/m4/ws_sequence.cpp
AUTHORS
audio/decoders/flac.h
audio/decoders/mp3.h
audio/decoders/vorbis.h
base/plugins.cpp
configure
dists/scummvm.rc
gui/credits.h
diff --git a/AUTHORS b/AUTHORS
index c20f43e..e152e3a 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 a90675c..f5e3168 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 cb0cc83..df2ee44 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 9e7600a..3a3052e 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 3e18e0e..e587b96 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 b7b0794..96667e6 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 3181d01..0000000
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 b27f9d4..0000000
Binary files a/dists/engine-data/mads.dat and /dev/null differ
diff --git a/dists/scummvm.rc b/dists/scummvm.rc
index ce287cd..d7d2b7f 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 80a3624..0000000
--- 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 e28c522..0000000
--- 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<SpriteAsset*> _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<InventoryObject *> _inventory;
-};
-
-} // End of namespace M4
-
-
-#endif
diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp
deleted file mode 100644
index 4f315dd..0000000
--- 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 68a2883..0000000
--- 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<AnimMessage> _messages;
- Common::Array<AnimFrameEntry> _frameEntries;
- Common::Array<AnimMiscEntry> _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<int> _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 e871218..0000000
--- 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<SpriteAssetFrame>::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<int> 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<int>(_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<int>(0, minHash);
- maxHash = MIN<int>(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 25996a4..0000000
--- 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<uint32> _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<uint32> _frameOffsets;
- Common::Array<SpriteAssetFrame> _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 d30e546..0000000
--- 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 65a25c1..0000000
--- 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 cb0ef74..0000000
--- 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 fa4ca6d..0000000
--- 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 <scene number>\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 <sound file>\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 <sound index> <DSR file>\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 <file> <uncompress>\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 <conversation file name>\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 <txr resource>\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 <res resource>\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<uint>(_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 <anim resource (*.aa)> <fullscreen>\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 fc473b6..0000000
--- 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 299fafb..0000000
--- 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<char *> 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 b47e8d2..0000000
--- 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::Array<EntryAction*>actions;
- Common::Array<ConvEntry*>entries;
-};
-
-struct EntryInfo {
- EntryType targetType;
- int32 nodeIndex;
- int32 entryIndex;
-};
-
-struct MessageEntry {
- Common::Array<char*>messageStrings;
-};
-
-enum ConverseStyle {CONVSTYLE_EARTH, CONVSTYLE_SPACE};
-
-typedef Common::HashMap<Common::String,EntryInfo,Common::IgnoreCase_Hash,Common::IgnoreCase_EqualTo> OffsetHashMap;
-typedef Common::HashMap<Common::String,int32,Common::IgnoreCase_Hash,Common::IgnoreCase_EqualTo> 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<ConvEntry *> _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<ConvEntry*>_convNodes;
- Common::Array<MessageEntry*>_madsMessageList;
- Common::Array<char *>_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 6b8af6b..0000000
--- 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 2a36fa0..0000000
--- 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<unsigned char>(*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 ea3519c..0000000
--- 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<DialogLine> _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 b476d08..0000000
--- 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 6e7cf68..0000000
--- 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 d4ba714..0000000
--- 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 5a9c73e..0000000
--- 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<Font *> _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 7a0b776..0000000
--- 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<int>::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 693dc9d..0000000
--- 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<Common::SharedPtr<MadsObject> > 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<uint16, uint16> DataMapHash;
-
-class MadsGlobals : public Globals {
-private:
- struct MessageItem {
- uint32 id;
- uint32 offset;
- uint16 uncompSize;
- uint16 compSize;
- };
-
- MadsEngine *_vm;
- Common::Array<char* > _madsVocab;
- Common::Array<char* > _madsQuotes;
- Common::Array<MessageItem> _madsMessages;
- MadsObjectArray _madsObjects;
- Common::List<int> _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 99130ae..0000000
--- 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<int>(x + scaledWidth, clipRect.right) - x;
- } else {
- clipX = x;
- scaledWidth = x + scaledWidth;
- }
- if (y >= 0) {
- scaledHeight = MIN<int>(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<Common::SharedPtr<M4Surface> > 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 f3dde45..0000000
--- 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 6bedfa7..0000000
--- 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
More information about the Scummvm-git-logs
mailing list