aboutsummaryrefslogtreecommitdiff
path: root/engines/parallaction
diff options
context:
space:
mode:
authorChristopher Page2008-07-14 00:10:09 +0000
committerChristopher Page2008-07-14 00:10:09 +0000
commitd2e8d4831e33f9e1c63d53c9dd615a15f67ab995 (patch)
tree308cc8bb9ab0bc80d006c84b8ff84267355cedcb /engines/parallaction
parent3ac3e84ecffa967f02eeb497e260a0de08e3d2e7 (diff)
parentef95c6ff70c1b428ab1d086a9b0b551fc82c8451 (diff)
downloadscummvm-rg350-d2e8d4831e33f9e1c63d53c9dd615a15f67ab995.tar.gz
scummvm-rg350-d2e8d4831e33f9e1c63d53c9dd615a15f67ab995.tar.bz2
scummvm-rg350-d2e8d4831e33f9e1c63d53c9dd615a15f67ab995.zip
Merged revisions 32744-32745,32747,32750-32759,32762-32764,32769,32777,32783,32785-32786,32789-32791,32798-32799,32801-32807,32809-32812,32816-32817,32819-32821,32823-32830,32832-32836,32838-32844,32846-32850,32852-32854,32858-32859,32865-32868,32873-32874,32879,32883,32895,32899,32902-32904,32910-32912,32923-32924,32930-32931,32938,32940,32948-32949,32951,32960-32964,32966-32970,32972-32974,32976,32978,32983,32986-32990,32992,32994,33002-33004,33006-33007,33009-33010,33014,33017,33021-33023,33030,33033 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk svn-id: r33051
Diffstat (limited to 'engines/parallaction')
-rw-r--r--engines/parallaction/balloons.cpp456
-rw-r--r--engines/parallaction/callables_ns.cpp9
-rw-r--r--engines/parallaction/debug.cpp14
-rw-r--r--engines/parallaction/dialogue.cpp36
-rw-r--r--engines/parallaction/disk.h36
-rw-r--r--engines/parallaction/disk_br.cpp31
-rw-r--r--engines/parallaction/disk_ns.cpp38
-rw-r--r--engines/parallaction/exec.h241
-rw-r--r--engines/parallaction/exec_br.cpp159
-rw-r--r--engines/parallaction/exec_ns.cpp277
-rw-r--r--engines/parallaction/gfxbase.cpp294
-rw-r--r--engines/parallaction/graphics.cpp576
-rw-r--r--engines/parallaction/graphics.h110
-rw-r--r--engines/parallaction/gui_br.cpp6
-rw-r--r--engines/parallaction/gui_ns.cpp2
-rw-r--r--engines/parallaction/input.cpp4
-rw-r--r--engines/parallaction/input.h2
-rw-r--r--engines/parallaction/module.mk1
-rw-r--r--engines/parallaction/objects.cpp14
-rw-r--r--engines/parallaction/objects.h7
-rw-r--r--engines/parallaction/parallaction.cpp104
-rw-r--r--engines/parallaction/parallaction.h171
-rw-r--r--engines/parallaction/parallaction_br.cpp25
-rw-r--r--engines/parallaction/parallaction_ns.cpp27
-rw-r--r--engines/parallaction/parser_br.cpp2
-rw-r--r--engines/parallaction/parser_ns.cpp2
-rw-r--r--engines/parallaction/sound.cpp4
-rw-r--r--engines/parallaction/walk.cpp173
28 files changed, 1714 insertions, 1107 deletions
diff --git a/engines/parallaction/balloons.cpp b/engines/parallaction/balloons.cpp
new file mode 100644
index 0000000000..fab92dada9
--- /dev/null
+++ b/engines/parallaction/balloons.cpp
@@ -0,0 +1,456 @@
+/* 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 "parallaction/graphics.h"
+#include "parallaction/parallaction.h"
+
+namespace Parallaction {
+
+
+#define BALLOON_TRANSPARENT_COLOR_NS 2
+#define BALLOON_TRANSPARENT_COLOR_BR 0
+
+#define BALLOON_TAIL_WIDTH 12
+#define BALLOON_TAIL_HEIGHT 10
+
+
+byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = {
+ {
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ },
+ {
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02
+ }
+};
+
+class BalloonManager_ns : public BalloonManager {
+
+ static int16 _dialogueBalloonX[5];
+
+ struct Balloon {
+ Common::Rect outerBox;
+ Common::Rect innerBox;
+ Graphics::Surface *surface;
+ GfxObj *obj;
+ } _intBalloons[5];
+
+ uint _numBalloons;
+
+ void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
+ int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
+ Balloon *getBalloon(uint id);
+
+ Gfx *_gfx;
+
+public:
+ BalloonManager_ns(Gfx *gfx);
+ ~BalloonManager_ns();
+
+ void freeBalloons();
+ int setLocationBalloon(char *text, bool endGame);
+ int setDialogueBalloon(char *text, uint16 winding, byte textColor);
+ int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
+ void setBalloonText(uint id, char *text, byte textColor);
+ int hitTestDialogueBalloon(int x, int y);
+};
+
+int16 BalloonManager_ns::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 };
+
+BalloonManager_ns::BalloonManager_ns(Gfx *gfx) : _numBalloons(0), _gfx(gfx) {
+
+}
+
+BalloonManager_ns::~BalloonManager_ns() {
+
+}
+
+
+BalloonManager_ns::Balloon* BalloonManager_ns::getBalloon(uint id) {
+ assert(id < _numBalloons);
+ return &_intBalloons[id];
+}
+
+int BalloonManager_ns::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) {
+ assert(_numBalloons < 5);
+
+ int id = _numBalloons;
+
+ Balloon *balloon = &_intBalloons[id];
+
+ int16 real_h = (winding == -1) ? h : h + 9;
+ balloon->surface = new Graphics::Surface;
+ balloon->surface->create(w, real_h, 1);
+ balloon->surface->fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR_NS);
+
+ Common::Rect r(w, h);
+ balloon->surface->fillRect(r, 0);
+ balloon->outerBox = r;
+
+ r.grow(-borderThickness);
+ balloon->surface->fillRect(r, 1);
+ balloon->innerBox = r;
+
+ if (winding != -1) {
+ // draws tail
+ // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill.
+ winding = (winding == 0 ? 1 : 0);
+ Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
+ s.moveTo(r.width()/2 - 5, r.bottom - 1);
+ _gfx->blt(s, _resBalloonTail[winding], balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR_NS);
+ }
+
+ _numBalloons++;
+
+ return id;
+}
+
+
+int BalloonManager_ns::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
+
+ int16 w, h;
+
+ _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+5, h, winding, 1);
+ Balloon *balloon = &_intBalloons[id];
+
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = x;
+ balloon->obj->y = y;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS;
+
+ return id;
+}
+
+int BalloonManager_ns::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
+
+ int16 w, h;
+
+ _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+5, h, winding, 1);
+ Balloon *balloon = &_intBalloons[id];
+
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = _dialogueBalloonX[id];
+ balloon->obj->y = 10;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS;
+
+ if (id > 0) {
+ balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].outerBox.height();
+ }
+
+
+ return id;
+}
+
+void BalloonManager_ns::setBalloonText(uint id, char *text, byte textColor) {
+ Balloon *balloon = getBalloon(id);
+ balloon->surface->fillRect(balloon->innerBox, 1);
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+}
+
+
+int BalloonManager_ns::setLocationBalloon(char *text, bool endGame) {
+
+ int16 w, h;
+
+ _gfx->getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR_NS);
+ Balloon *balloon = &_intBalloons[id];
+ _gfx->drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = 5;
+ balloon->obj->y = 5;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_NS;
+
+ return id;
+}
+
+int BalloonManager_ns::hitTestDialogueBalloon(int x, int y) {
+
+ Common::Point p;
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ p.x = x - _intBalloons[i].obj->x;
+ p.y = y - _intBalloons[i].obj->y;
+
+ if (_intBalloons[i].innerBox.contains(p))
+ return i;
+ }
+
+ return -1;
+}
+
+void BalloonManager_ns::freeBalloons() {
+ _gfx->destroyBalloons();
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ _intBalloons[i].obj = 0;
+ _intBalloons[i].surface = 0; // no need to delete surface, since it is done by destroyBalloons
+ }
+
+ _numBalloons = 0;
+}
+
+
+
+
+
+
+
+
+class BalloonManager_br : public BalloonManager {
+
+ struct Balloon {
+ Common::Rect box;
+ Graphics::Surface *surface;
+ GfxObj *obj;
+ } _intBalloons[3];
+
+ uint _numBalloons;
+
+ Frames *_leftBalloon;
+ Frames *_rightBalloon;
+ Disk *_disk;
+ Gfx *_gfx;
+
+ void cacheAnims();
+ void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
+ int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
+ Balloon *getBalloon(uint id);
+ Graphics::Surface *expandBalloon(Frames *data, int frameNum);
+
+
+public:
+ BalloonManager_br(Disk *disk, Gfx *gfx);
+ ~BalloonManager_br();
+
+ void freeBalloons();
+ int setLocationBalloon(char *text, bool endGame);
+ int setDialogueBalloon(char *text, uint16 winding, byte textColor);
+ int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
+ void setBalloonText(uint id, char *text, byte textColor);
+ int hitTestDialogueBalloon(int x, int y);
+};
+
+
+
+BalloonManager_br::Balloon* BalloonManager_br::getBalloon(uint id) {
+ assert(id < _numBalloons);
+ return &_intBalloons[id];
+}
+
+Graphics::Surface *BalloonManager_br::expandBalloon(Frames *data, int frameNum) {
+
+ Common::Rect rect;
+ data->getRect(frameNum, rect);
+
+ rect.translate(-rect.left, -rect.top);
+
+ Graphics::Surface *surf = new Graphics::Surface;
+ surf->create(rect.width(), rect.height(), 1);
+
+ _gfx->unpackBlt(rect, data->getData(frameNum), data->getRawSize(frameNum), surf, 0, BALLOON_TRANSPARENT_COLOR_BR);
+
+ return surf;
+}
+
+int BalloonManager_br::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
+ cacheAnims();
+
+ int id = _numBalloons;
+ Frames *src = 0;
+ int srcFrame = 0;
+
+ Balloon *balloon = &_intBalloons[id];
+
+ if (winding == 0) {
+ src = _leftBalloon;
+ srcFrame = 0;
+ } else
+ if (winding == 1) {
+ src = _rightBalloon;
+ srcFrame = 0;
+ }
+
+ assert(src);
+
+ balloon->surface = expandBalloon(src, srcFrame);
+ src->getRect(srcFrame, balloon->box);
+
+// drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = x;
+ balloon->obj->y = y;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR;
+
+ _numBalloons++;
+
+ return id;
+}
+
+int BalloonManager_br::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
+ cacheAnims();
+
+ int id = _numBalloons;
+ Frames *src = 0;
+ int srcFrame = 0;
+
+ Balloon *balloon = &_intBalloons[id];
+
+ if (winding == 0) {
+ src = _leftBalloon;
+ srcFrame = id;
+ } else
+ if (winding == 1) {
+ src = _rightBalloon;
+ srcFrame = 0;
+ }
+
+ assert(src);
+
+ balloon->surface = expandBalloon(src, srcFrame);
+ src->getRect(srcFrame, balloon->box);
+
+// drawWrappedText(_vm->_dialogueFont, balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = 0;
+ balloon->obj->y = 10;
+ balloon->obj->transparentKey = BALLOON_TRANSPARENT_COLOR_BR;
+
+ if (id > 0) {
+ balloon->obj->y += _intBalloons[id - 1].obj->y + _intBalloons[id - 1].box.height();
+ }
+
+ _numBalloons++;
+
+ return id;
+}
+
+void BalloonManager_br::setBalloonText(uint id, char *text, byte textColor) { }
+
+int BalloonManager_br::setLocationBalloon(char *text, bool endGame) {
+/*
+ int16 w, h;
+
+ getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
+
+ int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR);
+ Balloon *balloon = &_intBalloons[id];
+ drawWrappedText(_vm->_dialogueFont, balloon->surface, text, 0, MAX_BALLOON_WIDTH);
+
+ // TODO: extract some text to make a name for obj
+ balloon->obj = _gfx->registerBalloon(new SurfaceToFrames(balloon->surface), 0);
+ balloon->obj->x = 5;
+ balloon->obj->y = 5;
+*/
+ return 0;
+}
+
+int BalloonManager_br::hitTestDialogueBalloon(int x, int y) {
+
+ Common::Point p;
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ p.x = x - _intBalloons[i].obj->x;
+ p.y = y - _intBalloons[i].obj->y;
+
+ if (_intBalloons[i].box.contains(p))
+ return i;
+ }
+
+ return -1;
+}
+
+void BalloonManager_br::freeBalloons() {
+ _gfx->destroyBalloons();
+
+ for (uint i = 0; i < _numBalloons; i++) {
+ _intBalloons[i].obj = 0;
+ _intBalloons[i].surface = 0; // no need to delete surface, since it is done by destroyBalloons
+ }
+
+ _numBalloons = 0;
+}
+
+void BalloonManager_br::cacheAnims() {
+ if (!_leftBalloon) {
+ _leftBalloon = _disk->loadFrames("fumetto.ani");
+ _rightBalloon = _disk->loadFrames("fumdx.ani");
+ }
+}
+
+BalloonManager_br::BalloonManager_br(Disk *disk, Gfx *gfx) : _numBalloons(0), _disk(disk), _gfx(gfx), _leftBalloon(0), _rightBalloon(0) {
+}
+
+BalloonManager_br::~BalloonManager_br() {
+ delete _leftBalloon;
+ delete _rightBalloon;
+}
+
+void Parallaction::setupBalloonManager() {
+ if (_vm->getGameType() == GType_Nippon) {
+ _balloonMan = new BalloonManager_ns(_vm->_gfx);
+ } else
+ if (_vm->getGameType() == GType_BRA) {
+ _balloonMan = new BalloonManager_br(_vm->_disk, _vm->_gfx);
+ } else {
+ error("Unknown game type");
+ }
+}
+
+} // namespace Parallaction
diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp
index 68e6a70ffb..7c053715f6 100644
--- a/engines/parallaction/callables_ns.cpp
+++ b/engines/parallaction/callables_ns.cpp
@@ -341,7 +341,7 @@ void Parallaction_ns::_c_endComment(void *param) {
}
_input->waitUntilLeftClick();
- _gfx->freeBalloons();
+ _balloonMan->freeBalloons();
return;
}
@@ -417,6 +417,13 @@ void Parallaction_ns::_c_ridux(void *parm) {
}
void Parallaction_ns::_c_testResult(void *parm) {
+ if (_inTestResult) { // NOTE: _inTestResult has been added because the scripts call _c_testResult multiple times to cope with
+ // the multiple buffering that was used in the original engine. _inTestResult now prevents the engine
+ // from crashing when the scripts are executed.
+ return;
+ }
+ _inTestResult = true;
+
_gfx->updateScreen();
_disk->selectArchive("disk1");
diff --git a/engines/parallaction/debug.cpp b/engines/parallaction/debug.cpp
index 3c90a76f61..f57976594e 100644
--- a/engines/parallaction/debug.cpp
+++ b/engines/parallaction/debug.cpp
@@ -188,17 +188,15 @@ bool Debugger::Cmd_GfxObjects(int argc, const char **argv) {
const char *objType[] = { "DOOR", "GET", "ANIM" };
DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n"
- "| name | x | y | z | f | type | flag |\n"
+ "| name | x | y | z | f | type | visi |\n"
"+--------------------+-----+-----+-----+-----+--------+--------+\n");
- for (uint i = 0; i < 3; i++) {
- GfxObjList::iterator b = _vm->_gfx->_gfxobjList[i].begin();
- GfxObjList::iterator e = _vm->_gfx->_gfxobjList[i].end();
+ GfxObjList::iterator b = _vm->_gfx->_gfxobjList.begin();
+ GfxObjList::iterator e = _vm->_gfx->_gfxobjList.end();
- for ( ; b != e; b++) {
- GfxObj *obj = *b;
- DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], 6 );
- }
+ for ( ; b != e; b++) {
+ GfxObj *obj = *b;
+ DebugPrintf("|%-20s|%5i|%5i|%5i|%5i|%8s|%8x|\n", obj->getName(), obj->x, obj->y, obj->z, obj->frame, objType[obj->type], obj->isVisible() );
}
DebugPrintf("+--------------------+-----+-----+-----+-----+--------+--------+\n");
diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp
index eb2254cd80..a771f960a9 100644
--- a/engines/parallaction/dialogue.cpp
+++ b/engines/parallaction/dialogue.cpp
@@ -51,8 +51,8 @@ class DialogueManager {
bool _askPassword;
bool isNpc;
- Frames *_questioner;
- Frames *_answerer;
+ GfxObj *_questioner;
+ GfxObj *_answerer;
Question *_q;
@@ -93,7 +93,7 @@ uint16 DialogueManager::askPassword() {
uint16 passwordLen = 0;
_password[0] = '\0';
- _vm->_gfx->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
+ _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
_vm->_gfx->setItemFrame(id, 0);
@@ -113,7 +113,7 @@ uint16 DialogueManager::askPassword() {
}
if (changed) {
- _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 3);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
_vm->_gfx->updateScreen();
changed = false;
}
@@ -138,7 +138,7 @@ uint16 DialogueManager::askPassword() {
}
- _vm->_gfx->hideDialogueStuff();
+ _vm->hideDialogueStuff();
return 0;
@@ -157,7 +157,7 @@ bool DialogueManager::displayAnswer(uint16 i) {
// display suitable answers
if (((a->_yesFlags & flags) == a->_yesFlags) && ((a->_noFlags & ~flags) == a->_noFlags)) {
- int id = _vm->_gfx->setDialogueBalloon(a->_text, 1, 3);
+ int id = _vm->_balloonMan->setDialogueBalloon(a->_text, 1, 3);
assert(id >= 0);
_visAnswers[id] = i;
@@ -185,13 +185,13 @@ void DialogueManager::displayQuestion() {
if (!scumm_stricmp(_q->_text, "NULL")) return;
- _vm->_gfx->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
+ _vm->_balloonMan->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
int id = _vm->_gfx->setItem(_questioner, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y);
_vm->_gfx->setItemFrame(id, _q->_mood & 0xF);
_vm->_gfx->updateScreen();
_vm->_input->waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
+ _vm->hideDialogueStuff();
return;
}
@@ -224,7 +224,7 @@ void DialogueManager::run() {
answer = 0;
displayQuestion();
-
+
if (_vm->quit())
return;
@@ -244,7 +244,7 @@ void DialogueManager::run() {
}
if (cmdlist)
- _vm->runCommands(*cmdlist);
+ _vm->_cmdExec->run(*cmdlist);
}
@@ -256,31 +256,31 @@ int16 DialogueManager::selectAnswer() {
_vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
if (numAvailableAnswers == 1) {
- _vm->_gfx->setBalloonText(0, _q->_answers[0]->_text, 0);
+ _vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 0);
_vm->_input->waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
+ _vm->hideDialogueStuff();
return 0;
}
int oldSelection = -1;
- int selection;
+ int selection = 0;
uint32 event;
Common::Point p;
while (!_vm->quit()) {
-
+
_vm->_input->readInput();
_vm->_input->getCursorPos(p);
event = _vm->_input->getLastButtonEvent();
- selection = _vm->_gfx->hitTestDialogueBalloon(p.x, p.y);
+ selection = _vm->_balloonMan->hitTestDialogueBalloon(p.x, p.y);
if (selection != oldSelection) {
if (oldSelection != -1) {
- _vm->_gfx->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3);
+ _vm->_balloonMan->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3);
}
if (selection != -1) {
- _vm->_gfx->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0);
+ _vm->_balloonMan->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0);
_vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF);
}
}
@@ -295,7 +295,7 @@ int16 DialogueManager::selectAnswer() {
oldSelection = selection;
}
- _vm->_gfx->hideDialogueStuff();
+ _vm->hideDialogueStuff();
return _visAnswers[selection];
}
diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h
index b76c66aead..694d4efa6d 100644
--- a/engines/parallaction/disk.h
+++ b/engines/parallaction/disk.h
@@ -55,12 +55,12 @@ public:
virtual Script* loadLocation(const char *name) = 0;
virtual Script* loadScript(const char* name) = 0;
- virtual Frames* loadTalk(const char *name) = 0;
- virtual Frames* loadObjects(const char *name) = 0;
+ virtual GfxObj* loadTalk(const char *name) = 0;
+ virtual GfxObj* loadObjects(const char *name) = 0;
virtual Frames* loadPointer(const char *name) = 0;
- virtual Frames* loadHead(const char* name) = 0;
+ virtual GfxObj* loadHead(const char* name) = 0;
virtual Font* loadFont(const char* name) = 0;
- virtual Frames* loadStatic(const char* name) = 0;
+ virtual GfxObj* loadStatic(const char* name) = 0;
virtual Frames* loadFrames(const char* name) = 0;
virtual void loadSlide(BackgroundInfo& info, const char *filename) = 0;
virtual void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path) = 0;
@@ -147,12 +147,12 @@ public:
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
- Frames* loadTalk(const char *name);
- Frames* loadObjects(const char *name);
+ GfxObj* loadTalk(const char *name);
+ GfxObj* loadObjects(const char *name);
Frames* loadPointer(const char *name);
- Frames* loadHead(const char* name);
+ GfxObj* loadHead(const char* name);
Font* loadFont(const char* name);
- Frames* loadStatic(const char* name);
+ GfxObj* loadStatic(const char* name);
Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
@@ -181,12 +181,12 @@ public:
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
- Frames* loadTalk(const char *name);
- Frames* loadObjects(const char *name);
+ GfxObj* loadTalk(const char *name);
+ GfxObj* loadObjects(const char *name);
Frames* loadPointer(const char *name);
- Frames* loadHead(const char* name);
+ GfxObj* loadHead(const char* name);
Font* loadFont(const char* name);
- Frames* loadStatic(const char* name);
+ GfxObj* loadStatic(const char* name);
Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* background, const char* mask, const char* path);
@@ -220,12 +220,12 @@ public:
void setLanguage(uint16 language);
Script* loadLocation(const char *name);
Script* loadScript(const char* name);
- Frames* loadTalk(const char *name);
- Frames* loadObjects(const char *name);
+ GfxObj* loadTalk(const char *name);
+ GfxObj* loadObjects(const char *name);
Frames* loadPointer(const char *name);
- Frames* loadHead(const char* name);
+ GfxObj* loadHead(const char* name);
Font* loadFont(const char* name);
- Frames* loadStatic(const char* name);
+ GfxObj* loadStatic(const char* name);
Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path);
@@ -248,9 +248,9 @@ public:
AmigaDisk_br(Parallaction *vm);
virtual ~AmigaDisk_br();
- Frames* loadTalk(const char *name);
+ GfxObj* loadTalk(const char *name);
Font* loadFont(const char* name);
- Frames* loadStatic(const char* name);
+ GfxObj* loadStatic(const char* name);
Frames* loadFrames(const char* name);
void loadSlide(BackgroundInfo& info, const char *filename);
void loadScenery(BackgroundInfo& info, const char* name, const char* mask, const char* path);
diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp
index 5e88327879..ee1e111139 100644
--- a/engines/parallaction/disk_br.cpp
+++ b/engines/parallaction/disk_br.cpp
@@ -58,7 +58,7 @@ struct Sprites : public Frames {
}
~Sprites() {
- delete _sprites;
+ delete[] _sprites;
}
uint16 getNum() {
@@ -138,7 +138,7 @@ DosDisk_br::DosDisk_br(Parallaction* vm) : _vm(vm) {
DosDisk_br::~DosDisk_br() {
}
-Frames* DosDisk_br::loadTalk(const char *name) {
+GfxObj* DosDisk_br::loadTalk(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadTalk(%s)", name);
Common::File stream;
@@ -151,7 +151,7 @@ Frames* DosDisk_br::loadTalk(const char *name) {
errorFileNotFound(path);
}
- return createSprites(stream);
+ return new GfxObj(0, createSprites(stream), name);
}
Script* DosDisk_br::loadLocation(const char *name) {
@@ -184,7 +184,7 @@ Script* DosDisk_br::loadScript(const char* name) {
}
// there are no Head resources in Big Red Adventure
-Frames* DosDisk_br::loadHead(const char* name) {
+GfxObj* DosDisk_br::loadHead(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadHead");
return 0;
}
@@ -235,7 +235,7 @@ Font* DosDisk_br::loadFont(const char* name) {
}
-Frames* DosDisk_br::loadObjects(const char *name) {
+GfxObj* DosDisk_br::loadObjects(const char *name) {
debugC(5, kDebugDisk, "DosDisk_br::loadObjects");
return 0;
}
@@ -244,7 +244,7 @@ void genSlidePath(char *path, const char* name) {
sprintf(path, "%s.bmp", name);
}
-Frames* DosDisk_br::loadStatic(const char* name) {
+GfxObj* DosDisk_br::loadStatic(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadStatic");
char path[PATH_LEN];
@@ -256,7 +256,7 @@ Frames* DosDisk_br::loadStatic(const char* name) {
Graphics::Surface *surf = new Graphics::Surface;
loadBitmap(stream, *surf, 0);
- return new SurfaceToFrames(surf);
+ return new GfxObj(0, new SurfaceToFrames(surf), name);
}
Sprites* DosDisk_br::createSprites(Common::ReadStream &stream) {
@@ -287,9 +287,12 @@ Frames* DosDisk_br::loadFrames(const char* name) {
sprintf(path, "%s/ani/%s", _partPath, name);
Common::File stream;
- if (!stream.open(path))
- errorFileNotFound(path);
-
+ if (!stream.open(path)) {
+ sprintf(path, "%s/ani/%s.ani", _partPath, name);
+ if (!stream.open(path)) {
+ errorFileNotFound(path);
+ }
+ }
return createSprites(stream);
}
@@ -552,7 +555,7 @@ void AmigaDisk_br::loadSlide(BackgroundInfo& info, const char *name) {
return;
}
-Frames* AmigaDisk_br::loadStatic(const char* name) {
+GfxObj* AmigaDisk_br::loadStatic(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadStatic '%s'", name);
char path[PATH_LEN];
@@ -570,7 +573,7 @@ Frames* AmigaDisk_br::loadStatic(const char* name) {
free(pal);
- return new SurfaceToFrames(surf);
+ return new GfxObj(0, new SurfaceToFrames(surf));
}
Sprites* AmigaDisk_br::createSprites(const char *path) {
@@ -609,13 +612,13 @@ Frames* AmigaDisk_br::loadFrames(const char* name) {
return createSprites(path);
}
-Frames* AmigaDisk_br::loadTalk(const char *name) {
+GfxObj* AmigaDisk_br::loadTalk(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_br::loadTalk '%s'", name);
char path[PATH_LEN];
sprintf(path, "%s/talks/%s.tal", _partPath, name);
- return createSprites(path);
+ return new GfxObj(0, createSprites(path));
}
Font* AmigaDisk_br::loadFont(const char* name) {
diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp
index cdbe3458a7..55e6fc5e77 100644
--- a/engines/parallaction/disk_ns.cpp
+++ b/engines/parallaction/disk_ns.cpp
@@ -385,12 +385,12 @@ Cnv* DosDisk_ns::loadCnv(const char *filename) {
return new Cnv(numFrames, width, height, data);
}
-Frames* DosDisk_ns::loadTalk(const char *name) {
+GfxObj* DosDisk_ns::loadTalk(const char *name) {
const char *ext = strstr(name, ".talk");
if (ext != NULL) {
// npc talk
- return loadCnv(name);
+ return new GfxObj(0, loadCnv(name), name);
}
@@ -401,7 +401,7 @@ Frames* DosDisk_ns::loadTalk(const char *name) {
sprintf(v20, "%stal", name);
}
- return loadExternalCnv(v20);
+ return new GfxObj(0, loadExternalCnv(v20), name);
}
Script* DosDisk_ns::loadLocation(const char *name) {
@@ -434,14 +434,14 @@ Script* DosDisk_ns::loadScript(const char* name) {
return new Script(new DummyArchiveStream(_resArchive), true);
}
-Frames* DosDisk_ns::loadHead(const char* name) {
+GfxObj* DosDisk_ns::loadHead(const char* name) {
char path[PATH_LEN];
sprintf(path, "%shead", name);
path[8] = '\0';
- return loadExternalStaticCnv(path);
+ return new GfxObj(0, loadExternalStaticCnv(path));
}
@@ -457,15 +457,15 @@ Font* DosDisk_ns::loadFont(const char* name) {
}
-Frames* DosDisk_ns::loadObjects(const char *name) {
+GfxObj* DosDisk_ns::loadObjects(const char *name) {
char path[PATH_LEN];
sprintf(path, "%sobj", name);
- return loadExternalCnv(path);
+ return new GfxObj(0, loadExternalCnv(path), name);
}
-Frames* DosDisk_ns::loadStatic(const char* name) {
+GfxObj* DosDisk_ns::loadStatic(const char* name) {
char path[PATH_LEN];
@@ -487,7 +487,7 @@ Frames* DosDisk_ns::loadStatic(const char* name) {
Graphics::PackBitsReadStream decoder(_resArchive);
decoder.read(cnv->pixels, w*h);
- return new SurfaceToFrames(cnv);
+ return new GfxObj(0, new SurfaceToFrames(cnv), name);
}
Frames* DosDisk_ns::loadFrames(const char* name) {
@@ -1025,7 +1025,7 @@ Frames* AmigaDisk_ns::loadPointer(const char* name) {
return makeStaticCnv(stream);
}
-Frames* AmigaDisk_ns::loadStatic(const char* name) {
+GfxObj* AmigaDisk_ns::loadStatic(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadStatic '%s'", name);
Common::SeekableReadStream *s = openArchivedFile(name, true);
@@ -1033,7 +1033,7 @@ Frames* AmigaDisk_ns::loadStatic(const char* name) {
delete s;
- return cnv;
+ return new GfxObj(0, cnv, name);
}
Common::SeekableReadStream *AmigaDisk_ns::openArchivedFile(const char* name, bool errorOnFileNotFound) {
@@ -1276,7 +1276,7 @@ Frames* AmigaDisk_ns::loadFrames(const char* name) {
return cnv;
}
-Frames* AmigaDisk_ns::loadHead(const char* name) {
+GfxObj* AmigaDisk_ns::loadHead(const char* name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadHead '%s'", name);
char path[PATH_LEN];
@@ -1287,11 +1287,11 @@ Frames* AmigaDisk_ns::loadHead(const char* name) {
delete s;
- return cnv;
+ return new GfxObj(0, cnv, name);
}
-Frames* AmigaDisk_ns::loadObjects(const char *name) {
+GfxObj* AmigaDisk_ns::loadObjects(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadObjects");
char path[PATH_LEN];
@@ -1305,11 +1305,11 @@ Frames* AmigaDisk_ns::loadObjects(const char *name) {
Cnv *cnv = makeCnv(*s);
delete s;
- return cnv;
+ return new GfxObj(0, cnv, name);
}
-Frames* AmigaDisk_ns::loadTalk(const char *name) {
+GfxObj* AmigaDisk_ns::loadTalk(const char *name) {
debugC(1, kDebugDisk, "AmigaDisk_ns::loadTalk '%s'", name);
Common::SeekableReadStream *s;
@@ -1328,7 +1328,7 @@ Frames* AmigaDisk_ns::loadTalk(const char *name) {
Cnv *cnv = makeCnv(*s);
delete s;
- return cnv;
+ return new GfxObj(0, cnv, name);
}
Table* AmigaDisk_ns::loadTable(const char* name) {
@@ -1395,9 +1395,7 @@ Common::ReadStream* AmigaDisk_ns::loadSound(const char* name) {
char path[PATH_LEN];
sprintf(path, "%s.snd", name);
- openArchivedFile(path);
-
- return new DummyArchiveStream(_resArchive);
+ return openArchivedFile(path);
}
} // namespace Parallaction
diff --git a/engines/parallaction/exec.h b/engines/parallaction/exec.h
new file mode 100644
index 0000000000..887d6be526
--- /dev/null
+++ b/engines/parallaction/exec.h
@@ -0,0 +1,241 @@
+/* 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 PARALLACTION_EXEC_H
+#define PARALLACTION_EXEC_H
+
+#include "common/util.h"
+#include "parallaction/objects.h"
+
+
+namespace Parallaction {
+
+typedef Common::Functor0<void> Opcode;
+typedef Common::Array<const Opcode*> OpcodeSet;
+
+#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
+#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op()
+
+class Parallaction_ns;
+class Parallaction_br;
+
+class CommandExec {
+protected:
+ struct ParallactionStruct1 {
+ CommandPtr cmd;
+ ZonePtr z;
+ } _ctxt;
+
+ OpcodeSet _opcodes;
+
+public:
+ virtual void init() = 0;
+ virtual void run(CommandList &list, ZonePtr z = nullZonePtr);
+ CommandExec() {
+ }
+ virtual ~CommandExec() {
+ for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
+ delete *i;
+ _opcodes.clear();
+ }
+};
+
+class CommandExec_ns : public CommandExec {
+
+ Parallaction_ns *_vm;
+
+protected:
+ void updateGetZone(ZonePtr z, bool visible);
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+
+public:
+ void init();
+
+ CommandExec_ns(Parallaction_ns* vm);
+ ~CommandExec_ns();
+};
+
+class CommandExec_br : public CommandExec_ns {
+
+protected:
+ Parallaction_br *_vm;
+
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(character);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(add);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(let);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(music);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(give);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(text);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(part);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave);
+ DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave);
+
+public:
+ void init();
+
+ CommandExec_br(Parallaction_br* vm);
+ ~CommandExec_br();
+};
+
+
+
+
+
+class ProgramExec {
+protected:
+ struct ParallactionStruct2 {
+ AnimationPtr anim;
+ ProgramPtr program;
+ InstructionList::iterator inst;
+ uint16 modCounter;
+ bool suspend;
+ } _ctxt;
+
+ OpcodeSet _opcodes;
+
+ uint16 _modCounter;
+
+public:
+ virtual void init() = 0;
+ virtual void runScripts(ProgramList::iterator first, ProgramList::iterator last);
+ ProgramExec() : _modCounter(0) {
+ }
+ virtual ~ProgramExec() {
+ for (Common::Array<const Opcode*>::iterator i = _opcodes.begin(); i != _opcodes.end(); ++i)
+ delete *i;
+ _opcodes.clear();
+ }
+};
+
+class ProgramExec_ns : public ProgramExec {
+
+ Parallaction_ns *_vm;
+
+protected:
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+
+public:
+ void init();
+
+ ProgramExec_ns(Parallaction_ns *vm);
+ ~ProgramExec_ns();
+};
+
+class ProgramExec_br : public ProgramExec_ns {
+
+ Parallaction_br *_vm;
+
+protected:
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
+ DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
+
+public:
+ void init();
+ ProgramExec_br(Parallaction_br *vm);
+ ~ProgramExec_br();
+};
+
+} // namespace Parallaction
+
+#endif
diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp
index 3b67b4c370..edb832cffc 100644
--- a/engines/parallaction/exec_br.cpp
+++ b/engines/parallaction/exec_br.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
@@ -64,12 +65,13 @@ namespace Parallaction {
#define SetOpcodeTable(x) table = &x;
-typedef Common::Functor0Mem<void, Parallaction_br> OpcodeV2;
-#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::cmdOp_##op))
-#define DECLARE_COMMAND_OPCODE(op) void Parallaction_br::cmdOp_##op()
+typedef Common::Functor0Mem<void, CommandExec_br> OpcodeV1;
+#define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_br::cmdOp_##op))
+#define DECLARE_COMMAND_OPCODE(op) void CommandExec_br::cmdOp_##op()
-#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_br::instOp_##op))
-#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_br::instOp_##op()
+typedef Common::Functor0Mem<void, ProgramExec_br> OpcodeV2;
+#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_br::instOp_##op))
+#define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_br::instOp_##op()
void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
debugC(5, kDebugExec, "setupSubtitles(%s, %s, %i)", s, s2, y);
@@ -100,8 +102,13 @@ void Parallaction_br::setupSubtitles(char *s, char *s2, int y) {
}
void Parallaction_br::clearSubtitles() {
- _gfx->freeLabels();
- _subtitle[0] = _subtitle[1] = -1;
+ if (_subtitle[0] != -1) {
+ _gfx->hideLabel(_subtitle[0]);
+ }
+
+ if (_subtitle[1] != -1) {
+ _gfx->hideLabel(_subtitle[1]);
+ }
}
@@ -109,7 +116,7 @@ DECLARE_COMMAND_OPCODE(location) {
warning("Parallaction_br::cmdOp_location command not yet implemented");
// TODO: handle startPos and startPos2
- scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string);
+ _vm->scheduleLocationSwitch(_ctxt.cmd->u._string);
}
@@ -124,7 +131,7 @@ DECLARE_COMMAND_OPCODE(close) {
DECLARE_COMMAND_OPCODE(on) {
- CommandData *data = &_cmdRunCtxt.cmd->u;
+ CommandData *data = &_ctxt.cmd->u;
ZonePtr z = data->_zone;
if (z) {
@@ -132,28 +139,28 @@ DECLARE_COMMAND_OPCODE(on) {
z->_flags &= ~kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, true);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, true);
}
}
}
DECLARE_COMMAND_OPCODE(off) {
- CommandData *data = &_cmdRunCtxt.cmd->u;
+ CommandData *data = &_ctxt.cmd->u;
ZonePtr z = data->_zone;
if (z) {
z->_flags |= kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, false);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, false);
}
}
}
DECLARE_COMMAND_OPCODE(call) {
- callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z);
+ _vm->callFunction(_ctxt.cmd->u._callable, &_ctxt.z);
}
@@ -167,17 +174,17 @@ DECLARE_COMMAND_OPCODE(move) {
}
DECLARE_COMMAND_OPCODE(start) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing;
+ _ctxt.cmd->u._zone->_flags |= kFlagsActing;
}
DECLARE_COMMAND_OPCODE(stop) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing;
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsActing;
}
DECLARE_COMMAND_OPCODE(character) {
- debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _cmdRunCtxt.cmd->u._string);
- changeCharacter(_cmdRunCtxt.cmd->u._string);
+ debugC(9, kDebugExec, "Parallaction_br::cmdOp_character(%s)", _ctxt.cmd->u._string);
+ _vm->changeCharacter(_ctxt.cmd->u._string);
}
@@ -187,12 +194,12 @@ DECLARE_COMMAND_OPCODE(followme) {
DECLARE_COMMAND_OPCODE(onmouse) {
- _input->showCursor(true);
+ _vm->_input->showCursor(true);
}
DECLARE_COMMAND_OPCODE(offmouse) {
- _input->showCursor(false);
+ _vm->_input->showCursor(false);
}
@@ -207,42 +214,42 @@ DECLARE_COMMAND_OPCODE(leave) {
DECLARE_COMMAND_OPCODE(inc) {
- _counters[_cmdRunCtxt.cmd->u._lvalue] += _cmdRunCtxt.cmd->u._rvalue;
+ _vm->_counters[_ctxt.cmd->u._lvalue] += _ctxt.cmd->u._rvalue;
}
DECLARE_COMMAND_OPCODE(dec) {
- _counters[_cmdRunCtxt.cmd->u._lvalue] -= _cmdRunCtxt.cmd->u._rvalue;
+ _vm->_counters[_ctxt.cmd->u._lvalue] -= _ctxt.cmd->u._rvalue;
}
DECLARE_COMMAND_OPCODE(ifeq) {
- if (_counters[_cmdRunCtxt.cmd->u._lvalue] == _cmdRunCtxt.cmd->u._rvalue) {
- setLocationFlags(kFlagsTestTrue);
+ if (_vm->_counters[_ctxt.cmd->u._lvalue] == _ctxt.cmd->u._rvalue) {
+ _vm->setLocationFlags(kFlagsTestTrue);
} else {
- clearLocationFlags(kFlagsTestTrue);
+ _vm->clearLocationFlags(kFlagsTestTrue);
}
}
DECLARE_COMMAND_OPCODE(iflt) {
- if (_counters[_cmdRunCtxt.cmd->u._lvalue] < _cmdRunCtxt.cmd->u._rvalue) {
- setLocationFlags(kFlagsTestTrue);
+ if (_vm->_counters[_ctxt.cmd->u._lvalue] < _ctxt.cmd->u._rvalue) {
+ _vm->setLocationFlags(kFlagsTestTrue);
} else {
- clearLocationFlags(kFlagsTestTrue);
+ _vm->clearLocationFlags(kFlagsTestTrue);
}
}
DECLARE_COMMAND_OPCODE(ifgt) {
- if (_counters[_cmdRunCtxt.cmd->u._lvalue] > _cmdRunCtxt.cmd->u._rvalue) {
- setLocationFlags(kFlagsTestTrue);
+ if (_vm->_counters[_ctxt.cmd->u._lvalue] > _ctxt.cmd->u._rvalue) {
+ _vm->setLocationFlags(kFlagsTestTrue);
} else {
- clearLocationFlags(kFlagsTestTrue);
+ _vm->clearLocationFlags(kFlagsTestTrue);
}
}
DECLARE_COMMAND_OPCODE(let) {
- _counters[_cmdRunCtxt.cmd->u._lvalue] = _cmdRunCtxt.cmd->u._rvalue;
+ _vm->_counters[_ctxt.cmd->u._lvalue] = _ctxt.cmd->u._rvalue;
}
@@ -252,25 +259,25 @@ DECLARE_COMMAND_OPCODE(music) {
DECLARE_COMMAND_OPCODE(fix) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsFixed;
+ _ctxt.cmd->u._zone->_flags |= kFlagsFixed;
}
DECLARE_COMMAND_OPCODE(unfix) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsFixed;
}
DECLARE_COMMAND_OPCODE(zeta) {
- _location._zeta0 = _cmdRunCtxt.cmd->u._zeta0;
- _location._zeta1 = _cmdRunCtxt.cmd->u._zeta1;
- _location._zeta2 = _cmdRunCtxt.cmd->u._zeta2;
+ _vm->_location._zeta0 = _ctxt.cmd->u._zeta0;
+ _vm->_location._zeta1 = _ctxt.cmd->u._zeta1;
+ _vm->_location._zeta2 = _ctxt.cmd->u._zeta2;
}
DECLARE_COMMAND_OPCODE(scroll) {
warning("Parallaction_br::cmdOp_scroll not yet implemented");
- _gfx->setVar("scroll_x", _cmdRunCtxt.cmd->u._rvalue );
+ _vm->_gfx->setVar("scroll_x", _ctxt.cmd->u._rvalue );
}
@@ -285,8 +292,8 @@ DECLARE_COMMAND_OPCODE(give) {
DECLARE_COMMAND_OPCODE(text) {
- CommandData *data = &_cmdRunCtxt.cmd->u;
- setupSubtitles(data->_string, data->_string2, data->_zeta0);
+ CommandData *data = &_ctxt.cmd->u;
+ _vm->setupSubtitles(data->_string, data->_string2, data->_zeta0);
}
@@ -297,7 +304,7 @@ DECLARE_COMMAND_OPCODE(part) {
DECLARE_COMMAND_OPCODE(testsfx) {
warning("Parallaction_br::cmdOp_testsfx not completely implemented");
- clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled
+ _vm->clearLocationFlags(kFlagsTestTrue); // should test if sfx are enabled
}
@@ -319,7 +326,7 @@ DECLARE_COMMAND_OPCODE(offsave) {
DECLARE_INSTRUCTION_OPCODE(on) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
ZonePtr z = inst->_z;
if (z) {
@@ -327,28 +334,28 @@ DECLARE_INSTRUCTION_OPCODE(on) {
z->_flags &= ~kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, true);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, true);
}
}
}
DECLARE_INSTRUCTION_OPCODE(off) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
ZonePtr z = inst->_z;
if (z) {
z->_flags |= kFlagsRemove;
if ((z->_type & 0xFFFF) & kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, false);
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, false);
}
}
}
DECLARE_INSTRUCTION_OPCODE(set) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 rvalue = inst->_opB.getRValue();
int16* lvalue = inst->_opA.getLValue();
@@ -359,21 +366,21 @@ DECLARE_INSTRUCTION_OPCODE(set) {
DECLARE_INSTRUCTION_OPCODE(loop) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
- _instRunCtxt.program->_loopCounter = inst->_opB.getRValue();
- _instRunCtxt.program->_loopStart = _instRunCtxt.inst;
+ _ctxt.program->_loopCounter = inst->_opB.getRValue();
+ _ctxt.program->_loopStart = _ctxt.inst;
}
DECLARE_INSTRUCTION_OPCODE(inc) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 rvalue = inst->_opB.getRValue();
if (inst->_flags & kInstMod) { // mod
int16 _bx = (rvalue > 0 ? rvalue : -rvalue);
- if (_instRunCtxt.modCounter % _bx != 0) return;
+ if (_ctxt.modCounter % _bx != 0) return;
rvalue = (rvalue > 0 ? 1 : -1);
}
@@ -420,12 +427,12 @@ DECLARE_INSTRUCTION_OPCODE(wait) {
DECLARE_INSTRUCTION_OPCODE(start) {
- (*_instRunCtxt.inst)->_z->_flags |= kFlagsActing;
+ (*_ctxt.inst)->_z->_flags |= kFlagsActing;
}
DECLARE_INSTRUCTION_OPCODE(process) {
- _activeZone2 = (*_instRunCtxt.inst)->_z;
+ _vm->_activeZone2 = (*_ctxt.inst)->_z;
}
@@ -435,18 +442,18 @@ DECLARE_INSTRUCTION_OPCODE(move) {
DECLARE_INSTRUCTION_OPCODE(color) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 entry = inst->_opB.getRValue();
- _gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]);
+ _vm->_gfx->_palette.setEntry(entry, inst->_colors[0], inst->_colors[1], inst->_colors[2]);
}
DECLARE_INSTRUCTION_OPCODE(mask) {
#if 0
- Instruction *inst = *_instRunCtxt.inst;
+ Instruction *inst = *_ctxt.inst;
_gfx->_bgLayers[0] = inst->_opA.getRValue();
_gfx->_bgLayers[1] = inst->_opB.getRValue();
_gfx->_bgLayers[2] = inst->_opC.getRValue();
@@ -459,8 +466,8 @@ DECLARE_INSTRUCTION_OPCODE(print) {
}
DECLARE_INSTRUCTION_OPCODE(text) {
- InstructionPtr inst = (*_instRunCtxt.inst);
- setupSubtitles(inst->_text, inst->_text2, inst->_y);
+ InstructionPtr inst = (*_ctxt.inst);
+ _vm->setupSubtitles(inst->_text, inst->_text2, inst->_y);
}
@@ -489,21 +496,20 @@ DECLARE_INSTRUCTION_OPCODE(stop) {
}
DECLARE_INSTRUCTION_OPCODE(endscript) {
- if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) {
- _instRunCtxt.anim->_flags &= ~kFlagsActing;
- runCommands(_instRunCtxt.anim->_commands, _instRunCtxt.anim);
- _instRunCtxt.program->_status = kProgramDone;
+ if ((_ctxt.anim->_flags & kFlagsLooping) == 0) {
+ _ctxt.anim->_flags &= ~kFlagsActing;
+ _vm->_cmdExec->run(_ctxt.anim->_commands, _ctxt.anim);
+ _ctxt.program->_status = kProgramDone;
}
- _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin();
+ _ctxt.program->_ip = _ctxt.program->_instructions.begin();
- _instRunCtxt.suspend = true;
+ _ctxt.suspend = true;
}
-void Parallaction_br::initOpcodes() {
-
+void CommandExec_br::init() {
Common::Array<const Opcode*> *table = 0;
- SetOpcodeTable(_commandOpcodes);
+ SetOpcodeTable(_opcodes);
COMMAND_OPCODE(invalid);
COMMAND_OPCODE(set);
COMMAND_OPCODE(clear);
@@ -546,8 +552,21 @@ void Parallaction_br::initOpcodes() {
COMMAND_OPCODE(ret);
COMMAND_OPCODE(onsave);
COMMAND_OPCODE(offsave);
+}
+
+CommandExec_br::CommandExec_br(Parallaction_br* vm) : CommandExec_ns(vm), _vm(vm) {
+
+}
+
+CommandExec_br::~CommandExec_br() {
- SetOpcodeTable(_instructionOpcodes);
+}
+
+void ProgramExec_br::init() {
+
+ Common::Array<const Opcode*> *table = 0;
+
+ SetOpcodeTable(_opcodes);
INSTRUCTION_OPCODE(invalid);
INSTRUCTION_OPCODE(on);
INSTRUCTION_OPCODE(off);
@@ -582,6 +601,12 @@ void Parallaction_br::initOpcodes() {
INSTRUCTION_OPCODE(endscript);
}
+ProgramExec_br::ProgramExec_br(Parallaction_br *vm) : ProgramExec_ns(vm), _vm(vm) {
+}
+
+ProgramExec_br::~ProgramExec_br() {
+}
+
#if 0
void Parallaction_br::jobWaitRemoveLabelJob(void *parm, Job *job) {
diff --git a/engines/parallaction/exec_ns.cpp b/engines/parallaction/exec_ns.cpp
index 0c4addd9b7..b4578f80ad 100644
--- a/engines/parallaction/exec_ns.cpp
+++ b/engines/parallaction/exec_ns.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/parallaction.h"
#include "parallaction/sound.h"
@@ -52,18 +53,19 @@ namespace Parallaction {
#define SetOpcodeTable(x) table = &x;
-typedef Common::Functor0Mem<void, Parallaction_ns> OpcodeV2;
-#define COMMAND_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::cmdOp_##op))
-#define DECLARE_COMMAND_OPCODE(op) void Parallaction_ns::cmdOp_##op()
+typedef Common::Functor0Mem<void, CommandExec_ns> OpcodeV1;
+#define COMMAND_OPCODE(op) table->push_back(new OpcodeV1(this, &CommandExec_ns::cmdOp_##op))
+#define DECLARE_COMMAND_OPCODE(op) void CommandExec_ns::cmdOp_##op()
-#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &Parallaction_ns::instOp_##op))
-#define DECLARE_INSTRUCTION_OPCODE(op) void Parallaction_ns::instOp_##op()
+typedef Common::Functor0Mem<void, ProgramExec_ns> OpcodeV2;
+#define INSTRUCTION_OPCODE(op) table->push_back(new OpcodeV2(this, &ProgramExec_ns::instOp_##op))
+#define DECLARE_INSTRUCTION_OPCODE(op) void ProgramExec_ns::instOp_##op()
DECLARE_INSTRUCTION_OPCODE(on) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
inst->_a->_flags |= kFlagsActive;
inst->_a->_flags &= ~kFlagsRemove;
@@ -71,31 +73,31 @@ DECLARE_INSTRUCTION_OPCODE(on) {
DECLARE_INSTRUCTION_OPCODE(off) {
- (*_instRunCtxt.inst)->_a->_flags |= kFlagsRemove;
+ (*_ctxt.inst)->_a->_flags |= kFlagsRemove;
}
DECLARE_INSTRUCTION_OPCODE(loop) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
- _instRunCtxt.program->_loopCounter = inst->_opB.getRValue();
- _instRunCtxt.program->_loopStart = _instRunCtxt.inst;
+ _ctxt.program->_loopCounter = inst->_opB.getRValue();
+ _ctxt.program->_loopStart = _ctxt.inst;
}
DECLARE_INSTRUCTION_OPCODE(endloop) {
- if (--_instRunCtxt.program->_loopCounter > 0) {
- _instRunCtxt.inst = _instRunCtxt.program->_loopStart;
+ if (--_ctxt.program->_loopCounter > 0) {
+ _ctxt.inst = _ctxt.program->_loopStart;
}
}
DECLARE_INSTRUCTION_OPCODE(inc) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 _si = inst->_opB.getRValue();
if (inst->_flags & kInstMod) { // mod
int16 _bx = (_si > 0 ? _si : -_si);
- if (_instRunCtxt.modCounter % _bx != 0) return;
+ if (_modCounter % _bx != 0) return;
_si = (_si > 0 ? 1 : -1);
}
@@ -116,7 +118,7 @@ DECLARE_INSTRUCTION_OPCODE(inc) {
DECLARE_INSTRUCTION_OPCODE(set) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
int16 _si = inst->_opB.getRValue();
int16 *lvalue = inst->_opA.getLValue();
@@ -127,7 +129,7 @@ DECLARE_INSTRUCTION_OPCODE(set) {
DECLARE_INSTRUCTION_OPCODE(put) {
- InstructionPtr inst = *_instRunCtxt.inst;
+ InstructionPtr inst = *_ctxt.inst;
Graphics::Surface v18;
v18.w = inst->_a->width();
v18.h = inst->_a->height();
@@ -137,7 +139,7 @@ DECLARE_INSTRUCTION_OPCODE(put) {
int16 y = inst->_opB.getRValue();
bool mask = (inst->_flags & kInstMaskedPut) == kInstMaskedPut;
- _gfx->patchBackground(v18, x, y, mask);
+ _vm->_gfx->patchBackground(v18, x, y, mask);
}
DECLARE_INSTRUCTION_OPCODE(null) {
@@ -145,170 +147,177 @@ DECLARE_INSTRUCTION_OPCODE(null) {
}
DECLARE_INSTRUCTION_OPCODE(invalid) {
- error("Can't execute invalid opcode %i", (*_instRunCtxt.inst)->_index);
+ error("Can't execute invalid opcode %i", (*_ctxt.inst)->_index);
}
DECLARE_INSTRUCTION_OPCODE(call) {
- callFunction((*_instRunCtxt.inst)->_immediate, 0);
+ _vm->callFunction((*_ctxt.inst)->_immediate, 0);
}
DECLARE_INSTRUCTION_OPCODE(wait) {
if (_engineFlags & kEngineWalking)
- _instRunCtxt.suspend = true;
+ _ctxt.suspend = true;
}
DECLARE_INSTRUCTION_OPCODE(start) {
- (*_instRunCtxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive);
+ (*_ctxt.inst)->_a->_flags |= (kFlagsActing | kFlagsActive);
}
DECLARE_INSTRUCTION_OPCODE(sound) {
- _activeZone = (*_instRunCtxt.inst)->_z;
+ _vm->_activeZone = (*_ctxt.inst)->_z;
}
DECLARE_INSTRUCTION_OPCODE(move) {
- InstructionPtr inst = (*_instRunCtxt.inst);
+ InstructionPtr inst = (*_ctxt.inst);
int16 x = inst->_opA.getRValue();
int16 y = inst->_opB.getRValue();
- _char.scheduleWalk(x, y);
+ _vm->_char.scheduleWalk(x, y);
}
DECLARE_INSTRUCTION_OPCODE(endscript) {
- if ((_instRunCtxt.anim->_flags & kFlagsLooping) == 0) {
- _instRunCtxt.anim->_flags &= ~kFlagsActing;
- runCommands(_instRunCtxt.anim->_commands, _instRunCtxt.anim);
- _instRunCtxt.program->_status = kProgramDone;
+ if ((_ctxt.anim->_flags & kFlagsLooping) == 0) {
+ _ctxt.anim->_flags &= ~kFlagsActing;
+ _vm->_cmdExec->run(_ctxt.anim->_commands, _ctxt.anim);
+ _ctxt.program->_status = kProgramDone;
}
- _instRunCtxt.program->_ip = _instRunCtxt.program->_instructions.begin();
+ _ctxt.program->_ip = _ctxt.program->_instructions.begin();
- _instRunCtxt.suspend = true;
+ _ctxt.suspend = true;
}
DECLARE_COMMAND_OPCODE(invalid) {
- error("Can't execute invalid command '%i'", _cmdRunCtxt.cmd->_id);
+ error("Can't execute invalid command '%i'", _ctxt.cmd->_id);
}
DECLARE_COMMAND_OPCODE(set) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags |= _cmdRunCtxt.cmd->u._flags;
+ if (_ctxt.cmd->u._flags & kFlagsGlobal) {
+ _ctxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags |= _ctxt.cmd->u._flags;
} else {
- setLocationFlags(_cmdRunCtxt.cmd->u._flags);
+ _vm->setLocationFlags(_ctxt.cmd->u._flags);
}
}
DECLARE_COMMAND_OPCODE(clear) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags &= ~_cmdRunCtxt.cmd->u._flags;
+ if (_ctxt.cmd->u._flags & kFlagsGlobal) {
+ _ctxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags &= ~_ctxt.cmd->u._flags;
} else {
- clearLocationFlags(_cmdRunCtxt.cmd->u._flags);
+ _vm->clearLocationFlags(_ctxt.cmd->u._flags);
}
}
DECLARE_COMMAND_OPCODE(start) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsActing;
+ _ctxt.cmd->u._zone->_flags |= kFlagsActing;
}
DECLARE_COMMAND_OPCODE(speak) {
- _activeZone = _cmdRunCtxt.cmd->u._zone;
+ _vm->_activeZone = _ctxt.cmd->u._zone;
}
DECLARE_COMMAND_OPCODE(get) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsFixed;
- runZone(_cmdRunCtxt.cmd->u._zone);
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsFixed;
+ _vm->runZone(_ctxt.cmd->u._zone);
}
DECLARE_COMMAND_OPCODE(location) {
- scheduleLocationSwitch(_cmdRunCtxt.cmd->u._string);
+ _vm->scheduleLocationSwitch(_ctxt.cmd->u._string);
}
DECLARE_COMMAND_OPCODE(open) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsClosed;
- if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) {
- updateDoor(_cmdRunCtxt.cmd->u._zone);
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsClosed;
+ if (_ctxt.cmd->u._zone->u.door->gfxobj) {
+ _vm->updateDoor(_ctxt.cmd->u._zone);
}
}
DECLARE_COMMAND_OPCODE(close) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsClosed;
- if (_cmdRunCtxt.cmd->u._zone->u.door->gfxobj) {
- updateDoor(_cmdRunCtxt.cmd->u._zone);
+ _ctxt.cmd->u._zone->_flags |= kFlagsClosed;
+ if (_ctxt.cmd->u._zone->u.door->gfxobj) {
+ _vm->updateDoor(_ctxt.cmd->u._zone);
}
}
+void CommandExec_ns::updateGetZone(ZonePtr z, bool visible) {
+ if (!z) {
+ return;
+ }
+
+ if ((z->_type & 0xFFFF) == kZoneGet) {
+ _vm->_gfx->showGfxObj(z->u.get->gfxobj, visible);
+ }
+}
DECLARE_COMMAND_OPCODE(on) {
- ZonePtr z = _cmdRunCtxt.cmd->u._zone;
- // WORKAROUND: the original DOS-based engine didn't check u->_zone before dereferencing
- // the pointer to get structure members, thus leading to crashes in systems with memory
- // protection.
- // As a side note, the overwritten address is the 5th entry in the DOS interrupt table
- // (print screen handler): this suggests that a system would hang when the print screen
- // key is pressed after playing Nippon Safes, provided that this code path is taken.
+ ZonePtr z = _ctxt.cmd->u._zone;
+
if (z) {
z->_flags &= ~kFlagsRemove;
z->_flags |= kFlagsActive;
- if ((z->_type & 0xFFFF) == kZoneGet) {
- _gfx->showGfxObj(z->u.get->gfxobj, true);
- }
+ updateGetZone(z, true);
}
}
DECLARE_COMMAND_OPCODE(off) {
- _cmdRunCtxt.cmd->u._zone->_flags |= kFlagsRemove;
+ ZonePtr z = _ctxt.cmd->u._zone;
+
+ if (z) {
+ _ctxt.cmd->u._zone->_flags |= kFlagsRemove;
+ updateGetZone(z, false);
+ }
}
DECLARE_COMMAND_OPCODE(call) {
- callFunction(_cmdRunCtxt.cmd->u._callable, &_cmdRunCtxt.z);
+ _vm->callFunction(_ctxt.cmd->u._callable, &_ctxt.z);
}
DECLARE_COMMAND_OPCODE(toggle) {
- if (_cmdRunCtxt.cmd->u._flags & kFlagsGlobal) {
- _cmdRunCtxt.cmd->u._flags &= ~kFlagsGlobal;
- _commandFlags ^= _cmdRunCtxt.cmd->u._flags;
+ if (_ctxt.cmd->u._flags & kFlagsGlobal) {
+ _ctxt.cmd->u._flags &= ~kFlagsGlobal;
+ _commandFlags ^= _ctxt.cmd->u._flags;
} else {
- toggleLocationFlags(_cmdRunCtxt.cmd->u._flags);
+ _vm->toggleLocationFlags(_ctxt.cmd->u._flags);
}
}
DECLARE_COMMAND_OPCODE(drop){
- dropItem( _cmdRunCtxt.cmd->u._object );
+ _vm->dropItem( _ctxt.cmd->u._object );
}
DECLARE_COMMAND_OPCODE(quit) {
- _quit = true;
+ _vm->_quit = true;
_vm->quitGame();
}
DECLARE_COMMAND_OPCODE(move) {
- _char.scheduleWalk(_cmdRunCtxt.cmd->u._move.x, _cmdRunCtxt.cmd->u._move.y);
+ _vm->_char.scheduleWalk(_ctxt.cmd->u._move.x, _ctxt.cmd->u._move.y);
}
DECLARE_COMMAND_OPCODE(stop) {
- _cmdRunCtxt.cmd->u._zone->_flags &= ~kFlagsActing;
+ _ctxt.cmd->u._zone->_flags &= ~kFlagsActing;
}
@@ -357,16 +366,14 @@ void Parallaction_ns::drawAnimations() {
}
-void Parallaction_ns::runScripts() {
+void ProgramExec::runScripts(ProgramList::iterator first, ProgramList::iterator last) {
if (_engineFlags & kEnginePauseJobs) {
return;
}
debugC(9, kDebugExec, "runScripts");
- static uint16 modCounter = 0;
-
- for (ProgramList::iterator it = _location._programs.begin(); it != _location._programs.end(); it++) {
+ for (ProgramList::iterator it = first; it != last; it++) {
AnimationPtr a = (*it)->_anim;
@@ -383,17 +390,16 @@ void Parallaction_ns::runScripts() {
debugC(9, kDebugExec, "Animation: %s, instruction: %i", a->_name, (*inst)->_index); //_instructionNamesRes[(*inst)->_index - 1]);
- _instRunCtxt.inst = inst;
- _instRunCtxt.anim = AnimationPtr(a);
- _instRunCtxt.program = *it;
- _instRunCtxt.modCounter = modCounter;
- _instRunCtxt.suspend = false;
+ _ctxt.inst = inst;
+ _ctxt.anim = AnimationPtr(a);
+ _ctxt.program = *it;
+ _ctxt.suspend = false;
- (*_instructionOpcodes[(*inst)->_index])();
+ (*_opcodes[(*inst)->_index])();
- inst = _instRunCtxt.inst; // handles endloop correctly
+ inst = _ctxt.inst; // handles endloop correctly
- if (_instRunCtxt.suspend)
+ if (_ctxt.suspend)
goto label1;
inst++;
@@ -406,44 +412,54 @@ label1:
a->_z = a->_top + a->height();
}
- _char._ani->_z = _char._ani->height() + _char._ani->_top;
- if (_char._ani->gfxobj) {
- _char._ani->gfxobj->z = _char._ani->_z;
- }
- modCounter++;
+ _modCounter++;
return;
}
-void Parallaction::runCommands(CommandList& list, ZonePtr z) {
- if (list.size() == 0)
+void CommandExec::run(CommandList& list, ZonePtr z) {
+ if (list.size() == 0) {
+ debugC(3, kDebugExec, "runCommands: nothing to do");
return;
+ }
- debugC(3, kDebugExec, "runCommands");
+ debugC(3, kDebugExec, "runCommands starting");
+
+ uint32 useFlags = 0;
+ bool useLocalFlags;
CommandList::iterator it = list.begin();
for ( ; it != list.end(); it++) {
+ if (_vm->quit())
+ break;
+
CommandPtr cmd = *it;
- uint32 v8 = getLocationFlags();
if (_vm->quit())
break;
-
+
if (cmd->_flagsOn & kFlagsGlobal) {
- v8 = _commandFlags | kFlagsGlobal;
+ useFlags = _commandFlags | kFlagsGlobal;
+ useLocalFlags = false;
+ } else {
+ useFlags = _vm->getLocationFlags();
+ useLocalFlags = true;
}
- if ((cmd->_flagsOn & v8) != cmd->_flagsOn) continue;
- if ((cmd->_flagsOff & ~v8) != cmd->_flagsOff) continue;
+ bool onMatch = (cmd->_flagsOn & useFlags) == cmd->_flagsOn;
+ bool offMatch = (cmd->_flagsOff & ~useFlags) == cmd->_flagsOff;
+
+ debugC(3, kDebugExec, "runCommands[%i] (on: %x, off: %x), (%s = %x)", cmd->_id, cmd->_flagsOn, cmd->_flagsOff,
+ useLocalFlags ? "LOCALFLAGS" : "GLOBALFLAGS", useFlags);
-// debugC(3, kDebugExec, "runCommands[%i]: %s (on: %x, off: %x)", cmd->_id, _commandsNamesRes[cmd->_id-1], cmd->_flagsOn, cmd->_flagsOff);
+ if (!onMatch || !offMatch) continue;
- _cmdRunCtxt.z = z;
- _cmdRunCtxt.cmd = cmd;
+ _ctxt.z = z;
+ _ctxt.cmd = cmd;
- (*_commandOpcodes[cmd->_id])();
+ (*_opcodes[cmd->_id])();
}
debugC(3, kDebugExec, "runCommands completed");
@@ -452,6 +468,13 @@ void Parallaction::runCommands(CommandList& list, ZonePtr z) {
}
+CommandExec_ns::CommandExec_ns(Parallaction_ns* vm) : _vm(vm) {
+
+}
+
+CommandExec_ns::~CommandExec_ns() {
+
+}
//
// ZONE TYPE: EXAMINE
@@ -470,7 +493,7 @@ void Parallaction::displayComment(ExamineData *data) {
}
_gfx->setHalfbriteMode(true);
- _gfx->setSingleBalloon(data->_description, 0, 90, 0, 0);
+ _balloonMan->setSingleBalloon(data->_description, 0, 90, 0, 0);
Common::Rect r;
data->_cnv->getRect(0, r);
id = _gfx->setItem(data->_cnv, 140, (_screenHeight - r.height())/2);
@@ -478,7 +501,7 @@ void Parallaction::displayComment(ExamineData *data) {
id = _gfx->setItem(_char._head, 100, 152);
_gfx->setItemFrame(id, 0);
} else {
- _gfx->setSingleBalloon(data->_description, 140, 10, 0, 0);
+ _balloonMan->setSingleBalloon(data->_description, 140, 10, 0, 0);
id = _gfx->setItem(_char._talk, 190, 80);
_gfx->setItemFrame(id, 0);
}
@@ -528,7 +551,7 @@ uint16 Parallaction::runZone(ZonePtr z) {
debugC(3, kDebugExec, "runZone completed");
- runCommands(z->_commands, z);
+ _cmdExec->run(z->_commands, z);
return 0;
}
@@ -655,11 +678,34 @@ ZonePtr Parallaction::hitZone(uint32 type, uint16 x, uint16 y) {
}
-void Parallaction_ns::initOpcodes() {
+void CommandExec_ns::init() {
+ Common::Array<const Opcode*> *table = 0;
+
+ SetOpcodeTable(_opcodes);
+ COMMAND_OPCODE(invalid);
+ COMMAND_OPCODE(set);
+ COMMAND_OPCODE(clear);
+ COMMAND_OPCODE(start);
+ COMMAND_OPCODE(speak);
+ COMMAND_OPCODE(get);
+ COMMAND_OPCODE(location);
+ COMMAND_OPCODE(open);
+ COMMAND_OPCODE(close);
+ COMMAND_OPCODE(on);
+ COMMAND_OPCODE(off);
+ COMMAND_OPCODE(call);
+ COMMAND_OPCODE(toggle);
+ COMMAND_OPCODE(drop);
+ COMMAND_OPCODE(quit);
+ COMMAND_OPCODE(move);
+ COMMAND_OPCODE(stop);
+}
+
+void ProgramExec_ns::init() {
Common::Array<const Opcode*> *table = 0;
- SetOpcodeTable(_instructionOpcodes);
+ SetOpcodeTable(_opcodes);
INSTRUCTION_OPCODE(invalid);
INSTRUCTION_OPCODE(on);
INSTRUCTION_OPCODE(off);
@@ -681,25 +727,12 @@ void Parallaction_ns::initOpcodes() {
INSTRUCTION_OPCODE(move);
INSTRUCTION_OPCODE(endscript);
- SetOpcodeTable(_commandOpcodes);
- COMMAND_OPCODE(invalid);
- COMMAND_OPCODE(set);
- COMMAND_OPCODE(clear);
- COMMAND_OPCODE(start);
- COMMAND_OPCODE(speak);
- COMMAND_OPCODE(get);
- COMMAND_OPCODE(location);
- COMMAND_OPCODE(open);
- COMMAND_OPCODE(close);
- COMMAND_OPCODE(on);
- COMMAND_OPCODE(off);
- COMMAND_OPCODE(call);
- COMMAND_OPCODE(toggle);
- COMMAND_OPCODE(drop);
- COMMAND_OPCODE(quit);
- COMMAND_OPCODE(move);
- COMMAND_OPCODE(stop);
}
+ProgramExec_ns::ProgramExec_ns(Parallaction_ns *vm) : _vm(vm) {
+}
+
+ProgramExec_ns::~ProgramExec_ns() {
+}
} // namespace Parallaction
diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp
index 6599a1f81c..9e7eb12ed8 100644
--- a/engines/parallaction/gfxbase.cpp
+++ b/engines/parallaction/gfxbase.cpp
@@ -32,7 +32,7 @@
namespace Parallaction {
-GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : type(objType), _frames(frames), x(0), y(0), z(0), frame(0), layer(3), _flags(0), _keep(true) {
+GfxObj::GfxObj(uint objType, Frames *frames, const char* name) : type(objType), _frames(frames), x(0), y(0), z(0), frame(0), layer(3), _flags(kGfxObjNormal), _keep(true) {
if (name) {
_name = strdup(name);
} else {
@@ -86,93 +86,325 @@ void GfxObj::clearFlags(uint32 flags) {
}
GfxObj* Gfx::loadAnim(const char *name) {
- Frames *frames = _disk->loadFrames(name);
+ Frames* frames = _disk->loadFrames(name);
+ assert(frames);
+
GfxObj *obj = new GfxObj(kGfxObjTypeAnim, frames, name);
assert(obj);
+ // animation Z is not set here, but controlled by game scripts and user interaction.
+ // it is always >=0 and <screen height
+ obj->transparentKey = 0;
+ _gfxobjList.push_back(obj);
return obj;
}
GfxObj* Gfx::loadGet(const char *name) {
- Frames *frames = _disk->loadStatic(name);
- GfxObj *obj = new GfxObj(kGfxObjTypeGet, frames, name);
+ GfxObj *obj = _disk->loadStatic(name);
assert(obj);
+ obj->z = kGfxObjGetZ; // this preset Z value ensures that get zones are drawn after doors but before animations
+ obj->type = kGfxObjTypeGet;
+ obj->transparentKey = 0;
+ _gfxobjList.push_back(obj);
return obj;
}
GfxObj* Gfx::loadDoor(const char *name) {
Frames *frames = _disk->loadFrames(name);
+ assert(frames);
+
GfxObj *obj = new GfxObj(kGfxObjTypeDoor, frames, name);
assert(obj);
+ obj->z = kGfxObjDoorZ; // this preset Z value ensures that doors are drawn first
+ obj->transparentKey = 0;
+ _gfxobjList.push_back(obj);
return obj;
}
-void Gfx::clearGfxObjects() {
- _gfxobjList[0].clear();
- _gfxobjList[1].clear();
- _gfxobjList[2].clear();
+void Gfx::clearGfxObjects(uint filter) {
+
+ GfxObjList::iterator b = _gfxobjList.begin();
+ GfxObjList::iterator e = _gfxobjList.end();
+
+ for ( ; b != e; ) {
+ if (((*b)->_flags & filter) != 0) {
+ b = _gfxobjList.erase(b);
+ } else {
+ b++;
+ }
+ }
+
}
void Gfx::showGfxObj(GfxObj* obj, bool visible) {
- if (!obj || obj->isVisible() == visible) {
+ if (!obj) {
return;
}
if (visible) {
obj->setFlags(kGfxObjVisible);
- _gfxobjList[obj->type].push_back(obj);
} else {
obj->clearFlags(kGfxObjVisible);
- _gfxobjList[obj->type].remove(obj);
}
-
}
-bool compareAnimationZ(const GfxObj* a1, const GfxObj* a2) {
+bool compareZ(const GfxObj* a1, const GfxObj* a2) {
return a1->z < a2->z;
}
void Gfx::sortAnimations() {
- GfxObjList::iterator first = _gfxobjList[kGfxObjTypeAnim].begin();
- GfxObjList::iterator last = _gfxobjList[kGfxObjTypeAnim].end();
+ GfxObjList::iterator first = _gfxobjList.begin();
+ GfxObjList::iterator last = _gfxobjList.end();
- Common::sort(first, last, compareAnimationZ);
+ Common::sort(first, last, compareZ);
}
-void Gfx::drawGfxObjects(Graphics::Surface &surf) {
+
+void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf, bool scene) {
+ if (!obj->isVisible()) {
+ return;
+ }
Common::Rect rect;
byte *data;
+ uint scrollX = (scene) ? -_varScrollX : 0;
+
+ obj->getRect(obj->frame, rect);
+ rect.translate(obj->x + scrollX, obj->y);
+ data = obj->getData(obj->frame);
+
+ if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) {
+ blt(rect, data, &surf, obj->layer, obj->transparentKey);
+ } else {
+ unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, obj->transparentKey);
+ }
+
+}
+
+
+void Gfx::drawGfxObjects(Graphics::Surface &surf) {
+
sortAnimations();
// TODO: some zones don't appear because of wrong masking (3 or 0?)
- // TODO: Dr.Ki is not visible inside the club
+ GfxObjList::iterator b = _gfxobjList.begin();
+ GfxObjList::iterator e = _gfxobjList.end();
+
+ for (; b != e; b++) {
+ drawGfxObject(*b, surf, true);
+ }
+}
+
+
+
+void Gfx::drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color) {
+ byte *dst = (byte*)surf->getBasePtr(x, y);
+ font->setColor(color);
+ font->drawString(dst, surf->w, text);
+}
+
+void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) {
+
+ uint16 lines = 0;
+ uint16 linewidth = 0;
+
+ uint16 rx = 10;
+ uint16 ry = 4;
+
+ uint16 blankWidth = font->getStringWidth(" ");
+ uint16 tokenWidth = 0;
+
+ char token[MAX_TOKEN_LEN];
+
+ if (wrapwidth == -1)
+ wrapwidth = _vm->_screenWidth;
+
+ while (strlen(text) > 0) {
+
+ text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true);
- for (uint i = 0; i < 3; i++) {
+ if (!scumm_stricmp(token, "%p")) {
+ lines++;
+ rx = 10;
+ ry = 4 + lines*10; // y
- GfxObjList::iterator b = _gfxobjList[i].begin();
- GfxObjList::iterator e = _gfxobjList[i].end();
+ strcpy(token, "> .......");
+ strncpy(token+2, _password, strlen(_password));
+ tokenWidth = font->getStringWidth(token);
+ } else {
+ tokenWidth = font->getStringWidth(token);
- for (; b != e; b++) {
- GfxObj *obj = *b;
- if (obj->isVisible()) {
- obj->getRect(obj->frame, rect);
- rect.translate(obj->x - _varScrollX, obj->y);
- data = obj->getData(obj->frame);
- if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) {
- blt(rect, data, &surf, obj->layer, 0);
- } else {
- unpackBlt(rect, data, obj->getRawSize(obj->frame), &surf, obj->layer, 0);
+ linewidth += tokenWidth;
+
+ if (linewidth > wrapwidth) {
+ // wrap line
+ lines++;
+ rx = 10; // x
+ ry = 4 + lines*10; // y
+ linewidth = tokenWidth;
+ }
+
+ if (!scumm_stricmp(token, "%s")) {
+ sprintf(token, "%d", _score);
+ }
+
+ }
+
+ drawText(font, surf, rx, ry, token, color);
+
+ rx += tokenWidth + blankWidth;
+ linewidth += blankWidth;
+
+ text = Common::ltrim(text);
+ }
+
+}
+
+
+// this is the maximum size of an unpacked frame in BRA
+byte _unpackedBitmap[640*401];
+
+#if 0
+void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
+
+ byte *d = _unpackedBitmap;
+
+ while (size > 0) {
+
+ uint8 p = *data++;
+ size--;
+ uint8 color = p & 0xF;
+ uint8 repeat = (p & 0xF0) >> 4;
+ if (repeat == 0) {
+ repeat = *data++;
+ size--;
+ }
+
+ memset(d, color, repeat);
+ d += repeat;
+ }
+
+ blt(r, _unpackedBitmap, surf, z, transparentColor);
+}
+#endif
+void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
+
+ byte *d = _unpackedBitmap;
+ uint pixelsLeftInLine = r.width();
+
+ while (size > 0) {
+ uint8 p = *data++;
+ size--;
+ uint8 color = p & 0xF;
+ uint8 repeat = (p & 0xF0) >> 4;
+ if (repeat == 0) {
+ repeat = *data++;
+ size--;
+ }
+ if (repeat == 0) {
+ // end of line
+ repeat = pixelsLeftInLine;
+ pixelsLeftInLine = r.width();
+ } else {
+ pixelsLeftInLine -= repeat;
+ }
+
+ memset(d, color, repeat);
+ d += repeat;
+ }
+
+ blt(r, _unpackedBitmap, surf, z, transparentColor);
+}
+
+
+void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) {
+
+ Common::Point dp;
+ Common::Rect q(r);
+
+ Common::Rect clipper(surf->w, surf->h);
+
+ q.clip(clipper);
+ if (!q.isValidRect()) return;
+
+ dp.x = q.left;
+ dp.y = q.top;
+
+ q.translate(-r.left, -r.top);
+
+ byte *s = data + q.left + q.top * r.width();
+ byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
+
+ uint sPitch = r.width() - q.width();
+ uint dPitch = surf->w - q.width();
+
+
+ if (_varRenderMode == 2) {
+
+ for (uint16 i = 0; i < q.height(); i++) {
+
+ for (uint16 j = 0; j < q.width(); j++) {
+ if (*s != transparentColor) {
+ if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) {
+ byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i);
+ if (z >= v) *d = 5;
+ } else {
+ *d = 5;
+ }
+ }
+
+ s++;
+ d++;
+ }
+
+ s += sPitch;
+ d += dPitch;
+ }
+
+ } else {
+ if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) {
+
+ for (uint16 i = 0; i < q.height(); i++) {
+
+ for (uint16 j = 0; j < q.width(); j++) {
+ if (*s != transparentColor) {
+ byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i);
+ if (z >= v) *d = *s;
+ }
+
+ s++;
+ d++;
+ }
+
+ s += sPitch;
+ d += dPitch;
+ }
+
+ } else {
+
+ for (uint16 i = q.top; i < q.bottom; i++) {
+ for (uint16 j = q.left; j < q.right; j++) {
+ if (*s != transparentColor)
+ *d = *s;
+
+ s++;
+ d++;
}
+
+ s += sPitch;
+ d += dPitch;
}
+
}
}
+
}
+
} // namespace Parallaction
diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp
index 58fb02a750..32d0e303eb 100644
--- a/engines/parallaction/graphics.cpp
+++ b/engines/parallaction/graphics.cpp
@@ -64,10 +64,6 @@ int32 Gfx::getVar(const Common::String &name) {
#define LABEL_TRANSPARENT_COLOR 0xFF
-#define BALLOON_TRANSPARENT_COLOR 2
-
-
-int16 Gfx::_dialogueBalloonX[5] = { 80, 120, 150, 150, 150 };
void halfbritePixel(int x, int y, int color, void *data) {
byte *buffer = (byte*)data;
@@ -238,37 +234,6 @@ void Palette::rotate(uint first, uint last, bool forward) {
}
-#define BALLOON_TAIL_WIDTH 12
-#define BALLOON_TAIL_HEIGHT 10
-
-
-byte _resBalloonTail[2][BALLOON_TAIL_WIDTH*BALLOON_TAIL_HEIGHT] = {
- {
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- },
- {
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02,
- 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02
- }
-};
-
void Gfx::setPalette(Palette pal) {
byte sysPal[256*4];
@@ -356,21 +321,19 @@ void Gfx::drawItems() {
Graphics::Surface *surf = g_system->lockScreen();
for (uint i = 0; i < _numItems; i++) {
- blt(_items[i].rect, _items[i].data->getData(_items[i].frame), surf, LAYER_FOREGROUND, _items[i].transparentColor);
+ drawGfxObject(_items[i].data, *surf, false);
}
g_system->unlockScreen();
}
void Gfx::drawBalloons() {
- if (_numBalloons == 0) {
+ if (_balloons.size() == 0) {
return;
}
Graphics::Surface *surf = g_system->lockScreen();
- for (uint i = 0; i < _numBalloons; i++) {
- Common::Rect r(_balloons[i].surface.w, _balloons[i].surface.h);
- r.moveTo(_balloons[i].x, _balloons[i].y);
- blt(r, (byte*)_balloons[i].surface.getBasePtr(0, 0), surf, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR);
+ for (uint i = 0; i < _balloons.size(); i++) {
+ drawGfxObject(_balloons[i], *surf, false);
}
g_system->unlockScreen();
}
@@ -521,145 +484,6 @@ void Gfx::invertBackground(const Common::Rect& r) {
}
-// this is the maximum size of an unpacked frame in BRA
-byte _unpackedBitmap[640*401];
-
-#if 0
-void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
-
- byte *d = _unpackedBitmap;
-
- while (size > 0) {
-
- uint8 p = *data++;
- size--;
- uint8 color = p & 0xF;
- uint8 repeat = (p & 0xF0) >> 4;
- if (repeat == 0) {
- repeat = *data++;
- size--;
- }
-
- memset(d, color, repeat);
- d += repeat;
- }
-
- blt(r, _unpackedBitmap, surf, z, transparentColor);
-}
-#endif
-void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
-
- byte *d = _unpackedBitmap;
- uint pixelsLeftInLine = r.width();
-
- while (size > 0) {
- uint8 p = *data++;
- size--;
- uint8 color = p & 0xF;
- uint8 repeat = (p & 0xF0) >> 4;
- if (repeat == 0) {
- repeat = *data++;
- size--;
- }
- if (repeat == 0) {
- // end of line
- repeat = pixelsLeftInLine;
- pixelsLeftInLine = r.width();
- } else {
- pixelsLeftInLine -= repeat;
- }
-
- memset(d, color, repeat);
- d += repeat;
- }
-
- blt(r, _unpackedBitmap, surf, z, transparentColor);
-}
-
-
-void Gfx::blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor) {
-
- Common::Point dp;
- Common::Rect q(r);
-
- Common::Rect clipper(surf->w, surf->h);
-
- q.clip(clipper);
- if (!q.isValidRect()) return;
-
- dp.x = q.left;
- dp.y = q.top;
-
- q.translate(-r.left, -r.top);
-
- byte *s = data + q.left + q.top * r.width();
- byte *d = (byte*)surf->getBasePtr(dp.x, dp.y);
-
- uint sPitch = r.width() - q.width();
- uint dPitch = surf->w - q.width();
-
-
- if (_varRenderMode == 2) {
-
- for (uint16 i = 0; i < q.height(); i++) {
-
- for (uint16 j = 0; j < q.width(); j++) {
- if (*s != transparentColor) {
- if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) {
- byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i);
- if (z >= v) *d = 5;
- } else {
- *d = 5;
- }
- }
-
- s++;
- d++;
- }
-
- s += sPitch;
- d += dPitch;
- }
-
- } else {
- if (_backgroundInfo.mask.data && (z < LAYER_FOREGROUND)) {
-
- for (uint16 i = 0; i < q.height(); i++) {
-
- for (uint16 j = 0; j < q.width(); j++) {
- if (*s != transparentColor) {
- byte v = _backgroundInfo.mask.getValue(dp.x + j, dp.y + i);
- if (z >= v) *d = *s;
- }
-
- s++;
- d++;
- }
-
- s += sPitch;
- d += dPitch;
- }
-
- } else {
-
- for (uint16 i = q.top; i < q.bottom; i++) {
- for (uint16 j = q.left; j < q.right; j++) {
- if (*s != transparentColor)
- *d = *s;
-
- s++;
- d++;
- }
-
- s += sPitch;
- d += dPitch;
- }
-
- }
- }
-
-}
-
@@ -669,10 +493,9 @@ void setupLabelSurface(Graphics::Surface &surf, uint w, uint h) {
surf.fillRect(Common::Rect(w,h), LABEL_TRANSPARENT_COLOR);
}
-Label *Gfx::renderFloatingLabel(Font *font, char *text) {
+uint Gfx::renderFloatingLabel(Font *font, char *text) {
- Label *label = new Label;
- Graphics::Surface *cnv = &label->_cnv;
+ Graphics::Surface *cnv = new Graphics::Surface;
uint w, h;
@@ -698,14 +521,74 @@ Label *Gfx::renderFloatingLabel(Font *font, char *text) {
drawText(font, cnv, 0, 0, text, 0);
}
- return label;
+ GfxObj *obj = new GfxObj(kGfxObjTypeLabel, new SurfaceToFrames(cnv), "floatingLabel");
+ obj->transparentKey = LABEL_TRANSPARENT_COLOR;
+ obj->layer = LAYER_FOREGROUND;
+
+ uint id = _labels.size();
+ _labels.insert_at(id, obj);
+
+ return id;
+}
+
+void Gfx::showFloatingLabel(uint label) {
+ assert(label < _labels.size());
+
+ hideFloatingLabel();
+
+ _labels[label]->x = -1000;
+ _labels[label]->y = -1000;
+ _labels[label]->setFlags(kGfxObjVisible);
+
+ _floatingLabel = label;
+}
+
+void Gfx::hideFloatingLabel() {
+ if (_floatingLabel != NO_FLOATING_LABEL) {
+ _labels[_floatingLabel]->clearFlags(kGfxObjVisible);
+ }
+ _floatingLabel = NO_FLOATING_LABEL;
+}
+
+
+void Gfx::updateFloatingLabel() {
+ if (_floatingLabel == NO_FLOATING_LABEL) {
+ return;
+ }
+
+ int16 _si, _di;
+
+ Common::Point cursor;
+ _vm->_input->getCursorPos(cursor);
+
+ Common::Rect r;
+ _labels[_floatingLabel]->getRect(0, r);
+
+ if (_vm->_input->_activeItem._id != 0) {
+ _si = cursor.x + 16 - r.width()/2;
+ _di = cursor.y + 34;
+ } else {
+ _si = cursor.x + 8 - r.width()/2;
+ _di = cursor.y + 21;
+ }
+
+ if (_si < 0) _si = 0;
+ if (_di > 190) _di = 190;
+
+ if (r.width() + _si > _vm->_screenWidth)
+ _si = _vm->_screenWidth - r.width();
+
+ _labels[_floatingLabel]->x = _si;
+ _labels[_floatingLabel]->y = _di;
}
+
+
+
uint Gfx::createLabel(Font *font, const char *text, byte color) {
- assert(_numLabels < MAX_NUM_LABELS);
+ assert(_labels.size() < MAX_NUM_LABELS);
- Label *label = new Label;
- Graphics::Surface *cnv = &label->_cnv;
+ Graphics::Surface *cnv = new Graphics::Surface;
uint w, h;
@@ -726,122 +609,65 @@ uint Gfx::createLabel(Font *font, const char *text, byte color) {
drawText(font, cnv, 0, 0, text, color);
}
- uint id = _numLabels;
- _labels[id] = label;
- _numLabels++;
+ GfxObj *obj = new GfxObj(kGfxObjTypeLabel, new SurfaceToFrames(cnv), "label");
+ obj->transparentKey = LABEL_TRANSPARENT_COLOR;
+ obj->layer = LAYER_FOREGROUND;
+
+ int id = _labels.size();
+
+ _labels.insert_at(id, obj);
return id;
}
void Gfx::showLabel(uint id, int16 x, int16 y) {
- assert(id < _numLabels);
- _labels[id]->_visible = true;
+ assert(id < _labels.size());
+ _labels[id]->setFlags(kGfxObjVisible);
+
+ Common::Rect r;
+ _labels[id]->getRect(0, r);
if (x == CENTER_LABEL_HORIZONTAL) {
- x = CLIP<int16>((_vm->_screenWidth - _labels[id]->_cnv.w) / 2, 0, _vm->_screenWidth/2);
+ x = CLIP<int16>((_vm->_screenWidth - r.width()) / 2, 0, _vm->_screenWidth/2);
}
if (y == CENTER_LABEL_VERTICAL) {
- y = CLIP<int16>((_vm->_screenHeight - _labels[id]->_cnv.h) / 2, 0, _vm->_screenHeight/2);
+ y = CLIP<int16>((_vm->_screenHeight - r.height()) / 2, 0, _vm->_screenHeight/2);
}
- _labels[id]->_pos.x = x;
- _labels[id]->_pos.y = y;
+ _labels[id]->x = x;
+ _labels[id]->y = y;
}
void Gfx::hideLabel(uint id) {
- assert(id < _numLabels);
- _labels[id]->_visible = false;
+ assert(id < _labels.size());
+ _labels[id]->clearFlags(kGfxObjVisible);
}
void Gfx::freeLabels() {
- for (uint i = 0; i < _numLabels; i++) {
+ for (uint i = 0; i < _labels.size(); i++) {
delete _labels[i];
}
- _numLabels = 0;
-}
-
-
-void Gfx::setFloatingLabel(Label *label) {
- _floatingLabel = label;
-
- if (_floatingLabel) {
- _floatingLabel->resetPosition();
- }
-}
-
-void Gfx::updateFloatingLabel() {
- if (!_floatingLabel) {
- return;
- }
-
- int16 _si, _di;
-
- Common::Point cursor;
- _vm->_input->getCursorPos(cursor);
-
- if (_vm->_input->_activeItem._id != 0) {
- _si = cursor.x + 16 - _floatingLabel->_cnv.w/2;
- _di = cursor.y + 34;
- } else {
- _si = cursor.x + 8 - _floatingLabel->_cnv.w/2;
- _di = cursor.y + 21;
- }
-
- if (_si < 0) _si = 0;
- if (_di > 190) _di = 190;
-
- if (_floatingLabel->_cnv.w + _si > _vm->_screenWidth)
- _si = _vm->_screenWidth - _floatingLabel->_cnv.w;
-
- _floatingLabel->_pos.x = _si;
- _floatingLabel->_pos.y = _di;
+ _labels.clear();
+ _floatingLabel = NO_FLOATING_LABEL;
}
void Gfx::drawLabels() {
- if ((!_floatingLabel) && (_numLabels == 0)) {
+ if (_labels.size() == 0) {
return;
}
+
updateFloatingLabel();
Graphics::Surface* surf = g_system->lockScreen();
- for (uint i = 0; i < _numLabels; i++) {
- if (_labels[i]->_visible) {
- Common::Rect r(_labels[i]->_cnv.w, _labels[i]->_cnv.h);
- r.moveTo(_labels[i]->_pos);
- blt(r, (byte*)_labels[i]->_cnv.getBasePtr(0, 0), surf, LAYER_FOREGROUND, LABEL_TRANSPARENT_COLOR);
- }
- }
-
- if (_floatingLabel) {
- Common::Rect r(_floatingLabel->_cnv.w, _floatingLabel->_cnv.h);
- r.moveTo(_floatingLabel->_pos);
- blt(r, (byte*)_floatingLabel->_cnv.getBasePtr(0, 0), surf, LAYER_FOREGROUND, LABEL_TRANSPARENT_COLOR);
+ for (uint i = 0; i < _labels.size(); i++) {
+ drawGfxObject(_labels[i], *surf, false);
}
g_system->unlockScreen();
}
-Label::Label() {
- resetPosition();
- _visible = false;
-}
-
-Label::~Label() {
- free();
-}
-
-void Label::free() {
- _cnv.free();
- resetPosition();
-}
-
-void Label::resetPosition() {
- _pos.x = -1000;
- _pos.y = -1000;
-}
-
void Gfx::getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height) {
@@ -917,10 +743,8 @@ Gfx::Gfx(Parallaction* vm) :
setPalette(_palette);
- _numBalloons = 0;
_numItems = 0;
- _numLabels = 0;
- _floatingLabel = 0;
+ _floatingLabel = NO_FLOATING_LABEL;
_screenX = 0;
_screenY = 0;
@@ -943,20 +767,21 @@ Gfx::Gfx(Parallaction* vm) :
Gfx::~Gfx() {
freeBackground();
+ freeLabels();
return;
}
-int Gfx::setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor) {
+int Gfx::setItem(GfxObj* frames, uint16 x, uint16 y, byte transparentColor) {
int id = _numItems;
_items[id].data = frames;
- _items[id].x = x;
- _items[id].y = y;
-
- _items[id].transparentColor = transparentColor;
+ _items[id].data->x = x;
+ _items[id].data->y = y;
+ _items[id].data->layer = LAYER_FOREGROUND;
+ _items[id].data->transparentKey = transparentColor;
_numItems++;
@@ -965,206 +790,35 @@ int Gfx::setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor) {
void Gfx::setItemFrame(uint item, uint16 f) {
assert(item < _numItems);
- _items[item].frame = f;
- _items[item].data->getRect(f, _items[item].rect);
- _items[item].rect.moveTo(_items[item].x, _items[item].y);
-}
-
-Gfx::Balloon* Gfx::getBalloon(uint id) {
- assert(id < _numBalloons);
- return &_balloons[id];
-}
-
-int Gfx::createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness) {
- assert(_numBalloons < 5);
-
- int id = _numBalloons;
-
- Gfx::Balloon *balloon = &_balloons[id];
-
- int16 real_h = (winding == -1) ? h : h + 9;
- balloon->surface.create(w, real_h, 1);
- balloon->surface.fillRect(Common::Rect(w, real_h), BALLOON_TRANSPARENT_COLOR);
-
- Common::Rect r(w, h);
- balloon->surface.fillRect(r, 0);
- balloon->outerBox = r;
-
- r.grow(-borderThickness);
- balloon->surface.fillRect(r, 1);
- balloon->innerBox = r;
-
- if (winding != -1) {
- // draws tail
- // TODO: this bitmap tail should only be used for Dos games. Amiga should use a polygon fill.
- winding = (winding == 0 ? 1 : 0);
- Common::Rect s(BALLOON_TAIL_WIDTH, BALLOON_TAIL_HEIGHT);
- s.moveTo(r.width()/2 - 5, r.bottom - 1);
- blt(s, _resBalloonTail[winding], &balloon->surface, LAYER_FOREGROUND, BALLOON_TRANSPARENT_COLOR);
- }
-
- _numBalloons++;
-
- return id;
-}
-
-int Gfx::setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) {
-
- int16 w, h;
-
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
-
- int id = createBalloon(w+5, h, winding, 1);
- Gfx::Balloon *balloon = &_balloons[id];
-
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
-
- balloon->x = x;
- balloon->y = y;
-
- return id;
-}
-
-int Gfx::setDialogueBalloon(char *text, uint16 winding, byte textColor) {
-
- int16 w, h;
-
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
-
- int id = createBalloon(w+5, h, winding, 1);
- Gfx::Balloon *balloon = &_balloons[id];
-
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
-
- balloon->x = _dialogueBalloonX[id];
- balloon->y = 10;
-
- if (id > 0) {
- balloon->y += _balloons[id - 1].y + _balloons[id - 1].outerBox.height();
- }
-
-
- return id;
+ _items[item].data->frame = f;
+ _items[item].data->setFlags(kGfxObjVisible);
}
-void Gfx::setBalloonText(uint id, char *text, byte textColor) {
- Gfx::Balloon *balloon = getBalloon(id);
- balloon->surface.fillRect(balloon->innerBox, 1);
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, textColor, MAX_BALLOON_WIDTH);
-}
-
-
-int Gfx::setLocationBalloon(char *text, bool endGame) {
-
- int16 w, h;
-
- getStringExtent(_vm->_dialogueFont, text, MAX_BALLOON_WIDTH, &w, &h);
-
- int id = createBalloon(w+(endGame ? 5 : 10), h+5, -1, BALLOON_TRANSPARENT_COLOR);
- Gfx::Balloon *balloon = &_balloons[id];
- drawWrappedText(_vm->_dialogueFont, &balloon->surface, text, 0, MAX_BALLOON_WIDTH);
-
- balloon->x = 5;
- balloon->y = 5;
- return id;
-}
+GfxObj* Gfx::registerBalloon(Frames *frames, const char *text) {
-int Gfx::hitTestDialogueBalloon(int x, int y) {
+ GfxObj *obj = new GfxObj(kGfxObjTypeBalloon, frames, text);
- Common::Point p;
+ obj->layer = LAYER_FOREGROUND;
+ obj->frame = 0;
+ obj->setFlags(kGfxObjVisible);
- for (uint i = 0; i < _numBalloons; i++) {
- p.x = x - _balloons[i].x;
- p.y = y - _balloons[i].y;
-
- if (_balloons[i].innerBox.contains(p))
- return i;
- }
+ _balloons.push_back(obj);
- return -1;
+ return obj;
}
-
-void Gfx::freeBalloons() {
- for (uint i = 0; i < _numBalloons; i++) {
- _balloons[i].surface.free();
+void Gfx::destroyBalloons() {
+ for (uint i = 0; i < _balloons.size(); i++) {
+ delete _balloons[i];
}
- _numBalloons = 0;
+ _balloons.clear();
}
void Gfx::freeItems() {
_numItems = 0;
}
-void Gfx::hideDialogueStuff() {
- freeItems();
- freeBalloons();
-}
-
-void Gfx::drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color) {
- byte *dst = (byte*)surf->getBasePtr(x, y);
- font->setColor(color);
- font->drawString(dst, surf->w, text);
-}
-
-void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth) {
-
- uint16 lines = 0;
- uint16 linewidth = 0;
-
- uint16 rx = 10;
- uint16 ry = 4;
-
- uint16 blankWidth = font->getStringWidth(" ");
- uint16 tokenWidth = 0;
-
- char token[MAX_TOKEN_LEN];
-
- if (wrapwidth == -1)
- wrapwidth = _vm->_screenWidth;
-
- while (strlen(text) > 0) {
-
- text = parseNextToken(text, token, MAX_TOKEN_LEN, " ", true);
-
- if (!scumm_stricmp(token, "%p")) {
- lines++;
- rx = 10;
- ry = 4 + lines*10; // y
-
- strcpy(token, "> .......");
- strncpy(token+2, _password, strlen(_password));
- tokenWidth = font->getStringWidth(token);
- } else {
- tokenWidth = font->getStringWidth(token);
-
- linewidth += tokenWidth;
-
- if (linewidth > wrapwidth) {
- // wrap line
- lines++;
- rx = 10; // x
- ry = 4 + lines*10; // y
- linewidth = tokenWidth;
- }
-
- if (!scumm_stricmp(token, "%s")) {
- sprintf(token, "%d", _score);
- }
-
- }
-
- drawText(font, surf, rx, ry, token, color);
-
- rx += tokenWidth + blankWidth;
- linewidth += blankWidth;
-
- text = Common::ltrim(text);
- }
-
-}
-
void Gfx::freeBackground() {
_backgroundInfo.free();
}
diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h
index f03b8538b8..09f4b2f244 100644
--- a/engines/parallaction/graphics.h
+++ b/engines/parallaction/graphics.h
@@ -157,11 +157,11 @@ struct SurfaceToMultiFrames : public Frames {
r.setHeight(_height);
}
uint getRawSize(uint16 index) {
- assert(index == 0);
+ assert(index < _num);
return getSize(index);
}
uint getSize(uint16 index) {
- assert(index == 0);
+ assert(index < _num);
return _width * _height;
}
@@ -326,20 +326,6 @@ public:
#define CENTER_LABEL_HORIZONTAL -1
#define CENTER_LABEL_VERTICAL -1
-struct Label {
- Graphics::Surface _cnv;
-
- Common::Point _pos;
- bool _visible;
-
- Label();
- ~Label();
-
- void free();
- void resetPosition();
-};
-
-
#define MAX_BALLOON_WIDTH 130
@@ -354,25 +340,39 @@ class Disk;
enum {
kGfxObjVisible = 1,
+ kGfxObjNormal = 2,
+ kGfxObjCharacter = 4,
kGfxObjTypeDoor = 0,
kGfxObjTypeGet = 1,
- kGfxObjTypeAnim = 2
+ kGfxObjTypeAnim = 2,
+ kGfxObjTypeLabel = 3,
+ kGfxObjTypeBalloon = 4,
+ kGfxObjTypeCharacter = 8
+};
+
+enum {
+ kGfxObjDoorZ = -200,
+ kGfxObjGetZ = -100
};
class GfxObj {
char *_name;
Frames *_frames;
- uint32 _flags;
bool _keep;
public:
int16 x, y;
- uint16 z;
+
+ int32 z;
+
+ uint32 _flags;
+
uint type;
uint frame;
uint layer;
+ uint transparentKey;
GfxObj(uint type, Frames *frames, const char *name = NULL);
virtual ~GfxObj();
@@ -453,6 +453,20 @@ enum {
kBackgroundSlide = 2
};
+
+class BalloonManager {
+public:
+ virtual ~BalloonManager() { }
+
+ virtual void freeBalloons() = 0;
+ virtual int setLocationBalloon(char *text, bool endGame) = 0;
+ virtual int setDialogueBalloon(char *text, uint16 winding, byte textColor) = 0;
+ virtual int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor) = 0;
+ virtual void setBalloonText(uint id, char *text, byte textColor) = 0;
+ virtual int hitTestDialogueBalloon(int x, int y) = 0;
+};
+
+
typedef Common::HashMap<Common::String, int32, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> VarMap;
class Gfx {
@@ -461,33 +475,33 @@ public:
Disk *_disk;
VarMap _vars;
- GfxObjList _gfxobjList[3];
+ GfxObjList _gfxobjList;
GfxObj* loadAnim(const char *name);
GfxObj* loadGet(const char *name);
GfxObj* loadDoor(const char *name);
void drawGfxObjects(Graphics::Surface &surf);
void showGfxObj(GfxObj* obj, bool visible);
- void clearGfxObjects();
+ void clearGfxObjects(uint filter);
void sortAnimations();
+
// labels
- void setFloatingLabel(Label *label);
- Label *renderFloatingLabel(Font *font, char *text);
+ void showFloatingLabel(uint label);
+ void hideFloatingLabel();
+
+ uint renderFloatingLabel(Font *font, char *text);
uint createLabel(Font *font, const char *text, byte color);
void showLabel(uint id, int16 x, int16 y);
void hideLabel(uint id);
void freeLabels();
// dialogue balloons
- int setLocationBalloon(char *text, bool endGame);
- int setDialogueBalloon(char *text, uint16 winding, byte textColor);
- int setSingleBalloon(char *text, uint16 x, uint16 y, uint16 winding, byte textColor);
- void setBalloonText(uint id, char *text, byte textColor);
- int hitTestDialogueBalloon(int x, int y);
void getStringExtent(Font *font, char *text, uint16 maxwidth, int16* width, int16* height);
+ GfxObj* registerBalloon(Frames *frames, const char *text);
+ void destroyBalloons();
// other items
- int setItem(Frames* frames, uint16 x, uint16 y, byte transparentColor = 0);
+ int setItem(GfxObj* obj, uint16 x, uint16 y, byte transparentColor = 0);
void setItemFrame(uint item, uint16 f);
void hideDialogueStuff();
void freeBalloons();
@@ -549,36 +563,22 @@ protected:
Graphics::Surface _bitmapMask;
int32 getRenderMode(const char *type);
-protected:
- static int16 _dialogueBalloonX[5];
-
- struct Balloon {
- uint16 x;
- uint16 y;
- Common::Rect outerBox;
- Common::Rect innerBox;
- uint16 winding;
- Graphics::Surface surface;
- } _balloons[5];
-
- uint _numBalloons;
+public:
struct Item {
- uint16 x;
- uint16 y;
- uint16 frame;
- Frames *data;
-
- byte transparentColor;
- Common::Rect rect;
+ GfxObj *data;
} _items[14];
uint _numItems;
- #define MAX_NUM_LABELS 5
- Label* _labels[MAX_NUM_LABELS];
- uint _numLabels;
- Label *_floatingLabel;
+ #define MAX_NUM_LABELS 20
+ #define NO_FLOATING_LABEL 1000
+
+ typedef Common::Array<GfxObj*> GfxObjArray;
+ GfxObjArray _labels;
+ GfxObjArray _balloons;
+
+ uint _floatingLabel;
void drawInventory();
void updateFloatingLabel();
@@ -588,13 +588,11 @@ protected:
void copyRect(const Common::Rect &r, Graphics::Surface &src, Graphics::Surface &dst);
- int createBalloon(int16 w, int16 h, int16 winding, uint16 borderThickness);
- Balloon *getBalloon(uint id);
-
// low level text and patches
void drawText(Font *font, Graphics::Surface* surf, uint16 x, uint16 y, const char *text, byte color);
void drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte color, int16 wrapwidth);
+ void drawGfxObject(GfxObj *obj, Graphics::Surface &surf, bool scene);
void blt(const Common::Rect& r, byte *data, Graphics::Surface *surf, uint16 z, byte transparentColor);
void unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor);
};
diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp
index e073a7c989..391459a12f 100644
--- a/engines/parallaction/gui_br.cpp
+++ b/engines/parallaction/gui_br.cpp
@@ -123,7 +123,7 @@ int Parallaction_br::guiShowMenu() {
// TODO: filter menu entries according to progress in game
#define NUM_MENULINES 7
- Frames *_lines[NUM_MENULINES];
+ GfxObj *_lines[NUM_MENULINES];
const char *menuStrings[NUM_MENULINES] = {
"SEE INTRO",
@@ -158,7 +158,7 @@ int Parallaction_br::guiShowMenu() {
int i;
for (i = 0; i < availItems; i++) {
- _lines[i] = guiRenderMenuItem(menuStrings[i]);
+ _lines[i] = new GfxObj(0, guiRenderMenuItem(menuStrings[i]), "MenuItem");
uint id = _gfx->setItem(_lines[i], MENUITEMS_X, MENUITEMS_Y + MENUITEM_HEIGHT * i, 0xFF);
_gfx->setItemFrame(id, 0);
}
@@ -196,7 +196,7 @@ int Parallaction_br::guiShowMenu() {
}
_system->showMouse(false);
- _gfx->hideDialogueStuff();
+ hideDialogueStuff();
for (i = 0; i < availItems; i++) {
delete _lines[i];
diff --git a/engines/parallaction/gui_ns.cpp b/engines/parallaction/gui_ns.cpp
index 1d4d44fa46..9c48586dbc 100644
--- a/engines/parallaction/gui_ns.cpp
+++ b/engines/parallaction/gui_ns.cpp
@@ -166,6 +166,8 @@ void Parallaction_ns::guiStart() {
}
void Parallaction_ns::selectStartLocation() {
+ _inTestResult = false;
+
int character = guiSelectCharacter();
if (character == -1)
error("invalid character selected from menu screen");
diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp
index 0fc00ce03b..9d5ff4ef80 100644
--- a/engines/parallaction/input.cpp
+++ b/engines/parallaction/input.cpp
@@ -174,7 +174,7 @@ void Input::updateGameInput() {
void Input::updateCommentInput() {
waitUntilLeftClick();
- _vm->_gfx->hideDialogueStuff();
+ _vm->hideDialogueStuff();
_vm->_gfx->setHalfbriteMode(false);
_inputMode = kInputModeGame;
@@ -302,7 +302,7 @@ bool Input::translateInventoryInput() {
_vm->dropItem(z->u.merge->_obj1);
_vm->dropItem(z->u.merge->_obj2);
_vm->addInventoryItem(z->u.merge->_obj3);
- _vm->runCommands(z->_commands);
+ _vm->_cmdExec->run(z->_commands);
}
return true;
diff --git a/engines/parallaction/input.h b/engines/parallaction/input.h
index 46dbb08c4e..e06fe96705 100644
--- a/engines/parallaction/input.h
+++ b/engines/parallaction/input.h
@@ -44,7 +44,7 @@ struct InputData {
Common::Point _mousePos;
int16 _inventoryIndex;
ZonePtr _zone;
- Label* _label;
+ uint _label;
};
class Input {
diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk
index 2478b4b2e1..fb867f5285 100644
--- a/engines/parallaction/module.mk
+++ b/engines/parallaction/module.mk
@@ -1,6 +1,7 @@
MODULE := engines/parallaction
MODULE_OBJS := \
+ balloons.o \
callables_br.o \
callables_ns.o \
debug.o \
diff --git a/engines/parallaction/objects.cpp b/engines/parallaction/objects.cpp
index cac31911f4..66025cf0f7 100644
--- a/engines/parallaction/objects.cpp
+++ b/engines/parallaction/objects.cpp
@@ -54,6 +54,7 @@ Animation::Animation() {
Animation::~Animation() {
free(_scriptName);
+ gfxobj->release();
}
uint16 Animation::width() const {
@@ -182,7 +183,8 @@ Zone::~Zone() {
break;
}
- delete _label;
+
+ free(_linkedName);
}
void Zone::getRect(Common::Rect& r) const {
@@ -207,6 +209,16 @@ uint16 Zone::height() const {
return _bottom - _top;
}
+Dialogue::Dialogue() {
+ memset(_questions, 0, sizeof(_questions));
+}
+
+Dialogue::~Dialogue() {
+ for (int i = 0; i < NUM_QUESTIONS; i++) {
+ delete _questions[i];
+ }
+}
+
Answer::Answer() {
_text = NULL;
_mood = 0;
diff --git a/engines/parallaction/objects.h b/engines/parallaction/objects.h
index afa6cc5ed5..19835da9d0 100644
--- a/engines/parallaction/objects.h
+++ b/engines/parallaction/objects.h
@@ -181,6 +181,9 @@ struct Question {
struct Dialogue {
Question *_questions[NUM_QUESTIONS];
+
+ Dialogue();
+ ~Dialogue();
};
struct GetData { // size = 24
@@ -206,7 +209,7 @@ struct SpeakData { // size = 36
}
};
struct ExamineData { // size = 28
- Frames *_cnv;
+ GfxObj *_cnv;
uint16 _opBase; // unused
uint16 field_12; // unused
char* _description;
@@ -284,7 +287,7 @@ struct Zone {
int16 _bottom;
uint32 _type;
uint32 _flags;
- Label *_label;
+ uint _label;
uint16 field_2C; // unused
uint16 field_2E; // unused
TypeData u;
diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp
index ee8e0cbcc8..2fc809977f 100644
--- a/engines/parallaction/parallaction.cpp
+++ b/engines/parallaction/parallaction.cpp
@@ -84,18 +84,20 @@ Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gam
Parallaction::~Parallaction() {
- clearSet(_commandOpcodes);
- clearSet(_instructionOpcodes);
-
delete _debugger;
delete _globalTable;
delete _callableNames;
+ delete _cmdExec;
+ delete _programExec;
+ _gfx->clearGfxObjects(kGfxObjCharacter | kGfxObjNormal);
+ hideDialogueStuff();
+ delete _balloonMan;
freeLocation();
freeCharacter();
destroyInventory();
-
+
delete _localFlagNames;
delete _gfx;
delete _soundMan;
@@ -136,6 +138,8 @@ int Parallaction::init() {
_debugger = new Debugger(this);
+ setupBalloonManager();
+
return 0;
}
@@ -166,6 +170,8 @@ void Parallaction::freeCharacter() {
delete _objectsNames;
_objectsNames = 0;
+ _gfx->clearGfxObjects(kGfxObjCharacter);
+
_char.free();
return;
@@ -195,6 +201,9 @@ AnimationPtr Parallaction::findAnimation(const char *name) {
}
void Parallaction::freeAnimations() {
+ for (AnimationList::iterator it = _location._animations.begin(); it != _location._animations.end(); it++) {
+ (*it)->_commands.clear(); // See comment for freeZones(), about circular references.
+ }
_location._animations.clear();
return;
}
@@ -245,7 +254,7 @@ void Parallaction::freeLocation() {
_location._walkNodes.clear();
- _gfx->clearGfxObjects();
+ _gfx->clearGfxObjects(kGfxObjNormal);
freeBackground();
_location._programs.clear();
@@ -280,7 +289,7 @@ void Parallaction::setBackground(const char* name, const char* mask, const char*
}
void Parallaction::showLocationComment(const char *text, bool end) {
- _gfx->setLocationBalloon(const_cast<char*>(text), end);
+ _balloonMan->setLocationBalloon(const_cast<char*>(text), end);
}
@@ -289,12 +298,12 @@ void Parallaction::processInput(InputData *data) {
switch (data->_event) {
case kEvEnterZone:
debugC(2, kDebugInput, "processInput: kEvEnterZone");
- _gfx->setFloatingLabel(data->_label);
+ _gfx->showFloatingLabel(data->_label);
break;
case kEvExitZone:
debugC(2, kDebugInput, "processInput: kEvExitZone");
- _gfx->setFloatingLabel(0);
+ _gfx->hideFloatingLabel();
break;
case kEvAction:
@@ -307,7 +316,7 @@ void Parallaction::processInput(InputData *data) {
case kEvOpenInventory:
_input->stopHovering();
- _gfx->setFloatingLabel(0);
+ _gfx->hideFloatingLabel();
if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) {
setArrowCursor();
}
@@ -379,8 +388,12 @@ void Parallaction::runGame() {
_gfx->beginFrame();
if (_input->_inputMode == Input::kInputModeGame) {
- runScripts();
- walk();
+ _programExec->runScripts(_location._programs.begin(), _location._programs.end());
+ _char._ani->_z = _char._ani->height() + _char._ani->_top;
+ if (_char._ani->gfxobj) {
+ _char._ani->gfxobj->z = _char._ani->_z;
+ }
+ walk(_char);
drawAnimations();
}
@@ -415,14 +428,14 @@ void Parallaction::doLocationEnterTransition() {
pal.makeGrayscale();
_gfx->setPalette(pal);
- runScripts();
+ _programExec->runScripts(_location._programs.begin(), _location._programs.end());
drawAnimations();
_gfx->updateScreen();
showLocationComment(_location._comment, false);
_input->waitUntilLeftClick();
- _gfx->freeBalloons();
+ _balloonMan->freeBalloons();
// fades maximum intensity palette towards approximation of main palette
for (uint16 _si = 0; _si<6; _si++) {
@@ -482,6 +495,9 @@ void Parallaction::freeZones() {
debugC(2, kDebugExec, "freeZones preserving zone '%s'", z->_name);
it++;
} else {
+ (*it)->_commands.clear(); // Since commands may reference zones, and both commands and zones are kept stored into
+ // SharedPtr's, we need to kill commands explicitly to destroy any potential circular
+ // reference.
it = _location._zones.erase(it);
}
}
@@ -490,6 +506,34 @@ void Parallaction::freeZones() {
}
+enum {
+ WALK_LEFT = 0,
+ WALK_RIGHT = 1,
+ WALK_DOWN = 2,
+ WALK_UP = 3
+};
+
+struct WalkFrames {
+ int16 stillFrame[4];
+ int16 firstWalkFrame[4];
+ int16 numWalkFrames[4];
+ int16 frameRepeat[4];
+};
+
+WalkFrames _char20WalkFrames = {
+ { 0, 7, 14, 17 },
+ { 1, 8, 15, 18 },
+ { 6, 6, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
+WalkFrames _char24WalkFrames = {
+ { 0, 9, 18, 21 },
+ { 1, 10, 19, 22 },
+ { 8, 8, 2, 2 },
+ { 2, 2, 4, 4 }
+};
+
const char Character::_prefixMini[] = "mini";
const char Character::_suffixTras[] = "tras";
const char Character::_empty[] = "\0";
@@ -500,6 +544,9 @@ Character::Character(Parallaction *vm) : _vm(vm), _ani(new Animation), _builder(
_head = NULL;
_objs = NULL;
+ _direction = WALK_DOWN;
+ _step = 0;
+
_dummy = false;
_ani->_left = 150;
@@ -564,10 +611,14 @@ void Character::setName(const char *name) {
const char *end = begin + strlen(name);
_prefix = _empty;
+ _suffix = _empty;
_dummy = IS_DUMMY_CHARACTER(name);
if (!_dummy) {
+ if (!strstr(name, "donna")) {
+ _engineFlags &= ~kEngineTransformedDonna;
+ } else
if (_engineFlags & kEngineTransformedDonna) {
_suffix = _suffixTras;
} else {
@@ -576,8 +627,6 @@ void Character::setName(const char *name) {
_engineFlags |= kEngineTransformedDonna;
_suffix = _suffixTras;
end = s;
- } else {
- _suffix = _empty;
}
}
if (IS_MINI_CHARACTER(name)) {
@@ -618,4 +667,29 @@ void Parallaction::scheduleLocationSwitch(const char *location) {
}
+
+
+
+void Character::updateDirection(const Common::Point& pos, const Common::Point& to) {
+
+ Common::Point dist(to.x - pos.x, to.y - pos.y);
+ WalkFrames *frames = (_ani->getFrameNum() == 20) ? &_char20WalkFrames : &_char24WalkFrames;
+
+ _step++;
+
+ if (dist.x == 0 && dist.y == 0) {
+ _ani->_frame = frames->stillFrame[_direction];
+ return;
+ }
+
+ if (dist.x < 0)
+ dist.x = -dist.x;
+ if (dist.y < 0)
+ dist.y = -dist.y;
+
+ _direction = (dist.x > dist.y) ? ((to.x > pos.x) ? WALK_LEFT : WALK_RIGHT) : ((to.y > pos.y) ? WALK_DOWN : WALK_UP);
+ _ani->_frame = frames->firstWalkFrame[_direction] + (_step / frames->frameRepeat[_direction]) % frames->numWalkFrames[_direction];
+}
+
+
} // namespace Parallaction
diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h
index 9f8bbea1b0..461ddc674f 100644
--- a/engines/parallaction/parallaction.h
+++ b/engines/parallaction/parallaction.h
@@ -33,6 +33,7 @@
#include "engines/engine.h"
+#include "parallaction/exec.h"
#include "parallaction/input.h"
#include "parallaction/inventory.h"
#include "parallaction/parser.h"
@@ -201,9 +202,9 @@ struct Character {
AnimationPtr _ani;
- Frames *_head;
- Frames *_talk;
- Frames *_objs;
+ GfxObj *_head;
+ GfxObj *_talk;
+ GfxObj *_objs;
PathBuilder _builder;
WalkNodeList *_walkPath;
@@ -227,18 +228,19 @@ protected:
static const char _suffixTras[];
static const char _empty[];
+ int16 _direction, _step;
+
public:
void setName(const char *name);
const char *getName() const;
const char *getBaseName() const;
const char *getFullName() const;
bool dummy() const;
-};
+ void updateDirection(const Common::Point& pos, const Common::Point& to);
+};
-#define DECLARE_UNQUALIFIED_COMMAND_OPCODE(op) void cmdOp_##op()
-#define DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(op) void instOp_##op()
#define NUM_LOCATIONS 120
@@ -263,31 +265,14 @@ public:
Input *_input;
- OpcodeSet _commandOpcodes;
-
- struct ParallactionStruct1 {
- CommandPtr cmd;
- ZonePtr z;
- } _cmdRunCtxt;
-
- OpcodeSet _instructionOpcodes;
-
- struct ParallactionStruct2 {
- AnimationPtr anim;
- ProgramPtr program;
- InstructionList::iterator inst;
- uint16 modCounter;
- bool suspend;
- } _instRunCtxt;
-
void processInput(InputData* data);
void pauseJobs();
void resumeJobs();
- void finalizeWalk(WalkNodeList *list);
- int16 selectWalkFrame(const Common::Point& pos, const WalkNodePtr from);
- void clipMove(Common::Point& pos, const WalkNodePtr from);
+ void finalizeWalk(Character &character);
+ int16 selectWalkFrame(Character &character, const Common::Point& pos, const WalkNodePtr to);
+ void clipMove(Common::Point& pos, const Common::Point& to);
ZonePtr findZone(const char *name);
ZonePtr hitZone(uint32 type, uint16 x, uint16 y);
@@ -296,8 +281,6 @@ public:
void runDialogue(SpeakData*);
- void runCommands(CommandList& list, ZonePtr z = nullZonePtr);
-
AnimationPtr findAnimation(const char *name);
void freeAnimations();
@@ -331,6 +314,8 @@ public:
Gfx* _gfx;
Disk* _disk;
+ CommandExec* _cmdExec;
+ ProgramExec* _programExec;
Character _char;
void setLocationFlags(uint32 flags);
@@ -371,10 +356,8 @@ protected: // members
void runGame();
void updateView();
- void scheduleLocationSwitch(const char *location);
void doLocationEnterTransition();
virtual void changeLocation(char *location) = 0;
- virtual void changeCharacter(const char *name) = 0;
virtual void runPendingZones() = 0;
void allocateLocationSlot(const char *name);
void finalizeLocationParsing();
@@ -383,7 +366,7 @@ protected: // members
void displayComment(ExamineData *data);
- uint16 checkDoor();
+ void checkDoor(const Common::Point &foot);
void freeCharacter();
@@ -393,6 +376,9 @@ protected: // members
public:
+ void scheduleLocationSwitch(const char *location);
+ virtual void changeCharacter(const char *name) = 0;
+
virtual void callFunction(uint index, void* parm) { }
virtual void setArrowCursor() = 0;
@@ -402,12 +388,12 @@ public:
void updateDoor(ZonePtr z);
- virtual void runScripts() = 0;
- virtual void walk() = 0;
+ virtual void walk(Character &character) = 0;
virtual void drawAnimations() = 0;
void beep();
+ ZonePtr _zoneTrap;
public:
// const char **_zoneFlagNamesRes;
@@ -433,6 +419,15 @@ public:
Inventory *_inventory;
InventoryRenderer *_inventoryRenderer;
+ BalloonManager *_balloonMan;
+
+ void setupBalloonManager();
+
+ void hideDialogueStuff() {
+ _gfx->freeItems();
+ _balloonMan->freeBalloons();
+ }
+
};
@@ -528,7 +523,6 @@ private:
void initResources();
void initCursors();
- void initParsers();
static byte _resMouseArrow[256];
byte *_mouseArrow;
@@ -552,6 +546,9 @@ private:
ZonePtr _moveSarcExaZones[5];
AnimationPtr _rightHandAnim;
+ bool _inTestResult;
+
+
// common callables
void _c_play_boogie(void*);
void _c_startIntro(void*);
@@ -588,49 +585,12 @@ private:
const Callable *_callables;
protected:
- void runScripts();
- void walk();
+ void walk(Character &character);
void drawAnimations();
void parseLocation(const char *filename);
void loadProgram(AnimationPtr a, const char *filename);
- void initOpcodes();
-
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(invalid);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(set);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(clear);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(speak);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(get);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(toggle);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(quit);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
-
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(invalid);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endloop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(null);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(call);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(sound);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
-
void selectStartLocation();
void guiStart();
@@ -663,6 +623,9 @@ public:
typedef void (Parallaction_br::*Callable)(void*);
virtual void callFunction(uint index, void* parm);
void changeCharacter(const char *name);
+ void setupSubtitles(char *s, char *s2, int y);
+ void clearSubtitles();
+
public:
Table *_countersNames;
@@ -690,8 +653,6 @@ private:
void initResources();
void initFonts();
void freeFonts();
- void initOpcodes();
- void initParsers();
void setArrowCursor();
void setInventoryCursor(int pos);
@@ -733,68 +694,6 @@ private:
void parseLocation(const char* name);
void loadProgram(AnimationPtr a, const char *filename);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(location);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(open);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(close);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(on);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(off);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(call);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(drop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(move);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(start);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(stop);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(character);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(followme);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(onmouse);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(offmouse);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(add);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(leave);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(inc);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(dec);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifeq);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(iflt);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(ifgt);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(let);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(music);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(fix);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(unfix);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(zeta);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(scroll);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(swap);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(give);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(text);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(part);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(testsfx);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(ret);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(onsave);
- DECLARE_UNQUALIFIED_COMMAND_OPCODE(offsave);
-
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(on);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(off);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(loop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(inc);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(dec);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(set);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(put);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(wait);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(start);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(process);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(move);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(color);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mask);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(print);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(text);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(mul);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(div);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifeq);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(iflt);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(ifgt);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endif);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(stop);
- DECLARE_UNQUALIFIED_INSTRUCTION_OPCODE(endscript);
-
- void setupSubtitles(char *s, char *s2, int y);
- void clearSubtitles();
#if 0
void jobWaitRemoveLabelJob(void *parm, Job *job);
void jobPauseSfx(void *parm, Job *job);
diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp
index 72a829d7cb..090184e9fe 100644
--- a/engines/parallaction/parallaction_br.cpp
+++ b/engines/parallaction/parallaction_br.cpp
@@ -72,14 +72,21 @@ int Parallaction_br::init() {
initResources();
initFonts();
initCursors();
- initOpcodes();
_locationParser = new LocationParser_br(this);
_locationParser->init();
_programParser = new ProgramParser_br(this);
_programParser->init();
+ _cmdExec = new CommandExec_br(this);
+ _cmdExec->init();
+ _programExec = new ProgramExec_br(this);
+ _programExec->init();
+
_part = -1;
+ _subtitle[0] = -1;
+ _subtitle[1] = -1;
+
Parallaction::init();
return 0;
@@ -221,10 +228,16 @@ void Parallaction_br::changeLocation(char *location) {
// free open location stuff
clearSubtitles();
freeBackground();
- _gfx->clearGfxObjects();
+ _gfx->clearGfxObjects(kGfxObjNormal | kGfxObjCharacter);
_location._programs.clear();
+
+ _location._animations.remove(_char._ani);
+
freeZones();
freeAnimations();
+
+ _location._animations.push_front(_char._ani);
+
// free(_location._comment);
// _location._comment = 0;
// _location._commands.clear();
@@ -233,9 +246,9 @@ void Parallaction_br::changeLocation(char *location) {
// load new location
parseLocation(location);
- runCommands(_location._commands);
+ _cmdExec->run(_location._commands);
// doLocationEnterTransition();
- runCommands(_location._aCommands);
+ _cmdExec->run(_location._aCommands);
_engineFlags &= ~kEngineChangeLocation;
}
@@ -284,12 +297,16 @@ void Parallaction_br::loadProgram(AnimationPtr a, const char *filename) {
void Parallaction_br::changeCharacter(const char *name) {
+ printf("changeCharacter(%s)\n", name);
+
const char *charName = _char.getName();
if (!scumm_stricmp(charName, name)) {
return;
}
_char.setName(name);
+ _char._ani->gfxobj = _gfx->loadAnim(name);
+ _char._ani->gfxobj->setFlags(kGfxObjCharacter);
_char._talk = _disk->loadTalk(name);
}
diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp
index 318443bb18..e5baf1864d 100644
--- a/engines/parallaction/parallaction_ns.cpp
+++ b/engines/parallaction/parallaction_ns.cpp
@@ -135,18 +135,24 @@ int Parallaction_ns::init() {
initResources();
initFonts();
initCursors();
- initOpcodes();
_locationParser = new LocationParser_ns(this);
_locationParser->init();
_programParser = new ProgramParser_ns(this);
_programParser->init();
+ _cmdExec = new CommandExec_ns(this);
+ _cmdExec->init();
+ _programExec = new ProgramExec_ns(this);
+ _programExec->init();
+
_introSarcData1 = 0;
_introSarcData2 = 1;
_introSarcData3 = 200;
num_foglie = 0;
+ _inTestResult = false;
+
_location._animations.push_front(_char._ani);
Parallaction::init();
@@ -156,7 +162,7 @@ int Parallaction_ns::init() {
Parallaction_ns::~Parallaction_ns() {
freeFonts();
-
+
delete _locationParser;
delete _programParser;
delete _mouseComposedArrow;
@@ -185,7 +191,7 @@ void Parallaction_ns::setArrowCursor() {
debugC(1, kDebugInput, "setting mouse cursor to arrow");
// this stuff is needed to avoid artifacts with labels and selected items when switching cursors
- _gfx->setFloatingLabel(0);
+ _gfx->hideFloatingLabel();
_input->_activeItem._id = 0;
_system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
@@ -235,10 +241,10 @@ int Parallaction_ns::go() {
_globalTable = _disk->loadTable("global");
guiStart();
-
+
if (quit())
return _eventMan->shouldRTL();
-
+
changeLocation(_location._name);
if (quit())
@@ -296,14 +302,17 @@ void Parallaction_ns::changeLocation(char *location) {
_soundMan->playLocationMusic(location);
- _gfx->setFloatingLabel(0);
+ _gfx->hideFloatingLabel();
_gfx->freeLabels();
+ _zoneTrap = nullZonePtr;
+
_input->stopHovering();
if (_engineFlags & kEngineBlockInput) {
setArrowCursor();
}
+ _gfx->showGfxObj(_char._ani->gfxobj, false);
_location._animations.remove(_char._ani);
freeLocation();
@@ -325,6 +334,7 @@ void Parallaction_ns::changeLocation(char *location) {
}
_location._animations.push_front(_char._ani);
+ _gfx->showGfxObj(_char._ani->gfxobj, true);
strcpy(_saveData1, locname.location());
parseLocation(_saveData1);
@@ -349,11 +359,11 @@ void Parallaction_ns::changeLocation(char *location) {
// and acommands are executed, so that it can be set again if needed.
_engineFlags &= ~kEngineChangeLocation;
- runCommands(_location._commands);
+ _cmdExec->run(_location._commands);
doLocationEnterTransition();
- runCommands(_location._aCommands);
+ _cmdExec->run(_location._aCommands);
if (_location._hasSound)
_soundMan->playSfx(_location._soundFile, 0, true);
@@ -409,6 +419,7 @@ void Parallaction_ns::changeCharacter(const char *name) {
Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
_char._ani->gfxobj = _gfx->loadAnim(_char.getFullName());
+ _char._ani->gfxobj->setFlags(kGfxObjCharacter);
if (!_char.dummy()) {
if (getPlatform() == Common::kPlatformAmiga) {
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index 51da7eb396..defc917a72 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -390,7 +390,7 @@ DECLARE_LOCATION_PARSER(flags) {
if ((_vm->getLocationFlags() & kFlagsVisited) == 0) {
// only for 1st visit
- _vm->clearLocationFlags(kFlagsAll);
+ _vm->clearLocationFlags((uint32)kFlagsAll);
int _si = 1;
do {
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index c654e3008e..2f4d2df776 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -1059,7 +1059,7 @@ DECLARE_LOCATION_PARSER(flags) {
if ((_vm->getLocationFlags() & kFlagsVisited) == 0) {
// only for 1st visit
- _vm->clearLocationFlags(kFlagsAll);
+ _vm->clearLocationFlags((uint32)kFlagsAll);
int _si = 1;
do {
diff --git a/engines/parallaction/sound.cpp b/engines/parallaction/sound.cpp
index dd74e8f7aa..df6867a90c 100644
--- a/engines/parallaction/sound.cpp
+++ b/engines/parallaction/sound.cpp
@@ -175,6 +175,7 @@ void MidiPlayer::close() {
_mutex.lock();
_driver->setTimerCallback(NULL, NULL);
_driver->close();
+ delete _driver;
_driver = 0;
_parser->setMidiDriver(NULL);
delete _parser;
@@ -249,6 +250,9 @@ void DosSoundMan::stopMusic() {
}
void DosSoundMan::playCharacterMusic(const char *character) {
+ if (character == NULL) {
+ return;
+ }
if (!scumm_stricmp(_vm->_location._name, "night") ||
!scumm_stricmp(_vm->_location._name, "intsushi")) {
diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp
index 0a8ded9e29..40dfddb903 100644
--- a/engines/parallaction/walk.cpp
+++ b/engines/parallaction/walk.cpp
@@ -27,12 +27,6 @@
namespace Parallaction {
-static uint16 _doorData1 = 1000;
-static ZonePtr _zoneTrap;
-
-static uint16 walkData1 = 0;
-static uint16 walkData2 = 0; // next walk frame
-
inline byte PathBuffer::getValue(uint16 x, uint16 y) {
byte m = data[(x >> 3) + y * internalWidth];
@@ -259,172 +253,117 @@ uint16 PathBuilder::walkFunc1(int16 x, int16 y, WalkNodePtr Node) {
return 1;
}
-void Parallaction::clipMove(Common::Point& pos, const WalkNodePtr from) {
+void Parallaction::clipMove(Common::Point& pos, const Common::Point& to) {
- if ((pos.x < from->_x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
- pos.x = (pos.x + 2 < from->_x) ? pos.x + 2 : from->_x;
+ if ((pos.x < to.x) && (pos.x < _pathBuffer->w) && (_pathBuffer->getValue(pos.x + 2, pos.y) != 0)) {
+ pos.x = (pos.x + 2 < to.x) ? pos.x + 2 : to.x;
}
- if ((pos.x > from->_x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
- pos.x = (pos.x - 2 > from->_x) ? pos.x - 2 : from->_x;
+ if ((pos.x > to.x) && (pos.x > 0) && (_pathBuffer->getValue(pos.x - 2, pos.y) != 0)) {
+ pos.x = (pos.x - 2 > to.x) ? pos.x - 2 : to.x;
}
- if ((pos.y < from->_y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
- pos.y = (pos.y + 2 <= from->_y) ? pos.y + 2 : from->_y;
+ if ((pos.y < to.y) && (pos.y < _pathBuffer->h) && (_pathBuffer->getValue(pos.x, pos.y + 2) != 0)) {
+ pos.y = (pos.y + 2 <= to.y) ? pos.y + 2 : to.y;
}
- if ((pos.y > from->_y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
- pos.y = (pos.y - 2 >= from->_y) ? pos.y - 2 :from->_y;
+ if ((pos.y > to.y) && (pos.y > 0) && (_pathBuffer->getValue(pos.x, pos.y - 2) != 0)) {
+ pos.y = (pos.y - 2 >= to.y) ? pos.y - 2 : to.y;
}
return;
}
-int16 Parallaction::selectWalkFrame(const Common::Point& pos, const WalkNodePtr from) {
-
- Common::Point dist(from->_x - pos.x, from->_y - pos.y);
-
- if (dist.x < 0)
- dist.x = -dist.x;
- if (dist.y < 0)
- dist.y = -dist.y;
- walkData1++;
-
- // walk frame selection
- int16 v16;
- if (_char._ani->getFrameNum() == 20) {
-
- if (dist.x > dist.y) {
- walkData2 = (from->_x > pos.x) ? 0 : 7;
- walkData1 %= 12;
- v16 = walkData1 / 2;
- } else {
- walkData2 = (from->_y > pos.y) ? 14 : 17;
- walkData1 %= 8;
- v16 = walkData1 / 4;
- }
-
- } else {
-
- if (dist.x > dist.y) {
- walkData2 = (from->_x > pos.x) ? 0 : 9;
- walkData1 %= 16;
- v16 = walkData1 / 2;
- } else {
- walkData2 = (from->_y > pos.y) ? 18 : 21;
- walkData1 %= 8;
- v16 = walkData1 / 4;
- }
-
- }
-
- return v16;
-}
-
-uint16 Parallaction::checkDoor() {
-// printf("checkDoor()...");
-
- if (_currentLocationIndex != _doorData1) {
- _doorData1 = _currentLocationIndex;
- _zoneTrap = nullZonePtr;
- }
-
- _engineFlags &= ~kEngineWalking;
-
- Common::Point foot;
+void Parallaction::checkDoor(const Common::Point &foot) {
- _char.getFoot(foot);
ZonePtr z = hitZone(kZoneDoor, foot.x, foot.y);
-
if (z) {
-
if ((z->_flags & kFlagsClosed) == 0) {
_location._startPosition = z->u.door->_startPos;
_location._startFrame = z->u.door->_startFrame;
-
scheduleLocationSwitch(z->u.door->_location);
_zoneTrap = nullZonePtr;
-
} else {
- runCommands(z->_commands, z);
+ _cmdExec->run(z->_commands, z);
}
}
- _char.getFoot(foot);
z = hitZone(kZoneTrap, foot.x, foot.y);
-
if (z) {
setLocationFlags(kFlagsEnter);
- runCommands(z->_commands, z);
+ _cmdExec->run(z->_commands, z);
clearLocationFlags(kFlagsEnter);
_zoneTrap = z;
} else
if (_zoneTrap) {
setLocationFlags(kFlagsExit);
- runCommands(_zoneTrap->_commands, _zoneTrap);
+ _cmdExec->run(_zoneTrap->_commands, _zoneTrap);
clearLocationFlags(kFlagsExit);
_zoneTrap = nullZonePtr;
}
-// printf("done\n");
-
- _char._ani->_frame = walkData2;
- return _char._ani->_frame;
}
-void Parallaction::finalizeWalk(WalkNodeList *list) {
- checkDoor();
- delete list;
+void Parallaction::finalizeWalk(Character &character) {
+ _engineFlags &= ~kEngineWalking;
+
+ Common::Point foot;
+ character.getFoot(foot);
+ checkDoor(foot);
+
+ delete character._walkPath;
+ character._walkPath = 0;
}
-void Parallaction_ns::walk() {
+void Parallaction_ns::walk(Character &character) {
if ((_engineFlags & kEngineWalking) == 0) {
return;
}
- WalkNodeList *list = _char._walkPath;
-
- _char._ani->_oldPos.x = _char._ani->_left;
- _char._ani->_oldPos.y = _char._ani->_top;
-
- Common::Point pos;
- _char.getFoot(pos);
-
- WalkNodeList::iterator it = list->begin();
+ Common::Point curPos;
+ character.getFoot(curPos);
- if (it != list->end()) {
- if ((*it)->_x == pos.x && (*it)->_y == pos.y) {
+ // update target, if previous was reached
+ WalkNodeList::iterator it = character._walkPath->begin();
+ if (it != character._walkPath->end()) {
+ if ((*it)->_x == curPos.x && (*it)->_y == curPos.y) {
debugC(1, kDebugWalk, "walk reached node (%i, %i)", (*it)->_x, (*it)->_y);
- it = list->erase(it);
+ it = character._walkPath->erase(it);
}
}
- if (it == list->end()) {
- debugC(1, kDebugWalk, "walk reached last node");
-// j->_finished = 1;
- finalizeWalk(list);
- return;
- }
- _char._walkPath = list;
-
- // selectWalkFrame must be performed before position is changed by clipMove
- int16 v16 = selectWalkFrame(pos, *it);
- clipMove(pos, *it);
- _char.setFoot(pos);
+ // advance character towards the target
+ Common::Point targetPos;
+ if (it == character._walkPath->end()) {
+ debugC(1, kDebugWalk, "walk reached last node");
+ finalizeWalk(character);
+ targetPos = curPos;
+ } else {
+ if (*it) {
+ // targetPos is saved to help setting character direction
+ targetPos.x = (*it)->_x;
+ targetPos.y = (*it)->_y;
+ }
- Common::Point newpos(_char._ani->_left, _char._ani->_top);
+ Common::Point newPos(curPos);
+ clipMove(newPos, targetPos);
+ character.setFoot(newPos);
- if (newpos == _char._ani->_oldPos) {
- debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
-// j->_finished = 1;
- finalizeWalk(list);
- } else {
- _char._ani->_frame = v16 + walkData2 + 1;
+ if (newPos == curPos) {
+ debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
+ finalizeWalk(character);
+ }
}
- return;
+ // targetPos is used to select the direction (and the walkFrame) of a character,
+ // since it doesn't cause the sudden changes in orientation that newPos would.
+ // Since newPos is 'adjusted' according to walkable areas, an imaginary line drawn
+ // from curPos to newPos is prone to abrutply change in direction, thus making the
+ // code select 'too different' frames when walking diagonally against obstacles,
+ // and yielding an annoying shaking effect in the character.
+ character.updateDirection(curPos, targetPos);
}