aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/m4/console.cpp5
-rw-r--r--engines/m4/converse.cpp22
-rw-r--r--engines/m4/converse.h19
-rw-r--r--engines/m4/m4.cpp6
-rw-r--r--engines/m4/m4.h8
-rw-r--r--engines/m4/m4_scene.cpp226
-rw-r--r--engines/m4/m4_scene.h68
-rw-r--r--engines/m4/mads_scene.cpp647
-rw-r--r--engines/m4/mads_scene.h199
-rw-r--r--engines/m4/mads_views.h3
-rw-r--r--engines/m4/module.mk2
-rw-r--r--engines/m4/scene.cpp559
-rw-r--r--engines/m4/scene.h123
-rw-r--r--engines/m4/script.cpp2
-rw-r--r--engines/m4/staticres.cpp17
-rw-r--r--engines/m4/staticres.h13
16 files changed, 1225 insertions, 694 deletions
diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp
index 9683f4544e..8476b3ff53 100644
--- a/engines/m4/console.cpp
+++ b/engines/m4/console.cpp
@@ -214,8 +214,11 @@ 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 {
- _vm->_converse->startConversation(argv[1]);
+ error("MADS engine does not support conversations yet");
return false;
}
}
diff --git a/engines/m4/converse.cpp b/engines/m4/converse.cpp
index 18d61ef7ce..746ced5d11 100644
--- a/engines/m4/converse.cpp
+++ b/engines/m4/converse.cpp
@@ -103,7 +103,7 @@ void ConversationView::setNode(int32 nodeIndex) {
_activeItems.clear();
if (nodeIndex != -1) {
- ConvEntry *node = _vm->_converse->getNode(nodeIndex);
+ ConvEntry *node = _m4Vm->_converse->getNode(nodeIndex);
for (uint i = 0; i < node->entries.size(); ++i) {
if (!node->entries[i]->visible)
@@ -137,7 +137,7 @@ void ConversationView::setNode(int32 nodeIndex) {
//printf("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 = _vm->_converse->getEntryInfo(node->fallthroughOffset);
+ const EntryInfo *entryInfo = _m4Vm->_converse->getEntryInfo(node->fallthroughOffset);
//printf("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);
@@ -228,7 +228,7 @@ void ConversationView::selectEntry(int entryIndex) {
// Hide selected entry, unless it has a persistent flag set
if (!(_activeItems[entryIndex]->flags & kEntryPersists)) {
//printf("Hiding selected entry\n");
- _vm->_converse->getNode(_currentNodeIndex)->entries[entryIndex]->visible = false;
+ _m4Vm->_converse->getNode(_currentNodeIndex)->entries[entryIndex]->visible = false;
} else {
//printf("Selected entry is persistent, not hiding it\n");
}
@@ -266,8 +266,8 @@ void ConversationView::playNextReply() {
ConvEntry *currentEntry = _activeItems[_highlightedIndex]->entries[i];
if (currentEntry->isConditional) {
- if (!_vm->_converse->evaluateCondition(
- _vm->_converse->getValue(currentEntry->condition.offset),
+ if (!_m4Vm->_converse->evaluateCondition(
+ _m4Vm->_converse->getValue(currentEntry->condition.offset),
currentEntry->condition.op, currentEntry->condition.val))
continue; // don't play this reply
}
@@ -315,7 +315,7 @@ void ConversationView::playNextReply() {
//printf("Current selection does %i actions\n", _activeItems[entryIndex]->actions.size());
for (uint32 i = 0; i < _activeItems[_highlightedIndex]->actions.size(); i++) {
- if (!_vm->_converse->performAction(_activeItems[_highlightedIndex]->actions[i]))
+ if (!_m4Vm->_converse->performAction(_activeItems[_highlightedIndex]->actions[i]))
break;
} // end for
@@ -1220,4 +1220,14 @@ bool Converse::performAction(EntryAction *action) {
} // 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
index 973122b9f2..609711b10f 100644
--- a/engines/m4/converse.h
+++ b/engines/m4/converse.h
@@ -30,8 +30,8 @@
#include "common/hashmap.h"
#include "m4/globals.h"
-#include "m4/m4.h"
#include "m4/viewmgr.h"
+#include "m4/sound.h"
namespace M4 {
@@ -195,6 +195,23 @@ private:
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/m4.cpp b/engines/m4/m4.cpp
index 7b3a84e98d..5ce21b4a57 100644
--- a/engines/m4/m4.cpp
+++ b/engines/m4/m4.cpp
@@ -137,7 +137,6 @@ MadsM4Engine::~MadsM4Engine() {
delete _inventory;
delete _viewManager;
delete _rails;
- delete _converse;
delete _script;
delete _ws;
delete _random;
@@ -178,7 +177,6 @@ Common::Error MadsM4Engine::run() {
_viewManager = new ViewManager(this);
_inventory = new Inventory(this);
_sound = new Sound(this, _mixer, 255);
- _converse = new Converse(this);
_script = new ScriptInterpreter(this);
_ws = new WoodScript(this);
_animation = new Animation(this);
@@ -304,6 +302,7 @@ M4Engine::M4Engine(OSystem *syst, const M4GameDescription *gameDesc): MadsM4Engi
M4Engine::~M4Engine() {
delete _resourceManager;
delete _globals;
+ delete _converse;
}
Common::Error M4Engine::run() {
@@ -316,6 +315,9 @@ Common::Error M4Engine::run() {
// Set up needed common functionality
MadsM4Engine::run();
+ // M4 specific initialisation
+ _converse = new Converse(this);
+
_scene = new M4Scene(this);
_script->open("m4.dat");
diff --git a/engines/m4/m4.h b/engines/m4/m4.h
index 6d79b47f5f..bebda02ca6 100644
--- a/engines/m4/m4.h
+++ b/engines/m4/m4.h
@@ -40,6 +40,8 @@
#include "m4/events.h"
#include "m4/font.h"
#include "m4/scene.h"
+#include "m4/mads_scene.h"
+#include "m4/m4_scene.h"
#include "m4/actor.h"
#include "m4/sound.h"
#include "m4/rails.h"
@@ -84,6 +86,7 @@ class M4InterfaceView;
class ConversationView;
class Actor;
class Converse;
+class MadsConversation;
class ScriptInterpreter;
class WoodScript;
class Animation;
@@ -193,7 +196,6 @@ public:
ConversationView *_conversationView;
Sound *_sound;
Rails *_rails;
- Converse *_converse;
ScriptInterpreter *_script;
WoodScript *_ws;
Animation *_animation;
@@ -204,6 +206,8 @@ public:
class MadsEngine : public MadsM4Engine {
public:
+ MadsConversation _converse;
+public:
MadsEngine(OSystem *syst, const M4GameDescription *gameDesc);
virtual ~MadsEngine();
@@ -215,6 +219,8 @@ public:
class M4Engine : public MadsM4Engine {
public:
+ Converse *_converse;
+public:
M4Engine(OSystem *syst, const M4GameDescription *gameDesc);
virtual ~M4Engine();
diff --git a/engines/m4/m4_scene.cpp b/engines/m4/m4_scene.cpp
new file mode 100644
index 0000000000..1d5cc171a3
--- /dev/null
+++ b/engines/m4/m4_scene.cpp
@@ -0,0 +1,226 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+
+#include "m4/dialogs.h"
+#include "m4/globals.h"
+#include "m4/scene.h"
+#include "m4/events.h"
+#include "m4/graphics.h"
+#include "m4/rails.h"
+#include "m4/font.h"
+#include "m4/m4_views.h"
+#include "m4/mads_views.h"
+#include "m4/compression.h"
+
+namespace M4 {
+
+M4Scene::M4Scene(M4Engine *vm): Scene(vm) {
+ _vm = vm;
+ _sceneSprites = NULL;
+ _interfaceSurface = new M4InterfaceView(vm);
+}
+
+M4Scene::~M4Scene() {
+ delete _sceneSprites;
+}
+
+void M4Scene::loadSceneSprites(int sceneNumber) {
+ char filename[kM4MaxFilenameSize];
+ sprintf(filename, "%i.ssb", sceneNumber);
+
+ Common::SeekableReadStream *sceneS = _vm->res()->get(filename);
+ _sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename);
+ _vm->res()->toss(filename);
+
+ printf("Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount());
+}
+
+void M4Scene::loadScene(int sceneNumber) {
+ Scene::loadScene(sceneNumber);
+
+ _backgroundSurface->loadBackground(sceneNumber);
+ _palData = NULL;
+
+ if (_vm->getGameType() == GType_Burger &&
+ sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER)
+ setStatusText("");
+
+ // Load scene def file (*.CHK)
+ loadSceneResources(sceneNumber);
+ loadSceneInverseColorTable(sceneNumber);
+
+ // TODO: set walker scaling
+ // TODO: destroy woodscript buffer
+
+ // Load scene walk path file (*.COD/*.WW?)
+ loadSceneCodes(sceneNumber);
+
+ // Load inverse color table file (*.IPL)
+ loadSceneInverseColorTable(sceneNumber);
+
+ if (_vm->getGameType() != GType_Burger) {
+ // Load scene sprites file (*.SSB)
+ loadSceneSprites(sceneNumber);
+
+ // Load scene sprite codes file (*.SSC)
+ loadSceneSpriteCodes(sceneNumber);
+ }
+
+
+ if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) {
+ _m4Vm->scene()->getInterface()->show();
+ showSprites();
+ }
+
+ // Purge resources
+ _vm->res()->purge();
+}
+
+void M4Scene::loadSceneCodes(int sceneNumber, int index) {
+ char filename[kM4MaxFilenameSize];
+ Common::SeekableReadStream *sceneS;
+
+ sprintf(filename, "%i.cod", sceneNumber);
+ sceneS = _vm->res()->openFile(filename);
+ _walkSurface->loadCodesM4(sceneS);
+ _vm->res()->toss(filename);
+}
+
+void M4Scene::show() {
+ Scene::show();
+ _vm->_viewManager->addView(_interfaceSurface);
+}
+
+void M4Scene::checkHotspotAtMousePos(int x, int y) {
+ if (_vm->getGameType() == GType_Riddle)
+ return;
+
+ // TODO: loads of things to do here, only the mouse cursor and the status
+ // text is changed for now
+
+ // Only scene hotspots are checked for now, not parallax/props, as the
+ // latter ones are not used by Orion Burger
+ HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
+ if (currentHotSpot != NULL && currentHotSpot->getActive()) {
+ if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
+ _vm->_mouse->getCursorNum() != CURSOR_TAKE &&
+ _vm->_mouse->getCursorNum() != CURSOR_USE &&
+ _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) {
+ _vm->_mouse->setCursorNum(currentHotSpot->getCursor());
+ }
+ _m4Vm->scene()->getInterface()->setStatusText(currentHotSpot->getPrep());
+ } else {
+ if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
+ _vm->_mouse->getCursorNum() != CURSOR_TAKE &&
+ _vm->_mouse->getCursorNum() != CURSOR_USE &&
+ _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) {
+ _vm->_mouse->setCursorNum(0);
+ } else {
+
+ }
+ }
+}
+
+void M4Scene::leftClick(int x, int y) {
+ if (_vm->getGameType() == GType_Burger) {
+ // Place a Wilbur sprite with the correct facing
+ HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
+ if (currentHotSpot != NULL && currentHotSpot->getActive()) {
+ update();
+ _vm->_actor->setWalkerDirection(currentHotSpot->getFacing());
+ /*
+ int posX = currentHotSpot->getFeetX();
+ int posY = currentHotSpot->getFeetY() -
+ scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0);
+ //_vm->_actor->placeWalkerSpriteAt(0, posX, posY);
+ */
+
+ // Player said.... (for scene scripts)
+ printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
+
+ // FIXME: This should be moved somewhere else, and is incomplete
+ if (_m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) {
+ if (_vm->_mouse->getVerb() == NULL) {
+ strcpy(_vm->_player->verb, currentHotSpot->getVerb());
+ } else {
+ strcpy(_vm->_player->verb, _vm->_mouse->getVerb());
+ }
+ } else {
+ strcpy(_vm->_player->verb, _m4Vm->scene()->getInterface()->_inventory.getSelectedObjectName());
+ }
+ strcpy(_vm->_player->noun, currentHotSpot->getVocab());
+ strcpy(_vm->_player->object, "");
+ _vm->_player->commandReady = true;
+
+ printf("## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun);
+
+ }
+ }
+}
+
+void M4Scene::rightClick(int x, int y) {
+ if (_vm->getGameType() == GType_Burger) {
+ nextCommonCursor();
+ _m4Vm->scene()->getInterface()->_inventory.clearSelected();
+ }
+}
+
+void M4Scene::setAction(int action, int objectId) {
+}
+
+void M4Scene::setStatusText(const char *text) {
+ getInterface()->setStatusText(text);
+}
+
+void M4Scene::update() {
+
+}
+
+void M4Scene::nextCommonCursor() {
+ int cursorIndex = _vm->_mouse->getCursorNum();
+
+ switch (cursorIndex) {
+ case CURSOR_ARROW:
+ cursorIndex = CURSOR_LOOK;
+ break;
+ case CURSOR_LOOK:
+ cursorIndex = CURSOR_TAKE;
+ break;
+ case CURSOR_TAKE:
+ cursorIndex = CURSOR_USE;
+ break;
+ case CURSOR_USE:
+ cursorIndex = CURSOR_ARROW;
+ break;
+ default:
+ cursorIndex = CURSOR_ARROW;
+ }
+
+ _vm->_mouse->setCursorNum(cursorIndex);
+}
+
+} // End of namespace M4
diff --git a/engines/m4/m4_scene.h b/engines/m4/m4_scene.h
new file mode 100644
index 0000000000..be04a52dce
--- /dev/null
+++ b/engines/m4/m4_scene.h
@@ -0,0 +1,68 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_M4_SCENE_H
+#define M4_M4_SCENE_H
+
+class View;
+
+#include "m4/scene.h"
+
+namespace M4 {
+
+#define TITLE_SCENE_BURGER 951 // 951 = intro, 901 = demo menu, 971 = first scene
+#define MAINMENU_SCENE_BURGER 903
+#define FIRST_SCENE 101
+
+class M4Scene : public Scene {
+private:
+ M4Engine *_vm;
+ SpriteAsset *_sceneSprites;
+ SpriteAsset *_walkerSprite;
+
+ void loadSceneSprites(int sceneNumber);
+ void nextCommonCursor();
+public:
+ M4Scene(M4Engine *vm);
+ virtual ~M4Scene();
+
+ // Methods that differ between engines
+ virtual void loadScene(int sceneNumber);
+ virtual void leaveScene() {};
+ virtual void loadSceneCodes(int sceneNumber, int index = 0);
+ virtual void show();
+ virtual void checkHotspotAtMousePos(int x, int y);
+ virtual void leftClick(int x, int y);
+ virtual void rightClick(int x, int y);
+ virtual void setAction(int action, int objectId = -1);
+ virtual void setStatusText(const char *text);
+ virtual void update();
+
+ M4InterfaceView *getInterface() { return (M4InterfaceView *)_interfaceSurface; };
+};
+
+} // End of namespace M4
+
+#endif
diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp
new file mode 100644
index 0000000000..51f4cb72ba
--- /dev/null
+++ b/engines/m4/mads_scene.cpp
@@ -0,0 +1,647 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+
+#include "m4/mads_scene.h"
+#include "m4/dialogs.h"
+#include "m4/globals.h"
+#include "m4/scene.h"
+#include "m4/events.h"
+#include "m4/graphics.h"
+#include "m4/rails.h"
+#include "m4/font.h"
+#include "m4/m4_views.h"
+#include "m4/mads_views.h"
+#include "m4/compression.h"
+#include "m4/staticres.h"
+
+namespace M4 {
+
+MadsScene::MadsScene(MadsEngine *vm): Scene(vm) {
+ _vm = vm;
+
+ strcpy(_statusText, "");
+ _interfaceSurface = new MadsInterfaceView(vm);
+ _spriteSlotsStart = 0;
+ for (int i = 0; i < 3; ++i)
+ actionNouns[i] = 0;
+}
+
+/**
+ * Secondary scene loading code
+ */
+void MadsScene::loadScene2(const char *aaName) {
+ // Load up the properties for the scene
+ _sceneInfo.load(_currentScene);
+
+ // Load scene walk paths
+ loadSceneCodes(_currentScene);
+}
+
+/**
+ * Existing ScummVM code that needs to be eventually replaced with MADS code
+ */
+void MadsScene::loadSceneTemporary() {
+ /* Existing code that eventually needs to be replaced with the proper MADS code */
+ // Set system palette entries
+ _vm->_palette->blockRange(0, 7);
+ RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0},
+ {0x00<<2, 0x10<<2, 0x16<<2, 0}};
+ _vm->_palette->setPalette(&sysColors[0], 4, 3);
+
+ _backgroundSurface->loadBackground(_currentScene, &_palData);
+ _vm->_palette->addRange(_palData);
+ _backgroundSurface->translate(_palData);
+
+ if (_currentScene < 900) {
+ /*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT,
+ _backgroundSurface->width(), _backgroundSurface->height()),
+ _vm->_palette->BLACK);*/
+ // TODO: interface palette
+ _interfaceSurface->madsloadInterface(0, &_interfacePal);
+ _vm->_palette->addRange(_interfacePal);
+ _interfaceSurface->translate(_interfacePal);
+ _backgroundSurface->copyFrom(_interfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44);
+
+ _interfaceSurface->initialise();
+ }
+
+ // Don't load other screen resources for system screens
+ if (_currentScene >= 900)
+ return;
+
+ loadSceneHotSpotsMads(_currentScene);
+
+ // TODO: set walker scaling
+ // TODO: destroy woodscript buffer
+
+ // Load inverse color table file (*.IPL)
+ loadSceneInverseColorTable(_currentScene);
+}
+
+void MadsScene::loadScene(int sceneNumber) {
+ // Close the menu if it's active
+ View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU);
+ if (mainMenu != NULL) {
+ _vm->_viewManager->deleteView(mainMenu);
+ }
+
+ // Handle common scene setting
+ Scene::loadScene(sceneNumber);
+
+ // Signal the script engine what scene is to be active
+ _sceneLogic.selectScene(sceneNumber);
+ _sceneLogic.setupScene();
+
+ // Add the scene if necessary to the list of scenes that have been visited
+ _vm->globals()->addVisitedScene(sceneNumber);
+
+ // Secondary scene load routine
+ loadScene2("*I0.AA");
+
+ // Do any scene specific setup
+ _sceneLogic.enterScene();
+
+ // Existing ScummVM code that needs to be eventually replaced with MADS code
+ loadSceneTemporary();
+
+ // Purge resources
+ _vm->res()->purge();
+}
+
+void MadsScene::leaveScene() {
+ _sceneResources.hotspots->clear();
+ _sceneResources.parallax->clear();
+ _sceneResources.props->clear();
+
+ delete _sceneResources.hotspots;
+ delete _sceneResources.parallax;
+ delete _sceneResources.props;
+
+ // Delete the sprites
+ for (uint i = 0; i <_sceneSprites.size(); ++i) delete _sceneSprites[i];
+ _sceneSprites.clear();
+
+ delete _backgroundSurface;
+ delete _walkSurface;
+
+ Scene::leaveScene();
+}
+
+void MadsScene::show() {
+ Scene::show();
+ _vm->_viewManager->addView(_interfaceSurface);
+}
+
+void MadsScene::loadSceneCodes(int sceneNumber, int index) {
+ char filename[kM4MaxFilenameSize];
+ Common::SeekableReadStream *sceneS;
+
+ if (_vm->getGameType() == GType_Phantom || _vm->getGameType() == GType_DragonSphere) {
+ sprintf(filename, "rm%i.ww%i", sceneNumber, index);
+ MadsPack walkData(filename, _vm);
+ sceneS = walkData.getItemStream(0);
+ _walkSurface->loadCodesMads(sceneS);
+ _vm->res()->toss(filename);
+ } else if (_vm->getGameType() == GType_RexNebular) {
+ // For Rex Nebular, the walk areas are part of the scene info
+ byte *destP = _walkSurface->getBasePtr(0, 0);
+ const byte *srcP = _sceneInfo.walkData;
+ byte runLength;
+ while ((runLength = *srcP++) != 0) {
+ Common::set_to(destP, destP + runLength, *srcP++);
+ destP += runLength;
+ }
+ }
+}
+
+void MadsScene::checkHotspotAtMousePos(int x, int y) {
+ HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
+ if (currentHotSpot != NULL) {
+ _vm->_mouse->setCursorNum(currentHotSpot->getCursor());
+
+ // This is the "easy" interface, which updates the status text when the mouse is moved
+ // TODO: toggle this code for easy/normal interface mode
+ char statusText[50];
+ int verbId = 0;//***DEBUG****_currentAction;
+ if (verbId == kVerbNone)
+ verbId = currentHotSpot->getVerbID();
+ if (verbId == kVerbNone)
+ verbId = kVerbWalkTo;
+
+ sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab());
+
+ statusText[0] = toupper(statusText[0]); // capitalize first letter
+ setStatusText(statusText);
+ } else {
+ _vm->_mouse->setCursorNum(0);
+ setStatusText("");
+ }
+}
+
+void MadsScene::leftClick(int x, int y) {
+ HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
+ if (currentHotSpot != NULL) {
+ char statusText[50];
+ if (currentHotSpot->getVerbID() != 0) {
+ sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
+ } else {
+ sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(kVerbWalkTo), currentHotSpot->getVocab());
+ }
+
+ statusText[0] = toupper(statusText[0]); // capitalize first letter
+ setStatusText(statusText);
+ }
+}
+
+void MadsScene::rightClick(int x, int y) {
+ // ***DEBUG*** - sample dialog display
+ int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a);
+ const char *msg = _madsVm->globals()->loadMessage(idx);
+ Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
+ _vm->_viewManager->addView(dlg);
+ _vm->_viewManager->moveToFront(dlg);
+}
+
+void MadsScene::setAction(int action, int objectId) {
+ VALIDATE_MADS;
+ char statusText[50];
+
+ error("todo");
+ // TODO: Actually executing actions directly for objects. Also, some object actions are special in that
+ // a second object can be selected, as in 'use gun to shoot person', with requires a target
+/*
+ // Set up the new action
+ strcpy(statusText, _madsVm->globals()->getVocab(action));
+ statusText[0] = toupper(statusText[0]); // capitalize first letter
+
+ if (objectId != -1) {
+ MadsObject *obj = _madsVm->globals()->getObject(objectId);
+ sprintf(statusText + strlen(statusText), " %s", _madsVm->globals()->getVocab(obj->descId));
+ } else {
+ _currentAction = action;
+ }
+*/
+ setStatusText(statusText);
+}
+
+void MadsScene::setStatusText(const char *text) {
+ strcpy(_statusText, text);
+}
+
+/**
+ * Draws all the elements of the scene
+ */
+void MadsScene::drawElements() {
+
+ // Display animations
+ for (int idx = 0; idx < _spriteSlotsStart; ++idx) {
+
+ }
+
+
+ // Text display
+ _textDisplay.draw(this);
+
+ // Copy the user interface surface onto the surface
+ _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height());
+
+/*
+ // At this point, in the original engine, the dirty/changed areas were copied to the screen. At the moment,
+ // the current M4 engine framework doesn't support dirty areas, but this is being kept in case that ever changes
+ for (int idx = 0; idx < DIRTY_AREA_SIZE; ++idx) {
+ if (_dirtyAreas[idx].active && _dirtyAreas[idx].active2 &&
+ (_dirtyAreas[idx].bounds.width() > 0) && (_dirtyAreas[idx].bounds.height() > 0)) {
+ // Copy changed area to screen
+
+ }
+ }
+*/
+
+ // Some kind of copying over of slot entries
+ for (int idx = 0, idx2 = 0; idx < _spriteSlotsStart; ++idx) {
+ if (_spriteSlots[idx].spriteId >= 0) {
+ if (idx != idx2) {
+ // Copy over the slot entry
+ _spriteSlots[idx2] = _spriteSlots[idx];
+ }
+ ++idx2;
+ }
+ }
+}
+
+
+void MadsScene::update() {
+ // Copy the bare scene in
+ _backgroundSurface->copyTo(this);
+
+ // Draw all the various elements
+ drawElements();
+
+ // Handle display of any status text
+ if (_statusText[0]) {
+ // Text colors are inverted in Dragonsphere
+ if (_vm->getGameType() == GType_DragonSphere)
+ _vm->_font->setColors(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK);
+ else
+ _vm->_font->setColors(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK);
+
+ _vm->_font->setFont(FONT_MAIN_MADS);
+ _vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0);
+ }
+
+ //***DEBUG***
+ _sceneSprites[0]->getFrame(1)->copyTo(this, 120, 90, 0);
+}
+
+int MadsScene::loadSceneSpriteSet(const char *setName) {
+ char resName[100];
+ strcpy(resName, setName);
+
+ // Append a '.SS' if it doesn't alreayd have an extension
+ if (!strchr(resName, '.'))
+ strcat(resName, ".SS");
+
+ Common::SeekableReadStream *data = _vm->res()->get(resName);
+ SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName);
+ spriteSet->translate(_vm->_palette);
+ _vm->res()->toss(resName);
+
+ _sceneSprites.push_back(spriteSet);
+ return _sceneSprites.size() - 1;
+}
+
+void MadsScene::loadPlayerSprites(const char *prefix) {
+ const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' };
+ char setName[80];
+
+ strcpy(setName, "*");
+ strcat(setName, prefix);
+ strcat(setName, "_0.SS");
+ char *digitP = strchr(setName, '_') + 1;
+
+ for (int idx = 0; idx < 8; ++idx) {
+ *digitP = suffixList[idx];
+
+ if (_vm->res()->resourceExists(setName)) {
+ loadSceneSpriteSet(setName);
+ return;
+ }
+ }
+
+ error("Couldn't find player sprites");
+}
+
+/*--------------------------------------------------------------------------*/
+
+MadsAction::MadsAction() {
+ clear();
+}
+
+void MadsAction::clear() {
+ _actionMode = ACTMODE_NONE;
+ _articleNumber = 0;
+ _lookFlag = false;
+ _statusText[0] = '\0';
+ _selectedRow = -1;
+ _currentHotspot = -1;
+ //word_86F3A/word_86F4C
+ _currentAction = kVerbNone;
+ _objectNameId = -1;
+ _objectDescId = -1;
+ //word_83334
+}
+
+void MadsAction::appendVocab(int vocabId, bool capitalise) {
+ char *s = _statusText + strlen(_statusText);
+ const char *vocabStr = _madsVm->globals()->getVocab(vocabId);
+ strcpy(s, vocabStr);
+ if (capitalise)
+ *s = toupper(*s);
+
+ strcat(s, " ");
+}
+
+void MadsAction::set() {
+ bool flag = false;
+ _currentAction = -1;
+ _objectNameId = -1;
+ _objectDescId = -1;
+
+ if (_actionMode == ACTMODE_TALK) {
+ // Handle showing the conversation selection. Rex at least doesn't actually seem to use this
+ if (_selectedRow >= 0) {
+ const char *desc = _madsVm->_converse[_selectedRow].desc;
+ if (desc)
+ strcpy(_statusText, desc);
+ }
+ } else if (_lookFlag && (_selectedRow == 0)) {
+ // Two 'look' actions in succession, so the action becomes 'Look around'
+ strcpy(_statusText, lookAroundStr);
+ } else {
+ if ((_actionMode == ACTMODE_OBJECT) && (_selectedRow >= 0) && (_flags1 == 2) && (_flags2 == 0)) {
+ // Use/to action
+ int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
+ MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+
+ _objectNameId = objEntry->descId;
+ _currentAction = objEntry->vocabList[_selectedRow].vocabId;
+
+ // Set up the status text stirng
+ strcpy(_statusText, useStr);
+ appendVocab(_objectNameId);
+ strcpy(_statusText, toStr);
+ appendVocab(_currentAction);
+ } else {
+ // Handling for if an action has been selected
+ if (_selectedRow >= 0) {
+ if (_actionMode == ACTMODE_VERB) {
+ // Standard verb action
+ _currentAction = verbList[_selectedRow].verb;
+ } else {
+ // Selected action on an inventory object
+ int selectedObject = _madsVm->scene()->getInterface()->getSelectedObject();
+ MadsObject *objEntry = _madsVm->globals()->getObject(selectedObject);
+
+ _currentAction = objEntry->vocabList[_selectedRow].vocabId;
+ }
+
+ appendVocab(_currentAction, true);
+
+ if (_currentAction == kVerbLook) {
+ // Add in the word 'add'
+ strcat(_statusText, atStr);
+ strcat(_statusText, " ");
+ }
+ }
+
+ // Handling for if a hotspot has been selected/highlighted
+ if ((_currentHotspot >= 0) && (_selectedRow >= 0) && (_articleNumber > 0) && (_flags1 == 2)) {
+ flag = true;
+
+ strcat(_statusText, englishMADSArticleList[_articleNumber]);
+ strcat(_statusText, " ");
+ }
+
+ if (_currentHotspot >= 0) {
+ if (_selectedRow < 0) {
+
+ }
+
+ //loc_21CE2
+ }
+ }
+ }
+
+ //word_83334 = -1;
+}
+
+/*--------------------------------------------------------------------------*/
+
+void MadsSceneInfo::load(int sId) {
+ const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sId, ".DAT");
+ Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr);
+ MadsPack sceneInfo(rawStream);
+
+ // Basic scene info
+ Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
+
+ int resSceneId = stream->readUint16LE();
+ assert(resSceneId == sId);
+
+ artFileNum = stream->readUint16LE();
+ field_4 = stream->readUint16LE();
+ width = stream->readUint16LE();
+ height = stream->readUint16LE();
+ assert((width == 320) && (height == 156));
+
+ stream->skip(24);
+
+ objectCount = stream->readUint16LE();
+
+ stream->skip(40);
+
+ for (int i = 0; i < objectCount; ++i) {
+ objects[i].load(stream);
+ }
+
+ // For Rex Nebular, read in the scene's compressed walk surface information
+ if (_vm->getGameType() == GType_RexNebular) {
+ delete walkData;
+
+ stream = sceneInfo.getItemStream(1);
+ walkData = (byte *)malloc(stream->size());
+ stream->read(walkData, stream->size());
+ }
+
+ _vm->_resourceManager->toss(sceneInfoStr);
+}
+
+/*--------------------------------------------------------------------------*/
+
+MadsScreenText::MadsScreenText() {
+ for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i)
+ _textDisplay[i].active = false;
+ for (int i = 0; i < TIMED_TEXT_SIZE; ++i)
+ _timedText[i].flags = 0;
+ _abortTimedText = false;
+}
+
+/**
+ * Adds the specified string to the list of on-screen display text
+ */
+int MadsScreenText::add(const Common::Point &destPos, uint fontColours, int widthAdjust, const char *msg, Font *font) {
+ // Find a free slot
+ int idx = 0;
+ while ((idx < TEXT_DISPLAY_SIZE) && _textDisplay[idx].active)
+ ++idx;
+ if (idx == TEXT_DISPLAY_SIZE)
+ error("Ran out of text display slots");
+
+ // Set up the entry values
+ _textDisplay[idx].active = true;
+ _textDisplay[idx].active2 = 1;
+ _textDisplay[idx].bounds.left = destPos.x;
+ _textDisplay[idx].bounds.top = destPos.y;
+ _textDisplay[idx].bounds.setWidth(font->getWidth(msg, widthAdjust));
+ _textDisplay[idx].bounds.setHeight(font->getHeight());
+ _textDisplay[idx].font = font;
+ strncpy(_textDisplay[idx].message, msg, 100);
+ _textDisplay[idx].message[99] = '\0';
+ _textDisplay[idx].colour1 = fontColours & 0xff;
+ _textDisplay[idx].colour2 = fontColours >> 8;
+ _textDisplay[idx].spacing = widthAdjust;
+
+ return idx;
+}
+
+/**
+ * Adds a new entry to the timed on-screen text display list
+ */
+int MadsScreenText::addTimed(const Common::Point &destPos, uint fontColours, uint flags, int vUnknown, uint32 timeout, const char *message) {
+ // Find a free slot
+ int idx = 0;
+ while ((idx < TIMED_TEXT_SIZE) && ((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0))
+ ++idx;
+ if (idx == TIMED_TEXT_SIZE) {
+ if (vUnknown == 0)
+ return -1;
+
+ error("Ran out of timed text display slots");
+ }
+
+ // Set up the entry values
+ _timedText[idx].flags = flags | TEXTFLAG_ACTIVE;
+ strcpy(_timedText[idx].message, message);
+ _timedText[idx].colour1 = fontColours & 0xff;
+ _timedText[idx].colour2 = fontColours >> 8;
+ _timedText[idx].position.x = destPos.x;
+ _timedText[idx].position.y = destPos.y;
+ _timedText[idx].textDisplayIndex = -1;
+ _timedText[idx].timeout = timeout;
+ _timedText[idx].frameTimer = g_system->getMillis();
+ _timedText[idx].field_1C = vUnknown;
+ _timedText[idx].field_1D = 0; /* word_84206 */
+
+ // Copy the current action noun list
+ for (int i = 0; i < 3; ++i)
+ _timedText[idx].actionNouns[i] = _madsVm->scene()->actionNouns[i];
+
+ if (flags & TEXTFLAG_2) {
+ warning("word_844b8 and dword_845a0 not yet implemented");
+ }
+
+ return idx;
+}
+
+/**
+ * Draws any text display entries to the screen
+ */
+void MadsScreenText::draw(M4Surface *surface) {
+ for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
+ if (_textDisplay[idx].active && (_textDisplay[idx].active2 >= 0)) {
+ _textDisplay[idx].font->setColours(_textDisplay[idx].colour1, 0xFF,
+ (_textDisplay[idx].colour2 == 0) ? _textDisplay[idx].colour1 : _textDisplay[idx].colour2);
+ _textDisplay[idx].font->writeString(surface, _textDisplay[idx].message,
+ _textDisplay[idx].bounds.left, _textDisplay[idx].bounds.top, _textDisplay[idx].bounds.width(),
+ _textDisplay[idx].spacing);
+ }
+ }
+
+ // Clear up any now inactive text display entries
+ for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
+ if (_textDisplay[idx].active2 < 0) {
+ _textDisplay[idx].active = false;
+ _textDisplay[idx].active2 = 0;
+ }
+ }
+}
+
+void MadsScreenText::timedDisplay() {
+ for (int idx = 0; !_abortTimedText && (idx < TEXT_DISPLAY_SIZE); ++idx) {
+ if (((_timedText[idx].flags & TEXTFLAG_ACTIVE) != 0) &&
+ (_timedText[idx].frameTimer <= g_system->getMillis()))
+ // Add the specified entry
+ addTimedText(&_timedText[idx]);
+ }
+}
+
+void MadsScreenText::addTimedText(TimedText *entry) {
+ if ((entry->flags & TEXTFLAG_40) != 0) {
+ this->setActive2(entry->textDisplayIndex);
+ entry->flags &= 0x7F;
+ return;
+ }
+
+ if ((entry->flags & TEXTFLAG_8) == 0)
+ // FIXME: Adjust timeouts for ScumVM's milli counter
+ entry->timeout -= 3;
+
+ if ((entry->flags & TEXTFLAG_4) != 0) {
+ Text4A &rec = _text4A[entry->unk4AIndex];
+ if ((rec.field25 != 0) || (rec.active == 0))
+ entry->timeout = 0;
+ }
+
+ if ((entry->timeout == 0) && !_abortTimedText) {
+ entry->flags |= TEXTFLAG_40;
+
+ if (entry->field_1C) {
+ _abortTimedText = entry->field_1C;
+ //word_84208 = entry->field_1D;
+
+ if (entry->field_1D != 1) {
+ // Restore the action list
+ for (int i = 0; i < 3; ++i)
+ _madsVm->scene()->actionNouns[i] = entry->actionNouns[i];
+ }
+ }
+ }
+
+ // TODO: code from 'loc_244ec' onwards
+}
+
+} // End of namespace M4
diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h
new file mode 100644
index 0000000000..321c13103e
--- /dev/null
+++ b/engines/m4/mads_scene.h
@@ -0,0 +1,199 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_MADS_SCENE_H
+#define M4_MADS_SCENE_H
+
+#include "m4/scene.h"
+
+namespace M4 {
+
+#define INTERFACE_HEIGHT 106
+#define MADS_SURFACE_HEIGHT 156
+
+struct SpriteSlot {
+ int16 spriteId;
+ int16 scale;
+ uint16 spriteListIndex;
+};
+
+struct DirtyArea {
+ bool active;
+ bool active2;
+ Common::Rect bounds;
+};
+
+class MadsSceneInfo {
+public:
+ int sceneId;
+ int artFileNum;
+ int field_4;
+ int width;
+ int height;
+
+ int objectCount;
+ MadsObject objects[32];
+
+ int walkSize;
+ byte *walkData;
+
+ MadsSceneInfo() { walkSize = 0; walkData = NULL; }
+ ~MadsSceneInfo() { delete walkData; }
+ void load(int sceneId);
+};
+
+#define TIMED_TEXT_SIZE 10
+#define TEXT_DISPLAY_SIZE 40
+#define TEXT_4A_SIZE 30
+
+enum TalkTextFlags {TEXTFLAG_2 = 2, TEXTFLAG_4 = 4, TEXTFLAG_8 = 8, TEXTFLAG_40 = 0x40,
+ TEXTFLAG_ACTIVE = 0x80};
+
+struct TextDisplay {
+ bool active;
+ int spacing;
+ int16 active2;
+ Common::Rect bounds;
+ int colour1, colour2;
+ Font *font;
+ char message[100];
+};
+
+struct TimedText {
+ uint8 flags;
+ int colour1;
+ int colour2;
+ Common::Point position;
+ int textDisplayIndex;
+ int unk4AIndex;
+ uint32 timeout;
+ uint32 frameTimer;
+ bool field_1C;
+ uint8 field_1D;
+ uint16 actionNouns[3];
+ char message[100];
+};
+
+struct Text4A {
+ uint8 active;
+ uint8 field25;
+};
+
+class MadsScreenText {
+private:
+ TextDisplay _textDisplay[TEXT_DISPLAY_SIZE];
+ TimedText _timedText[TIMED_TEXT_SIZE];
+ Text4A _text4A[TEXT_4A_SIZE];
+ bool _abortTimedText;
+
+ void addTimedText(TimedText *entry);
+public:
+ MadsScreenText();
+
+ // TextDisplay list
+ int add(const Common::Point &destPos, uint fontColours, int widthAdjust, const char *msg, Font *font);
+ void setActive2(int16 idx) { _textDisplay[idx].active2 = -1; }
+ // TimedText list
+ int addTimed(const Common::Point &destPos, uint fontColours, uint flags, int vUnknown, uint32 timeout, const char *message);
+
+ void draw(M4Surface *surface);
+ void timedDisplay();
+};
+
+enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6};
+
+class MadsAction {
+private:
+ char _statusText[100];
+ int _currentHotspot;
+ int _objectNameId;
+ int _objectDescId;
+ int _currentAction;
+ int8 _flags1, _flags2;
+ MadsActionMode _actionMode;
+ int _articleNumber;
+ bool _lookFlag;
+ int _selectedRow;
+
+ void appendVocab(int vocabId, bool capitalise = false);
+public:
+ MadsAction();
+
+ void clear();
+ void set();
+};
+
+typedef Common::Array<SpriteAsset *> SpriteAssetArray;
+
+#define SPRITE_SLOTS_SIZE 50
+#define DIRTY_AREA_SIZE 90
+
+class MadsScene : public Scene {
+private:
+ MadsEngine *_vm;
+ char _statusText[100];
+
+ MadsSceneLogic _sceneLogic;
+ MadsSceneInfo _sceneInfo;
+ SpriteAsset *_playerSprites;
+ SpriteAssetArray _sceneSprites;
+ SpriteSlot _spriteSlots[50];
+ MadsScreenText _textDisplay;
+ DirtyArea _dirtyAreas[DIRTY_AREA_SIZE];
+ int _spriteSlotsStart;
+
+ void drawElements();
+ void loadScene2(const char *aaName);
+ void loadSceneTemporary();
+ void clearAction();
+ void appendActionVocab(int vocabId, bool capitalise);
+ void setAction();
+public:
+ char _aaName[100];
+ uint16 actionNouns[3];
+public:
+ MadsScene(MadsEngine *vm);
+
+ // Methods that differ between engines
+ virtual void loadScene(int sceneNumber);
+ virtual void leaveScene();
+ virtual void loadSceneCodes(int sceneNumber, int index = 0);
+ virtual void show();
+ virtual void checkHotspotAtMousePos(int x, int y);
+ virtual void leftClick(int x, int y);
+ virtual void rightClick(int x, int y);
+ virtual void setAction(int action, int objectId = -1);
+ virtual void setStatusText(const char *text);
+ virtual void update();
+
+ int loadSceneSpriteSet(const char *setName);
+ void loadPlayerSprites(const char *prefix);
+
+ MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; };
+};
+
+} // End of namespace M4
+
+#endif
diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h
index d984f77589..fa6247d4a9 100644
--- a/engines/m4/mads_views.h
+++ b/engines/m4/mads_views.h
@@ -34,6 +34,8 @@
namespace M4 {
+#define CHEAT_SEQUENCE_MAX 8
+
class IntegerList : public Common::Array<int> {
public:
int indexOf(int v) {
@@ -74,6 +76,7 @@ public:
virtual void initialise();
virtual void setSelectedObject(int objectNumber);
virtual void addObjectToInventory(int objectNumber);
+ int getSelectedObject() { return _selectedObject; }
void onRefresh(RectList *rects, M4Surface *destSurface);
bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);
diff --git a/engines/m4/module.mk b/engines/m4/module.mk
index d88536fa1a..1b08ea2188 100644
--- a/engines/m4/module.mk
+++ b/engines/m4/module.mk
@@ -17,10 +17,12 @@ MODULE_OBJS = \
hotspot.o \
m4.o \
m4_menus.o \
+ m4_scene.o \
m4_views.o \
mads_anim.o \
mads_logic.o \
mads_menus.o \
+ mads_scene.o \
mads_views.o \
midi.o \
rails.o \
diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp
index 673a375fa2..a9905f5b2f 100644
--- a/engines/m4/scene.cpp
+++ b/engines/m4/scene.cpp
@@ -406,563 +406,4 @@ void Scene::showMADSV2TextBox(char *text, int x, int y, char *faceName) {
boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1);
}
-/*--------------------------------------------------------------------------*/
-
-M4Scene::M4Scene(M4Engine *vm): Scene(vm) {
- _vm = vm;
- _sceneSprites = NULL;
- _interfaceSurface = new M4InterfaceView(vm);
-}
-
-M4Scene::~M4Scene() {
- delete _sceneSprites;
-}
-
-void M4Scene::loadSceneSprites(int sceneNumber) {
- char filename[kM4MaxFilenameSize];
- sprintf(filename, "%i.ssb", sceneNumber);
-
- Common::SeekableReadStream *sceneS = _vm->res()->get(filename);
- _sceneSprites = new SpriteAsset(_vm, sceneS, sceneS->size(), filename);
- _vm->res()->toss(filename);
-
- printf("Scene has %d sprites, each one having %d colors\n", _sceneSprites->getCount(), _sceneSprites->getColorCount());
-}
-
-void M4Scene::loadScene(int sceneNumber) {
- Scene::loadScene(sceneNumber);
-
- _backgroundSurface->loadBackground(sceneNumber);
- _palData = NULL;
-
- if (_vm->getGameType() == GType_Burger &&
- sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER)
- setStatusText("");
-
- // Load scene def file (*.CHK)
- loadSceneResources(sceneNumber);
- loadSceneInverseColorTable(sceneNumber);
-
- // TODO: set walker scaling
- // TODO: destroy woodscript buffer
-
- // Load scene walk path file (*.COD/*.WW?)
- loadSceneCodes(sceneNumber);
-
- // Load inverse color table file (*.IPL)
- loadSceneInverseColorTable(sceneNumber);
-
- if (_vm->getGameType() != GType_Burger) {
- // Load scene sprites file (*.SSB)
- loadSceneSprites(sceneNumber);
-
- // Load scene sprite codes file (*.SSC)
- loadSceneSpriteCodes(sceneNumber);
- }
-
-
- if (sceneNumber != TITLE_SCENE_BURGER && sceneNumber != MAINMENU_SCENE_BURGER) {
- _m4Vm->scene()->getInterface()->show();
- showSprites();
- }
-
- // Purge resources
- _vm->res()->purge();
-}
-
-void M4Scene::loadSceneCodes(int sceneNumber, int index) {
- char filename[kM4MaxFilenameSize];
- Common::SeekableReadStream *sceneS;
-
- sprintf(filename, "%i.cod", sceneNumber);
- sceneS = _vm->res()->openFile(filename);
- _walkSurface->loadCodesM4(sceneS);
- _vm->res()->toss(filename);
-}
-
-void M4Scene::show() {
- Scene::show();
- _vm->_viewManager->addView(_interfaceSurface);
-}
-
-void M4Scene::checkHotspotAtMousePos(int x, int y) {
- if (_vm->getGameType() == GType_Riddle)
- return;
-
- // TODO: loads of things to do here, only the mouse cursor and the status
- // text is changed for now
-
- // Only scene hotspots are checked for now, not parallax/props, as the
- // latter ones are not used by Orion Burger
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL && currentHotSpot->getActive()) {
- if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
- _vm->_mouse->getCursorNum() != CURSOR_TAKE &&
- _vm->_mouse->getCursorNum() != CURSOR_USE &&
- _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) {
- _vm->_mouse->setCursorNum(currentHotSpot->getCursor());
- }
- _m4Vm->scene()->getInterface()->setStatusText(currentHotSpot->getPrep());
- } else {
- if (_vm->_mouse->getCursorNum() != CURSOR_LOOK &&
- _vm->_mouse->getCursorNum() != CURSOR_TAKE &&
- _vm->_mouse->getCursorNum() != CURSOR_USE &&
- _m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) {
- _vm->_mouse->setCursorNum(0);
- } else {
-
- }
- }
-}
-
-void M4Scene::leftClick(int x, int y) {
- if (_vm->getGameType() == GType_Burger) {
- // Place a Wilbur sprite with the correct facing
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL && currentHotSpot->getActive()) {
- update();
- _vm->_actor->setWalkerDirection(currentHotSpot->getFacing());
- /*
- int posX = currentHotSpot->getFeetX();
- int posY = currentHotSpot->getFeetY() -
- scaleValue(_vm->_actor->getWalkerHeight(), _vm->_actor->getWalkerScaling(), 0);
- //_vm->_actor->placeWalkerSpriteAt(0, posX, posY);
- */
-
- // Player said.... (for scene scripts)
- printf("Player said: %s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
-
- // FIXME: This should be moved somewhere else, and is incomplete
- if (_m4Vm->scene()->getInterface()->_inventory.getSelectedIndex() == -1) {
- if (_vm->_mouse->getVerb() == NULL) {
- strcpy(_vm->_player->verb, currentHotSpot->getVerb());
- } else {
- strcpy(_vm->_player->verb, _vm->_mouse->getVerb());
- }
- } else {
- strcpy(_vm->_player->verb, _m4Vm->scene()->getInterface()->_inventory.getSelectedObjectName());
- }
- strcpy(_vm->_player->noun, currentHotSpot->getVocab());
- strcpy(_vm->_player->object, "");
- _vm->_player->commandReady = true;
-
- printf("## Player said: %s %s\n", _vm->_player->verb, _vm->_player->noun);
-
- }
- }
-}
-
-void M4Scene::rightClick(int x, int y) {
- if (_vm->getGameType() == GType_Burger) {
- nextCommonCursor();
- _m4Vm->scene()->getInterface()->_inventory.clearSelected();
- }
-}
-
-void M4Scene::setAction(int action, int objectId) {
-}
-
-void M4Scene::setStatusText(const char *text) {
- getInterface()->setStatusText(text);
-}
-
-void M4Scene::update() {
-
-}
-
-void M4Scene::nextCommonCursor() {
- int cursorIndex = _vm->_mouse->getCursorNum();
-
- switch (cursorIndex) {
- case CURSOR_ARROW:
- cursorIndex = CURSOR_LOOK;
- break;
- case CURSOR_LOOK:
- cursorIndex = CURSOR_TAKE;
- break;
- case CURSOR_TAKE:
- cursorIndex = CURSOR_USE;
- break;
- case CURSOR_USE:
- cursorIndex = CURSOR_ARROW;
- break;
- default:
- cursorIndex = CURSOR_ARROW;
- }
-
- _vm->_mouse->setCursorNum(cursorIndex);
-}
-
-/*--------------------------------------------------------------------------*/
-
-MadsScene::MadsScene(MadsEngine *vm): Scene(vm) {
- _vm = vm;
-
- strcpy(_statusText, "");
- _interfaceSurface = new MadsInterfaceView(vm);
- _currentAction = kVerbNone;
- _spriteSlotsStart = 0;
-}
-
-/**
- * Secondary scene loading code
- */
-void MadsScene::loadScene2(const char *aaName) {
- // Load up the properties for the scene
- _sceneInfo.load(_currentScene);
-
- // Load scene walk paths
- loadSceneCodes(_currentScene);
-}
-
-/**
- * Existing ScummVM code that needs to be eventually replaced with MADS code
- */
-void MadsScene::loadSceneTemporary() {
- /* Existing code that eventually needs to be replaced with the proper MADS code */
- // Set system palette entries
- _vm->_palette->blockRange(0, 7);
- RGB8 sysColors[3] = { {0x1f<<2, 0x2d<<2, 0x31<<2, 0}, {0x24<<2, 0x37<<2, 0x3a<<2, 0},
- {0x00<<2, 0x10<<2, 0x16<<2, 0}};
- _vm->_palette->setPalette(&sysColors[0], 4, 3);
-
- _backgroundSurface->loadBackground(_currentScene, &_palData);
- _vm->_palette->addRange(_palData);
- _backgroundSurface->translate(_palData);
-
- if (_currentScene < 900) {
- /*_backgroundSurface->fillRect(Common::Rect(0, MADS_SURFACE_HEIGHT,
- _backgroundSurface->width(), _backgroundSurface->height()),
- _vm->_palette->BLACK);*/
- // TODO: interface palette
- _interfaceSurface->madsloadInterface(0, &_interfacePal);
- _vm->_palette->addRange(_interfacePal);
- _interfaceSurface->translate(_interfacePal);
- _backgroundSurface->copyFrom(_interfaceSurface, Common::Rect(0, 0, 320, 44), 0, 200 - 44);
-
- _interfaceSurface->initialise();
- }
-
- // Don't load other screen resources for system screens
- if (_currentScene >= 900)
- return;
-
- loadSceneHotSpotsMads(_currentScene);
-
- // TODO: set walker scaling
- // TODO: destroy woodscript buffer
-
- // Load inverse color table file (*.IPL)
- loadSceneInverseColorTable(_currentScene);
-}
-
-void MadsScene::loadScene(int sceneNumber) {
- // Close the menu if it's active
- View *mainMenu = _vm->_viewManager->getView(VIEWID_MAINMENU);
- if (mainMenu != NULL) {
- _vm->_viewManager->deleteView(mainMenu);
- }
-
- // Handle common scene setting
- Scene::loadScene(sceneNumber);
-
- // Signal the script engine what scene is to be active
- _sceneLogic.selectScene(sceneNumber);
- _sceneLogic.setupScene();
-
- // Add the scene if necessary to the list of scenes that have been visited
- _vm->globals()->addVisitedScene(sceneNumber);
-
- // Secondary scene load routine
- loadScene2("*I0.AA");
-
- // Do any scene specific setup
- _sceneLogic.enterScene();
-
- // Existing ScummVM code that needs to be eventually replaced with MADS code
- loadSceneTemporary();
-
- // Purge resources
- _vm->res()->purge();
-}
-
-void MadsScene::leaveScene() {
- _sceneResources.hotspots->clear();
- _sceneResources.parallax->clear();
- _sceneResources.props->clear();
-
- delete _sceneResources.hotspots;
- delete _sceneResources.parallax;
- delete _sceneResources.props;
-
- // Delete the sprites
- for (uint i = 0; i <_sceneSprites.size(); ++i) delete _sceneSprites[i];
- _sceneSprites.clear();
-
- delete _backgroundSurface;
- delete _walkSurface;
-
- Scene::leaveScene();
-}
-
-void MadsScene::show() {
- Scene::show();
- _vm->_viewManager->addView(_interfaceSurface);
-}
-
-void MadsScene::loadSceneCodes(int sceneNumber, int index) {
- char filename[kM4MaxFilenameSize];
- Common::SeekableReadStream *sceneS;
-
- if (_vm->getGameType() == GType_Phantom || _vm->getGameType() == GType_DragonSphere) {
- sprintf(filename, "rm%i.ww%i", sceneNumber, index);
- MadsPack walkData(filename, _vm);
- sceneS = walkData.getItemStream(0);
- _walkSurface->loadCodesMads(sceneS);
- _vm->res()->toss(filename);
- } else if (_vm->getGameType() == GType_RexNebular) {
- // For Rex Nebular, the walk areas are part of the scene info
- byte *destP = _walkSurface->getBasePtr(0, 0);
- const byte *srcP = _sceneInfo.walkData;
- byte runLength;
- while ((runLength = *srcP++) != 0) {
- Common::set_to(destP, destP + runLength, *srcP++);
- destP += runLength;
- }
- }
-}
-
-void MadsScene::checkHotspotAtMousePos(int x, int y) {
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL) {
- _vm->_mouse->setCursorNum(currentHotSpot->getCursor());
-
- // This is the "easy" interface, which updates the status text when the mouse is moved
- // TODO: toggle this code for easy/normal interface mode
- char statusText[50];
- int verbId = _currentAction;
- if (verbId == kVerbNone)
- verbId = currentHotSpot->getVerbID();
- if (verbId == kVerbNone)
- verbId = kVerbWalkTo;
-
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(verbId), currentHotSpot->getVocab());
-
- statusText[0] = toupper(statusText[0]); // capitalize first letter
- setStatusText(statusText);
- } else {
- _vm->_mouse->setCursorNum(0);
- setStatusText("");
- }
-}
-
-void MadsScene::leftClick(int x, int y) {
- HotSpot *currentHotSpot = _sceneResources.hotspots->findByXY(x, y);
- if (currentHotSpot != NULL) {
- char statusText[50];
- if (currentHotSpot->getVerbID() != 0) {
- sprintf(statusText, "%s %s\n", currentHotSpot->getVerb(), currentHotSpot->getVocab());
- } else {
- sprintf(statusText, "%s %s\n", _madsVm->globals()->getVocab(kVerbWalkTo), currentHotSpot->getVocab());
- }
-
- statusText[0] = toupper(statusText[0]); // capitalize first letter
- setStatusText(statusText);
- }
-}
-
-void MadsScene::rightClick(int x, int y) {
- // ***DEBUG*** - sample dialog display
- int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a);
- const char *msg = _madsVm->globals()->loadMessage(idx);
- Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG");
- _vm->_viewManager->addView(dlg);
- _vm->_viewManager->moveToFront(dlg);
-}
-
-void MadsScene::setAction(int action, int objectId) {
- VALIDATE_MADS;
- char statusText[50];
-
- // TODO: Actually executing actions directly for objects. Also, some object actions are special in that
- // a second object can be selected, as in 'use gun to shoot person', with requires a target
-
- // Set up the new action
- strcpy(statusText, _madsVm->globals()->getVocab(action));
- statusText[0] = toupper(statusText[0]); // capitalize first letter
-
- if (objectId != -1) {
- MadsObject *obj = _madsVm->globals()->getObject(objectId);
- sprintf(statusText + strlen(statusText), " %s", _madsVm->globals()->getVocab(obj->descId));
- } else {
- _currentAction = action;
- }
-
- setStatusText(statusText);
-}
-
-void MadsScene::setStatusText(const char *text) {
- strcpy(_statusText, text);
-}
-
-/**
- * Draws all the elements of the scene
- */
-void MadsScene::drawElements() {
-
- // Display animations
- for (int idx = 0; idx < _spriteSlotsStart; ++idx) {
-
- }
-
-
- // Text display loop
- for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
- if (_textDisplay[idx].active && (_textDisplay[idx].field_A >= 0)) {
- _textDisplay[idx].font->setColours(0xFF, (_textDisplay[idx].colour2 == 0) ?
- _textDisplay[idx].colour1 : _textDisplay[idx].colour2, _textDisplay[idx].colour1);
- _textDisplay[idx].font->writeString(this, _textDisplay[idx].message,
- _textDisplay[idx].bounds.left, _textDisplay[idx].bounds.top,
- width() - _textDisplay[idx].bounds.left, _textDisplay[idx].spacing);
- }
- }
-
- // Copy the user interface surface onto the surface
- _interfaceSurface->copyTo(this, 0, this->height() - _interfaceSurface->height());
-
-/*
- // At this point, in the original engine, the dirty/changed areas were copied to the screen. At the moment,
- // the current M4 engine framework doesn't support dirty areas, but this is being kept in case that ever changes
- for (int idx = 0; idx < DIRTY_AREA_SIZE; ++idx) {
- if (_dirtyAreas[idx].active && _dirtyAreas[idx].active2 &&
- (_dirtyAreas[idx].bounds.width() > 0) && (_dirtyAreas[idx].bounds.height() > 0)) {
- // Copy changed area to screen
-
- }
- }
-*/
-
- // Some kind of copying over of slot entries
- for (int idx = 0, idx2 = 0; idx < _spriteSlotsStart; ++idx) {
- if (_spriteSlots[idx].spriteId >= 0) {
- if (idx != idx2) {
- // Copy over the slot entry
- _spriteSlots[idx2] = _spriteSlots[idx];
- }
- ++idx2;
- }
- }
-
- // Clear up any now inactive text display entries
- for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
- if (_textDisplay[idx].field_A < 0) {
- _textDisplay[idx].active = false;
- _textDisplay[idx].field_A = 0;
- }
- }
-}
-
-
-void MadsScene::update() {
- // Copy the bare scene in
- _backgroundSurface->copyTo(this);
-
- // Draw all the various elements
- drawElements();
-
- // Handle display of any status text
- if (_statusText[0]) {
- // Text colors are inverted in Dragonsphere
- if (_vm->getGameType() == GType_DragonSphere)
- _vm->_font->setColors(_vm->_palette->BLACK, _vm->_palette->WHITE, _vm->_palette->BLACK);
- else
- _vm->_font->setColors(_vm->_palette->WHITE, _vm->_palette->BLACK, _vm->_palette->BLACK);
-
- _vm->_font->setFont(FONT_MAIN_MADS);
- _vm->_font->writeString(this, _statusText, (width() - _vm->_font->getWidth(_statusText)) / 2, 142, 0);
- }
-
- //***DEBUG***
- _sceneSprites[0]->getFrame(1)->copyTo(this, 120, 90, 0);
-}
-
-int MadsScene::loadSceneSpriteSet(const char *setName) {
- char resName[100];
- strcpy(resName, setName);
-
- // Append a '.SS' if it doesn't alreayd have an extension
- if (!strchr(resName, '.'))
- strcat(resName, ".SS");
-
- Common::SeekableReadStream *data = _vm->res()->get(resName);
- SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName);
- spriteSet->translate(_vm->_palette);
- _vm->res()->toss(resName);
-
- _sceneSprites.push_back(spriteSet);
- return _sceneSprites.size() - 1;
-}
-
-void MadsScene::loadPlayerSprites(const char *prefix) {
- const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' };
- char setName[80];
-
- strcpy(setName, "*");
- strcat(setName, prefix);
- strcat(setName, "_0.SS");
- char *digitP = strchr(setName, '_') + 1;
-
- for (int idx = 0; idx < 8; ++idx) {
- *digitP = suffixList[idx];
-
- if (_vm->res()->resourceExists(setName)) {
- loadSceneSpriteSet(setName);
- return;
- }
- }
-
- error("Couldn't find player sprites");
-}
-
-/*--------------------------------------------------------------------------*/
-
-void MadsSceneInfo::load(int sId) {
- const char *sceneInfoStr = MADSResourceManager::getResourceName(RESPREFIX_RM, sId, ".DAT");
- Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneInfoStr);
- MadsPack sceneInfo(rawStream);
-
- // Basic scene info
- Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);
-
- int resSceneId = stream->readUint16LE();
- assert(resSceneId == sId);
-
- artFileNum = stream->readUint16LE();
- field_4 = stream->readUint16LE();
- width = stream->readUint16LE();
- height = stream->readUint16LE();
- assert((width == 320) && (height == 156));
-
- stream->skip(24);
-
- objectCount = stream->readUint16LE();
-
- stream->skip(40);
-
- for (int i = 0; i < objectCount; ++i) {
- objects[i].load(stream);
- }
-
- // For Rex Nebular, read in the scene's compressed walk surface information
- if (_vm->getGameType() == GType_RexNebular) {
- delete walkData;
-
- stream = sceneInfo.getItemStream(1);
- walkData = (byte *)malloc(stream->size());
- stream->read(walkData, stream->size());
- }
-
- _vm->_resourceManager->toss(sceneInfoStr);
-}
-
} // End of namespace M4
diff --git a/engines/m4/scene.h b/engines/m4/scene.h
index 78e179b4ac..0f4fc6c48d 100644
--- a/engines/m4/scene.h
+++ b/engines/m4/scene.h
@@ -41,16 +41,8 @@ class View;
namespace M4 {
-#define TITLE_SCENE_BURGER 951 // 951 = intro, 901 = demo menu, 971 = first scene
-#define MAINMENU_SCENE_BURGER 903
-#define FIRST_SCENE 101
#define MAX_CHK_FILENAME_SIZE 144
-#define INTERFACE_HEIGHT 106
-#define MADS_SURFACE_HEIGHT 156
-
-#define CHEAT_SEQUENCE_MAX 8
-
enum MADSVerbs {
kVerbNone = 0,
kVerbLook = 3,
@@ -136,121 +128,6 @@ public:
bool onEvent(M4EventType eventType, int32 param1, int x, int y, bool &captureEvents);
};
-class M4Scene : public Scene {
-private:
- M4Engine *_vm;
- SpriteAsset *_sceneSprites;
- SpriteAsset *_walkerSprite;
-
- void loadSceneSprites(int sceneNumber);
- void nextCommonCursor();
-public:
- M4Scene(M4Engine *vm);
- virtual ~M4Scene();
-
- // Methods that differ between engines
- virtual void loadScene(int sceneNumber);
- virtual void leaveScene() {};
- virtual void loadSceneCodes(int sceneNumber, int index = 0);
- virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y);
- virtual void leftClick(int x, int y);
- virtual void rightClick(int x, int y);
- virtual void setAction(int action, int objectId = -1);
- virtual void setStatusText(const char *text);
- virtual void update();
-
- M4InterfaceView *getInterface() { return (M4InterfaceView *)_interfaceSurface; };
-};
-
-struct SpriteSlot {
- int16 spriteId;
- int16 scale;
- uint16 spriteListIndex;
-};
-
-struct TextDisplay {
- bool active;
- int spacing;
- Common::Rect bounds;
- int16 field_A;
- uint8 colour1, colour2;
- Font *font;
- char message[100];
-};
-
-struct DirtyArea {
- bool active;
- bool active2;
- Common::Rect bounds;
-};
-
-class MadsSceneInfo {
-public:
- int sceneId;
- int artFileNum;
- int field_4;
- int width;
- int height;
-
- int objectCount;
- MadsObject objects[32];
-
- int walkSize;
- byte *walkData;
-
- MadsSceneInfo() { walkSize = 0; walkData = NULL; }
- ~MadsSceneInfo() { delete walkData; }
- void load(int sceneId);
-};
-
-typedef Common::Array<SpriteAsset *> SpriteAssetArray;
-
-#define SPRITE_SLOTS_SIZE 50
-#define TEXT_DISPLAY_SIZE 40
-#define DIRTY_AREA_SIZE 90
-
-class MadsScene : public Scene {
-private:
- MadsEngine *_vm;
-
- int _currentAction;
- char _statusText[100];
- MadsSceneLogic _sceneLogic;
- MadsSceneInfo _sceneInfo;
- SpriteAsset *_playerSprites;
- SpriteAssetArray _sceneSprites;
- SpriteSlot _spriteSlots[50];
- TextDisplay _textDisplay[TEXT_DISPLAY_SIZE];
- DirtyArea _dirtyAreas[DIRTY_AREA_SIZE];
- int _spriteSlotsStart;
-
- void drawElements();
- void loadScene2(const char *aaName);
- void loadSceneTemporary();
-public:
- char _aaName[100];
-public:
- MadsScene(MadsEngine *vm);
-
- // Methods that differ between engines
- virtual void loadScene(int sceneNumber);
- virtual void leaveScene();
- virtual void loadSceneCodes(int sceneNumber, int index = 0);
- virtual void show();
- virtual void checkHotspotAtMousePos(int x, int y);
- virtual void leftClick(int x, int y);
- virtual void rightClick(int x, int y);
- virtual void setAction(int action, int objectId = -1);
- virtual void setStatusText(const char *text);
- virtual void update();
-
- int loadSceneSpriteSet(const char *setName);
- void loadPlayerSprites(const char *prefix);
-
- MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; };
-};
-
} // End of namespace M4
#endif
diff --git a/engines/m4/script.cpp b/engines/m4/script.cpp
index 62fade13d3..412707d95e 100644
--- a/engines/m4/script.cpp
+++ b/engines/m4/script.cpp
@@ -1103,7 +1103,7 @@ int ScriptInterpreter::o1_loadConversation() {
//int flag = INTEGER(2);
// TODO; just to show something
- _vm->_converse->startConversation(name);
+ _m4Vm->_converse->startConversation(name);
return 3;
}
diff --git a/engines/m4/staticres.cpp b/engines/m4/staticres.cpp
index d376c30bcc..21cb719a2c 100644
--- a/engines/m4/staticres.cpp
+++ b/engines/m4/staticres.cpp
@@ -37,5 +37,22 @@ const char *cheatingEnabledDesc[3] = {
NULL
};
+const char *atStr = "at";
+const char *lookAroundStr = "Look around";
+const char *toStr = "to ";
+const char *useStr = "Use ";
+
+VerbInit verbList[10] = {
+ {kVerbLook, 2, 0},
+ {kVerbTake, 2, 0},
+ {kVerbPush, 2, 0},
+ {kVerbOpen, 2, 0},
+ {kVerbPut, 1, -1},
+ {kVerbTalkTo, 2, 0},
+ {kVerbGive, 1, 2},
+ {kVerbPull, 2, 0},
+ {kVerbClose, 2, 0},
+ {kVerbThrow, 1, 3}
+};
} // End of namespace M4
diff --git a/engines/m4/staticres.h b/engines/m4/staticres.h
index 754e37db46..7d33aff189 100644
--- a/engines/m4/staticres.h
+++ b/engines/m4/staticres.h
@@ -35,6 +35,19 @@ extern const char *englishMADSArticleList[9];
extern const char *cheatingEnabledDesc[3];
+extern const char *atStr;
+extern const char *lookAroundStr;
+extern const char *toStr;
+extern const char *useStr;
+
+struct VerbInit {
+ int verb;
+ int8 flag1;
+ int8 flag2;
+};
+
+extern VerbInit verbList[10];
+
} // End of namespace M4
#endif