aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Menshakov2009-09-03 20:59:17 +0000
committerVladimir Menshakov2009-09-03 20:59:17 +0000
commitebe1b94eb1561b566124b7dcbb73cf3b0a659b33 (patch)
treed4f182bc5b5b46ce5933913a1a8066dc089889ea
parent9b2104db32d074886daa0ec48624193351d6ed51 (diff)
downloadscummvm-rg350-ebe1b94eb1561b566124b7dcbb73cf3b0a659b33.tar.gz
scummvm-rg350-ebe1b94eb1561b566124b7dcbb73cf3b0a659b33.tar.bz2
scummvm-rg350-ebe1b94eb1561b566124b7dcbb73cf3b0a659b33.zip
imported teenagent engine sources.
svn-id: r43922
-rw-r--r--base/plugins.cpp3
-rwxr-xr-xconfigure1
-rw-r--r--engines/engines.mk5
-rw-r--r--engines/teenagent/actor.cpp70
-rw-r--r--engines/teenagent/actor.h34
-rw-r--r--engines/teenagent/animation.cpp185
-rw-r--r--engines/teenagent/animation.h64
-rw-r--r--engines/teenagent/callbacks.cpp1807
-rw-r--r--engines/teenagent/detection.cpp150
-rw-r--r--engines/teenagent/dialog.cpp106
-rw-r--r--engines/teenagent/dialog.h42
-rw-r--r--engines/teenagent/font.cpp142
-rw-r--r--engines/teenagent/font.h48
-rw-r--r--engines/teenagent/inventory.cpp285
-rw-r--r--engines/teenagent/inventory.h84
-rw-r--r--engines/teenagent/module.mk26
-rw-r--r--engines/teenagent/music.cpp162
-rw-r--r--engines/teenagent/music.h77
-rw-r--r--engines/teenagent/objects.cpp86
-rw-r--r--engines/teenagent/objects.h104
-rw-r--r--engines/teenagent/pack.cpp83
-rw-r--r--engines/teenagent/pack.h49
-rw-r--r--engines/teenagent/resources.cpp144
-rw-r--r--engines/teenagent/resources.h56
-rw-r--r--engines/teenagent/scene.cpp511
-rw-r--r--engines/teenagent/scene.h166
-rw-r--r--engines/teenagent/segment.cpp37
-rw-r--r--engines/teenagent/segment.h80
-rw-r--r--engines/teenagent/surface.cpp95
-rw-r--r--engines/teenagent/surface.h52
-rw-r--r--engines/teenagent/teenagent.cpp484
-rw-r--r--engines/teenagent/teenagent.h110
32 files changed, 5348 insertions, 0 deletions
diff --git a/base/plugins.cpp b/base/plugins.cpp
index 446c26e57c..6f821f7327 100644
--- a/base/plugins.cpp
+++ b/base/plugins.cpp
@@ -157,6 +157,9 @@ public:
#if PLUGIN_ENABLED_STATIC(TUCKER)
LINK_PLUGIN(TUCKER)
#endif
+ #if PLUGIN_ENABLED_STATIC(TEENAGENT)
+ LINK_PLUGIN(TEENAGENT)
+ #endif
// Music plugins
// TODO: Use defines to disable or enable each MIDI driver as a
diff --git a/configure b/configure
index a157ecc544..4b7f626eb4 100755
--- a/configure
+++ b/configure
@@ -105,6 +105,7 @@ add_engine sword2 "Broken Sword 2" yes
add_engine tinsel "Tinsel" yes
add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
add_engine tucker "Bud Tucker in Double Trouble" yes
+add_engine teenagent "Teen Agent" no
#
diff --git a/engines/engines.mk b/engines/engines.mk
index acda075b46..19f99020ec 100644
--- a/engines/engines.mk
+++ b/engines/engines.mk
@@ -145,3 +145,8 @@ ifdef ENABLE_TUCKER
DEFINES += -DENABLE_TUCKER=$(ENABLE_TUCKER)
MODULES += engines/tucker
endif
+
+ifdef ENABLE_TEENAGENT
+DEFINES += -DENABLE_TEENAGENT=$(ENABLE_TEENAGENT)
+MODULES += engines/teenagent
+endif
diff --git a/engines/teenagent/actor.cpp b/engines/teenagent/actor.cpp
new file mode 100644
index 0000000000..9c8ff8e14a
--- /dev/null
+++ b/engines/teenagent/actor.cpp
@@ -0,0 +1,70 @@
+/* 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: https://www.switchlink.se/svn/teen/actor.cpp $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+#include "actor.h"
+#include "objects.h"
+
+using namespace TeenAgent;
+
+void Actor::render(Graphics::Surface * surface, const Common::Point & position, uint8 orientation, int delta_frame) {
+ uint8 frames_left_right[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+ uint8 frames_up[] = {18, 19, 20, 21, 22, 23, 24, 25, };
+ uint8 frames_down[] = {10, 11, 12, 13, 14, 15, 16, 17, };
+
+ Surface * s = NULL;
+
+ if (delta_frame == 0) {
+ index = 0; //static animation
+ }
+ int dx, dy;
+ switch(orientation) {
+ case Object::ActorLeft:
+ case Object::ActorRight:
+ if (index >= sizeof(frames_left_right))
+ index = 1;
+ s = frames + frames_left_right[index];
+ dx = 11;
+ dy = 62;
+ break;
+ case Object::ActorUp:
+ if (index >= sizeof(frames_up))
+ index = 1;
+ s = frames + frames_up[index];
+ dx = 29;
+ dy = 67;
+ break;
+ case Object::ActorDown:
+ if (index >= sizeof(frames_down))
+ index = 1;
+ s = frames + frames_down[index];
+ dx = 29;
+ dy = 67;
+ break;
+ default:
+ return;
+ }
+ index += delta_frame;
+
+ if (s != NULL)
+ s->render(surface, position.x - dx, position.y - dy, orientation == Object::ActorLeft);
+}
diff --git a/engines/teenagent/actor.h b/engines/teenagent/actor.h
new file mode 100644
index 0000000000..ca49ee4923
--- /dev/null
+++ b/engines/teenagent/actor.h
@@ -0,0 +1,34 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#include "animation.h"
+#include "common/rect.h"
+
+namespace TeenAgent {
+
+class Actor : public Animation {
+public:
+ void render(Graphics::Surface * surface, const Common::Point & position, uint8 orientation, int delta_frame);
+};
+} \ No newline at end of file
diff --git a/engines/teenagent/animation.cpp b/engines/teenagent/animation.cpp
new file mode 100644
index 0000000000..3330acee2f
--- /dev/null
+++ b/engines/teenagent/animation.cpp
@@ -0,0 +1,185 @@
+/* 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: https://www.switchlink.se/svn/teen/animation.cpp $
+ * $Id: animation.cpp 296 2009-09-01 19:55:58Z megath $
+ */
+
+
+#include "animation.h"
+#include "common/endian.h"
+
+using namespace TeenAgent;
+
+Animation::Animation() : id(0), x(0), y(0), loop(true), data(0), data_size(0), frames_count(0), frames(0), index(0) {
+}
+
+Surface * Animation::currentFrame(int dt) {
+ if (frames == NULL || frames_count == 0)
+ return NULL;
+
+ Surface * r;
+
+ if (data != NULL) {
+ uint32 frame = 3 * index;
+ //debug(0, "%u/%u", index, data_size / 3);
+ index += dt;
+
+ if (!loop && index >= data_size / 3) {
+ return NULL;
+ }
+
+ if (data[frame] - 1 >= frames_count) {
+ warning("invalid frame %u(0x%x) (max %u) index %u, mod %u", frame, frame, frames_count, index - 1, data_size / 3);
+ return NULL;
+ }
+
+ r = frames + data[frame] - 1;
+ uint16 pos = READ_LE_UINT16(data + frame + 1);
+ index %= (data_size / 3);
+
+ if (pos != 0) {
+ x = r->x = pos % 320;
+ y = r->y = pos / 320;
+ }
+ } else {
+ //debug(0, "index %u", index);
+ r = frames + index;
+ index += dt;
+ index %= frames_count;
+ }
+
+ return r;
+}
+
+
+void Animation::free() {
+ id = 0;
+ x = y = 0;
+ loop = true;
+
+ delete[] data;
+ data = NULL;
+ data_size = 0;
+
+ frames_count = 0;
+ delete[] frames;
+ frames = NULL;
+
+ index = 0;
+}
+
+void Animation::load(Common::SeekableReadStream * s, Type type) {
+ //fixme: do not reload the same animation each time
+ free();
+
+ if (s == NULL && s->size() <= 1) {
+ debug(0, "empty animation");
+ return;
+ }
+
+ uint16 pos = 0;
+ int off = 0;
+ switch(type) {
+ case TypeLan:
+ data_size = s->readUint16LE();
+ if (s->eos()) {
+ debug(0, "empty animation");
+ return;
+ }
+
+ data_size -= 2;
+ data = new byte[data_size];
+ data_size = s->read(data, data_size);
+/* for(int i = 0; i < data_size; ++i) {
+ debug(0, "%02x ", data[i]);
+ }
+ debug(0, ", %u frames", data_size / 3);
+*/
+ frames_count = s->readByte();
+ debug(0, "%u physical frames", frames_count);
+ if (frames_count == 0)
+ return;
+
+ frames = new Surface[frames_count];
+
+ s->skip(frames_count * 2 - 2); //sizes
+ pos = s->readUint16LE();
+ //debug(0, "pos?: %04x", pos);
+
+ for(uint16 i = 0; i < frames_count; ++i) {
+ frames[i].load(s, Surface::TypeLan);
+ frames[i].x = 0;
+ frames[i].y = 0;
+ }
+ break;
+
+ case TypeInventory: {
+ data_size = 3 * s->readByte();
+ data = new byte[data_size];
+
+ frames_count = 0;
+ for(byte i = 0; i < data_size / 3; ++i) {
+ int idx = i * 3;
+ byte unk = s->readByte();
+ data[idx] = s->readByte();
+ if (data[idx] == 0)
+ data[idx] = 1; //fixme: investigate
+ if (data[idx] > frames_count)
+ frames_count = data[idx];
+ data[idx + 1] = 0;
+ data[idx + 2] = 0;
+ //debug(0, "frame #%u", data[idx]);
+ }
+
+ frames = new Surface[frames_count];
+
+ for(uint16 i = 0; i < frames_count; ++i) {
+ frames[i].load(s, Surface::TypeOns);
+ }
+ }
+ break;
+
+ case TypeVaria:
+ frames_count = s->readByte();
+ debug(0, "loading varia resource, %u physical frames", frames_count);
+ uint16 offset[255];
+ for(byte i = 0; i < frames_count; ++i) {
+ offset[i] = s->readUint16LE();
+ debug(0, "%u: %04x", i, offset[i]);
+ }
+ frames = new Surface[frames_count];
+ for(uint16 i = 0; i < frames_count; ++i) {
+ debug(0, "%04x", offset[i]);
+ s->seek(offset[i] + off);
+ frames[i].load(s, Surface::TypeOns);
+ frames[i].x = 0;
+ frames[i].y = 0;
+ }
+
+ break;
+ }
+
+ debug(0, "%u frames", data_size / 3);
+}
+
+Animation::~Animation() {
+ free();
+}
diff --git a/engines/teenagent/animation.h b/engines/teenagent/animation.h
new file mode 100644
index 0000000000..4304dc92a4
--- /dev/null
+++ b/engines/teenagent/animation.h
@@ -0,0 +1,64 @@
+/* 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: https://www.switchlink.se/svn/teen/animation.h $
+ * $Id: animation.h 214 2009-08-14 06:09:26Z megath $
+ */
+
+
+#ifndef TEENAGENT_ANIMATION_H__
+#define TEENAGENT_ANIMATION_H__
+
+#include "common/stream.h"
+#include "surface.h"
+
+namespace TeenAgent {
+class Animation {
+public:
+ uint16 id, x, y;
+ bool loop;
+
+ enum Type {TypeLan, TypeVaria, TypeInventory};
+
+ Animation();
+ void load(Common::SeekableReadStream * s, Type type = TypeLan);
+ void free();
+
+ Surface * currentFrame(int dt = 1);
+ ~Animation();
+
+ bool empty() const { return frames == NULL; }
+
+ //uint16 width() const { return frames? frames[0].w: 0; }
+ //uint16 height() const { return frames? frames[0].h: 0; }
+
+protected:
+ byte * data;
+ uint16 data_size;
+
+ uint16 frames_count;
+ Surface * frames;
+ uint16 index;
+};
+}
+
+
+#endif
+
diff --git a/engines/teenagent/callbacks.cpp b/engines/teenagent/callbacks.cpp
new file mode 100644
index 0000000000..2d78fc8c01
--- /dev/null
+++ b/engines/teenagent/callbacks.cpp
@@ -0,0 +1,1807 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#include "scene.h"
+#include "teenagent.h"
+#include "resources.h"
+#include "dialog.h"
+
+using namespace TeenAgent;
+
+#define CHECK_FLAG(addr, v) (res->dseg.get_byte(addr) == (v))
+#define SET_FLAG(addr, v) (res->dseg.set_byte((addr), (v)))
+#define GET_FLAG(addr) (res->dseg.get_byte(addr))
+
+void TeenAgentEngine::rejectMessage() {
+ Resources * res = Resources::instance();
+ //random reject message:
+ uint i = random.getRandomNumber(3);
+ //debug(0, "reject message: %s", (const char *)res->dseg.ptr(res->dseg.get_word(0x339e + 2 * i)));
+ scene->displayMessage((const char *)res->dseg.ptr(res->dseg.get_word(0x339e + 2 * i)));
+}
+
+void TeenAgentEngine::anotherMansionTry() {
+ Resources * res = Resources::instance();
+ byte tries = ++ *(res->dseg.ptr(0xDBEA));
+ debug(0, "another mansion try: %u", tries);
+ if (tries >= 7)
+ return;
+ uint16 ptr = res->dseg.get_word(res->dseg.get_word((tries - 2) * 2 + 0x6035));
+
+ playMusic(11);
+ debug(0, "FIXME: cutscene: meanwhile in a mansion #%u, %04x", tries, ptr);
+ processCallback(ptr);
+ playMusic(6);
+ if (scene->getId() == 11 && CHECK_FLAG(0xDBEC, 1))
+ return;
+ //call 0xac27
+}
+
+bool TeenAgentEngine::processCallback(uint16 addr) {
+ if (addr == 0)
+ return false;
+
+ Resources * res = Resources::instance();
+ debug(0, "processCallback(%04x)", addr);
+ byte * code = res->cseg.ptr(addr);
+
+ //try trivial callbacks first
+ if (code[0] == 0xbb && code[3] == 0xe8 && code[6] == 0xc3) {
+ //call display_message, r
+ uint16 msg = READ_LE_UINT16(code + 1);
+ uint16 func = 6 + addr + READ_LE_UINT16(code + 4);
+ debug(0, "call %04x", func);
+ //debug(0, "trivial callback, showing message %s", (const char *)res->dseg.ptr(addr));
+ switch(func) {
+ case 0x11c5:
+ Dialog::show(scene, msg);
+ return true;
+ case 0xa055:
+ displayMessage((const char *)res->dseg.ptr(msg));
+ return true;
+ }
+ }
+
+ if (code[0] == 0xe8 && code[3] == 0xc3) {
+ uint func = 3 + addr + READ_LE_UINT16(code + 1);
+ debug(0, "call %04x and return", func);
+ if (func == 0xa4d6) {
+ rejectMessage();
+ return true;
+ }
+ }
+
+ if (code[0] == 0xc7 && code[1] == 0x06 && code[2] == 0xf3 && code[3] == 0xb4 &&
+ code[6] == 0xb8 && code[9] == 0xbb && code[12] == 0xbf &&
+ code[22] == 0xe8 && code[25] == 0xc3) {
+ loadScene(code[4], Common::Point(
+ (READ_LE_UINT16(code + 7) + READ_LE_UINT16(code + 13) + 1) / 2 ,
+ READ_LE_UINT16(code + 10)));
+ scene->setOrientation(code[21]);
+ return true;
+ }
+
+ switch(addr) {
+
+ case 0x4021:
+ //pulling out mysterious object
+ if (CHECK_FLAG(0xdbe1, 1)) {
+ playAnimation(844);
+ playAnimation(846);
+ playAnimation(845);
+ displayMessage(0x5696);
+ } else {
+ displayMessage(0x570f);
+ }
+ return true;
+
+ case 0x4094: //climbing to the pole near mudpool
+ if (CHECK_FLAG(0xDBE4, 1)) {
+ displayMessage(0x57b2);
+ return true;
+ } else {
+ playSound(76);
+ playAnimation(864);
+ playAnimation(866);
+ //InventoryObject *obj = inventory->selectedObject();
+ //if (obj != NULL && obj->id == 0x55) {
+
+ //implement pause and using real object:
+ if (inventory->has(0x55)) {
+ playSound(5, 4);
+ playAnimation(867);
+ inventory->remove(0x55);
+ inventory->add(0x56);
+ moveTo(86, 195, true); //warp and orientation 1
+ playAnimation(868);
+ SET_FLAG(0xDBE4, 1);
+ } else {
+ //fail!
+ moveTo(86, 195, true); //warp and orientation 1
+ playAnimation(868);
+ Dialog::pop(scene, 0xDB72);
+ }
+ return true;
+ }
+
+ case 0x419c: //getting the bird
+ setOns(0, 0);
+ playSound(56, 10);
+ playAnimation(875);
+ disableObject(6);
+ inventory->add(0x5c);
+ return true;
+
+
+ case 0x41ce:
+ moveTo(Common::Point(197, 159));
+ setOns(0, 0);
+ playSound(71);
+ playAnimation(833);
+ moveTo(Common::Point(225, 159));
+ inventory->add(0x4e);
+ disableObject(3);
+ return true;
+
+ case 0x4267:
+ playSound(23, 8);
+ setOns(1, 0);
+ playAnimation(841);
+ setOns(1, 0x61);
+ setOns(2, 0);
+ playSound(63, 12);
+ playAnimation(842);
+ //shown in different positions
+ displayMessage(0x5656);
+ displayMessage(0x567a);
+ displayMessage(0x5682);
+ playAnimation(843);
+ moveTo(223, 149, true);
+ disableObject(7);
+ disableObject(1);
+ inventory->add(0x51);
+ displayMessage(0x5646);
+ return true;
+
+ case 0x4388:
+ playSound(80);
+ loadScene(8, 155, 199);
+ scene->setOrientation(1);
+ return true;
+
+ case 0x43b5: //HQ, first trial - prison
+ playSound(70);
+ playAnimation(962);
+ loadScene(7, 30, 184, 2);
+ if (res->dseg.get_byte(0xDBDF) < 2) {
+ moveTo(Common::Point(134, 167));
+ displayMessage(0x54f7);
+ setLan(1, 0);
+ playAnimation(812, 1, true);
+ playAnimation(811);
+ Dialog::show(scene, 0x6117, 813);
+ loadScene(6, Common::Point(230, 184));
+ Dialog::show(scene, 0x626a, 814);
+ playAnimation(815, 1);
+ setOns(1, 0);
+
+ Dialog::show(scene, 0x62dc);
+
+ SET_FLAG(0xDBDF, 1);
+ SET_FLAG(0xDB90, 5);
+ }
+ return true;
+
+ case 0x4482:
+ if (CHECK_FLAG(0xDBDF, 0)) {
+ playAnimation(968);
+ displayMessage(0x5511);
+ } else {
+ playSound(80);
+ playAnimation(968);
+ loadScene(6, Common::Point(280, 186));
+ }
+ return true;
+
+ case 0x44fc: //pull out spring from bed
+ playSound(53, 25);
+ playAnimation(839);
+ moveTo(278, scene->getPosition().y, true);
+ inventory->add(0x50);
+ disableObject(1);
+ return true;
+
+ case 0x44cb:
+ if (CHECK_FLAG(0xDBE5, 1)) {
+ scene->displayMessage((const char *)res->dseg.ptr(0x57c0));
+ } else {
+ playSound(49);
+ playAnimation(869);
+ inventory->add(0x58);
+ SET_FLAG(0xDBE5, 1);
+ }
+ return true;
+
+ case 0x4539: //prison cell: use crates
+ if (CHECK_FLAG(0xdbdd, 2)) {
+ //finished the meal - trap
+ displayMessage(0x55c0);
+ moveTo(306, 196);
+ //playAnimation(825, 1); //very long empty animation. what for?
+ setLan(1, 0);
+ playSound(71, 4);
+ playAnimation(823);
+
+ //skipped one 826 animation for this scene!
+ playSound(74, 4); //delay 10 in code
+ loadScene(5, scene->getPosition());
+ playAnimation(826);
+ loadScene(6, scene->getPosition());
+ setOns(3, 0x5b);
+ displayMessage(0x55db);
+ SET_FLAG(0xdbdd, 3);
+ strcpy(scene->getObject(4)->name, "body");
+ } else {
+ if (Dialog::pop(scene, 0xdb5c) != 0x636b) //not 'im getting hungry'
+ return true;
+
+ playSound(52, 8);
+ playAnimation(820, 1);
+ setOns(3, 0x59);
+ //some moving animation is missing here
+ displayMessage(0x551f);
+ enableObject(4);
+ SET_FLAG(0xdbdc, 1);
+ }
+ return true;
+
+ case 0x4662:
+ if (CHECK_FLAG(0xDBDD, 3)) {
+ moveTo(280, 179);
+ playSound(49, 7);
+ playAnimation(827);
+ inventory->add(0x4d);
+ SET_FLAG(0xDBDE, 1);
+ } else
+ displayMessage(0x5905);
+ return true;
+
+ case 0x46af: //prison cell: use live cable
+ if (CHECK_FLAG(0xdbdc, 1)) {
+ displayMessage(0x555d);
+ setOns(2, 0);
+ playAnimation(821);
+ setOns(2, 0x5a);
+ setOns(3, 0);
+ playSound(22, 2);
+ playAnimation(822);
+ displayMessage(0x5577);
+ disableObject(5);
+ SET_FLAG(0xdbdd, 1);
+ } else
+ displayMessage(0x5528);
+ return true;
+
+ case 0x4705: { //prison: getting lamp bulb
+ moveTo(144, 185);
+ playSound(56, 15);
+ setOns(0, 86); //hiding lamp
+ playAnimation(816, 0, true);
+ playAnimation(817, 1, true);
+ waitAnimation();
+ setOns(0, 87);
+
+ playSound(34, 1);
+ playAnimation(818);
+ playAnimation(819, 1, true);
+ waitAnimation();
+
+ moveTo(160, 188, true);
+ setOns(2, 88);
+
+ disableObject(6);
+ enableObject(5);
+ inventory->add(0x4c);
+ }
+ return true;
+
+ case 0x4794: //prison cell door
+ if (res->dseg.get_byte(0xDBDF) >= 2) {
+ loadScene(5, 287, 143);
+ } else {
+ displayMessage(0x592f);
+ }
+ return true;
+
+ case 0x47bc: //prison: examining trash can
+ playSound(49, 5);
+ playAnimation(966);
+ displayMessage(0x5955);
+ return true;
+
+ case 0x47db: //prison: use switch
+ if (CHECK_FLAG(0xDBDF, 1)) {
+ playSound(71, 4);
+ playAnimation(823);
+ if (CHECK_FLAG(0xDBDD, 0)) {
+ displayMessage(0x4d80);
+ } else {
+ playSound(74, 1);
+ playAnimation(824, 1);
+ if (CHECK_FLAG(0xDBDD, 1)) {
+ displayMessage(0x559a);
+ SET_FLAG(0xDBDD, 2);
+ }
+ }
+ } else {
+ displayMessage(0x52f6);
+ }
+ return true;
+
+ case 0x4871:
+ playAnimation(965);
+ displayMessage(0x5511);
+ return true;
+
+ case 0x4893: //taking pills
+ if (CHECK_FLAG(0xDBE6, 1)) {
+ SET_FLAG(0xDBE6, 2);
+ setOns(1, 0x67);
+ playSound(5, 9);
+ playAnimation(872);
+ inventory->add(0x5a);
+ disableObject(7);
+ } else {
+ playAnimation(964);
+ displayMessage(0x5511);
+ }
+ return true;
+
+ case 0x4918: //talking with barmen
+ if (CHECK_FLAG(0xDBE7, 1)) {
+ moveTo(140, 152);
+ if (CHECK_FLAG(0xDBE8, 1)) {
+ Dialog::show(scene, 0x6f20);
+ displayMessage(0x5883, 0xef);
+ //reloadLan();
+ setLan(1, 0);
+ playAnimation(882, 1);
+ playSound(75, 10);
+ setOns(2, 0);
+ playAnimation(883, 1);
+ disableObject(1);
+ disableObject(2);
+ SET_FLAG(0xDBE9, 1);
+ } else
+ displayMessage(0x5855);
+ } else {
+ if (CHECK_FLAG(0xDBDF, 3)) {
+ if (CHECK_FLAG(0xDBE3, 1)) {
+ Dialog::show(scene, 0x6BD6, 857);
+ } else {
+ Dialog::show(scene, 0x69B5, 857); //taking mug
+ playAnimation(859, 0, true);
+ playAnimation(858, 1, true);
+ waitAnimation();
+ playSound(75, 6);
+ playAnimation(860);
+ Dialog::show(scene, 0x69C2, 857);
+ inventory->add(0x55);
+ SET_FLAG(0xDBE3, 1);
+ SET_FLAG(0xDBF0, 0);
+ }
+ } else {
+ Dialog::pop(scene, 0xDB68, 857);
+ }
+ }
+ return true;
+
+ case 0x4f14: //use the hollow
+ displayMessage(CHECK_FLAG(0xDBA1, 1)? 0x370f: 0x36c2);
+ return true;
+
+ case 0x4a64:
+ if (CHECK_FLAG(0xDBF0, 1)) {
+ displayMessage(0x5e25);
+ } else {
+ loadScene(5, 35, 162);
+ }
+ return true;
+
+ case 0x4bf5:
+ playAnimation(959);
+ loadScene(8, 40, 152, 3);
+ return true;
+
+ case 0x483a:
+ Dialog::pop(scene, 0xdb82);
+ return true;
+
+ case 0x4844:
+ playSound(80, 4);
+ playAnimation(963);
+ loadScene(5, 166, 158);
+ return true;
+
+ case 0x48ea:
+ setOns(0, 0);
+ playSound(5, 9);
+ playAnimation(836);
+ inventory->add(0x4f);
+ disableObject(12);
+ return true;
+
+ case 0x4a8c:
+ if (CHECK_FLAG(0xDBE9, 1)) {
+ playSound(89, 5);
+ playAnimation(958);
+ loadScene(9, 240, 182, 4);
+ } else if (CHECK_FLAG(0xDBE9, 1)) {
+ displayMessage(0x5894);
+ } else {
+ Dialog::pop(scene, 0xDB8A, 857);
+ }
+ return true;
+
+ case 0x4af4: //taking the crumbs
+ setOns(0, 0);
+ playAnimation(861);
+ playSound(49);
+ inventory->add(0x57);
+ disableObject(6);
+ return true;
+
+ case 0x4b35:
+ playSound(15, 7);
+ playAnimation(884);
+ playSound(55, 1);
+ playAnimation(885, 1);
+ Dialog::show(scene, 0x67e5, 886);
+ playMusic(3);
+ loadScene(40, 198, 186, 1);
+ Dialog::show(scene, 0x7f20);
+ inventory->clear();
+ inventory->add(0x1d);
+ //showFullscreenMessage(0xe45c);
+ loadScene(1, 198, 186);
+ playAnimation(956, 0, true);
+ Dialog::show(scene, 0x8bc4);
+ waitAnimation();
+ loadScene(15, 157, 199, 1);
+ playMusic(6);
+ return true;
+
+ case 0x4c3e: //get the grenade
+ playSound(32, 24);
+ playAnimation(862);
+ reloadLan();
+ playAnimation(863, 1);
+ inventory->add(0x54);
+ disableObject(1);
+ SET_FLAG(0xDBE2, 2);
+ return true;
+
+ case 0x4c70:
+ if (CHECK_FLAG(0xDBE2, 0)) {
+ if (CHECK_FLAG(0xDBDA, 1)) { //papers are shown
+ Dialog::pop(scene, 0xDB4C);
+ } else {
+ Dialog::pop(scene, 0xDB40);
+ }
+ return true;
+ } else {
+ displayMessage(0x5722);
+
+ scene->displayMessage("He's totally addicted.");
+ }
+ return true;
+
+ case 0x4c1c:
+ playAnimation(960);
+ displayMessage(0x5511);
+ return true;
+
+ case 0x4cac:
+ if (CHECK_FLAG(0xdbda, 1)) { //papers are shown
+ loadScene(5, 124, 199);
+ } else {
+ playAnimation(809, 1, true);
+ Dialog::show(scene, 0x5FE9);
+ moveTo(Common::Point(269, 175));
+ Dialog::pop(scene, 0xDB56);
+ }
+ return true;
+
+ case 0x4cf1: { //talking with mansion guard
+ playAnimation(529, 1);
+ SET_FLAG(0xda96, 1);
+ if (Dialog::pop(scene, 0xdaa6) != 0x1b4)
+ return true;
+ Common::Point p = scene->getPosition();
+ moveTo(159, 189);
+
+ playAnimation(550);
+ playAnimation(551, 1);
+
+ moveTo(p);
+ inventory->add(0x13);
+ playAnimation(529, 1);
+ Dialog::pop(scene, 0xdaa6);
+ }
+ return true;
+
+ case 0x4e61:
+ loadScene(14, 280, 198);
+ return true;
+
+ case 0x4f25:
+ playAnimation(967);
+ displayMessage(0x3542);
+ return true;
+
+ case 0x4f32:
+ if (CHECK_FLAG(0xDBA1, 1)) {
+ break;
+ } else {
+ playAnimation(49);
+ playSound(56);
+ //there's some black magic here! investigate!
+ playAnimation(587);
+ displayMessage(0x4652);
+ displayMessage(0x3668);
+ return true;
+ }
+
+ case 0x500d: //picking up wild plant
+ if (CHECK_FLAG(0xDB9E, 1)) {
+ displayMessage(0x35E8); //there are no more
+ } else {
+ SET_FLAG(0xDB9E, 1);
+ setOns(2, 0);
+ playAnimation(552);
+ setOns(2, 0x12);
+ inventory->add(0x14);
+ }
+ return true;
+
+ case 0x5104:
+ loadScene(11, 319, 198, 4); //orientation: left
+ if (CHECK_FLAG(0xDB9C, 1))
+ return true;
+
+ SET_FLAG(0xDB9C, 1); //guard's drinking, boo!
+ playAnimation(544, 1);
+ displayMessage(0x3563);
+ playSound(17);
+ playAnimation(545, 1);
+ setOns(0, 16);
+ enableObject(2);
+ Dialog::show(scene, 0x0917);
+
+ return true;
+
+ case 0x5217:
+ displayMessage(CHECK_FLAG(0xDB9F, 1)? 0x402e: 0x34e1);
+ return true;
+
+ case 0x5237:
+ if (!CHECK_FLAG(0xDB9F, 1)) {
+ displayMessage(0x34e1);
+ } else if (CHECK_FLAG(0xDBA0, 1))
+ displayMessage(0x3E31);
+ else {
+ moveTo(173, 138);
+ playAnimation(583);
+ playAnimation(584);
+ playSound(72);
+ playAnimation(585);
+ loadScene(11, 194, 160);
+ playSound(28);
+ moveTo(138, 163);
+ displayMessage(0x3650);
+ SET_FLAG(0xDBA0, 1);
+ }
+ return true;
+
+ case 0x55a8: {
+ uint16 d = Dialog::pop(scene, 0xdb08);
+ if (d == 0x2c5d) {
+ setOns(0, 0);
+ playAnimation(570, 1);
+ displayMessage(0x551f);
+ disableObject(5);
+ SET_FLAG(0xDBB0, 1);
+ } else if (d != 0x2c9b) {
+ playAnimation(569, 1);
+ }
+ }
+ return true;
+
+ case 0x5663:
+ displayMessage(CHECK_FLAG(0xDBB0, 1)? 0x41b1: 0x417e);
+ return true;
+
+ case 0x569c:
+ playAnimation(983);
+ displayMessage(0x5955);
+ return true;
+
+ case 0x56b7:
+ playAnimation(984);
+ displayMessage(0x5955);
+ return true;
+
+ case 0x5728:
+ inventory->add(0x0d);
+ disableObject(14);
+ setOns(0, 0);
+ playAnimation(566);
+ return true;
+
+ case 0x5793:
+ if (!CHECK_FLAG(0xDB94, 1)) {
+ displayMessage(0x3e63);
+ } else if (CHECK_FLAG(0xDB95, 1)) {
+ displayMessage(0x3e75);
+ } else {
+ SET_FLAG(0xDB95, 1);
+ moveTo(188, 179);
+ playSound(7, 16);
+ playAnimation(519);
+ moveTo(168, 179);
+ inventory->add(3);
+ }
+ return true;
+
+ case 0x5d88:
+ if (CHECK_FLAG(0xDBA5, 1)) { //dry laundry
+ SET_FLAG(0xDBA5, 2);
+ Dialog::show(scene, 0x1F4F);
+ playAnimation(604, 1);
+
+ loadScene(21, scene->getPosition());
+ setOns(0, 0);
+ disableObject(4);
+ enableObject(12);
+ playSound(46);
+ playAnimation(606, 1);
+ loadScene(23, scene->getPosition());
+ playAnimation(605, 1);
+ Dialog::show(scene, 0x2002);
+ } else {
+ uint16 d = Dialog::pop(scene, 0xdada);
+ if (d == 0x1913)
+ displayMessage(0x34d5); //+orientation = 3
+ }
+ return true;
+
+ case 0x5ff3: //get duster
+ if (CHECK_FLAG(0xDB9A, 0)) {
+ Dialog::pop(scene, 0xdaf6);
+ } else {
+ Dialog::show(scene, 0x1e1e);
+ inventory->add(12);
+ disableObject(12);
+ setOns(0, 0);
+ playSound(5);
+ playAnimation(541);
+ }
+ return true;
+
+ case 0x646e:
+ case 0x6475:
+ Dialog::show(scene, 0x32C1);
+ return true;
+
+ case 0x6507:
+ if (CHECK_FLAG(0xDB96, 1)) {
+ rejectMessage();
+ } else
+ displayMessage(0x47e7);
+ return true;
+
+ case 0x65c3:
+ if (CHECK_FLAG(0xDBA9, 1)) {
+ playAnimation(635);
+ setOns(5, 0);
+ playSound(63);
+ playAnimation(636);
+ inventory->add(47);
+ inventory->add(48);
+ displayMessage(0x3b83);
+ SET_FLAG(0xDBA9, 2);
+ SET_FLAG(0xDBA8, 0);
+ } else
+ displayMessage(0x4808);
+ return true;
+
+ case 0x7866:
+ if (CHECK_FLAG(0xdbdd, 3)) {
+ displayMessage(0x55ff);
+ return true;
+ } else
+ return false;
+
+ case 0x7878: {
+ byte v = res->dseg.get_byte(0xDBDB) + 1;
+ if (v <= 6)
+ SET_FLAG(0xDBDB, v);
+
+ switch(v) {
+ case 1:
+ displayMessage(0x5411);
+ return true;
+ case 2:
+ displayMessage(0x5463);
+ return true;
+ case 3:
+ displayMessage(0x5475);
+ return true;
+ case 4:
+ displayMessage(0x5484);
+ return true;
+ case 5:
+ displayMessage(0x54c4);
+ return true;
+ default:
+ displayMessage(0x54d5);
+ return true;
+ }
+ }
+
+ case 0x78a9:
+ if (CHECK_FLAG(0xDBE6, 1)) {
+ displayMessage(0x5827);
+ return true;
+ } else
+ return false;
+
+ case 0x78bb:
+ if (CHECK_FLAG(0xDBE8, 1)) {
+ displayMessage(0x58b0);
+ return true;
+ } else
+ return false;
+
+ //case 0x78f5: //trunk description
+ // if (CHECK_FLAG(0xDB95, 1)) {
+ // displayMessage(0x3e75);
+ // }
+ // return;
+
+ case 0x78ce:
+ if (!CHECK_FLAG(0xDBA1, 1)) {
+ displayMessage(0x3694);
+ return true;
+ } else
+ return false;
+
+ case 0x792b: //left click on ann
+ moveTo(245, 198, 1);
+ if (CHECK_FLAG(0xDBAF, 1))
+ return false;
+
+ Dialog::show(scene, 0x2193);
+ SET_FLAG(0xDBAF, 1);
+ return true;
+
+ case 0x7b26: //cutting the fence
+ setOns(0, 0);
+ playSound(5, 2);
+ playAnimation(837);
+ playSound(51, 3);
+ playAnimation(838);
+ setOns(0, 0x60);
+ moveTo(281, scene->getPosition().y, true);
+ disableObject(4);
+ SET_FLAG(0xDBE1, 1);
+ return true;
+
+ case 0x7b89: //digging mysterious object
+ if (CHECK_FLAG(0xDBE1, 1)) {
+ playAnimation(844);
+ setOns(1, 0);
+ playSound(5, 5);
+ playAnimation(847);
+ playSound(5, 11);
+ playAnimation(848);
+ setOns(1, 0x64);
+ playAnimation(845);
+ disableObject(3);
+ inventory->add(0x52);
+ inventory->remove(0x51);
+ } else
+ displayMessage(0x56da);
+ return true;
+
+ case 0x7bfd:
+ playSound(76, 18);
+ playAnimation(873);
+ moveTo(240, 163);
+ displayMessage(0x5837);
+ playSound(77, 2);
+ setLan(1, 0);
+ playAnimation(874, 1);
+ setOns(0, 0x68);
+ inventory->remove(0x5b);
+ enableObject(6);
+ disableObject(1);
+ return true;
+
+ case 0x7ce5: //put spring on the solid ground
+ playSound(5, 2);
+ playAnimation(840);
+ setOns(1, 0x61);
+ inventory->remove(0x50);
+ disableObject(2);
+ enableObject(7);
+ return true;
+
+ case 0x7d1a: //captain's key + door
+ if (res->dseg.get_byte(0xDBDF) <= 1) {
+ playSound(5, 2);
+ playAnimation(828);
+ moveTo(262, 160, true);
+ disableObject(4);
+ disableObject(3);
+ setOns(0, 0);
+ setOns(1, 85);
+ setOns(2, 0);
+ setOns(3, 0);
+ loadScene(5, scene->getPosition());
+ setOns(0, 92);
+ playAnimation(829, 1);
+ setOns(0, 0);
+ Dialog::show(scene, 0x63a5, 830);
+ loadScene(7, 130, 195);
+ playMusic(4);
+ setLan(1, 1);
+
+ Dialog::show(scene, 0x6406, 832);
+
+ //playAnimation(831, 1);
+
+ SET_FLAG(0xDBDF, 2);
+
+ } else
+ displayMessage(0x52f6);
+ return true;
+
+ case 0x7e02: //tickling the captain
+ if (CHECK_FLAG(0xdbe0, 1)) {
+ displayMessage(0x5632);
+ } else {
+ playSound(5, 6);
+ playAnimation(834, 0, true);
+ playAnimation(835, 1, true);
+ waitAnimation();
+
+ setOns(0, 94);
+ Dialog::show(scene, 0x65e9, 832);
+ enableObject(12);
+ SET_FLAG(0xdbe0, 1);
+ }
+ return true;
+
+ case 0x7e4f: //giving magazine to captain
+ playSound(5, 3);
+ Dialog::show(scene, 0x66c0);
+ playAnimation(852, 0, true);
+ playAnimation(853, 0, true);
+ displayMessage(0x5742);
+ displayMessage(0x5757);
+ displayMessage(0x5770);
+ displayMessage(0x5782);
+ displayMessage(0x5799);
+ playAnimation(856, 1);
+ playSound(5, 3);
+ //playAnimation(854);
+ Dialog::show(scene, 0x66fe);
+ playAnimation(855, 1);
+ moveTo(30, 181);
+ disableObject(1);
+ setLan(1, 0);
+ SET_FLAG(0xDBDF, 3);
+ SET_FLAG(0xDBF0, 1);
+ loadScene(8, 155, 199);
+ return true;
+
+ case 0x7fbd: //using bird & bartender
+ playSound(5, 3);
+ playAnimation(876);
+ setOns(1, 0);
+ playAnimation(877, 2);
+ playAnimation(880, 2, true);
+
+ Dialog::show(scene, 0x6f0e, 857);
+ setOns(2, 0x6a);
+ reloadLan();
+ playAnimation(878, 1);
+ playAnimation(879, 1);
+ inventory->remove(0x5c);
+ enableObject(1);
+ SET_FLAG(0xDBE7, 1);
+ return true;
+
+ case 0x8047:
+ playSound(32, 5);
+ playAnimation(881);
+ setOns(2, 0x6b);
+ inventory->remove(0x56);
+ inventory->add(0x55);
+ SET_FLAG(0xDBE8, 1);
+ return true;
+
+ case 0x808b:
+ if (CHECK_FLAG(0xDBDA, 1)) {
+ //alredy shown
+ displayMessage(0x53F2);
+ } else {
+ playSound(5);
+ displayMessage(0x53DD);
+ playAnimation(810, false);
+ Dialog::show(scene, 0x60BF);
+ SET_FLAG(0xDBDA, 1);
+ }
+ return true;
+
+ case 0x80c3: //show kaleydoscope to the guard
+ Dialog::show(scene, 0x6811, 809);
+ playSound(5, 3);
+ playAnimation(849, 0, true);
+ playAnimation(851, 1, true);
+ waitAnimation();
+
+ playAnimation(850, 1);
+ reloadLan();
+ inventory->add(0x53);
+ inventory->remove(0x52);
+ enableObject(1);
+ SET_FLAG(0xDBE2, 1);
+ return true;
+
+ //Shore
+
+ case 0x4d56:
+ inventory->add(16);
+ disableObject(2);
+ setOns(0, 0);
+ playSound(5);
+ playAnimation(547);
+ return true;
+
+
+ case 0x4eb9://Pick up wrapper
+ inventory->add(0x12);
+ setOns(1, 0);
+ playAnimation(549);
+ disableObject(13);
+ return true;
+
+ case 0x5348:
+ if (CHECK_FLAG(0xdb99, 1)) { //got broken paddle from boat
+ displayMessage(0x351f);
+ } else {
+ SET_FLAG(0xDB99, 1);
+ playSound(57, 6);
+ playAnimation(536);
+ Dialog::show(scene, 0x30c3);
+ inventory->add(0x8);
+ }
+ return true;
+
+ case 0x53a1:
+ if (CHECK_FLAG(0xdbb2, 1)) { //spoken to man in well
+ displayMessage(0x411d);
+ } else {
+ SET_FLAG(0xDBB2, 1);
+ displayMessage(0x408a);
+ displayMessage(0x4091);
+ displayMessage(0x4098);
+ displayMessage(0x40a7);
+ displayMessage(0x40b6);
+ displayMessage(0x40ce);
+ displayMessage(0x40e8);
+ displayMessage(0x410f);
+ }
+ return true;
+
+
+ case 0x5458: {
+ setOns(2, 0);
+ playSound(34);
+ playAnimation(535);
+ inventory->add(11);
+ disableObject(1);
+
+ byte * scene_15_ons = scene->getOns(15); //patch ons for the scene 15
+ scene_15_ons[0] = 0;
+
+ byte f = GET_FLAG(0xDB98) + 1;
+ SET_FLAG(0xDB98, f);
+ if (f >= 2) {
+ //disable object boat for scene 15!!
+ scene->getObject(1, 15)->enabled = 0;
+ }
+ }
+ return true;
+
+ case 0x54b3: {
+ setOns(1, 0);
+ setOns(3, 0);
+ playSound(33);
+ playAnimation(534);
+ inventory->add(10);
+ disableObject(2);
+ setOns(1, 10);
+
+ byte * scene_15_ons = scene->getOns(15); //patch ons for the scene 15
+ scene_15_ons[1] = 0;
+ byte f = GET_FLAG(0xDB98) + 1;
+ SET_FLAG(0xDB98, f);
+ if (f >= 2) {
+ //disable object boat for scene 15!!
+ scene->getObject(1, 15)->enabled = 0;
+ }
+ }
+ return true;
+
+ case 0x5502:
+ setOns(0, 0);
+ loadScene(15, 115, 180, 1);
+ playAnimation(568);
+ playMusic(6);
+ return true;
+
+ case 0x5561://Enter lakeside house
+ moveTo(81, 101);
+ loadScene(19, 223, 193);
+ return true;
+
+ case 0x563b:
+ playSound(5);
+ playAnimation(561);
+ setOns(1, 0);
+ inventory->add(26);
+ disableObject(6);
+ return true;
+
+ case 0x5756://Open car door
+ playSound(11, 4);
+ playAnimation(514);
+ setOns(4, 8);
+ setOns(2, 5);
+ enableObject(14);
+ enableObject(15);
+ enableObject(16);
+ disableObject(1);
+ return true;
+
+ case 0x5805://Enter basketball house
+ playSound(70, 6);
+ moveTo(161, 165);
+ playAnimation(513);
+ loadScene(22, 51, 180);
+ return true;
+
+ case 0x5832://Ring doorbell
+ playAnimation(509);
+ displayMessage(0x5dce);
+ return true;
+
+ case 0x58a2:
+ Dialog::pop(scene, 0xdaba);
+ strcpy(scene->getObject(13)->name, (const char *)res->dseg.ptr(0x92e5));
+ return true;
+
+ case 0x58b7://Get comb from car
+ disableObject(14);
+ setOns(4,0);
+ playSound(5, 7);
+ playAnimation(521);
+ setOns(4, 0);
+ inventory->add(0x6);
+ return true;
+
+ case 0x58df://Pull trunk lever in car
+ SET_FLAG(0xDB94, 1);
+ playSound(6, 1);
+ setOns(3, 6);
+ playAnimation(515);
+ return true;
+
+ case 0x593e://Enter annes house
+ moveTo(100, 176);
+ //Need to add support for the choice of music
+ //After speaking with anne the default room song changes
+ loadScene(23, 94, 190);
+ if (CHECK_FLAG(0xdbee, 1)) {//spoken with anne
+ //playMusic(6);//Play lovers music
+ //i've added music changing right into scene.
+ }
+ return true;
+
+ case 0x5994:
+ processCallback(0x599b);
+ processCallback(0x5a21);
+ return true;
+
+ case 0x599b:
+ return true;
+
+ case 0x5a21:
+ loadScene(24, 230, 170, 1);
+ playSound(52, 3);
+ playAnimation(601);
+ moveTo(230, 179, 3);
+ if (!CHECK_FLAG(0xDBA4, 1))
+ displayMessage(0x37ea); //it's kinda dark here
+ return true;
+
+ case 0x5a8b:
+ if (!CHECK_FLAG(0xDBAD, 1)) {
+ playSound(43, 4); //grrrrrr
+ setLan(1, 0);
+ playAnimation(656, 1);
+ setLan(1, 0xff);
+ displayMessage(0x3c16);
+ } else if (!CHECK_FLAG(0xDBA3, 1)) {//Dog has bone
+ playSound(28, 3);
+ playAnimation(596);
+ setOns(1, 30);
+ //loadScene(24, 100, 100);//TODO: Extend and fix the coords
+ SET_FLAG(0xDBA3, 1);
+ enableObject(8);
+ } else {
+ setOns(1, 0);
+ playSound(4, 4);
+ playAnimation(597);
+ SET_FLAG(0xDBA3, 0);
+ disableObject(8);
+ displayMessage(0x37b8);
+ setOns(1, 32, 24);
+ enableObject(4, 24);
+ }
+ return true;
+
+ case 0x5b3a://Click on dog
+ Dialog::pop(scene, 0xDB14);
+ return true;
+
+ case 0x5be1://Talk to grandpa
+ Dialog::pop(scene, 0xDAC4);
+ return true;
+
+ case 0x5c0d: //grandpa - drawers
+ if (CHECK_FLAG(0xDBA7, 1)) {
+ displayMessage(0x3bac);
+ } else {
+ if (!CHECK_FLAG(0xDB92, 1))
+ Dialog::show(scene, 0x15a0); //can I search your drawers?
+
+ playSound(66);
+ playAnimation(631);
+ inventory->add(47);
+ SET_FLAG(0xDBA7, 1);
+ }
+ return true;
+
+ case 0x5c84:
+ if (CHECK_FLAG(0xDB92, 1)) {
+ inventory->add(2);
+ disableObject(7);
+ playSound(32);
+ setOns(0, 0);
+ playAnimation(520);
+ } else {
+ Dialog::pop(scene, 0xDACE);
+ }
+ return true;
+
+ case 0x5cf0://Exit basketball house
+ playSound(88, 5);
+ playAnimation(981);
+ loadScene(20, 161, 165);
+ return true;
+
+ case 0x5d24: //getting the fan
+ if (CHECK_FLAG(0xDB92, 1)) {
+ setLan(2, 0);
+ playSound(32);
+ playAnimation(508);
+ disableObject(13);
+ inventory->add(7);
+ } else {
+ Dialog::pop(scene, 0xDAD4);
+ }
+ return true;
+
+ case 0x5e4d: //right click on ann
+ if (!CHECK_FLAG(0xDB97, 0)) {
+ displayMessage(0x3d59);
+ } else {
+ moveTo(245, 198, 1);
+ Dialog::show(scene, 0x21d7);
+ SET_FLAG(0xDB97, 1);
+ playSound(13);
+ playAnimation(528, 1);
+ playMusic(7);
+ SET_FLAG(0xDBEE, 1);
+ playSound(56);
+ playAnimation(525);
+ playSound(56);
+ playAnimation(526);
+ playSound(54);
+ playAnimation(527);
+ Dialog::show(scene, 0x2219);
+ strcpy(scene->getObject(2)->name, (const char *)res->dseg.ptr(0x9820));
+ }
+ return true;
+
+ case 0x5f73://Exit annes house
+ //Need to fully understand what this does, there is a compare in the asm
+ //I assume it is probably to do with the music
+ loadScene(21, 161, 165);
+
+ return true;
+
+ case 0x5fba:
+ if (CHECK_FLAG(0xDBB1, 1)) {
+ displayMessage(0x4380);
+ } else {
+ Dialog::pop(scene, 0xDAFC);
+ }
+ return true;
+
+ case 0x6480: //flips
+ if (CHECK_FLAG(0xDB96, 1)) {
+ setOns(3, 36);
+ playSound(56);
+ playAnimation(613);
+ inventory->add(39);
+ disableObject(5);
+ displayMessage(0x387c);
+ } else
+ displayMessage(0x3eb2);
+ return true;
+
+ case 0x64c4: //mask (maybe flips) :)
+ if (CHECK_FLAG(0xDB96, 1)) {
+ setOns(2, 35);
+ playSound(63);
+ playAnimation(612);
+ inventory->add(40);
+ disableObject(6);
+ } else
+ displayMessage(0x3eb2);
+ return true;
+
+ case 0x78f5://Describe trunk
+ if (CHECK_FLAG(0xdb95, 1)) {//trunk closed
+ displayMessage(0x3e75);
+ return true;
+ }
+ else {
+ displayMessage(0x9080);
+ return true;
+ }
+
+ case 0x7907://Describe car lever
+ if (CHECK_FLAG(0xdb94, 1)) {//Already pulled lever?
+ displayMessage(0x3e4f);
+ return true;
+ } else
+ return false;
+
+ case 0x612b://climb basement ladder(exit)
+ playSound(52, 10);
+ playAnimation(600);
+ loadScene(21, 297, 178, 3);
+ return true;
+
+ case 0x6351:
+ if (CHECK_FLAG(0xdaca, 1)) { //cave bush is cut down
+ playMusic(8);
+ loadScene(26, 319, 169);
+ return true;
+ } else {
+ displayMessage(0x3bd2);
+ return true;
+ }
+
+ case 0x6592: //Rake
+ setOns(1, 0);
+ playSound(18, 10);
+ playAnimation(553);
+ inventory->add(0x15);
+ displayMessage(0x3605);
+ disableObject(11);
+ return true;
+
+ case 0x62d0://Get bone from under rock
+ playSound(26, 6);
+ setOns(0, 0);
+ playAnimation(594);
+ setOns(0, 29);
+ displayMessage(0x463c);
+ disableObject(1);
+ inventory->add(36);
+ playSound(5, 3);
+ playAnimation(595);
+ displayMessage(0x3790);
+ return true;
+
+ case 0x6411://Kick hen
+ if (CHECK_FLAG(0xdb93, 1)) { //already kicked hen
+ displayMessage(0x3e08);
+ return true;
+ } else {
+ SET_FLAG(0xdb93, 1);
+ playSound(30, 26);
+ displayMessage(0x3dc6);
+ playAnimation(500, 0, true);
+ playAnimation(501, 1, true);
+ waitAnimation();
+ setOns(0, 1);
+ enableObject(14);
+ displayMessage(0x3df4);
+ return true;
+ }
+
+ case 0x6519://Sickle
+ setOns(4, 0);
+ playSound(5, 11);
+ playAnimation(625);
+ inventory->add(0x2c);
+ disableObject(8);
+ return true;
+
+ case 0x655b://Get needle from haystack
+ if (CHECK_FLAG(0xdabb, 1)) { //already have needle
+ displayMessage(0x356a);
+ return true;
+ } else {
+ SET_FLAG(0xdabb, 1);
+ playSound(49, 3);
+ playAnimation(548);
+ inventory->add(0x11);
+ displayMessage(0x35b2);
+ return true;
+ }
+
+ case 0x663c://Feather
+ setOns(0, 0);
+ playSound(5, 9);
+ playAnimation(511);
+ inventory->add(1);
+ disableObject(15);
+ return true;
+
+ case 0x7f23://Use grenade on captains drawer
+ if (CHECK_FLAG(0xDBDF, 3)) {
+ playSound(5, 3);
+ playAnimation(870);
+ playSound(54, 15);
+ playAnimation(871);
+ SET_FLAG(0xDBE6, 1);
+ setOns(1, 0x66);
+ moveTo(224, 194, true);
+ debug(0, "FIXME: add cut message: 57DF");
+ inventory->remove(0x59);
+ } else {
+ displayMessage(0x5de2);
+ }
+ return true;
+
+ case 0x509a:
+ moveTo(203, 169);
+ setOns(1, 0);
+ playSound(5);
+ playAnimation(543);
+ inventory->add(15);
+ disableObject(9);
+ return true;
+
+ case 0x78e0:
+ moveTo(203, 169);
+ return false;
+
+ case 0x7919:
+ if (!CHECK_FLAG(0xDBA5, 1))
+ return false;
+ displayMessage(0x3E98);
+ return true;
+
+ case 0x7950:
+ if (!CHECK_FLAG(0xDBB1, 1))
+ return false;
+
+ displayMessage(0x3DAF);
+ return true;
+
+ case 0x8174:
+ setOns(0, 0);
+ playSound(5);
+ playAnimation(542);
+ setOns(1, 15);
+ disableObject(3);
+ enableObject(9);
+ return true;
+
+ case 0x8312: //hedgehog + plastic apple
+ playSound(5);
+ Dialog::show(scene, 0x3000);
+ setLan(1, 0);
+ playAnimation(562);
+ playAnimation(563, 1);
+ disableObject(6);
+ displayMessage(0x363f);
+ inventory->remove(27);
+ inventory->add(28);
+ return true;
+
+ case 0x84c7:
+ playSound(20);
+ playAnimation(530);
+ loadScene(16, 236, 95, 1);
+ setOns(0, 9);
+ playAnimation(531);
+ playSound(36);
+ playAnimation(532);
+ playAnimation(533);
+ playMusic(9);
+ return true;
+
+ case 0x8538://Sharpen sickle on well
+ setOns(2, 0);
+ //TODO: Remove handle sprite
+ playAnimation(643);
+ inventory->remove(0x2c);
+ inventory->add(0x2e);
+ return true;
+
+ case 0x85eb:
+ if (CHECK_FLAG(0xDBB0, 1)) {
+ enableObject(6);
+ playSound(25);
+ playAnimation(559);
+ setOns(1, 23);
+ SET_FLAG(0xDBB0, 2);
+ } else
+ displayMessage(0x3d86);
+
+ return true;
+
+ case 0x863d:
+ playSound(12);
+ playAnimation(554);
+ inventory->remove(19);
+ inventory->add(22);
+ return true;
+
+ case 0x8665:
+ playSound(5);
+ playAnimation(567);
+ inventory->remove(12);
+ inventory->add(33);
+ return true;
+
+ case 0x86a9: //correcting height of the pole with spanner
+ if (CHECK_FLAG(0xDB92, 1)) {
+ displayMessage(0x3d40);
+ } else {
+ SET_FLAG(0xDB92, 1);
+ Dialog::show(scene, 0x0fcd);
+ playSound(5);
+ playAnimation(506, 1);
+ playAnimation(504);
+ setOns(0, 0);
+ playSound(24);
+ playAnimation(505);
+ displayMessage(0x3cfb);
+ playAnimation(507, 1);
+ setOns(0, 4);
+ Object * obj = scene->getObject(3);
+ obj->rect.top += 20;
+ obj->rect.bottom += 20;
+ playSound(10);
+ playAnimation(503, 1);
+ setLan(1, 0, 22);
+ scene->getObject(1, 22)->enabled = 0;
+ scene->getObject(13, 20)->enabled = 0;
+ setLan(1, 0);
+ disableObject(1);
+ disableObject(2);
+ disableObject(14);
+ disableObject(15);
+ disableObject(16);
+ moveTo(162, 164);
+ displayMessage(0x3d01, 0xe5);
+ displayMessage(0x3d20, 0xd8);
+ moveTo(162, 191);
+ setOns(1, 0);
+ setOns(2, 0);
+ setOns(3, 0);
+ setOns(4, 0);
+ scene->getWalkbox(0)->rect.clear();
+ playSound(62);
+ //patch lan, 1
+ displayMessage(0x3d3a);
+ scene->getObject(7)->actor_rect.left = 228;
+ scene->getObject(7)->actor_rect.top = 171;
+ scene->getObject(8)->actor_rect.left = 290;
+ scene->getObject(8)->actor_rect.top = 171;
+ }
+ return true;
+
+ case 0x88c9: //give flower to old lady
+ if (CHECK_FLAG(0xDB9A, 1))
+ return processCallback(0x890b);
+
+ playAnimation(523, 1);
+ inventory->remove(10);
+ SET_FLAG(0xDB9A, 1);
+ processCallback(0x88DE);
+ return true;
+
+ case 0x890b:
+ Dialog::pop(scene, 0xDAF0);
+ return true;
+
+ case 0x8918://give flower to old lady
+ if (CHECK_FLAG(0xDB9A, 1))
+ return processCallback(0x890B);
+
+ playAnimation(523, 1);
+ inventory->remove(11);
+ SET_FLAG(0xDB9A, 1);
+ processCallback(0x88DE);
+ return true;
+
+ case 0x88de:
+ playSound(5);
+ Dialog::show(scene, 0x1B5F);
+ playAnimation(537);
+ playAnimation(538, 1);
+ Dialog::show(scene, 0x1BE0);
+ return true;
+
+ case 0x892d:
+ if (CHECK_FLAG(0xDB9B, 1))
+ return processCallback(0x89aa);
+
+ processCallback(0x8942);
+ inventory->remove(10);
+ SET_FLAG(0xDB9B, 1);
+ return true;
+
+ case 0x8942:
+ playSound(5);
+ Dialog::show(scene, 0x2293);
+ playAnimation(540);
+ playAnimation(539, 1);
+ Dialog::show(scene, 0x24b1);
+ Dialog::show(scene, 0x24d7);
+ Dialog::show(scene, 0x2514);
+ moveTo(scene->getPosition().x, scene->getPosition().y + 1);
+ Dialog::show(scene, 0x2570);
+ return true;
+
+ case 0x89aa:
+ Dialog::pop(scene, 0xdb02);
+ return true;
+
+ case 0x89b7:
+ if (CHECK_FLAG(0xDB9B, 1))
+ return processCallback(0x89aa);
+
+ processCallback(0x8942);
+ inventory->remove(11);
+ SET_FLAG(0xDB9B, 1);
+ return true;
+
+ case 0x89cc:
+ inventory->remove(23);
+ playSound(5);
+ Dialog::show(scene, 0x2634);
+ playAnimation(555);
+ playAnimation(556, 1);
+ playAnimation(557);
+ playAnimation(558, 1);
+ Dialog::show(scene, 0x2971);
+ inventory->add(24);
+ return true;
+
+ case 0x8a22:
+ playAnimation(560);
+ playSound(45);
+ inventory->remove(26);
+ inventory->add(27);
+ Dialog::show(scene, 0x1ecd);
+ Dialog::show(scene, 0x1f09);
+ SET_FLAG(0xDBB1, 1);
+ return true;
+
+ case 0x8b82: //use fan on laundry
+ setOns(0, 0);
+ playSound(5);
+ playAnimation(602);
+ displayMessage(0x464a);
+ playAnimation(603);
+ setOns(0, 27);
+ SET_FLAG(0xDBA5, 1);
+ return true;
+
+ case 0x8bfc://Give bone to dog
+ displayMessage(0x3c31);
+ playSound(5, 3);
+ playAnimation(657, 0, true);
+ playAnimation(658, 1, true);
+ waitAnimation();
+
+ playAnimation(659, 1);
+
+ displayMessage(0x3c3d);
+ inventory->remove(36);
+ SET_FLAG(0xDBAD, 1);
+ //TODO:Adjust Walkboxes
+ return true;
+
+ case 0x8c6e://Use car jack on rock
+ playSound(5, 3);
+ playAnimation(592);
+ playSound(1, 5);
+ playAnimation(593);
+ setOns(0, 28);
+ disableObject(35);
+ enableObject(1);
+ inventory->remove(35);
+ return true;
+
+ case 0x8cc8://Cut bush with sickle
+ moveTo(Common::Point(234, 152));
+ setOns(1, 45);
+ playAnimation(645);
+ playAnimation(646);
+ playAnimation(647);
+ SET_FLAG(0xdaca, 1);
+ inventory->remove(0x2e);
+ disableObject(2);
+ return true;
+
+ case 0x8f1d:
+ Dialog::show(scene, 0x2dd6);
+ displayMessage(0x34c7);
+ setLan(3, 0);
+ setLan(4, 0);
+ playSound(56);
+ playAnimation(516);
+ playAnimation(517, 2);
+ playAnimation(518, 3);
+ disableObject(2);
+ disableObject(3);
+ inventory->remove(2);
+ SET_FLAG(0xDB96, 1);
+ return true;
+
+ case 0x9054: //mouse hole
+ if (CHECK_FLAG(0xDBAB, 1)) {
+ displayMessage(0x3c0b);
+ } else {
+ playSound(5);
+ moveTo(99, scene->getPosition().y);
+ playAnimation(632);
+ setOns(5, 40);
+ moveTo(239, 139, true);
+ playAnimation(633);
+ SET_FLAG(0xDBA8, 1);
+ inventory->remove(47);
+ if (!CHECK_FLAG(0xDBAA, 1)) {
+ SET_FLAG(0xDBAA, 1);
+ displayMessage(0x3b8b);
+ }
+ }
+ return true;
+
+ case 0x98fa://Right click to open toolbox
+ inventory->remove(3);
+ inventory->add(4);
+ inventory->add(35);
+ inventory->activate(false);
+ inventory->resetSelectedObject();
+ displayMessage(0x3468);
+ return true;
+
+ case 0x9910:
+ inventory->remove(4);
+ inventory->add(5);
+ inventory->activate(false);
+ inventory->resetSelectedObject();
+ displayMessage(0x3490);
+ return true;
+
+
+ //very last part of the game:
+
+
+ case 0x6be1: //handle to the bathroom
+ if (!CHECK_FLAG(0xDBD9, 1)) {
+ displayMessage(0x5326); //i'd better catch johnny
+ } else {
+ playSound(88);
+ playAnimation(808);
+ loadScene(36, 41, 195);
+ }
+ return true;
+
+ case 0x6bad:
+ playAnimation(971);
+ loadScene(32, 139, 199);
+ return true;
+
+ case 0x9c79:
+ if (scene->getId() != 36) {
+ displayMessage(0x52a9);
+ } else if (CHECK_FLAG(0xDBF1, 1)) {
+ displayMessage(0x52F6);
+ } else {
+ SET_FLAG(0xDBF1, 1);
+ moveTo(102, 195);
+ playAnimation(794);
+ //scene->getWalkbox(0)->rect.left = 0;
+ //scene->getWalkbox(0)->rect.top = 0;
+ moveTo(151, 197);
+ playAnimation(795);
+ moveTo(186, 198, true);
+ moveTo(220, 198);
+ scene->getWalkbox(0)->rect.top = 200;
+
+ Object * obj = scene->getObject(1);
+ obj->actor_rect.left = obj->actor_rect.right = 270;
+ obj->actor_rect.top = obj->actor_rect.bottom = 193;
+ obj->actor_orientation = 2;
+
+ obj = scene->getObject(3);
+ obj->actor_rect.left = obj->actor_rect.right = 254;
+ obj->actor_rect.top = obj->actor_rect.bottom = 193;
+ obj->actor_orientation = 1;
+ SET_FLAG(0xDBD7, 1);
+ }
+ return true;
+
+ case 0x66b5:
+ playAnimation(969);
+ playSound(89);
+ loadScene(33, 319, 181);
+ return true;
+ }
+
+ //unimplemented callback :(
+ for(uint i = 0; i < 32; ++i) {
+ debug(0, "code[%u] = %02x ", i, code[i]);
+ }
+ //error("invalid callback %04x called", addr);
+ debug(0, "invalid callback %04x called", addr);
+ return true;
+}
diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp
new file mode 100644
index 0000000000..7519448e6e
--- /dev/null
+++ b/engines/teenagent/detection.cpp
@@ -0,0 +1,150 @@
+/* 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: https://www.switchlink.se/svn/teen/detection.cpp $
+ * $Id: detection.cpp 215 2009-08-14 07:11:27Z megath $
+ */
+
+
+#include "engines/advancedDetector.h"
+#include "base/plugins.h"
+#include "teenagent/teenagent.h"
+#include "common/system.h"
+#include "common/savefile.h"
+
+static const PlainGameDescriptor teenAgentGames[] = {
+ { "teenagent", "Teen agent" },
+ { 0, 0 }
+};
+
+
+static const ADGameDescription teenAgentGameDescriptions[] = {
+ {
+ "teenagent",
+ "",
+ AD_ENTRY1s("teenagnt.exe", "b886cae8f875ea5eaefed04a8cc3c8a1", 152690),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ ADGF_NO_FLAGS,
+ Common::GUIO_NONE
+ },
+ AD_TABLE_END_MARKER
+};
+
+static const ADParams detectionParams = {
+ (const byte *)teenAgentGameDescriptions,
+ sizeof(ADGameDescription),
+ 512,
+ teenAgentGames,
+ 0,
+ "teenagent",
+ 0,
+ 0,
+ Common::GUIO_NONE
+};
+
+#define MAX_SAVES 20
+
+class TeenAgentMetaEngine : public AdvancedMetaEngine {
+public:
+ TeenAgentMetaEngine() : AdvancedMetaEngine(detectionParams) {
+ }
+
+ virtual const char *getName() const {
+ return "Teen Agent Engine";
+ }
+
+ virtual const char *getOriginalCopyright() const {
+ return "TEENAGENT demo and TEENAGENT name copyright (c) Metropolis 1994.";
+ }
+
+ virtual bool hasFeature(MetaEngineFeature f) const {
+ switch (f) {
+ case kSupportsListSaves:
+ case kSupportsDeleteSave:
+ case kSupportsLoadingDuringStartup:
+ //case kSavesSupportThumbnail:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+ if (desc) {
+ *engine = new TeenAgent::TeenAgentEngine(syst);
+ }
+ return desc != 0;
+ }
+
+// virtual const ADGameDescription *fallbackDetect(const Common::FSList &fslist) const {
+// return 0;
+// }
+
+ static Common::String generateGameStateFileName(const char *target, int slot) {
+ char slotStr[16];
+ snprintf(slotStr, sizeof(slotStr), ".%d", slot);
+ return slotStr;
+ }
+
+ virtual SaveStateList listSaves(const char *target) const {
+ Common::String pattern = target;
+ pattern += ".*";
+
+ Common::StringList filenames = g_system->getSavefileManager()->listSavefiles(pattern);
+ bool slotsTable[MAX_SAVES];
+ memset(slotsTable, 0, sizeof(slotsTable));
+ SaveStateList saveList;
+ for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
+ int slot;
+ const char *ext = strrchr(file->c_str(), '.');
+ if (ext && (slot = atoi(ext + 1)) >= 0 && slot < MAX_SAVES) {
+ Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(*file);
+ if (in) {
+ slotsTable[slot] = true;
+ delete in;
+ }
+ }
+ }
+ for (int slot = 0; slot < MAX_SAVES; ++slot) {
+ if (slotsTable[slot]) {
+ char description[64];
+ snprintf(description, sizeof(description), "teenagent.%02d", slot);
+ saveList.push_back(SaveStateDescriptor(slot, description));
+ }
+ }
+ return saveList;
+ }
+
+ virtual int getMaximumSaveSlot() const {
+ return MAX_SAVES - 1;
+ }
+
+ virtual void removeSaveState(const char *target, int slot) const {
+ Common::String filename = generateGameStateFileName(target, slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
+ }
+};
+
+#if PLUGIN_ENABLED_DYNAMIC(TEENAGENT)
+ REGISTER_PLUGIN_DYNAMIC(TEENAGENT, PLUGIN_TYPE_ENGINE, TeenAgentMetaEngine);
+#else
+ REGISTER_PLUGIN_STATIC(TEENAGENT, PLUGIN_TYPE_ENGINE, TeenAgentMetaEngine);
+#endif
diff --git a/engines/teenagent/dialog.cpp b/engines/teenagent/dialog.cpp
new file mode 100644
index 0000000000..1ecffeefa0
--- /dev/null
+++ b/engines/teenagent/dialog.cpp
@@ -0,0 +1,106 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#include "dialog.h"
+#include "resources.h"
+#include "scene.h"
+
+using namespace TeenAgent;
+
+void Dialog::show(Scene * scene, uint16 addr, uint16 animation) {
+ debug(0, "Dialog::show(%04x, %u)", addr, animation);
+ Resources * res = Resources::instance();
+ int n = 0;
+ Common::String message;
+ byte color = 0xd1;
+
+ while (n < 4) {
+ byte c = res->eseg.get_byte(addr++);
+ switch(c) {
+ case 0:
+ ++n;
+ if (n == 3) {
+ color = color == 0xd1? 0xd0: 0xd1;
+ //debug(0, "changing color", message);
+ }
+ continue;
+ case 0xff:
+ {
+ SceneEvent e(SceneEvent::WaitForAnimation);
+ scene->push(e);
+ }
+ ++n;
+ continue;
+ default:
+ if (n > 1) {
+ if (!message.empty()) {
+ if (animation != 0) {
+ SceneEvent e(SceneEvent::PlayAnimation);
+ e.animation = animation;
+ e.color = 0x83; //3rd slot, async animation
+ scene->push(e);
+ }
+ SceneEvent e(SceneEvent::Message);
+ e.message = message;
+ e.color = color;
+ scene->push(e);
+ }
+ message = (const char *)Resources::instance()->eseg.ptr(addr - 1);
+ } else if (n == 1) {
+ message += '\n';
+ message += (const char *)Resources::instance()->eseg.ptr(addr - 1);
+ } else if (n == 0 && message.empty()) {
+ message = (const char *)Resources::instance()->eseg.ptr(addr - 1);
+ }
+ n = 0;
+ }
+ }
+ if (!message.empty()) {
+ if (animation != 0) {
+ SceneEvent e(SceneEvent::PlayAnimation);
+ e.animation = animation;
+ e.color = 0x83; //3rd slot, async animation
+ scene->push(e);
+ } //copy paste ninja was here
+ SceneEvent e(SceneEvent::Message);
+ e.message = message;
+ e.color = color;
+ scene->push(e);
+ }
+}
+
+uint16 Dialog::pop(Scene *scene, uint16 addr, uint16 animation) {
+ debug(0, "Dialog::pop(%04x, %u)", addr, animation);
+ Resources * res = Resources::instance();
+ uint16 next;
+ do {
+ next = res->dseg.get_word(addr);
+ addr += 2;
+ } while(next == 0);
+ uint16 next2 = res->dseg.get_word(addr);
+ if (next2 != 0xffff)
+ res->dseg.set_word(addr - 2, 0);
+ show(scene, next, animation);
+ return next;
+}
diff --git a/engines/teenagent/dialog.h b/engines/teenagent/dialog.h
new file mode 100644
index 0000000000..7bac3a0d4f
--- /dev/null
+++ b/engines/teenagent/dialog.h
@@ -0,0 +1,42 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#ifndef TEENAGENT_DIALOG_H__
+#define TEENAGENT_DIALOG_H__
+
+#include "common/endian.h"
+#include "common/str.h"
+
+namespace TeenAgent {
+
+class Scene;
+class Dialog {
+public:
+ static uint16 pop(Scene *scene, uint16 addr, uint16 animation = 0);
+ static void show(Scene *scene, uint16 addr, uint16 animation = 0);
+};
+}
+
+#endif
+
diff --git a/engines/teenagent/font.cpp b/engines/teenagent/font.cpp
new file mode 100644
index 0000000000..b0527011f3
--- /dev/null
+++ b/engines/teenagent/font.cpp
@@ -0,0 +1,142 @@
+/* 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: https://www.switchlink.se/svn/teen/font.cpp $
+ * $Id: font.cpp 242 2009-08-15 11:44:27Z megath $
+ */
+
+
+#include "font.h"
+#include "resources.h"
+
+using namespace TeenAgent;
+
+Font::Font() : grid_color(0xd0), color(0xd1), data(0) {
+}
+
+void Font::load(int id) {
+ delete[] data;
+ data = NULL;
+
+ Common::SeekableReadStream * s = Resources::instance()->varia.getStream(id);
+ if (s == NULL)
+ error("loading font %d failed", id);
+
+ data = new byte[s->size()];
+ s->read(data, s->size());
+ debug(0, "font size: %d", s->size());
+}
+
+uint Font::render(Graphics::Surface *surface, int x, int y, char c) {
+ unsigned idx = (unsigned char)c;
+ if (idx < 0x20 || idx >= 0x81) {
+ debug(0, "unhandled char 0x%02x", idx);
+ return 0;
+ }
+ idx -= 0x20;
+ byte * glyph = data + READ_LE_UINT16(data + idx * 2);
+
+ uint h = glyph[0], w = glyph[1];
+ if (surface == NULL || surface->pixels == NULL)
+ return w;
+
+ //debug(0, "char %c, width: %dx%d", c, w, h);
+ glyph += 2;
+ byte * dst = (byte *)surface->getBasePtr(x, y);
+ for(uint i = 0; i < h; ++i) {
+ for(uint j = 0; j < w; ++j) {
+ byte v = *glyph++;
+ switch(v) {
+ case 1:
+ dst[j] = 0;
+ break;
+ case 2:
+ dst[j] = color;
+ break;
+ }
+ }
+ dst += surface->pitch;
+ }
+ return w - 1;
+}
+
+static uint find_in_str(const Common::String &str, char c, uint pos = 0) {
+ while(pos < str.size() && str[pos] != c) ++pos;
+ return pos;
+}
+
+uint Font::render(Graphics::Surface *surface, int x, int y, const Common::String &str, bool show_grid) {
+ const int height = 10;
+ if (surface != NULL) {
+ uint max_w = render(NULL, 0, 0, str, false);
+ if (show_grid)
+ grid(surface, x - 4, y - 2, max_w + 8, 8 + 6, grid_color);
+
+ uint i = 0, j;
+ do {
+ j = find_in_str(str, '\n', i);
+ Common::String line(str.c_str() + i, j - i);
+ //debug(0, "line: %s", line.c_str());
+
+ uint w = render(NULL, 0, 0, line, false);
+ int xp = x + (max_w - w) / 2;
+ for (uint k = 0; k < line.size(); ++k) {
+ xp += render(surface, xp, y, line[k]);
+ }
+
+ y += height;
+ i = j + 1;
+ } while(i < str.size());
+ return max_w;
+ } else {
+ //surface == NULL;
+ uint w = 0, max_w = 0;
+ for (uint i = 0; i < str.size(); ++i) {
+ char c = str[i];
+ if (c == '\n') {
+ y += height;
+ if (w > max_w)
+ max_w = w;
+ w = 0;
+ continue;
+ }
+ w += render(NULL, 0, 0, c);
+ }
+ if (w > max_w)
+ max_w = w;
+
+ return max_w;
+ }
+}
+
+void Font::grid(Graphics::Surface *surface, int x, int y, int w, int h, byte color) {
+ byte * dst = (byte *)surface->getBasePtr(x, y);
+ for(int i = 0; i < h; ++i) {
+ for(int j = 0; j < w; ++j) {
+ if (((i ^ j) & 1) == 0)
+ dst[j] = color;
+ }
+ dst += surface->pitch;
+ }
+}
+
+Font::~Font() {
+ delete[] data;
+}
diff --git a/engines/teenagent/font.h b/engines/teenagent/font.h
new file mode 100644
index 0000000000..1012a1cf33
--- /dev/null
+++ b/engines/teenagent/font.h
@@ -0,0 +1,48 @@
+/* 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: https://www.switchlink.se/svn/teen/font.h $
+ * $Id: font.h 173 2009-08-11 08:10:22Z megath $
+ */
+
+#ifndef TEENAGENT_FONT_H__
+#define TEENAGENT_FONT_H__
+
+#include "graphics/surface.h"
+
+namespace TeenAgent {
+class Font {
+public:
+ byte grid_color, color;
+
+ Font();
+ void load(int id);
+ uint render(Graphics::Surface *surface, int x, int y, const Common::String &str, bool grid = false);
+ uint render(Graphics::Surface *surface, int x, int y, char c);
+ static void grid(Graphics::Surface *surface, int x, int y, int w, int h, byte color);
+
+ ~Font();
+private:
+ byte *data;
+};
+}
+
+#endif
+
diff --git a/engines/teenagent/inventory.cpp b/engines/teenagent/inventory.cpp
new file mode 100644
index 0000000000..6ee720d3f5
--- /dev/null
+++ b/engines/teenagent/inventory.cpp
@@ -0,0 +1,285 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#include "inventory.h"
+#include "resources.h"
+#include "common/stream.h"
+#include "objects.h"
+#include "teenagent.h"
+
+using namespace TeenAgent;
+
+void Inventory::init(TeenAgentEngine * engine) {
+ _engine = engine;
+ _active = false;
+ Resources * res = Resources::instance();
+
+ Common::SeekableReadStream * s = res->varia.getStream(3);
+ assert(s != NULL);
+ debug(0, "loading inventory background...");
+ background.load(s, Surface::TypeOns);
+
+ items = res->varia.getStream(4);
+ assert(items != NULL);
+
+ byte offsets = items->readByte();
+ assert(offsets == 92);
+ for(byte i = 0; i < offsets; ++i) {
+ offset[i] = items->readUint16LE();
+ }
+ objects = res->dseg.ptr(0xc4a4);
+ inventory = res->dseg.ptr(0xc48d);
+
+ for(int y = 0; y < 4; ++y)
+ for(int x = 0; x < 6; ++x) {
+ int i = y * 6 + x;
+ graphics[i].rect.left = 28 + 45 * x - 1;
+ graphics[i].rect.top = 23 + 31 * y - 1;
+ graphics[i].rect.right = graphics[i].rect.left + 40;
+ graphics[i].rect.bottom = graphics[i].rect.top + 26;
+ }
+
+ hovered_obj = selected_obj = NULL;
+}
+
+bool Inventory::has(byte item) const {
+ for(int i = 0; i < 24; ++i) {
+ if (inventory[i] == item)
+ return true;
+ }
+ return false;
+}
+
+void Inventory::remove(byte item) {
+ debug(0, "removing %02x from inventory", item);
+ int i;
+ for(i = 0; i < 24; ++i) {
+ if (inventory[i] == item) {
+ break;
+ }
+ }
+ for(; i < 23; ++i) {
+ inventory[i] = inventory[i + 1];
+ graphics[i].free();
+ }
+ inventory[23] = 0;
+ graphics[23].free();
+}
+
+void Inventory::clear() {
+ debug(0, "clearing inventory");
+ for(int i = 0; i < 24; ++i) {
+ inventory[i] = 0;
+ graphics[i].free();
+ }
+}
+
+
+void Inventory::add(byte item) {
+ if (has(item))
+ return;
+ debug(0, "adding %02x to inventory", item);
+ for(int i = 0; i < 24; ++i) {
+ if (inventory[i] == 0) {
+ inventory[i] = item;
+ return;
+ }
+ }
+ error("no room for item %02x", item);
+}
+
+bool Inventory::processEvent(const Common::Event &event) {
+ Resources * res = Resources::instance();
+
+ switch(event.type) {
+ case Common::EVENT_MOUSEMOVE:
+ mouse = event.mouse;
+ if (!active() && event.mouse.y < 5) {
+ activate(true);
+ return _active;
+ }
+
+ if (event.mouse.x < 17 || event.mouse.x >= 303 || event.mouse.y >= 153) {
+ activate(false);
+ return _active;
+ }
+
+ if (!_active)
+ return false;
+
+ hovered_obj = NULL;
+
+ for(int i = 0; i < 24; ++i) {
+ byte item = inventory[i];
+ if (item == 0)
+ continue;
+
+ graphics[i].hovered = graphics[i].rect.in(mouse);
+ if (graphics[i].hovered)
+ hovered_obj = (InventoryObject *)res->dseg.ptr(READ_LE_UINT16(objects + item * 2));
+ }
+ return true;
+
+ case Common::EVENT_LBUTTONDOWN: {
+ //check combine
+ if (selected_obj == NULL || hovered_obj == NULL)
+ return _active;
+
+ int id1 = selected_obj->id;
+ int id2 = hovered_obj->id;
+
+ debug(0, "combine(0x%02x, 0x%02x)!", id1, id2);
+ byte * table = res->dseg.ptr(0xC335);
+ while(table[0] != 0 && table[1] != 0) {
+ if (
+ (id1 == table[0] && id2 == table[1]) ||
+ (id2 == table[0] && id1 == table[1])
+ ) {
+ remove(id1);
+ remove(id2);
+ add(table[2]);
+ uint16 msg = READ_LE_UINT16(table + 3);
+ _engine->displayMessage(msg);
+ _engine->playSoundNow(69);
+ activate(false);
+ resetSelectedObject();
+ return true;
+ }
+ table += 5;
+ }
+ _engine->displayMessage(0xc3e2);
+ activate(false);
+ resetSelectedObject();
+ return true;
+ }
+
+ case Common::EVENT_RBUTTONDOWN:
+ if (!_active)
+ return false;
+
+ if (hovered_obj != NULL) {
+ byte id = hovered_obj->id;
+ debug(0, "rclick object %u", id);
+ uint i = 0;
+ for(byte * table = res->dseg.ptr(0xBB6F + 3); //original offset + 3 bytes.
+ table[0] != 0 && i < 7; table += 3, ++i) {
+ if (table[0] == id) {
+ resetSelectedObject();
+ activate(false);
+ if (_engine->processCallback(READ_LE_UINT16(table + 1)))
+ return true;
+ else {
+ //some callbacks returns false if they need to display default description
+ _engine->displayMessage(hovered_obj->description());
+ activate(false);
+ resetSelectedObject();
+ return true;
+ }
+ }
+ }
+ }
+
+ selected_obj = hovered_obj;
+ if (selected_obj)
+ debug(0, "selected object %s", selected_obj->name);
+ return true;
+
+ case Common::EVENT_KEYDOWN:
+ if (_active && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ activate(false);
+ return true;
+ }
+ return false;
+
+ case Common::EVENT_LBUTTONUP:
+ case Common::EVENT_RBUTTONUP:
+ return _active;
+
+ default:
+ return false;
+ }
+}
+
+
+void Inventory::Item::free() {
+ animation.free();
+ surface.free();
+}
+
+void Inventory::Item::render(Inventory * inventory, InventoryObject *obj, Graphics::Surface * dst) {
+ Resources * res = Resources::instance();
+
+ rect.render(dst, hovered? 233: 234);
+ if (obj->animated) {
+ if (animation.empty()) {
+ debug(0, "loading item %d from offset %x", obj->id, inventory->offset[obj->id - 1]);
+ inventory->items->seek(inventory->offset[obj->id - 1]);
+ animation.load(inventory->items, Animation::TypeInventory);
+ }
+ Surface * s = animation.currentFrame();
+ if (s != NULL)
+ s->render(dst, rect.left + 1, rect.top + 1);
+ } else {
+ if (surface.empty()) {
+ debug(0, "loading item %d from offset %x", obj->id, inventory->offset[obj->id - 1]);
+ inventory->items->seek(inventory->offset[obj->id - 1]);
+ surface.load(inventory->items, Surface::TypeOns);
+ }
+ surface.render(dst, rect.left + 1, rect.top + 1);
+ }
+
+ Common::String name;
+ if (inventory->selected_obj && inventory->selected_obj != inventory->hovered_obj) {
+ name = inventory->selected_obj->name;
+ name += " & ";
+ }
+ name += obj->name;
+
+ if (hovered) {
+ int w = res->font7.render(NULL, 0, 0, name, true);
+ res->font7.render(dst, (320 - w) / 2, 180, name, true);
+ }
+}
+
+void Inventory::render(Graphics::Surface * surface) {
+ if (!_active)
+ return;
+
+ background.render(surface);
+ Resources * res = Resources::instance();
+
+ for (int y = 0; y < 4; y++) {
+ for (int x = 0; x < 6; x++) {
+ int idx = x + 6 * y;
+ byte item = inventory[idx];
+ if (item == 0)
+ continue;
+
+ //debug(0, "%d,%d -> %u", x0, y0, item);
+
+ InventoryObject * obj = (InventoryObject *)res->dseg.ptr(READ_LE_UINT16(objects + item * 2));
+ graphics[idx].render(this, obj, surface);
+ }
+ }
+}
diff --git a/engines/teenagent/inventory.h b/engines/teenagent/inventory.h
new file mode 100644
index 0000000000..f2f8f94a52
--- /dev/null
+++ b/engines/teenagent/inventory.h
@@ -0,0 +1,84 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#ifndef TEENAGENT_INVENTORY_H__
+#define TEENAGENT_INVENTORY_H__
+
+#include "surface.h"
+#include "animation.h"
+#include "common/events.h"
+#include "objects.h"
+
+namespace TeenAgent {
+
+struct InventoryObject;
+class TeenAgentEngine;
+
+class Inventory {
+public:
+ void init(TeenAgentEngine * engine);
+ void render(Graphics::Surface * surface);
+
+ void clear();
+ void add(byte item);
+ bool has(byte item) const;
+ void remove(byte item);
+
+ void activate(bool a) { _active = a; }
+ bool active() const { return _active; }
+
+ bool processEvent(const Common::Event &event);
+
+ InventoryObject *selectedObject() { return selected_obj; }
+ void resetSelectedObject() { selected_obj = NULL; }
+
+private:
+ TeenAgentEngine *_engine;
+ Surface background;
+ Common::SeekableReadStream *items;
+ uint16 offset[92];
+
+ byte *objects;
+ byte *inventory;
+ struct Item {
+ Animation animation;
+ Surface surface;
+ Rect rect;
+ bool hovered;
+
+ Item() : hovered(false) {}
+ void free();
+ void render(Inventory *inventory, InventoryObject *obj, Graphics::Surface * surface);
+ } graphics[24];
+
+ bool _active;
+ Common::Point mouse;
+ int hovered;
+
+ InventoryObject *hovered_obj, *selected_obj;
+};
+}
+
+#endif
+
diff --git a/engines/teenagent/module.mk b/engines/teenagent/module.mk
new file mode 100644
index 0000000000..6432eba310
--- /dev/null
+++ b/engines/teenagent/module.mk
@@ -0,0 +1,26 @@
+MODULE := engines/teenagent
+
+MODULE_OBJS := \
+ detection.o \
+ teenagent.o \
+ resources.o \
+ pack.o \
+ segment.o \
+ scene.o \
+ animation.o \
+ font.o \
+ surface.o \
+ actor.o \
+ callbacks.o \
+ inventory.o \
+ objects.o \
+ music.o \
+ dialog.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_TEENAGENT), DYNAMIC_PLUGIN)
+ PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/teenagent/music.cpp b/engines/teenagent/music.cpp
new file mode 100644
index 0000000000..ba902e571a
--- /dev/null
+++ b/engines/teenagent/music.cpp
@@ -0,0 +1,162 @@
+/* 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: https://www.switchlink.se/svn/teen/old_engine/music.cpp $
+ * $Id: music.cpp 121 2009-08-02 20:04:53Z megath $
+ *
+ */
+
+#include "music.h"
+#include "resources.h"
+
+using namespace TeenAgent;
+
+static uint32 noteToPeriod[3][12] = {
+ {855, 807, 761, 720, 678, 640, 604, 569, 537, 508, 480, 453},
+ {428, 404, 381, 360, 338, 320, 301, 285, 269, 254, 239, 226},
+ {214, 201, 189, 179, 170, 160, 151, 143, 135, 127, 120, 113}
+};
+
+MusicPlayer::MusicPlayer() : Paula(false, 44100, 5000), _id(0) {
+}
+
+MusicPlayer::~MusicPlayer() {
+}
+
+bool MusicPlayer::load(int id) {
+ Resources * res = Resources::instance();
+
+ Common::SeekableReadStream *stream = res->mmm.getStream(id);
+ if (stream == NULL)
+ return false;
+
+ char header[4];
+ stream->read(header, 4);
+ //check header?
+
+ memset(_samples, 0, sizeof(_samples));
+
+ // Load the samples
+
+ sampleCount = stream->readByte();
+
+ debug(0, "sampleCount = %d", sampleCount);
+
+ for (byte currSample = 0; currSample < sampleCount; currSample++) {
+ byte sample = stream->readByte();
+
+ // Load the sample data
+ byte sampleResource = ((sample >> 4) & 0x0F) * 10 + (sample & 0x0F);
+ debug(0, "currSample = %d, sample = 0x%02x, resource: %d", currSample, sample, sampleResource);
+ uint32 sampleSize = res->sam_mmm.get_size(sampleResource);
+ Common::SeekableReadStream *in = res->sam_mmm.getStream(sampleResource);
+
+ if (in == 0) {
+ warning("load: invalid sample %d (0x%02x)", sample, sample);
+ _samples[sample].data = NULL;
+ _samples[sample].size = 0;
+ continue;
+ }
+
+ byte *sampleData = new byte[sampleSize];
+ in->read(sampleData, sampleSize);
+
+ // Convert the sample from signed to unsigned
+ for (uint32 i = 0; i < sampleSize; i++)
+ *sampleData ^= 0x80;
+
+ delete _samples[sample].data;
+ _samples[sample].data = sampleData;
+ _samples[sample].size = sampleSize;
+ }
+
+ // Load the music data
+
+ _rows.clear();
+
+ Row row;
+ row.channels[0].sample = 0;
+ row.channels[1].sample = 0;
+ row.channels[2].sample = 0;
+
+ row.channels[0].volume = 64;
+ row.channels[1].volume = 64;
+ row.channels[2].volume = 64;
+
+ while (!stream->eos()) {
+
+ byte cmd = stream->readByte();
+
+ if ((cmd & 0xF0) == 0x50) {
+ row.channels[(cmd & 0x0F) - 1].sample = stream->readByte();
+ } else if ((cmd & 0xF0) == 0x40) {
+ row.channels[(cmd & 0x0F) - 1].volume = (stream->readByte() + 1) * 2;
+ } else {
+ row.channels[0].note = cmd;
+ row.channels[1].note = stream->readByte();
+ row.channels[2].note = stream->readByte();
+ _rows.push_back(row);
+ }
+
+ }
+ _currRow = 0;
+ _id = id;
+ return true;
+}
+
+void MusicPlayer::start() {
+ _currRow = 0;
+ startPaula();
+}
+
+void MusicPlayer::stop() {
+ stopPaula();
+}
+
+void MusicPlayer::interrupt() {
+ _currRow %= _rows.size();
+
+ Row *row = &_rows[_currRow];
+ for (int chn = 0; chn < 3; ++chn) {
+ setChannelVolume(chn, row->channels[chn].volume);
+
+ //debug(0, "row->channels[%d].volume = %d", chn, row->channels[chn].volume);
+
+ byte sample = (row->channels[chn].sample);
+ if (row->channels[chn].note != 0 && sample != 0) {
+
+ //debug(0, "row->channels[%d].note = %d", chn, row->channels[chn].note);
+ //debug(0, "row->channels[%d].sample = %d", chn, row->channels[chn].sample);
+
+ byte note = row->channels[chn].note;
+ if (_samples[sample].size == 0) {
+ warning("interrupt: invalid sample %u (0x%02x)", sample, sample);
+ continue;
+ }
+
+ setChannelData(chn, (const int8*)_samples[sample].data, NULL, _samples[sample].size, 0);
+ setChannelPeriod(chn, noteToPeriod[((note >> 4) & 0x0F) - 1][(note & 0x0F)]);
+ }
+ }
+
+ //debug(0, "------------------------------------------------");
+
+ ++_currRow;
+}
diff --git a/engines/teenagent/music.h b/engines/teenagent/music.h
new file mode 100644
index 0000000000..b76891ae7c
--- /dev/null
+++ b/engines/teenagent/music.h
@@ -0,0 +1,77 @@
+/* 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: https://www.switchlink.se/svn/teen/old_engine/music.h $
+ * $Id: music.h 121 2009-08-02 20:04:53Z megath $
+ *
+ */
+
+#ifndef TEEN_MUSIC_H
+#define TEEN_MUSIC_H
+
+#include "sound/mods/paula.h"
+
+namespace TeenAgent {
+
+class MusicPlayer : public Audio::Paula {
+public:
+
+ MusicPlayer();
+ ~MusicPlayer();
+
+ bool load(int id);
+ int getId() const { return _id; }
+
+ void start();
+ void stop();
+
+protected:
+ int _id;
+
+ struct Row {
+ struct Channel{
+ byte sample;
+ byte volume;
+ byte note;
+ Channel(): sample(0), volume(0), note(0) {}
+ } channels[3];
+ };
+
+ struct {
+ const byte *data;
+ uint32 size;
+ } _samples[256];
+ byte sampleCount;
+
+ struct {
+ byte volume;
+ const byte *data;
+ uint32 size;
+ } _channels[3];
+
+ Common::Array<Row> _rows;
+ uint _currRow;
+
+ void interrupt();
+};
+
+} // End of namespace Teen
+
+#endif // TEEN_MUSIC_H
diff --git a/engines/teenagent/objects.cpp b/engines/teenagent/objects.cpp
new file mode 100644
index 0000000000..2bfe4bb5d9
--- /dev/null
+++ b/engines/teenagent/objects.cpp
@@ -0,0 +1,86 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 172 2009-08-11 08:06:58Z megath $
+ */
+
+#include "objects.h"
+#include "common/debug.h"
+
+using namespace TeenAgent;
+
+void Rect::render(Graphics::Surface *surface, uint8 color) const {
+ surface->hLine(left, bottom, right, color);
+ surface->vLine(left, bottom, top, color);
+ surface->hLine(left, top, right, color);
+ surface->vLine(right, bottom, top, color);
+}
+
+void Walkbox::dump() {
+ debug(0, "walkbox %02x %02x [%d, %d, %d, %d] %02x %02x %02x %02x ", unk00, unk01,
+ rect.left, rect.right, rect.top, rect.bottom,
+ unk0a, unk0b, unk0c, unk0d);
+}
+
+void Object::dump() {
+ debug(0, "object: %u %u [%u,%u,%u,%u], actor: [%u,%u,%u,%u], orientation: %u, name: %s", id, enabled,
+ rect.left, rect.top, rect.right, rect.bottom,
+ actor_rect.left, actor_rect.top, actor_rect.right, actor_rect.bottom,
+ actor_orientation, name
+ );
+}
+
+Common::String Object::description(const char *name) {
+ const char * desc = name + strlen(name) + 1;
+ if (*desc == 0)
+ return Common::String();
+
+ Common::String result;
+
+ while(*desc != 1 && *desc != 0) {
+ Common::String line;
+ while(*desc != 1 && *desc != 0) {
+ //debug(0, "%02x ", *desc);
+ line += *desc++;
+ }
+
+ if (line.empty())
+ break;
+
+ ++desc;
+ result += line;
+ result += '\n';
+ }
+ if (!result.empty())
+ result.deleteLastChar();
+ else
+ result = "Cool.";
+ return result;
+}
+
+
+Common::String Object::description() const {
+ return description(name);
+}
+
+Common::String InventoryObject::description() const {
+ return Object::description(name);
+}
diff --git a/engines/teenagent/objects.h b/engines/teenagent/objects.h
new file mode 100644
index 0000000000..04f1cd335c
--- /dev/null
+++ b/engines/teenagent/objects.h
@@ -0,0 +1,104 @@
+/* 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: https://www.switchlink.se/svn/teen/objects.h $
+ * $Id: objects.h 282 2009-08-30 22:12:01Z megath $
+ */
+
+
+#ifndef TEENAGENT_OBJECTS_H__
+#define TEENAGENT_OBJECTS_H__
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace TeenAgent {
+
+//move into separate header:
+
+#include "common/pack-start.h" // START STRUCT PACKING
+
+struct Rect {
+ uint16 left, top, right, bottom;
+ inline bool in(const Common::Point &point) const {
+ return point.x >= left && point.x <= right && point.y >= top && point.y <= bottom;
+ }
+ inline Common::Point center() const {
+ return Common::Point((right + left) / 2, (bottom + top) / 2);
+ }
+ inline bool valid() const {
+ return left < 320 && right < 320 && top < 200 && bottom < 200;
+ }
+ void render(Graphics::Surface *surface, uint8 color) const;
+ void dump() {
+ debug(0, "rect[%u, %u, %u, %u]", left, top, right, bottom);
+ }
+
+ void clear() {
+ left = top = right = bottom = 0;
+ }
+} PACKED_STRUCT;
+
+struct Object {
+ byte id;
+ Rect rect;
+ Rect actor_rect;
+ byte actor_orientation;
+ byte enabled;
+ char name[1];
+
+ enum {ActorUp = 1, ActorRight = 2, ActorDown = 3, ActorLeft = 4 };
+
+ void dump();
+ static Common::String description(const char *name);
+ Common::String description() const;
+} PACKED_STRUCT;
+
+struct InventoryObject {
+ byte id;
+ byte animated;
+ char name[1];
+ Common::String description() const;
+} PACKED_STRUCT;
+
+struct UseObject {
+ byte inventory_id;
+ byte object_id;
+ byte unk02;
+ uint16 x, y;
+ uint16 callback;
+} PACKED_STRUCT;
+
+struct Walkbox {
+ byte unk00;
+ byte unk01;
+ Rect rect;
+ byte unk0a;
+ byte unk0b;
+ byte unk0c;
+ byte unk0d;
+ void dump();
+} PACKED_STRUCT;
+
+#include "common/pack-end.h" // END STRUCT PACKING
+
+}
+
+#endif
diff --git a/engines/teenagent/pack.cpp b/engines/teenagent/pack.cpp
new file mode 100644
index 0000000000..a0d9bbd499
--- /dev/null
+++ b/engines/teenagent/pack.cpp
@@ -0,0 +1,83 @@
+/* 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: https://www.switchlink.se/svn/teen/pack.cpp $
+ * $Id: pack.cpp 182 2009-08-11 21:16:14Z megath $
+ */
+
+
+#include "pack.h"
+#include "common/util.h"
+#include "common/debug.h"
+
+using namespace TeenAgent;
+
+Pack::Pack() : count(0), offsets(0) {}
+
+Pack::~Pack() {
+ close();
+}
+
+
+void Pack::close() {
+ delete[] offsets;
+ offsets = NULL;
+ file.close();
+}
+
+
+void Pack::open(const Common::String &filename) {
+ file.open(filename);
+ count = file.readUint32LE();
+ debug(0, "opened %s, found %u entries", filename.c_str(), count);
+ offsets = new uint32[count + 1];
+ for(uint32 i = 0; i <= count; ++i) {
+ offsets[i] = file.readUint32LE();
+ //debug(0, "%d: %06x", i, offsets[i]);
+ }
+/* for(uint32 i = 0; i < count; ++i) {
+ debug(0, "%d: len = %d", i, offsets[i + 1] - offsets[i]);
+ }
+*/
+}
+
+uint32 Pack::get_size(uint32 id) const {
+ if (id < 1 || id > count)
+ return 0;
+ return offsets[id] - offsets[id - 1];
+}
+
+uint32 Pack::read(uint32 id, byte *dst, uint32 size) const {
+ if (id < 1 || id > count)
+ return 0;
+
+ file.seek(offsets[id - 1]);
+ uint32 rsize = offsets[id] - offsets[id - 1];
+ uint32 r = file.read(dst, MIN(rsize, size));
+ //debug(0, "read(%u, %u) = %u", id, size, r);
+ return r;
+}
+
+Common::SeekableReadStream * Pack::getStream(uint32 id) const {
+ if (id < 1 || id > count)
+ return 0;
+ debug(0, "stream: %04x-%04x", offsets[id - 1], offsets[id]);
+ return new Common::SeekableSubReadStream(&file, offsets[id - 1], offsets[id], false);
+}
diff --git a/engines/teenagent/pack.h b/engines/teenagent/pack.h
new file mode 100644
index 0000000000..5765151ac9
--- /dev/null
+++ b/engines/teenagent/pack.h
@@ -0,0 +1,49 @@
+/* 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: https://www.switchlink.se/svn/teen/pack.h $
+ * $Id: pack.h 182 2009-08-11 21:16:14Z megath $
+ */
+
+
+#ifndef TEENAGENT_PACK_H__
+#define TEENAGENT_PACK_H__
+
+#include "common/file.h"
+
+namespace TeenAgent {
+class Pack {
+ mutable Common::File file;
+ uint32 count;
+ uint32 *offsets;
+
+public:
+ Pack();
+ ~Pack();
+ void open(const Common::String &filename);
+ void close();
+ uint32 get_size(uint32 id) const;
+ uint32 read(uint32 id, byte *dst, uint32 size) const;
+ Common::SeekableReadStream * getStream(uint32 id) const;
+};
+
+}
+
+#endif
diff --git a/engines/teenagent/resources.cpp b/engines/teenagent/resources.cpp
new file mode 100644
index 0000000000..94a23d14a0
--- /dev/null
+++ b/engines/teenagent/resources.cpp
@@ -0,0 +1,144 @@
+/* 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: https://www.switchlink.se/svn/teen/resources.cpp $
+ * $Id: resources.cpp 274 2009-08-25 21:04:54Z megath $
+ */
+
+#include "resources.h"
+
+using namespace TeenAgent;
+
+Resources::Resources() {}
+
+Resources * Resources::instance() {
+ static Resources i;
+ return &i;
+}
+
+void Resources::deinit() {
+ varia.close();
+ off.close();
+ on.close();
+ ons.close();
+ lan000.close();
+ lan500.close();
+ mmm.close();
+ sam_mmm.close();
+ sam_sam.close();
+}
+
+void Resources::loadArchives() {
+ off.open("off.res");
+ varia.open("varia.res");
+ on.open("on.res");
+ ons.open("ons.res");
+ lan000.open("lan_000.res");
+ lan500.open("lan_500.res");
+ mmm.open("mmm.res");
+ sam_mmm.open("sam_mmm.res");
+ sam_sam.open("sam_sam.res");
+
+ font7.load(7);
+
+ Common::File exe;
+ if (!exe.open("Teenagnt.exe")) {
+ error("cannot open exe file");
+ return;
+ }
+ exe.seek(0x0200);
+ cseg.read(&exe, 0xb3b0); //code
+
+ exe.seek(0xb5b0);
+ dseg.read(&exe, 0xe790); //data
+
+ exe.seek(0x1c890);
+ eseg.read(&exe, 0x8be2);
+
+ exe.close();
+}
+
+void Resources::loadOff(Graphics::Surface &surface, byte * palette, int id) {
+ uint32 size = off.get_size(id);
+ if (size == 0) {
+ error("invalid background %d", id);
+ return;
+ }
+ byte buf[64768];
+ off.read(id, buf, sizeof(buf));
+
+ byte * src = buf;
+ byte * dst = (byte *)surface.pixels;
+ memcpy(dst, src, 64000);
+ memcpy(palette, buf + 64000, 768);
+}
+
+Common::SeekableReadStream * Resources::loadLan(uint32 id) const {
+ return id <= 500? loadLan000(id): lan500.getStream(id - 500);
+}
+
+Common::SeekableReadStream * Resources::loadLan000(uint32 id) const {
+ switch(id) {
+
+ case 81:
+ if (dseg.get_byte(0xDBAD))
+ return lan500.getStream(160);
+ break;
+
+ case 137:
+ if (dseg.get_byte(0xDBC5) == 1) {
+ if (dseg.get_byte(0xDBC6) == 1)
+ return lan500.getStream(203);
+ else
+ return lan500.getStream(202);
+ }
+ break;
+
+ case 25:
+ if (dseg.get_byte(0xDBDF) == 2) {
+ return lan500.getStream(332);
+ }
+ break;
+
+ case 37:
+ if (dseg.get_byte(0xdbe2) == 1) {
+ return lan500.getStream(351);
+ } else if (dseg.get_byte(0xdbe2) == 2) {
+ return lan500.getStream(364);
+ }
+ break;
+
+ case 29:
+ if (dseg.get_byte(0xDBE7) == 1) {
+ return lan500.getStream(380);
+ }
+
+ case 30:
+ if (dseg.get_byte(0xDBE7) == 1) {
+ return lan500.getStream(381);
+ }
+
+ case 42:
+ if (dseg.get_byte(0xDBEC) == 1) {
+ return lan500.getStream(400);
+ }
+ }
+ return lan000.getStream(id);
+}
diff --git a/engines/teenagent/resources.h b/engines/teenagent/resources.h
new file mode 100644
index 0000000000..d3fea56e95
--- /dev/null
+++ b/engines/teenagent/resources.h
@@ -0,0 +1,56 @@
+/* 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: https://www.switchlink.se/svn/teen/resources.h $
+ * $Id: resources.h 260 2009-08-19 07:29:19Z megath $
+ */
+
+
+#ifndef TEENAGENT_RESOURCES_H__
+#define TEENAGENT_RESOURCES_H__
+
+#include "pack.h"
+#include "segment.h"
+#include "font.h"
+#include "graphics/surface.h"
+
+namespace TeenAgent {
+
+class Resources {
+protected:
+ Resources();
+public:
+ static Resources * instance();
+ void loadArchives();
+ void deinit();
+ void loadOff(Graphics::Surface &surface, byte *palette, int id);
+ Common::SeekableReadStream * loadLan(uint32 id) const;
+ Common::SeekableReadStream * loadLan000(uint32 id) const;
+ //void loadOn(Graphics::Surface &surface, int id, uint16 &dst, uint16 * flags);
+ //void loadOns(Graphics::Surface &surface, int id, uint16 &dst);
+
+ Pack varia, off, on, ons, lan000, lan500, mmm, sam_mmm, sam_sam;
+ Segment cseg, dseg, eseg;
+ Font font7;
+};
+
+}
+
+#endif
diff --git a/engines/teenagent/scene.cpp b/engines/teenagent/scene.cpp
new file mode 100644
index 0000000000..8e39008e8e
--- /dev/null
+++ b/engines/teenagent/scene.cpp
@@ -0,0 +1,511 @@
+/* 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: https://www.switchlink.se/svn/teen/scene.cpp $
+ * $Id: scene.cpp 303 2009-09-03 20:09:57Z megath $
+ */
+
+
+#include "scene.h"
+#include "resources.h"
+#include "surface.h"
+#include "common/debug.h"
+#include "objects.h"
+#include "teenagent.h"
+#include "dialog.h"
+#include "music.h"
+
+using namespace TeenAgent;
+
+Scene::Scene() : _engine(NULL),
+ _system(NULL),
+ _id(0), ons(0), walkboxes(0),
+ orientation(Object::ActorRight),
+ current_event(SceneEvent::None),
+ sound_id(0), sound_delay(0) {}
+
+void Scene::warp(const Common::Point & _point, byte o) {
+ Common::Point point(_point);
+ destination = position = position0 = point;
+ progress = 0; progress_total = 1;
+ if (o)
+ orientation = o;
+}
+
+void Scene::moveTo(const Common::Point & _point, byte orient, bool validate) {
+ Common::Point point(_point);
+ debug(0, "moveTo(%d, %d, %u)", point.x, point.y, orient);
+ if (validate) {
+ for(byte i = 0; i < walkboxes; ++i) {
+ if (walkbox[i]->rect.in(point)) {
+ debug(0, "bumped into walkbox %u", i);
+ return;
+ }
+ }
+ }
+ if (point == position) {
+ if (orient != 0)
+ orientation = orient;
+ nextEvent();
+ return;
+ }
+ destination = point;
+ orientation = orient;
+ position0 = position;
+ progress_total = 1 + sqrt((float)position.sqrDist(destination)) / 10;
+ progress = 0;
+}
+
+
+void Scene::init(TeenAgentEngine *engine, OSystem * system) {
+ _engine = engine;
+ _system = system;
+
+ Resources * res = Resources::instance();
+ Common::SeekableReadStream * s = res->varia.getStream(1);
+ if (s == NULL)
+ error("invalid resource data");
+
+ teenagent.load(s, Animation::TypeVaria);
+
+ s = res->varia.getStream(2);
+ if (s == NULL)
+ error("invalid resource data");
+
+ teenagent_idle.load(s, Animation::TypeVaria);
+}
+
+byte *Scene::getOns(int id) {
+ Resources * res = Resources::instance();
+ return res->dseg.ptr(res->dseg.get_word(0xb4f5 + (id - 1) * 2));
+}
+
+byte * Scene::getLans(int id) {
+ Resources * res = Resources::instance();
+ return res->dseg.ptr(0xd89e + (id - 1) * 4);
+}
+
+void Scene::loadOns() {
+ debug(0, "loading ons animation");
+ Resources * res = Resources::instance();
+
+ uint16 addr = res->dseg.get_word(0xb4f5 + (_id - 1) * 2);
+ //debug(0, "ons index: %04x", addr);
+
+ ons_count = 0;
+ byte b;
+ byte on_id[16];
+ while((b = res->dseg.get_byte(addr)) != 0xff) {
+ debug(0, "on: %04x = %02x", addr, b);
+ ++addr;
+ if (b == 0)
+ continue;
+
+ on_id[ons_count++] = b;
+ }
+
+ delete[] ons;
+ ons = NULL;
+
+ if (ons_count > 0) {
+ ons = new Surface[ons_count];
+ for(uint32 i = 0; i < ons_count; ++i) {
+ Common::SeekableReadStream * s = res->ons.getStream(on_id[i]);
+ if (s != NULL)
+ ons[i].load(s, Surface::TypeOns);
+ }
+ }
+}
+
+void Scene::loadLans() {
+ debug(0, "loading lans animation");
+ Resources * res = Resources::instance();
+ //load lan000
+ byte * table_27 = res->dseg.ptr(0x32C7);
+ memset(table_27, 0, 27 * 4);
+
+ for (int i = 0; i < 4; ++i) {
+ animations[i].free();
+
+ uint16 bx = 0xd89e + (_id - 1) * 4 + i;
+ byte bxv = res->dseg.get_byte(bx);
+ debug(0, "lan: [%04x] = %02x", bx, bxv);
+ if (bxv == 0)
+ continue;
+
+ Common::SeekableReadStream * s = res->loadLan000(4 * (_id - 1) + i + 1);
+ if (s != NULL) {
+ animations[i].load(s, Animation::TypeLan);
+ if (bxv != 0 && bxv != 0xff)
+ animations[i].id = bxv;
+ delete s;
+ }
+
+ //uint16 bp = res->dseg.get_word();
+ }
+
+}
+
+void Scene::init(int id, const Common::Point &pos) {
+ debug(0, "init(%d)", id);
+ _id = id;
+
+ if (background.pixels == NULL)
+ background.create(320, 200, 1);
+
+ warp(pos);
+
+ Resources * res = Resources::instance();
+ res->loadOff(background, palette, id);
+ if (id == 24) {
+ //dark scene
+ if (res->dseg.get_byte(0xDBA4) != 1) {
+ //dim down palette
+ uint i;
+ for(i = 0; i < 624; ++i) {
+ palette[i] = palette[i] > 0x20? palette[i] - 0x20: 0;
+ }
+ for(i = 726; i < 768; ++i) {
+ palette[i] = palette[i] > 0x20? palette[i] - 0x20: 0;
+ }
+ }
+ }
+ setPalette(_system, palette, 4);
+
+ Common::SeekableReadStream *stream = res->on.getStream(id);
+ on.load(stream, Surface::TypeOn);
+ delete stream;
+
+ loadOns();
+ loadLans();
+
+ byte * walkboxes_base = res->dseg.ptr(READ_LE_UINT16(res->dseg.ptr(0x6746 + (id - 1) * 2)));
+ walkboxes = *walkboxes_base++;
+
+ debug(0, "found %d walkboxes", walkboxes);
+ for (byte i = 0; i < walkboxes; ++i) {
+ walkbox[i] = (Walkbox *)(walkboxes_base + 14 * i);
+ walkbox[i]->dump();
+ }
+
+ if (id == 23 && res->dseg.get_byte(0xdbee) == 1) {
+ //talked to anne, lovers music
+ if (_engine->music->getId() != 6)
+ _engine->music->load(6);
+ } else {
+ //check music
+ int now_playing = _engine->music->getId();
+
+ if (now_playing != res->dseg.get_byte(0xDB90))
+ _engine->music->load(res->dseg.get_byte(0xDB90));
+ }
+
+}
+
+void Scene::playAnimation(byte idx, uint id) {
+ assert(idx < 4);
+ Common::SeekableReadStream * s = Resources::instance()->loadLan(id + 1);
+ if (s == NULL)
+ error("playing animation %u failed", id);
+
+ custom_animations[idx].load(s);
+ custom_animations[idx].loop = idx == 3; //looping face animation.
+}
+
+void Scene::push(const SceneEvent &event) {
+ //debug(0, "push");
+ //event.dump();
+ events.push_back(event);
+}
+
+bool Scene::processEvent(const Common::Event &event) {
+ if (!message.empty()) {
+ if (
+ event.type == Common::EVENT_LBUTTONDOWN ||
+ event.type == Common::EVENT_RBUTTONDOWN
+ ) {
+ message.clear();
+ custom_animations[3].free();
+ nextEvent();
+ return true;
+ }
+ }
+ return false;
+}
+
+bool Scene::render(OSystem * system) {
+ //render background
+ bool busy = false;
+
+ system->copyRectToScreen((const byte *)background.pixels, background.pitch, 0, 0, background.w, background.h);
+
+ Graphics::Surface * surface = system->lockScreen();
+
+ if (ons != NULL) {
+ for(uint32 i = 0; i < ons_count; ++i) {
+ Surface* s = ons + i;
+ if (s != NULL)
+ s->render(surface);
+ }
+ }
+
+ for(int i = 3; i >= 0; --i) {
+ Animation &a = animations[i];
+ Surface *s = a.currentFrame();
+ if (s == NULL)
+ continue;
+
+ s->render(surface);
+
+ if (a.id == 0)
+ continue;
+
+ Object * obj = getObject(a.id);
+ if (obj != NULL) {
+ obj->rect.left = s->x;
+ obj->rect.top = s->y;
+ obj->rect.right = s->w + s->x;
+ obj->rect.bottom = s->h + s->y;
+ //obj->dump();
+ }
+ }
+
+ //render on
+ if (on.pixels != NULL) {
+ on.render(surface);
+ }
+
+ bool hide_actor = false;
+ bool got_any_animation = false;
+
+ for(int i = 3; i >= 0; --i) {
+ Animation &a = custom_animations[i];
+ Surface *s = a.currentFrame();
+ if (s == NULL) {
+ if (!a.empty() && current_event.type == SceneEvent::PlayAnimation) {
+ debug(0, "animation %u stopped", current_event.animation);
+ a.free();
+ nextEvent();
+ i = -1;
+ }
+ continue;
+ }
+
+ s->render(surface);
+ if (i == 0) {
+ //debug(0, "animation active @%u,%u, hiding actor", s->x, s->y);
+ hide_actor = true;
+ }
+ busy = true;
+ got_any_animation = true;
+ }
+
+ if (current_event.type == SceneEvent::WaitForAnimation && !got_any_animation) {
+ nextEvent();
+ }
+
+ if (destination != position) {
+ Common::Point dp(destination.x - position0.x, destination.y - position0.y);
+ int o;
+ if (ABS(dp.x) > ABS(dp.y))
+ o = dp.x > 0? Object::ActorRight: Object::ActorLeft;
+ else
+ o = dp.y > 0? Object::ActorDown: Object::ActorUp;
+
+ position.x = position0.x + dp.x * progress / progress_total;
+ position.y = position0.y + dp.y * progress / progress_total;
+ teenagent.render(surface, position, o, 1);
+ ++progress;
+ if (progress >= progress_total) {
+ position = destination;
+ if (orientation == 0)
+ orientation = o; //save last orientation
+ nextEvent();
+ } else
+ busy = true;
+ } else if (!hide_actor) {
+ teenagent.render(surface, position, orientation, 0);
+ }
+
+ busy |= processEventQueue();
+ //if (!current_event.empty())
+ // current_event.dump();
+
+ for (byte i = 0; i < walkboxes; ++i) {
+ Walkbox * w = walkbox[i];
+ w->rect.render(surface, 0xd0 + i);
+ }
+
+ if (!message.empty()) {
+ Resources::instance()->font7.render(surface, message_pos.x, message_pos.y, message);
+ busy = true;
+ }
+
+ system->unlockScreen();
+
+
+ if (sound_id != 0 && sound_delay != 0) {
+ if (--sound_delay == 0) {
+ debug(0, "delayed sound %u started", sound_id);
+ _engine->playSoundNow(sound_id);
+ sound_id = 0;
+ }
+ }
+
+ return busy;
+}
+
+bool Scene::processEventQueue() {
+ while (!events.empty() && current_event.empty()) {
+ //debug(0, "processing next event");
+ current_event = events.front();
+ events.pop_front();
+ switch(current_event.type) {
+
+ case SceneEvent::SetOn: {
+ byte * ptr = getOns(current_event.scene == 0? _id: current_event.scene);
+ debug(0, "on[%u] = %02x", current_event.ons - 1, current_event.color);
+ ptr[current_event.ons - 1] = current_event.color;
+ loadOns();
+ current_event.clear();
+ } break;
+
+ case SceneEvent::SetLan: {
+ if (current_event.lan != 0) {
+ debug(0, "lan[%u] = %02x", current_event.lan - 1, current_event.color);
+ byte * ptr = getLans(current_event.scene == 0? _id: current_event.scene);
+ ptr[current_event.lan - 1] = current_event.color;
+ }
+ loadLans();
+ current_event.clear();
+ } break;
+
+ case SceneEvent::LoadScene: {
+ init(current_event.scene, current_event.dst);
+ current_event.clear();
+ } break;
+
+ case SceneEvent::Walk: {
+ if (current_event.color != 0) {
+ warp(current_event.dst, current_event.orientation);
+ current_event.clear();
+ } else
+ moveTo(current_event.dst, current_event.orientation);
+ } break;
+
+ case SceneEvent::Message: {
+ //debug(0, "pop(%04x)", current_event.message);
+ message = current_event.message;
+ message_pos = messagePosition(message, position);
+ } break;
+
+ case SceneEvent::PlayAnimation: {
+ debug(0, "playing animation %u", current_event.animation);
+ playAnimation(current_event.color & 0x7f /*slot actually :)*/, current_event.animation);
+ if (current_event.color & 0x80)
+ nextEvent();
+ } break;
+
+ case SceneEvent::PlayMusic: {
+ debug(0, "setting music %u", current_event.music);
+ _engine->setMusic(current_event.music);
+ Resources::instance()->dseg.set_byte(0xDB90, current_event.music);
+ current_event.clear();
+ } break;
+
+ case SceneEvent::PlaySound: {
+ debug(0, "playing sound %u, delay: %u", current_event.sound, current_event.color);
+ if (current_event.color == 0) {
+ _engine->playSoundNow(current_event.sound);
+ } else {
+ sound_id = current_event.sound;
+ sound_delay = current_event.color;
+ }
+
+ current_event.clear();
+ } break;
+
+ case SceneEvent::EnableObject: {
+ debug(0, "%s object #%u", current_event.color?"enabling":"disabling", current_event.object - 1);
+ Object * obj = getObject(current_event.object - 1, current_event.scene == 0? _id: current_event.scene);
+ obj->enabled = current_event.color;
+ current_event.clear();
+ } break;
+
+ case SceneEvent::WaitForAnimation:
+ debug(0, "waiting for the animation");
+ break;
+
+ default:
+ error("empty/unhandler event[%d]", (int)current_event.type);
+ }
+ }
+ return !current_event.empty();
+}
+
+void Scene::setPalette(OSystem *system, const byte * buf, unsigned mul) {
+ byte p[1024];
+
+ memset(p, 0, 1024);
+ for(int i = 0; i < 256; ++i) {
+ for(int c = 0; c < 3; ++c)
+ p[i * 4 + c] = buf[i * 3 + c] * mul;
+ }
+
+ system->setPalette(p, 0, 256);
+}
+
+Object * Scene::getObject(int id, int scene_id) {
+ if (scene_id == 0)
+ scene_id = _id;
+
+ Resources * res = Resources::instance();
+ uint16 addr = res->dseg.get_word(0x7254 + (scene_id - 1) * 2);
+ //debug(0, "object base: %04x, x: %d, %d", addr, point.x, point.y);
+ uint16 object = res->dseg.get_word(addr + 2 * id - 2);
+
+ Object *obj = (Object *)res->dseg.ptr(object);
+ return obj;
+}
+
+Common::Point Scene::messagePosition(const Common::String &str, const Common::Point & position) {
+ Resources * res = Resources::instance();
+ uint w = res->font7.render(NULL, 0, 0, str);
+ Common::Point message_pos = position;
+ message_pos.x -= w / 2;
+ message_pos.y -= 62;
+ if (message_pos.x + w > 320)
+ message_pos.x = 320 - w;
+ if (message_pos.x < 0)
+ message_pos.x = 0;
+
+ return message_pos;
+}
+
+void Scene::displayMessage(const Common::String &str) {
+ debug(0, "displayMessage: %s", str.c_str());
+ message = str;
+ message_pos = messagePosition(str, position);
+}
+
+void Scene::clear() {
+ events.clear();
+ current_event.clear();
+}
diff --git a/engines/teenagent/scene.h b/engines/teenagent/scene.h
new file mode 100644
index 0000000000..88427f33d8
--- /dev/null
+++ b/engines/teenagent/scene.h
@@ -0,0 +1,166 @@
+/* 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: https://www.switchlink.se/svn/teen/scene.h $
+ * $Id: scene.h 296 2009-09-01 19:55:58Z megath $
+ */
+
+
+#ifndef TEENAGENT_SCENE_H__
+#define TEENAGENT_SCENE_H__
+
+#include "surface.h"
+#include "actor.h"
+#include "common/system.h"
+#include "common/list.h"
+
+namespace TeenAgent {
+
+struct Walkbox;
+struct Object;
+
+class TeenAgentEngine;
+class Dialog;
+
+struct SceneEvent {
+ enum Type {
+ None, Message, Walk, PlayAnimation,
+ LoadScene, SetOn, SetLan, PlayMusic,
+ PlaySound, EnableObject, WaitForAnimation
+ } type;
+
+ Common::String message;
+ byte color;
+ uint16 animation;
+ byte orientation;
+ Common::Point dst;
+ byte scene; //fixme: put some of these to the union?
+ byte ons;
+ byte lan;
+ byte music;
+ byte sound;
+ byte object;
+
+ SceneEvent(Type type_) :
+ type(type_), message(), color(0xd1), animation(0), orientation(0), dst(),
+ scene(0), ons(0), lan(0), music(0), sound(0), object(0) {}
+
+ void clear() {
+ type = None;
+ message.clear();
+ color = 0xd1;
+ orientation = 0;
+ animation = 0;
+ dst.x = dst.y = 0;
+ scene = 0;
+ ons = 0;
+ lan = 0;
+ music = 0;
+ sound = 0;
+ object = 0;
+ }
+
+ inline bool empty() const {
+ return type == None;
+ }
+
+ void dump() const {
+ debug(0, "event[%d]: %s[%02x], animation: %u, dst: (%d, %d) [%u], scene: %u, ons: %u, lan: %u, object: %u, music: %u, sound: %u",
+ (int)type, message.c_str(), color, animation, dst.x, dst.y, orientation, scene, ons, lan, object, music, sound
+ );
+ }
+};
+
+class Scene {
+public:
+ Scene();
+
+ void init(TeenAgentEngine *engine, OSystem * system);
+ void init(int id, const Common::Point &pos);
+ bool render(OSystem * system);
+ int getId() const { return _id; }
+
+ void warp(const Common::Point & point, byte orientation = 0);
+
+ void moveTo(const Common::Point & point, byte orientation = 0, bool validate = 0);
+ Common::Point getPosition() const { return position; }
+
+ void displayMessage(const Common::String &str);
+ void setOrientation(uint8 o) { orientation = o; }
+ void playAnimation(byte idx, uint id);
+ void push(const SceneEvent &event);
+
+ bool processEvent(const Common::Event &event);
+
+ void clear();
+
+ byte * getOns(int id);
+ byte * getLans(int id);
+
+ bool eventRunning() const { return !current_event.empty(); }
+
+ Walkbox *getWalkbox(byte id) { return walkbox[id]; }
+ Object * getObject(int id, int scene_id = 0);
+
+private:
+ void loadOns();
+ void loadLans();
+
+ byte palette[768];
+ void setPalette(OSystem *system, const byte * palette, unsigned mul = 1);
+ static Common::Point messagePosition(const Common::String &str, const Common::Point & position);
+
+ bool processEventQueue();
+ inline void nextEvent() {
+ current_event.clear();
+ processEventQueue();
+ }
+
+ TeenAgentEngine *_engine;
+ OSystem * _system;
+
+ int _id;
+ Graphics::Surface background;
+ Surface on;
+ Surface *ons;
+ uint32 ons_count;
+ Animation animations[4], custom_animations[4];
+
+ Actor teenagent, teenagent_idle;
+ Common::Point position0, position, destination;
+ int progress, progress_total;
+ uint8 orientation;
+
+ byte walkboxes;
+ Walkbox * walkbox[255];
+
+ Common::String message;
+ Common::Point message_pos;
+
+ typedef Common::List<SceneEvent> EventList;
+ EventList events;
+ SceneEvent current_event;
+
+ byte sound_id, sound_delay;
+};
+}
+
+#endif
+
diff --git a/engines/teenagent/segment.cpp b/engines/teenagent/segment.cpp
new file mode 100644
index 0000000000..f6b029ae34
--- /dev/null
+++ b/engines/teenagent/segment.cpp
@@ -0,0 +1,37 @@
+/* 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: https://www.switchlink.se/svn/teen/segment.cpp $
+ * $Id: segment.cpp 188 2009-08-12 07:22:11Z megath $
+ */
+
+
+#include "segment.h"
+
+void Segment::read(Common::ReadStream *stream, uint32 s) {
+ _size = s;
+ _data = new byte[_size];
+ stream->read(_data, _size);
+}
+
+Segment::~Segment() {
+ delete[] _data;
+}
+
diff --git a/engines/teenagent/segment.h b/engines/teenagent/segment.h
new file mode 100644
index 0000000000..42b6cc0df9
--- /dev/null
+++ b/engines/teenagent/segment.h
@@ -0,0 +1,80 @@
+/* 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: https://www.switchlink.se/svn/teen/segment.h $
+ * $Id: segment.h 188 2009-08-12 07:22:11Z megath $
+ */
+
+
+#ifndef TEENAGENT_SEGMENT_H__
+#define TEENAGENT_SEGMENT_H__
+
+#include "common/stream.h"
+#include "common/endian.h"
+
+class Segment {
+ uint32 _size;
+ byte * _data;
+
+public:
+ Segment() : _size(0), _data(0) {}
+ ~Segment();
+
+ void read(Common::ReadStream *s, uint32 _size);
+
+ inline byte get_byte(uint32 offset) const {
+ assert(offset < _size);
+ return _data[offset];
+ }
+ inline uint16 get_word(uint32 offset) const {
+ assert(offset + 1 < _size);
+ return READ_LE_UINT16(_data + offset);
+ }
+ inline uint32 get_quad(uint32 offset) const {
+ assert(offset + 3 < _size);
+ return READ_LE_UINT32(_data + offset);
+ }
+ inline void set_byte(uint32 offset, byte v) const {
+ assert(offset < _size);
+ _data[offset] = v;
+ }
+ inline void set_word(uint32 offset, uint16 v) const {
+ assert(offset + 1 < _size);
+ return WRITE_LE_UINT16(_data + offset, v);
+ }
+ inline void set_quad(uint32 offset, uint32 v) const {
+ assert(offset + 3 < _size);
+ return WRITE_LE_UINT32(_data + offset, v);
+ }
+
+ const byte * ptr(uint32 addr) const {
+ assert(addr < _size);
+ return _data + addr;
+ }
+
+ byte * ptr(uint32 addr) {
+ assert(addr < _size);
+ return _data + addr;
+ }
+ uint size() const { return _size; }
+};
+
+#endif
+
diff --git a/engines/teenagent/surface.cpp b/engines/teenagent/surface.cpp
new file mode 100644
index 0000000000..154bbdb049
--- /dev/null
+++ b/engines/teenagent/surface.cpp
@@ -0,0 +1,95 @@
+/* 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: https://www.switchlink.se/svn/teen/surface.cpp $
+ * $Id: surface.cpp 214 2009-08-14 06:09:26Z megath $
+ */
+
+
+#include "surface.h"
+#include "pack.h"
+#include "common/stream.h"
+#include "common/debug.h"
+
+using namespace TeenAgent;
+
+Surface::Surface() : x(0), y(0) {
+ memset(flags, 0, sizeof(flags));
+}
+
+void Surface::load(Common::SeekableReadStream *stream, Type type) {
+ //debug(0, "load()");
+ free();
+
+ x = y = 0;
+ memset(flags, 0, sizeof(flags));
+
+ if (type == TypeOn) {
+ byte fn = stream->readByte();
+ if (stream->eos())
+ return;
+
+ for(byte i = 0; i < fn; ++i) {
+ flags[i] = stream->readUint16LE();
+ debug(0, "flags[%u] = %u (0x%04x)", i, flags[i], flags[i]);
+ }
+ }
+
+ uint16 w_ = stream->readUint16LE();
+ uint16 h_ = stream->readUint16LE();
+
+ if (type != TypeLan) {
+ uint16 pos = stream->readUint16LE();
+ x = pos % 320;
+ y = pos / 320;
+ }
+
+ //debug(0, "declared info: %ux%u (%04xx%04x) -> %u,%u", w_, h_, w_, h_, x, y);
+ if (stream->eos() || w_ == 0)
+ return;
+
+ if (w_ * h_ > stream->size()) {//rough but working
+ debug(0, "invalid surface %ux%u -> %u,%u", w_, h_, x, y);
+ return;
+ }
+
+ //debug(0, "creating surface %ux%u -> %u,%u", w_, h_, x, y);
+ create(w_, h_, 1);
+
+ stream->read(pixels, w_ * h_);
+}
+
+void Surface::render(Graphics::Surface * surface, int dx, int dy, bool mirror) {
+ assert(x + w <= surface->w);
+ assert(y + h <= surface->h);
+
+ byte *src = (byte *)pixels;
+ byte *dst = (byte *)surface->getBasePtr(dx + x, dy + y);
+
+ for(int i = 0; i < h; ++i) {
+ for(int j = 0; j < w; ++j) {
+ byte p = src[j];
+ if (p != 0xff)
+ dst[mirror? w - j - 1: j] = p;
+ }
+ dst += surface->pitch;
+ src += pitch;
+ }
+}
diff --git a/engines/teenagent/surface.h b/engines/teenagent/surface.h
new file mode 100644
index 0000000000..857d256c05
--- /dev/null
+++ b/engines/teenagent/surface.h
@@ -0,0 +1,52 @@
+/* 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: https://www.switchlink.se/svn/teen/surface.h $
+ * $Id: surface.h 154 2009-08-10 20:10:23Z megath $
+ */
+
+
+#ifndef TAGET_SURFACE_H__
+#define TAGET_SURFACE_H__
+
+#include "graphics/surface.h"
+#include "common/stream.h"
+
+namespace TeenAgent {
+
+class Pack;
+class Surface : public Graphics::Surface {
+public:
+ enum Type {TypeOn, TypeOns, TypeLan};
+
+ uint16 flags[255];
+ uint16 x, y;
+
+ Surface();
+ void load(Common::SeekableReadStream * stream, Type type);
+ void render(Graphics::Surface * surface, int dx = 0, int dy = 0, bool mirror = false);
+
+ bool empty() const { return pixels == NULL; }
+};
+
+}
+
+#endif
+
diff --git a/engines/teenagent/teenagent.cpp b/engines/teenagent/teenagent.cpp
new file mode 100644
index 0000000000..2d5d42ba3c
--- /dev/null
+++ b/engines/teenagent/teenagent.cpp
@@ -0,0 +1,484 @@
+/* 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: https://www.switchlink.se/svn/teen/tagent.cpp $
+ * $Id: tagent.cpp 304 2009-09-03 20:10:22Z megath $
+ */
+
+
+#include "teenagent/teenagent.h"
+#include "common/system.h"
+#include "common/events.h"
+#include "common/debug.h"
+#include "common/savefile.h"
+#include "common/config-manager.h"
+#include "sound/mixer.h"
+#include "scene.h"
+#include "objects.h"
+#include "music.h"
+
+using namespace TeenAgent;
+
+TeenAgentEngine::TeenAgentEngine(OSystem * system) : Engine(system), action(ActionNone) {
+ music = new MusicPlayer();
+}
+
+void TeenAgentEngine::processObject() {
+ if (dst_object == NULL)
+ return;
+
+ Resources * res = Resources::instance();
+ switch (action) {
+ case ActionExamine: {
+ byte * dcall = res->dseg.ptr(0xb5ce);
+ dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
+ dcall += 2 * dst_object->id - 2;
+ uint16 callback = READ_LE_UINT16(dcall);
+ if (callback == 0) {
+ Common::String desc = dst_object->description();
+ scene->displayMessage(desc);
+ //debug(0, "%s[%u]: description: %s", current_object->name, current_object->id, desc.c_str());
+ break;
+ }
+ processCallback(callback);
+ }
+ break;
+ case ActionUse:
+ {
+ InventoryObject *inv = inventory->selectedObject();
+ if (inv != NULL) {
+ byte * dcall = res->dseg.ptr(0xbb87);
+ dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
+ for(UseObject * obj = (UseObject *)dcall; obj->inventory_id != 0; ++obj) {
+ if (obj->inventory_id == inv->id && dst_object->id == obj->object_id) {
+ debug(0, "combine! %u,%u", obj->x, obj->y);
+ //moveTo(Common::Point(obj->x, obj->y), NULL, Examine);
+ processCallback(obj->callback);
+ inventory->resetSelectedObject();
+ return;
+ }
+ }
+
+ //error
+ inventory->resetSelectedObject();
+ scene->displayMessage("That's no good.");
+
+ break;
+ } else {
+ byte * dcall = res->dseg.ptr(0xb89c);
+ dcall = res->dseg.ptr(READ_LE_UINT16(dcall + scene->getId() * 2 - 2));
+ dcall += 2 * dst_object->id - 2;
+ uint16 callback = READ_LE_UINT16(dcall);
+ processCallback(callback);
+ }
+ }
+ break;
+
+ case ActionNone:
+ break;
+ }
+}
+
+
+void TeenAgentEngine::use(Object *object) {
+ if (object == NULL || scene->eventRunning())
+ return;
+
+ dst_object = object;
+ object->rect.dump();
+ object->actor_rect.dump();
+ if (object->actor_rect.valid()) //some objects have 0xffff in left/right
+ scene->moveTo(object->actor_rect.center(), object->actor_orientation);
+ if (object->actor_orientation > 0)
+ scene->setOrientation(object->actor_orientation);
+ action = ActionUse;
+}
+
+void TeenAgentEngine::examine(const Common::Point &point, Object *object) {
+ if (scene->eventRunning())
+ return;
+
+ if (object != NULL) {
+ Common::Point dst = object->actor_rect.center();
+ debug(0, "click %d, %d, object %d, %d", point.x, point.y, dst.x, dst.y);
+ if (object->actor_rect.valid())
+ scene->moveTo(dst, object->actor_orientation);
+ action = ActionExamine;
+ dst_object = object;
+ } else {
+ debug(0, "click %d, %d", point.x, point.y);
+ scene->moveTo(point, 0, true);
+ dst_object = NULL;
+ action = ActionNone;
+ }
+}
+
+void TeenAgentEngine::deinit() {
+ _mixer->stopAll();
+ delete scene;
+ scene = NULL;
+ delete inventory;
+ inventory = NULL;
+ //delete music;
+ //music = NULL;
+ Resources::instance()->deinit();
+}
+
+Common::Error TeenAgentEngine::loadGameState(int slot) {
+ debug(0, "loading from slot %d", slot);
+ char slotStr[16];
+ snprintf(slotStr, sizeof(slotStr), "teenagent.%d", slot);
+ Common::InSaveFile *in = _saveFileMan->openForLoading(slotStr);
+ if (in == NULL)
+ return Common::kReadPermissionDenied;
+
+ Resources * res = Resources::instance();
+
+ assert(res->dseg.size() >= 0x6478 + 0x777a);
+ char data[0x777a];
+ if (in->read(data, 0x777a) != 0x777a) {
+ delete in;
+ return Common::kReadingFailed;
+ }
+
+ delete in;
+
+ memcpy(res->dseg.ptr(0x6478), data, sizeof(data));
+
+ scene->clear();
+
+ setMusic(Resources::instance()->dseg.get_byte(0xDB90));
+
+ int id = res->dseg.get_byte(0xB4F3);
+ uint16 x = res->dseg.get_word(0x64AF), y = res->dseg.get_word(0x64B1);
+ scene->init(id, Common::Point(x, y));
+ return Common::kNoError;
+}
+
+Common::Error TeenAgentEngine::saveGameState(int slot, const char *desc) {
+ debug(0, "saving to slot %d", slot);
+ char slotStr[16];
+ snprintf(slotStr, sizeof(slotStr), "teenagent.%d", slot);
+ Common::OutSaveFile *out = _saveFileMan->openForSaving(slotStr);
+ if (out == NULL)
+ return Common::kWritePermissionDenied;
+
+ Resources * res = Resources::instance();
+ res->dseg.set_byte(0xB4F3, scene->getId());
+ Common::Point pos = scene->getPosition();
+ res->dseg.set_word(0x64AF, pos.x);
+ res->dseg.set_word(0x64B1, pos.y);
+
+ assert(res->dseg.size() >= 0x6478 + 0x777a);
+ strncpy((char *)res->dseg.ptr(0x6478), desc, 0x16);
+ out->write(res->dseg.ptr(0x6478), 0x777a);
+ delete out;
+ return Common::kNoError;
+}
+
+Common::Error TeenAgentEngine::run() {
+ Common::EventManager * _event = _system->getEventManager();
+
+ initGraphics(320, 200, false);
+
+ scene = new Scene;
+ inventory = new Inventory;
+
+ Resources * res = Resources::instance();
+ res->loadArchives();
+
+
+ scene->init(this, _system);
+ inventory->init(this);
+
+ //res.varia.read(6, palette, sizeof(palette));
+ //14,15 - on type 2
+ //scene->init(_system, 2);
+ //scene->init(_system, 27);
+ //scene->init(_system, 28);
+ scene->init(10, Common::Point(136, 153));
+ //scene->init(_system, 1);
+ _system->disableCursorPalette(true);
+
+ syncSoundSettings();
+
+ music->load(4);
+ _mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_musicHandle, music, -1, 255, 0, true, false);
+ music->start();
+
+ {
+ int load_slot = Common::ConfigManager::instance().getInt("save_slot");
+ debug(0, "slot: %d", load_slot);
+ if (load_slot >= 0)
+ loadGameState(load_slot);
+ }
+
+ uint32 frame = 0;
+
+ Common::Event event;
+ Common::Point mouse;
+
+ do {
+ _system->showMouse(true);
+ uint32 t0 = _system->getMillis();
+ Object * current_object = findObject(scene->getId(), mouse);
+
+ while (_event->pollEvent(event)) {
+ if (event.type == Common::EVENT_RTL) {
+ deinit();
+ return Common::kNoError;
+ }
+
+ if ((!scene_busy && inventory->processEvent(event)) || scene->processEvent(event))
+ continue;
+
+ //debug(0, "event");
+ switch(event.type) {
+ case Common::EVENT_LBUTTONDOWN:
+ examine(event.mouse, current_object);
+ break;
+ case Common::EVENT_RBUTTONDOWN:
+ use(current_object);
+ break;
+ case Common::EVENT_MOUSEMOVE:
+ mouse = event.mouse;
+ break;
+ default:;
+ }
+ }
+
+ uint32 f0 = frame * 10 / 25, f1 = (frame + 1) * 10 / 25;
+ if (f0 != f1) {
+ bool b = scene->render(_system);
+ scene_busy = b;
+ if (!inventory->active() && !scene_busy && action != ActionNone) {
+ processObject();
+ action = ActionNone;
+ dst_object = NULL;
+ }
+ }
+ bool busy = inventory->active() || scene_busy;
+
+ Graphics::Surface * surface = _system->lockScreen();
+
+ if (!busy) {
+ InventoryObject *selected_object = inventory->selectedObject();
+ if (current_object || selected_object) {
+ Common::String name;
+ if (selected_object) {
+ name += selected_object->name;
+ name += " & ";
+ }
+ if (current_object)
+ name += current_object->name;
+
+ uint w = res->font7.render(NULL, 0, 0, name);
+ res->font7.render(surface, (320 - w) / 2, 180, name, true);
+ if (current_object) {
+ current_object->rect.render(surface, 0x80);
+ current_object->actor_rect.render(surface, 0x81);
+ }
+ }
+ }
+
+ inventory->render(surface);
+
+ _system->unlockScreen();
+
+ _system->updateScreen();
+
+ uint32 dt = _system->getMillis() - t0;
+ if (dt < 40)
+ _system->delayMillis(40 - dt);
+
+ ++frame;
+ } while(!_event->shouldQuit());
+
+ deinit();
+ return Common::kNoError;
+}
+
+Object * TeenAgentEngine::findObject(int id, const Common::Point &point) {
+ Resources * res = Resources::instance();
+ uint16 addr = res->dseg.get_word(0x7254 + (id - 1) * 2);
+ //debug(0, "object base: %04x, x: %d, %d", addr, point.x, point.y);
+ uint16 object;
+ for(;(object = res->dseg.get_word(addr)) != 0; addr += 2) {
+ if (object == 0)
+ return NULL;
+
+ Object *obj = (Object *)res->dseg.ptr(object);
+ //obj->dump();
+ if (obj->enabled != 0 && obj->rect.in(point))
+ return obj;
+ }
+ return NULL;
+}
+
+void TeenAgentEngine::displayMessage(const Common::String &str, byte color) {
+ SceneEvent event(SceneEvent::Message);
+ event.message = str;
+ event.color = color;
+ scene->push(event);
+}
+
+
+void TeenAgentEngine::displayMessage(uint16 addr, byte color) {
+ Common::String message;
+ for (
+ const char * str = (const char *)Resources::instance()->dseg.ptr(addr);
+ str[0] != 0 || str[1] != 0;
+ ++str)
+ {
+ char c = str[0];
+ message += c != 0 && c != -1? c: '\n';
+ }
+ displayMessage(message, color);
+}
+
+void TeenAgentEngine::moveTo(const Common::Point & dst, bool warp) {
+ moveTo(dst.x, dst.y);
+}
+
+void TeenAgentEngine::moveTo(uint16 x, uint16 y, bool warp) {
+ SceneEvent event(SceneEvent::Walk);
+ event.dst.x = x;
+ event.dst.y = y;
+ event.color = warp? 1: 0;
+ scene->push(event);
+}
+
+void TeenAgentEngine::playAnimation(uint16 id, byte slot, bool async) {
+ SceneEvent event(SceneEvent::PlayAnimation);
+ event.animation = id;
+ event.color = slot;
+ if (async)
+ event.color |= 0x80;
+ scene->push(event);
+}
+
+void TeenAgentEngine::loadScene(byte id, const Common::Point &pos, byte o) {
+ loadScene(id, pos.x, pos.y, o);
+}
+
+void TeenAgentEngine::loadScene(byte id, uint16 x, uint16 y, byte o) {
+ SceneEvent event(SceneEvent::LoadScene);
+ event.scene = id;
+ event.dst.x = x;
+ event.dst.y = y;
+ event.orientation = o;
+ scene->push(event);
+}
+
+void TeenAgentEngine::setOns(byte id, byte value, byte scene_id) {
+ SceneEvent event(SceneEvent::SetOn);
+ event.ons = id + 1;
+ event.color = value;
+ event.scene = scene_id;
+ scene->push(event);
+}
+
+void TeenAgentEngine::setLan(byte id, byte value, byte scene_id) {
+ if (id == 0)
+ error("setting lan 0 is invalid");
+ SceneEvent event(SceneEvent::SetLan);
+ event.lan = id;
+ event.color = value;
+ event.scene = scene_id;
+ scene->push(event);
+}
+
+void TeenAgentEngine::reloadLan() {
+ SceneEvent event(SceneEvent::SetLan);
+ event.lan = 0;
+ scene->push(event);
+}
+
+
+void TeenAgentEngine::playMusic(byte id) {
+ SceneEvent event(SceneEvent::PlayMusic);
+ event.music = id;
+ scene->push(event);
+}
+
+void TeenAgentEngine::playSound(byte id, byte skip_frames) {
+ SceneEvent event(SceneEvent::PlaySound);
+ event.sound = id;
+ event.color = skip_frames;
+ scene->push(event);
+}
+
+void TeenAgentEngine::enableObject(byte id, byte scene_id) {
+ SceneEvent event(SceneEvent::EnableObject);
+ event.object = id + 1;
+ event.color = 1;
+ event.scene = scene_id;
+ scene->push(event);
+}
+
+void TeenAgentEngine::disableObject(byte id, byte scene_id) {
+ SceneEvent event(SceneEvent::EnableObject);
+ event.object = id + 1;
+ event.color = 0;
+ event.scene = scene_id;
+ scene->push(event);
+}
+
+void TeenAgentEngine::waitAnimation() {
+ SceneEvent event(SceneEvent::WaitForAnimation);
+ scene->push(event);
+}
+
+void TeenAgentEngine::playSoundNow(byte id) {
+ Resources * res = Resources::instance();
+ Common::SeekableReadStream * in = res->sam_sam.getStream(id);
+ if (in == NULL) {
+ debug(0, "skipping invalid sound %u", id);
+ return;
+ }
+
+ uint size = in->size();
+ char *data = new char[size];
+ in->read(data, size);
+ debug(0, "playing %u samples...", size);
+
+ _mixer->playRaw(Audio::Mixer::kSFXSoundType, &_soundHandle, data, size, 11025, Audio::Mixer::FLAG_AUTOFREE);
+}
+
+
+void TeenAgentEngine::setMusic(byte id) {
+ debug(0, "starting music %u", id);
+ if (!music->load(id))
+ return;
+ *Resources::instance()->dseg.ptr(0xDB90) = id;
+ music->start();
+}
+
+
+bool TeenAgentEngine::hasFeature(EngineFeature f) const {
+ switch(f) {
+ case kSupportsRTL:
+ case kSupportsLoadingDuringRuntime:
+ case kSupportsSavingDuringRuntime:
+ return true;
+ default:
+ return false;
+ }
+}
diff --git a/engines/teenagent/teenagent.h b/engines/teenagent/teenagent.h
new file mode 100644
index 0000000000..b99d108024
--- /dev/null
+++ b/engines/teenagent/teenagent.h
@@ -0,0 +1,110 @@
+/* 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: https://www.switchlink.se/svn/teen/tagent.h $
+ * $Id: tagent.h 304 2009-09-03 20:10:22Z megath $
+ */
+
+
+#ifndef TEENAGENT_ENGINE_H__
+#define TEENAGENT_ENGINE_H__
+
+#include "engines/engine.h"
+#include "pack.h"
+#include "resources.h"
+#include "inventory.h"
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+
+namespace TeenAgent {
+
+struct Object;
+class Scene;
+class MusicPlayer;
+
+class TeenAgentEngine: public Engine {
+public:
+ enum Action { ActionNone, ActionExamine, ActionUse };
+
+ TeenAgentEngine(OSystem * system);
+
+ virtual Common::Error run();
+ virtual Common::Error loadGameState(int slot);
+ virtual Common::Error saveGameState(int slot, const char *desc);
+ virtual bool canLoadGameStateCurrently() { return true; }
+ virtual bool canSaveGameStateCurrently() { return !scene_busy; }
+ virtual bool hasFeature(EngineFeature f) const;
+
+
+ void deinit();
+
+ Object * findObject(int id, const Common::Point &point);
+
+ void examine(const Common::Point &point, Object *object);
+ void use(Object *object);
+
+ bool processCallback(uint16 addr);
+ inline Scene * getScene() { return scene; }
+
+ //event driven:
+ void displayMessage(uint16 addr, byte color = 0xd1);
+ void displayMessage(const Common::String &str, byte color = 0xd1);
+ void moveTo(const Common::Point & dst, bool warp = false);
+ void moveTo(uint16 x, uint16 y, bool warp = false);
+ void playAnimation(uint16 id, byte slot = 0, bool async = false);
+ void loadScene(byte id, const Common::Point &pos, byte o = 0);
+ void loadScene(byte id, uint16 x, uint16 y, byte o = 0);
+ void setOns(byte id, byte value, byte scene_id = 0);
+ void setLan(byte id, byte value, byte scene_id = 0);
+ void reloadLan();
+ void rejectMessage();
+
+ void playMusic(byte id); //schedules play
+ void playSound(byte id, byte skip_frames = 0);
+ void playSoundNow(byte id);
+ void enableObject(byte id, byte scene_id = 0);
+ void disableObject(byte id, byte scene_id = 0);
+ void waitAnimation();
+
+ Common::RandomSource random;
+
+ Scene *scene;
+ Inventory *inventory;
+ MusicPlayer *music;
+
+ void setMusic(byte id);
+
+private:
+ void processObject();
+ void anotherMansionTry();
+
+ bool scene_busy;
+ Action action;
+ Object * dst_object;
+
+
+ Audio::AudioStream *_musicStream;
+ Audio::SoundHandle _musicHandle, _soundHandle;
+};
+
+}
+
+#endif
+