aboutsummaryrefslogtreecommitdiff
path: root/engines/zvision/scripting
diff options
context:
space:
mode:
authorMarisa-Chan2014-07-02 19:50:55 +0000
committerMarisa-Chan2014-07-02 19:50:55 +0000
commit23c1b508611d5fa4e7dfc47f8f5ec10a7de177e3 (patch)
tree4e5baf796851ebe649c078913fea71972d994c38 /engines/zvision/scripting
parentace0e5e88f63f34dad94962c95f57f3ec42258ae (diff)
downloadscummvm-rg350-23c1b508611d5fa4e7dfc47f8f5ec10a7de177e3.tar.gz
scummvm-rg350-23c1b508611d5fa4e7dfc47f8f5ec10a7de177e3.tar.bz2
scummvm-rg350-23c1b508611d5fa4e7dfc47f8f5ec10a7de177e3.zip
ZVISION: Reorgonize source files into directories.
Diffstat (limited to 'engines/zvision/scripting')
-rw-r--r--engines/zvision/scripting/actions.cpp10
-rw-r--r--engines/zvision/scripting/controls/input_control.cpp2
-rw-r--r--engines/zvision/scripting/controls/input_control.h2
-rw-r--r--engines/zvision/scripting/controls/lever_control.cpp2
-rw-r--r--engines/zvision/scripting/controls/slot_control.cpp219
-rw-r--r--engines/zvision/scripting/controls/slot_control.h86
-rw-r--r--engines/zvision/scripting/inventory.cpp123
-rw-r--r--engines/zvision/scripting/scr_file_handling.cpp2
-rw-r--r--engines/zvision/scripting/script_manager.cpp2
-rw-r--r--engines/zvision/scripting/script_manager.h2
-rw-r--r--engines/zvision/scripting/sidefx.cpp36
-rw-r--r--engines/zvision/scripting/sidefx.h124
-rw-r--r--engines/zvision/scripting/sidefx/animation_node.cpp211
-rw-r--r--engines/zvision/scripting/sidefx/animation_node.h84
-rw-r--r--engines/zvision/scripting/sidefx/music_node.cpp190
-rw-r--r--engines/zvision/scripting/sidefx/music_node.h82
-rw-r--r--engines/zvision/scripting/sidefx/syncsound_node.cpp86
-rw-r--r--engines/zvision/scripting/sidefx/syncsound_node.h56
-rw-r--r--engines/zvision/scripting/sidefx/timer_node.cpp (renamed from engines/zvision/scripting/controls/timer_node.cpp)2
-rw-r--r--engines/zvision/scripting/sidefx/timer_node.h (renamed from engines/zvision/scripting/controls/timer_node.h)2
-rw-r--r--engines/zvision/scripting/sidefx/ttytext_node.cpp175
-rw-r--r--engines/zvision/scripting/sidefx/ttytext_node.h76
22 files changed, 1561 insertions, 13 deletions
diff --git a/engines/zvision/scripting/actions.cpp b/engines/zvision/scripting/actions.cpp
index 3c341fbc80..22fbd4ff16 100644
--- a/engines/zvision/scripting/actions.cpp
+++ b/engines/zvision/scripting/actions.cpp
@@ -29,11 +29,11 @@
#include "zvision/graphics/render_manager.h"
#include "zvision/sound/zork_raw.h"
#include "zvision/video/zork_avi_decoder.h"
-#include "zvision/scripting/controls/timer_node.h"
-#include "zvision/music_node.h"
-#include "zvision/syncsound_node.h"
-#include "zvision/animation_node.h"
-#include "zvision/ttytext_node.h"
+#include "zvision/scripting/sidefx/timer_node.h"
+#include "zvision/scripting/sidefx/music_node.h"
+#include "zvision/scripting/sidefx/syncsound_node.h"
+#include "zvision/scripting/sidefx/animation_node.h"
+#include "zvision/scripting/sidefx/ttytext_node.h"
#include "common/file.h"
diff --git a/engines/zvision/scripting/controls/input_control.cpp b/engines/zvision/scripting/controls/input_control.cpp
index ca707b5ab0..ba1b634d42 100644
--- a/engines/zvision/scripting/controls/input_control.cpp
+++ b/engines/zvision/scripting/controls/input_control.cpp
@@ -26,7 +26,7 @@
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
-#include "zvision/strings/string_manager.h"
+#include "zvision/text/string_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/utility/utility.h"
diff --git a/engines/zvision/scripting/controls/input_control.h b/engines/zvision/scripting/controls/input_control.h
index 4a63f228a0..6fcdb2ca54 100644
--- a/engines/zvision/scripting/controls/input_control.h
+++ b/engines/zvision/scripting/controls/input_control.h
@@ -24,7 +24,7 @@
#define ZVISION_INPUT_CONTROL_H
#include "zvision/scripting/control.h"
-#include "zvision/strings/string_manager.h"
+#include "zvision/text/string_manager.h"
#include "common/rect.h"
diff --git a/engines/zvision/scripting/controls/lever_control.cpp b/engines/zvision/scripting/controls/lever_control.cpp
index 121fab97e1..7e3ee775fb 100644
--- a/engines/zvision/scripting/controls/lever_control.cpp
+++ b/engines/zvision/scripting/controls/lever_control.cpp
@@ -28,7 +28,7 @@
#include "zvision/scripting/script_manager.h"
#include "zvision/graphics/render_manager.h"
#include "zvision/cursors/cursor_manager.h"
-#include "zvision/meta_animation.h"
+#include "zvision/animation/meta_animation.h"
#include "zvision/utility/utility.h"
#include "common/stream.h"
diff --git a/engines/zvision/scripting/controls/slot_control.cpp b/engines/zvision/scripting/controls/slot_control.cpp
new file mode 100644
index 0000000000..c85b02b3cd
--- /dev/null
+++ b/engines/zvision/scripting/controls/slot_control.cpp
@@ -0,0 +1,219 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/controls/slot_control.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/cursors/cursor_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+
+
+namespace ZVision {
+
+SlotControl::SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream)
+ : Control(engine, key) {
+
+ _rendered_item = 0;
+ _bkg = NULL;
+
+ // Loop until we find the closing brace
+ Common::String line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ Common::String param;
+ Common::String values;
+ getParams(line, param, values);
+
+ while (!stream.eos() && !line.contains('}')) {
+ if (param.matchString("hotspot", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _hotspot = Common::Rect(x, y, width, height);
+ } else if (param.matchString("rectangle", true)) {
+ int x;
+ int y;
+ int width;
+ int height;
+
+ sscanf(values.c_str(), "%d %d %d %d", &x, &y, &width, &height);
+
+ _rectangle = Common::Rect(x, y, width, height);
+ } else if (param.matchString("cursor", true)) {
+ _cursor = _engine->getCursorManager()->getCursorId(values);
+ } else if (param.matchString("distance_id", true)) {
+ sscanf(values.c_str(), "%c", &_distance_id);
+ } else if (param.matchString("venus_id", true)) {
+ _venus_id = atoi(values.c_str());
+ } else if (param.matchString("eligible_objects", true)) {
+ char buf[256];
+ memset(buf, 0, 256);
+ strcpy(buf, values.c_str());
+
+ char *curpos = buf;
+ char *strend = buf + strlen(buf);
+ while (true) {
+ char *st = curpos;
+
+ if (st >= strend)
+ break;
+
+ while (*curpos != ' ' && curpos < strend)
+ curpos++;
+
+ *curpos = 0;
+ curpos++;
+
+ int obj = atoi(st);
+
+ _eligible_objects.push_back(obj);
+ }
+ }
+
+ line = stream.readLine();
+ trimCommentsAndWhiteSpace(&line);
+ getParams(line, param, values);
+ }
+
+ if (_hotspot.isEmpty() || _rectangle.isEmpty()) {
+ warning("Slot %u was parsed incorrectly", key);
+ }
+}
+
+SlotControl::~SlotControl() {
+ // Clear the state value back to 0
+ //_engine->getScriptManager()->setStateValue(_key, 0);
+
+ if (_bkg)
+ delete _bkg;
+}
+
+bool SlotControl::onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_hotspot.contains(backgroundImageSpacePos)) {
+ //ctrl_setvenus(ct);
+
+ int item = _engine->getScriptManager()->getStateValue(_key);
+ int mouse_item = _engine->getScriptManager()->getStateValue(StateKey_InventoryItem);
+ if (item != 0) {
+ if (mouse_item != 0) {
+ if (eligeblity(mouse_item)) {
+ _engine->getScriptManager()->invertory_drop(mouse_item);
+ _engine->getScriptManager()->invertory_add(item);
+ _engine->getScriptManager()->setStateValue(_key, mouse_item);
+ }
+ } else {
+ _engine->getScriptManager()->invertory_add(item);
+ _engine->getScriptManager()->setStateValue(_key, 0);
+ }
+ } else if (mouse_item == 0) {
+ if (eligeblity(0)) {
+ _engine->getScriptManager()->invertory_drop(0);
+ _engine->getScriptManager()->setStateValue(_key, 0);
+ }
+ } else if (eligeblity(mouse_item)) {
+ _engine->getScriptManager()->setStateValue(_key, mouse_item);
+ _engine->getScriptManager()->invertory_drop(mouse_item);
+ }
+ }
+ return false;
+}
+
+bool SlotControl::onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_hotspot.contains(backgroundImageSpacePos)) {
+ _engine->getCursorManager()->changeCursor(_cursor);
+ return true;
+ }
+
+ return false;
+}
+
+bool SlotControl::process(uint32 deltaTimeInMillis) {
+ if (_engine->getScriptManager()->getStateFlag(_key) & Puzzle::DISABLED)
+ return false;
+
+ if (_engine->canRender()) {
+ int cur_item = _engine->getScriptManager()->getStateValue(_key);
+ if (cur_item != _rendered_item) {
+ if (_rendered_item != 0 && cur_item == 0) {
+ _engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
+ _rendered_item = cur_item;
+ } else {
+ if (_rendered_item == 0) {
+ if (_bkg)
+ delete _bkg;
+
+ _bkg = _engine->getRenderManager()->getBkgRect(_rectangle);
+ } else {
+ _engine->getRenderManager()->blitSurfaceToBkg(*_bkg, _rectangle.left, _rectangle.top);
+ }
+
+ char buf[16];
+ if (_engine->getGameId() == GID_NEMESIS)
+ sprintf(buf, "%d%cobj.tga", cur_item, _distance_id);
+ else
+ sprintf(buf, "g0z%cu%2.2x1.tga", _distance_id, cur_item);
+
+ Graphics::Surface *srf = _engine->getRenderManager()->loadImage(buf);
+
+ int16 drawx = _rectangle.left;
+ int16 drawy = _rectangle.top;
+
+ if (_rectangle.width() > srf->w)
+ drawx = _rectangle.left + (_rectangle.width() - srf->w) / 2;
+
+ if (_rectangle.height() > srf->h)
+ drawy = _rectangle.top + (_rectangle.height() - srf->h) / 2;
+
+ _engine->getRenderManager()->blitSurfaceToBkg(*srf, drawx, drawy, 0);
+
+ delete srf;
+
+ _rendered_item = cur_item;
+ }
+ }
+ }
+ return false;
+}
+
+bool SlotControl::eligeblity(int item_id) {
+ for (Common::List<int>::iterator it = _eligible_objects.begin(); it != _eligible_objects.end(); it++)
+ if (*it == item_id)
+ return true;
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/controls/slot_control.h b/engines/zvision/scripting/controls/slot_control.h
new file mode 100644
index 0000000000..0ac8ec9ce0
--- /dev/null
+++ b/engines/zvision/scripting/controls/slot_control.h
@@ -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.
+ *
+ */
+
+#ifndef ZVISION_SLOT_CONTROL_H
+#define ZVISION_SLOT_CONTROL_H
+
+#include "zvision/scripting/control.h"
+
+#include "graphics/surface.h"
+
+#include "common/rect.h"
+#include "common/list.h"
+
+
+namespace ZVision {
+
+class SlotControl : public Control {
+public:
+ SlotControl(ZVision *engine, uint32 key, Common::SeekableReadStream &stream);
+ ~SlotControl();
+
+ /**
+ * Called when LeftMouse is lifted. Calls ScriptManager::setStateValue(_key, 1);
+ *
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ */
+ bool onMouseUp(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+ /**
+ * Called on every MouseMove. Tests if the mouse is inside _hotspot, and if so, sets the cursor.
+ *
+ * @param engine The base engine
+ * @param screenSpacePos The position of the mouse in screen space
+ * @param backgroundImageSpacePos The position of the mouse in background image space
+ * @return Was the cursor changed?
+ */
+ bool onMouseMove(const Common::Point &screenSpacePos, const Common::Point &backgroundImageSpacePos);
+
+ bool process(uint32 deltaTimeInMillis);
+
+private:
+ /**
+ * The area that will trigger the event
+ * This is in image space coordinates, NOT screen space
+ */
+ Common::Rect _rectangle;
+ Common::Rect _hotspot;
+
+ int _cursor;
+ char _distance_id;
+ int _venus_id;
+
+ int _rendered_item;
+
+ Common::List<int> _eligible_objects;
+
+ bool eligeblity(int item_id);
+
+ Graphics::Surface *_bkg;
+
+ /** The cursor to use when hovering over _hotspot */
+ Common::String _hoverCursor;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/inventory.cpp b/engines/zvision/scripting/inventory.cpp
new file mode 100644
index 0000000000..f8b22970c4
--- /dev/null
+++ b/engines/zvision/scripting/inventory.cpp
@@ -0,0 +1,123 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/script_manager.h"
+
+
+namespace ZVision {
+
+int8 ScriptManager::invertory_getCount() {
+ return getStateValue(StateKey_Inv_Cnt_Slot);
+}
+
+void ScriptManager::invertory_setCount(int8 cnt) {
+ setStateValue(StateKey_Inv_Cnt_Slot, cnt);
+}
+
+int16 ScriptManager::invertory_getItem(int8 id) {
+ if (id < 49 && id >= 0)
+ return getStateValue(StateKey_Inv_1_Slot + id);
+ return -1;
+}
+
+void ScriptManager::invertory_setItem(int8 id, int16 item) {
+ if (id < 49 && id >= 0)
+ setStateValue(StateKey_Inv_1_Slot + id, item);
+}
+
+void ScriptManager::invertory_add(int16 item) {
+ int8 cnt = invertory_getCount();
+
+ if (cnt < 49) {
+ bool not_exist = true;
+
+ if (cnt == 0) {
+ invertory_setItem(0, 0);
+ invertory_setCount(1); // we needed empty item for cycle code
+ cnt = 1;
+ }
+
+ for (int8 cur = 0; cur < cnt; cur++)
+ if (invertory_getItem(cur) == item) {
+ not_exist = false;
+ break;
+ }
+
+ if (not_exist) {
+ for (int8 i = cnt; i > 0; i--)
+ invertory_setItem(i, invertory_getItem(i - 1));
+
+ invertory_setItem(0, item);
+
+ setStateValue(StateKey_InventoryItem, item);
+
+ invertory_setCount(cnt + 1);
+ }
+ }
+}
+
+void ScriptManager::invertory_drop(int16 item) {
+ int8 items_cnt = invertory_getCount();
+
+ // if items in inventory > 0
+ if (items_cnt != 0) {
+ int8 index = 0;
+
+ // finding needed item
+ while (index < items_cnt) {
+ if (invertory_getItem(index) == item)
+ break;
+
+ index++;
+ }
+
+ // if item in the inventory
+ if (items_cnt != index) {
+ // shift all items left with rewrite founded item
+ for (int8 v = index; v < items_cnt - 1 ; v++)
+ invertory_setItem(v, invertory_getItem(v + 1));
+
+ // del last item
+ invertory_setItem(items_cnt - 1, 0);
+ invertory_setCount(invertory_getCount() - 1);
+
+ setStateValue(StateKey_InventoryItem, invertory_getItem(0));
+ }
+ }
+}
+void ScriptManager::invertory_cycle() {
+ int8 item_cnt = invertory_getCount();
+ int8 cur_item = invertory_getItem(0);
+ if (item_cnt > 1) {
+ for (int8 i = 0; i < item_cnt - 1; i++)
+ invertory_setItem(i, invertory_getItem(i + 1));
+
+ invertory_setItem(item_cnt - 1, cur_item);
+
+ setStateValue(StateKey_InventoryItem, invertory_getItem(0));
+
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/scr_file_handling.cpp b/engines/zvision/scripting/scr_file_handling.cpp
index fff187d369..5d697bd841 100644
--- a/engines/zvision/scripting/scr_file_handling.cpp
+++ b/engines/zvision/scripting/scr_file_handling.cpp
@@ -30,7 +30,7 @@
#include "zvision/scripting/actions.h"
#include "zvision/scripting/controls/push_toggle_control.h"
#include "zvision/scripting/controls/lever_control.h"
-#include "zvision/slot_control.h"
+#include "zvision/scripting/controls/slot_control.h"
#include "common/textconsole.h"
#include "common/file.h"
diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp
index 9713a34733..a27ae4dbf0 100644
--- a/engines/zvision/scripting/script_manager.cpp
+++ b/engines/zvision/scripting/script_manager.cpp
@@ -30,7 +30,7 @@
#include "zvision/core/save_manager.h"
#include "zvision/scripting/actions.h"
#include "zvision/utility/utility.h"
-#include "zvision/scripting/controls/timer_node.h"
+#include "zvision/scripting/sidefx/timer_node.h"
#include "common/algorithm.h"
#include "common/hashmap.h"
diff --git a/engines/zvision/scripting/script_manager.h b/engines/zvision/scripting/script_manager.h
index a835c13951..8ec364b35f 100644
--- a/engines/zvision/scripting/script_manager.h
+++ b/engines/zvision/scripting/script_manager.h
@@ -25,7 +25,7 @@
#include "zvision/scripting/puzzle.h"
#include "zvision/scripting/control.h"
-#include "zvision/sidefx.h"
+#include "zvision/scripting/sidefx.h"
#include "common/hashmap.h"
#include "common/queue.h"
diff --git a/engines/zvision/scripting/sidefx.cpp b/engines/zvision/scripting/sidefx.cpp
new file mode 100644
index 0000000000..c0b8a4d12f
--- /dev/null
+++ b/engines/zvision/scripting/sidefx.cpp
@@ -0,0 +1,36 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/sidefx.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/utility/utility.h"
+
+#include "common/stream.h"
+
+namespace ZVision {
+
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx.h b/engines/zvision/scripting/sidefx.h
new file mode 100644
index 0000000000..2c53467559
--- /dev/null
+++ b/engines/zvision/scripting/sidefx.h
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SIDEFX_H_INCLUDED
+#define SIDEFX_H_INCLUDED
+
+namespace Common {
+class SeekableReadStream;
+struct Point;
+class WriteStream;
+}
+
+namespace ZVision {
+
+class ZVision;
+
+class SideFX {
+public:
+
+ enum SideFXType {
+ SIDEFX_ANIM = 1,
+ SIDEFX_AUDIO = 2,
+ SIDEFX_DISTORT = 4,
+ SIDEFX_PANTRACK = 8,
+ SIDEFX_REGION = 16,
+ SIDEFX_TIMER = 32,
+ SIDEFX_TTYTXT = 64,
+ SIDEFX_UNK = 128,
+ SIDEFX_ALL = 255
+ };
+
+ SideFX() : _engine(0), _key(0), _type(SIDEFX_UNK) {}
+ SideFX(ZVision *engine, uint32 key, SideFXType type) : _engine(engine), _key(key), _type(type) {}
+ virtual ~SideFX() {}
+
+ uint32 getKey() {
+ return _key;
+ }
+ SideFXType getType() {
+ return _type;
+ }
+
+ virtual bool process(uint32 deltaTimeInMillis) {
+ return false;
+ }
+ /**
+ * Serialize a SideFX for save game use. This should only be used if a SideFX needs
+ * to save values that would be different from initialization. AKA a TimerNode needs to
+ * store the amount of time left on the timer. Any Controls overriding this *MUST* write
+ * their key as the first data outputted. The default implementation is NOP.
+ *
+ * NOTE: If this method is overridden, you MUST also override deserialize()
+ * and needsSerialization()
+ *
+ * @param stream Stream to write any needed data to
+ */
+ virtual void serialize(Common::WriteStream *stream) {}
+ /**
+ * De-serialize data from a save game stream. This should only be implemented if the
+ * SideFX also implements serialize(). The calling method assumes the size of the
+ * data read from the stream exactly equals that written in serialize(). The default
+ * implementation is NOP.
+ *
+ * NOTE: If this method is overridden, you MUST also override serialize()
+ * and needsSerialization()
+ *
+ * @param stream Save game file stream
+ */
+ virtual void deserialize(Common::SeekableReadStream *stream) {}
+ /**
+ * If a SideFX overrides serialize() and deserialize(), this should return true
+ *
+ * @return Does the SideFX need save game serialization?
+ */
+ virtual inline bool needsSerialization() {
+ return false;
+ }
+
+ virtual bool stop() {
+ return true;
+ }
+ virtual void kill() {}
+
+protected:
+ ZVision *_engine;
+ uint32 _key;
+ SideFXType _type;
+
+// Static member functions
+public:
+
+};
+
+// TODO: Implement InputControl
+// TODO: Implement SaveControl
+// TODO: Implement SlotControl
+// TODO: Implement SafeControl
+// TODO: Implement FistControl
+// TODO: Implement HotMovieControl
+// TODO: Implement PaintControl
+// TODO: Implement TilterControl
+
+} // End of namespace ZVision
+
+#endif // SIDEFX_H_INCLUDED
diff --git a/engines/zvision/scripting/sidefx/animation_node.cpp b/engines/zvision/scripting/sidefx/animation_node.cpp
new file mode 100644
index 0000000000..4a606adc9e
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/animation_node.cpp
@@ -0,0 +1,211 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/sidefx/animation_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/animation/meta_animation.h"
+
+#include "graphics/surface.h"
+
+
+namespace ZVision {
+
+AnimationNode::AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse)
+ : SideFX(engine, controlKey, SIDEFX_ANIM),
+ _DisposeAfterUse(DisposeAfterUse),
+ _mask(mask),
+ _animation(NULL) {
+
+ if (fileName.hasSuffix(".rlf") || fileName.hasSuffix(".avi")) {
+ _animation = new MetaAnimation(fileName, engine);
+ _frmDelay = _animation->frameTime();
+ } else {
+ warning("Unrecognized animation file type: %s", fileName.c_str());
+ }
+
+ if (frate > 0)
+ _frmDelay = 1000.0 / frate;
+}
+
+AnimationNode::~AnimationNode() {
+ if (_animation)
+ delete _animation;
+
+ _engine->getScriptManager()->setStateValue(_key, 2);
+
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ _engine->getScriptManager()->setStateValue((*it).slot, 2);
+
+ if ((*it)._scaled)
+ delete(*it)._scaled;
+ }
+
+ _playList.clear();
+}
+
+bool AnimationNode::process(uint32 deltaTimeInMillis) {
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ playnode *nod = &(*it);
+
+ nod->_delay -= deltaTimeInMillis;
+ if (nod->_delay <= 0) {
+ nod->_delay += _frmDelay;
+
+ const Graphics::Surface *frame = NULL;
+
+ if (nod->_cur_frm == -1) { // Start of new playlist node
+ nod->_cur_frm = nod->start;
+
+ _animation->seekToFrame(nod->_cur_frm);
+ frame = _animation->decodeNextFrame();
+
+ nod->_delay = _frmDelay;
+ if (nod->slot)
+ _engine->getScriptManager()->setStateValue(nod->slot, 1);
+ } else {
+ nod->_cur_frm++;
+
+ if (nod->_cur_frm > nod->stop) {
+ nod->loop--;
+
+ if (nod->loop == 0) {
+ if (nod->slot >= 0)
+ _engine->getScriptManager()->setStateValue(nod->slot, 2);
+ if (nod->_scaled)
+ delete nod->_scaled;
+ _playList.erase(it);
+ return _DisposeAfterUse;
+ }
+
+ nod->_cur_frm = nod->start;
+ _animation->seekToFrame(nod->_cur_frm);
+ }
+
+ frame = _animation->decodeNextFrame();
+ }
+
+ if (frame) {
+
+ uint32 dstw;
+ uint32 dsth;
+ if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) {
+ dstw = nod->pos.height();
+ dsth = nod->pos.width();
+ } else {
+ dstw = nod->pos.width();
+ dsth = nod->pos.height();
+ }
+
+ if (frame->w != dstw || frame->h != dsth) {
+ if (nod->_scaled)
+ if (nod->_scaled->w != dstw || nod->_scaled->h != dsth) {
+ delete nod->_scaled;
+ nod->_scaled = NULL;
+ }
+
+ if (!nod->_scaled) {
+ nod->_scaled = new Graphics::Surface;
+ nod->_scaled->create(dstw, dsth, frame->format);
+ }
+
+ _engine->getRenderManager()->scaleBuffer(frame->getPixels(), nod->_scaled->getPixels(), frame->w, frame->h, frame->format.bytesPerPixel, dstw, dsth);
+ frame = nod->_scaled;
+ }
+
+ if (_engine->getRenderManager()->getRenderTable()->getRenderState() == RenderTable::PANORAMA) {
+ Graphics::Surface *transposed = RenderManager::tranposeSurface(frame);
+ if (_mask > 0)
+ _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top, _mask);
+ else
+ _engine->getRenderManager()->blitSurfaceToBkg(*transposed, nod->pos.left, nod->pos.top);
+ delete transposed;
+ } else {
+ if (_mask > 0)
+ _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top, _mask);
+ else
+ _engine->getRenderManager()->blitSurfaceToBkg(*frame, nod->pos.left, nod->pos.top);
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+
+
+void AnimationNode::addPlayNode(int32 slot, int x, int y, int x2, int y2, int start_frame, int end_frame, int loops) {
+ playnode nod;
+ nod.loop = loops;
+ nod.pos = Common::Rect(x, y, x2 + 1, y2 + 1);
+ nod.start = start_frame;
+ nod.stop = end_frame;
+
+ if (nod.stop >= (int)_animation->frameCount())
+ nod.stop = _animation->frameCount() - 1;
+
+ nod.slot = slot;
+ nod._cur_frm = -1;
+ nod._delay = 0;
+ nod._scaled = NULL;
+ _playList.push_back(nod);
+}
+
+bool AnimationNode::stop() {
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ _engine->getScriptManager()->setStateValue((*it).slot, 2);
+ if ((*it)._scaled)
+ delete(*it)._scaled;
+ }
+
+ _playList.clear();
+
+ // We don't need to delete, it's may be reused
+ return false;
+}
+
+void AnimationNode::setNewFrameDelay(int32 newDelay) {
+ if (newDelay > 0) {
+ PlayNodes::iterator it = _playList.begin();
+ if (it != _playList.end()) {
+ playnode *nod = &(*it);
+ float percent = (float)nod->_delay / (float)_frmDelay;
+ nod->_delay = percent * newDelay; // Scale to new max
+ }
+
+ _frmDelay = newDelay;
+ }
+}
+
+int32 AnimationNode::getFrameDelay() {
+ return _frmDelay;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/animation_node.h b/engines/zvision/scripting/sidefx/animation_node.h
new file mode 100644
index 0000000000..4d1c74bccf
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/animation_node.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.
+ *
+ */
+
+#ifndef ZVISION_ANIMATION_NODE_H
+#define ZVISION_ANIMATION_NODE_H
+
+#include "zvision/scripting/sidefx.h"
+#include "common/rect.h"
+#include "common/list.h"
+
+
+namespace Common {
+class String;
+}
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace ZVision {
+
+class ZVision;
+class MetaAnimation;
+
+class AnimationNode : public SideFX {
+public:
+ AnimationNode(ZVision *engine, uint32 controlKey, const Common::String &fileName, int32 mask, int32 frate, bool DisposeAfterUse = true);
+ ~AnimationNode();
+
+ struct playnode {
+ Common::Rect pos;
+ int32 slot;
+ int32 start;
+ int32 stop;
+ int32 loop;
+ int32 _cur_frm;
+ int32 _delay;
+ Graphics::Surface *_scaled;
+ };
+
+private:
+ typedef Common::List<playnode> PlayNodes;
+
+ PlayNodes _playList;
+
+ int32 _mask;
+ bool _DisposeAfterUse;
+
+ MetaAnimation *_animation;
+ int32 _frmDelay;
+
+public:
+ bool process(uint32 deltaTimeInMillis);
+
+ void addPlayNode(int32 slot, int x, int y, int x2, int y2, int start_frame, int end_frame, int loops = 1);
+
+ bool stop();
+
+ void setNewFrameDelay(int32 newDelay);
+ int32 getFrameDelay();
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/sidefx/music_node.cpp b/engines/zvision/scripting/sidefx/music_node.cpp
new file mode 100644
index 0000000000..0351867dd9
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/music_node.cpp
@@ -0,0 +1,190 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/sidefx/music_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/sound/zork_raw.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "audio/decoders/wave.h"
+
+
+namespace ZVision {
+
+MusicNode::MusicNode(ZVision *engine, uint32 key, Common::String &filename, bool loop, int8 volume)
+ : SideFX(engine, key, SIDEFX_AUDIO) {
+ _loop = loop;
+ _volume = volume;
+ _crossfade = false;
+ _crossfade_target = 0;
+ _crossfade_time = 0;
+ _attenuate = 0;
+ _pantrack = false;
+ _pantrack_X = 0;
+ _sub = NULL;
+
+ Audio::RewindableAudioStream *audioStream;
+
+ if (filename.contains(".wav")) {
+ Common::File *file = new Common::File();
+ if (_engine->getSearchManager()->openFile(*file, filename)) {
+ audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
+ }
+ } else {
+ audioStream = makeRawZorkStream(filename, _engine);
+ }
+
+ _stereo = audioStream->isStereo();
+
+ if (_loop) {
+ Audio::LoopingAudioStream *loopingAudioStream = new Audio::LoopingAudioStream(audioStream, 0, DisposeAfterUse::YES);
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, loopingAudioStream, -1, _volume);
+ } else {
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream, -1, _volume);
+ }
+
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 1);
+
+ Common::String subname = filename;
+ subname.setChar('s', subname.size() - 3);
+ subname.setChar('u', subname.size() - 2);
+ subname.setChar('b', subname.size() - 1);
+
+ if (_engine->getSearchManager()->hasFile(subname))
+ _sub = new Subtitle(_engine, subname);
+}
+
+MusicNode::~MusicNode() {
+ _engine->_mixer->stopHandle(_handle);
+ if (_key != StateKey_NotSet)
+ _engine->getScriptManager()->setStateValue(_key, 2);
+ if (_sub)
+ delete _sub;
+ debug(1, "MusicNode: %d destroyed\n", _key);
+}
+
+void MusicNode::setPanTrack(int16 pos) {
+ if (!_stereo) {
+ _pantrack = true;
+ _pantrack_X = pos;
+ setVolume(_volume);
+ }
+}
+
+void MusicNode::unsetPanTrack() {
+ _pantrack = false;
+ setVolume(_volume);
+}
+
+void MusicNode::setFade(int32 time, uint8 target) {
+ _crossfade_target = target;
+ _crossfade_time = time;
+ _crossfade = true;
+}
+
+bool MusicNode::process(uint32 deltaTimeInMillis) {
+ if (! _engine->_mixer->isSoundHandleActive(_handle))
+ return stop();
+ else {
+ uint8 _newvol = _volume;
+
+ if (_crossfade) {
+ if (_crossfade_time > 0) {
+ if ((int32)deltaTimeInMillis > _crossfade_time)
+ deltaTimeInMillis = _crossfade_time;
+ _newvol += floor(((float)(_crossfade_target - _newvol) / (float)_crossfade_time)) * (float)deltaTimeInMillis;
+ _crossfade_time -= deltaTimeInMillis;
+ } else {
+ _crossfade = false;
+ _newvol = _crossfade_target;
+ }
+ }
+
+ if (_pantrack || _volume != _newvol)
+ setVolume(_newvol);
+
+ if (_sub)
+ _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100);
+ }
+ return false;
+}
+
+void MusicNode::setVolume(uint8 new_volume) {
+ if (_pantrack) {
+ int cur_x = _engine->getScriptManager()->getStateValue(StateKey_ViewPos);
+ cur_x -= _pantrack_X;
+ int32 _width = _engine->getRenderManager()->getBkgSize().x;
+ if (cur_x < (-_width) / 2)
+ cur_x += _width;
+ else if (cur_x >= _width / 2)
+ cur_x -= _width;
+
+ float norm = (float)cur_x / ((float)_width / 2.0);
+ float lvl = fabs(norm);
+ if (lvl > 0.5)
+ lvl = (lvl - 0.5) * 1.7;
+ else
+ lvl = 1.0;
+
+ float bal = sin(-norm * 3.1415926) * 127.0;
+
+ if (_engine->_mixer->isSoundHandleActive(_handle)) {
+ _engine->_mixer->setChannelBalance(_handle, bal);
+ _engine->_mixer->setChannelVolume(_handle, new_volume * lvl);
+ }
+ } else {
+ if (_engine->_mixer->isSoundHandleActive(_handle)) {
+ _engine->_mixer->setChannelBalance(_handle, 0);
+ _engine->_mixer->setChannelVolume(_handle, new_volume);
+ }
+ }
+
+ _volume = new_volume;
+}
+
+PanTrackNode::PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos)
+ : SideFX(engine, key, SIDEFX_PANTRACK) {
+ _slot = slot;
+
+ SideFX *fx = _engine->getScriptManager()->getSideFX(slot);
+ if (fx && fx->getType() == SIDEFX_AUDIO) {
+ MusicNode *mus = (MusicNode *)fx;
+ mus->setPanTrack(pos);
+ }
+}
+
+PanTrackNode::~PanTrackNode() {
+ SideFX *fx = _engine->getScriptManager()->getSideFX(_slot);
+ if (fx && fx->getType() == SIDEFX_AUDIO) {
+ MusicNode *mus = (MusicNode *)fx;
+ mus->unsetPanTrack();
+ }
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/music_node.h b/engines/zvision/scripting/sidefx/music_node.h
new file mode 100644
index 0000000000..066b8f80f4
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/music_node.h
@@ -0,0 +1,82 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_MUSIC_NODE_H
+#define ZVISION_MUSIC_NODE_H
+
+#include "audio/mixer.h"
+#include "zvision/scripting/sidefx.h"
+#include "zvision/subtitles/subtitles.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+class MusicNode : public SideFX {
+public:
+ MusicNode(ZVision *engine, uint32 key, Common::String &file, bool loop, int8 volume);
+ ~MusicNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+
+ void setVolume(uint8 volume);
+
+ void setPanTrack(int16 pos);
+ void unsetPanTrack();
+
+ void setFade(int32 time, uint8 target);
+
+private:
+ int32 _timeLeft;
+ bool _pantrack;
+ int32 _pantrack_X;
+ int32 _attenuate;
+ uint8 _volume;
+ bool _loop;
+ bool _crossfade;
+ uint8 _crossfade_target;
+ int32 _crossfade_time;
+ bool _stereo;
+ Audio::SoundHandle _handle;
+ Subtitle *_sub;
+};
+
+class PanTrackNode : public SideFX {
+public:
+ PanTrackNode(ZVision *engine, uint32 key, uint32 slot, int16 pos);
+ ~PanTrackNode();
+
+private:
+ uint32 _slot;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/sidefx/syncsound_node.cpp b/engines/zvision/scripting/sidefx/syncsound_node.cpp
new file mode 100644
index 0000000000..2bfdc349d1
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/syncsound_node.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.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/sidefx/syncsound_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/sound/zork_raw.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+#include "audio/decoders/wave.h"
+
+
+namespace ZVision {
+
+SyncSoundNode::SyncSoundNode(ZVision *engine, uint32 key, Common::String &filename, int32 syncto)
+ : SideFX(engine, key, SIDEFX_AUDIO) {
+ _syncto = syncto;
+ _sub = NULL;
+
+ Audio::RewindableAudioStream *audioStream;
+
+ if (filename.contains(".wav")) {
+ Common::File *file = new Common::File();
+ if (_engine->getSearchManager()->openFile(*file, filename)) {
+ audioStream = Audio::makeWAVStream(file, DisposeAfterUse::YES);
+ }
+ } else {
+ audioStream = makeRawZorkStream(filename, _engine);
+ }
+
+ _engine->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, audioStream);
+
+ Common::String subname = filename;
+ subname.setChar('s', subname.size() - 3);
+ subname.setChar('u', subname.size() - 2);
+ subname.setChar('b', subname.size() - 1);
+
+ if (_engine->getSearchManager()->hasFile(subname))
+ _sub = new Subtitle(_engine, subname);
+}
+
+SyncSoundNode::~SyncSoundNode() {
+ _engine->_mixer->stopHandle(_handle);
+ if (_sub)
+ delete _sub;
+}
+
+bool SyncSoundNode::process(uint32 deltaTimeInMillis) {
+ if (! _engine->_mixer->isSoundHandleActive(_handle))
+ return stop();
+ else {
+
+ if (_engine->getScriptManager()->getSideFX(_syncto) == NULL)
+ return stop();
+
+ if (_sub)
+ _sub->process(_engine->_mixer->getSoundElapsedTime(_handle) / 100);
+ }
+ return false;
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/syncsound_node.h b/engines/zvision/scripting/sidefx/syncsound_node.h
new file mode 100644
index 0000000000..c16ffebe7f
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/syncsound_node.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.
+ *
+ */
+
+#ifndef ZVISION_SYNCSOUND_NODE_H
+#define ZVISION_SYNCSOUND_NODE_H
+
+#include "audio/mixer.h"
+#include "zvision/scripting/sidefx.h"
+#include "zvision/subtitles/subtitles.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+class SyncSoundNode : public SideFX {
+public:
+ SyncSoundNode(ZVision *engine, uint32 key, Common::String &file, int32 syncto);
+ ~SyncSoundNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+private:
+ int32 _syncto;
+ Audio::SoundHandle _handle;
+ Subtitle *_sub;
+};
+
+} // End of namespace ZVision
+
+#endif
diff --git a/engines/zvision/scripting/controls/timer_node.cpp b/engines/zvision/scripting/sidefx/timer_node.cpp
index e68610f537..6e71101acd 100644
--- a/engines/zvision/scripting/controls/timer_node.cpp
+++ b/engines/zvision/scripting/sidefx/timer_node.cpp
@@ -22,7 +22,7 @@
#include "common/scummsys.h"
-#include "zvision/scripting/controls/timer_node.h"
+#include "zvision/scripting/sidefx/timer_node.h"
#include "zvision/zvision.h"
#include "zvision/scripting/script_manager.h"
diff --git a/engines/zvision/scripting/controls/timer_node.h b/engines/zvision/scripting/sidefx/timer_node.h
index f6584becda..7a26aff251 100644
--- a/engines/zvision/scripting/controls/timer_node.h
+++ b/engines/zvision/scripting/sidefx/timer_node.h
@@ -23,7 +23,7 @@
#ifndef ZVISION_TIMER_NODE_H
#define ZVISION_TIMER_NODE_H
-#include "zvision/sidefx.h"
+#include "zvision/scripting/sidefx.h"
namespace ZVision {
diff --git a/engines/zvision/scripting/sidefx/ttytext_node.cpp b/engines/zvision/scripting/sidefx/ttytext_node.cpp
new file mode 100644
index 0000000000..68636eb422
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/ttytext_node.cpp
@@ -0,0 +1,175 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+
+#include "zvision/scripting/sidefx/ttytext_node.h"
+
+#include "zvision/zvision.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/graphics/render_manager.h"
+#include "zvision/text/text.h"
+
+#include "common/stream.h"
+#include "common/file.h"
+
+
+namespace ZVision {
+
+ttyTextNode::ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay) :
+ SideFX(engine, key, SIDEFX_TTYTXT),
+ _fnt(engine) {
+ _delay = delay;
+ _r = r;
+ _txtpos = 0;
+ _nexttime = 0;
+ _dx = 0;
+ _dy = 0;
+
+ Common::File *infile = _engine->getSearchManager()->openFile(file);
+ if (infile) {
+ while (!infile->eos()) {
+ Common::String asciiLine = readWideLine(*infile);
+ if (asciiLine.empty()) {
+ continue;
+ }
+ _txtbuf += asciiLine;
+ }
+
+ delete infile;
+ }
+ _img.create(_r.width(), _r.height(), _engine->_pixelFormat);
+ _style.sharp = true;
+ _style.readAllStyle(_txtbuf);
+ _style.setFont(_fnt);
+ _engine->getScriptManager()->setStateValue(_key, 1);
+}
+
+ttyTextNode::~ttyTextNode() {
+ _engine->getScriptManager()->setStateValue(_key, 2);
+ _img.free();
+}
+
+bool ttyTextNode::process(uint32 deltaTimeInMillis) {
+ _nexttime -= deltaTimeInMillis;
+
+ if (_nexttime < 0) {
+ if (_txtpos < _txtbuf.size()) {
+ if (_txtbuf[_txtpos] == '<') {
+ int32 strt = _txtpos;
+ int32 endt = 0;
+ int16 ret = 0;
+ while (_txtbuf[_txtpos] != '>' && _txtpos < _txtbuf.size())
+ _txtpos++;
+ endt = _txtpos;
+ if (strt != -1)
+ if ((endt - strt - 1) > 0)
+ ret = _style.parseStyle(_txtbuf.c_str() + strt + 1, endt - strt - 1);
+
+ if (ret & (TXT_RET_FNTCHG | TXT_RET_FNTSTL | TXT_RET_NEWLN)) {
+ if (ret & TXT_RET_FNTCHG)
+ _style.setFont(_fnt);
+ if (ret & TXT_RET_FNTSTL)
+ _style.setFontStyle(_fnt);
+
+ if (ret & TXT_RET_NEWLN)
+ newline();
+ }
+
+ if (ret & TXT_RET_HASSTBOX) {
+ Common::String buf;
+ buf.format("%d", _style.statebox);
+
+ for (uint8 j = 0; j < buf.size(); j++)
+ outchar(buf[j]);
+ }
+
+ _txtpos++;
+ } else {
+ int8 charsz = getUtf8CharSize(_txtbuf[_txtpos]);
+
+ uint16 chr = readUtf8Char(_txtbuf.c_str() + _txtpos);
+
+ if (chr == ' ') {
+ uint32 i = _txtpos + charsz;
+ uint16 width = _fnt.getCharWidth(chr);
+
+ while (i < _txtbuf.size() && _txtbuf[i] != ' ' && _txtbuf[i] != '<') {
+
+ int8 chsz = getUtf8CharSize(_txtbuf[i]);
+ uint16 uchr = readUtf8Char(_txtbuf.c_str() + _txtpos);
+
+ width += _fnt.getCharWidth(uchr);
+
+ i += chsz;
+ }
+
+ if (_dx + width > _r.width())
+ newline();
+ else
+ outchar(chr);
+ } else
+ outchar(chr);
+
+ _txtpos += charsz;
+ }
+ _nexttime = _delay;
+ _engine->getRenderManager()->blitSurfaceToBkg(_img, _r.left, _r.top);
+ } else
+ return stop();
+ }
+
+ return false;
+}
+
+void ttyTextNode::scroll() {
+ int32 scrl = 0;
+ while (_dy - scrl > _r.height() - _fnt.getFontHeight())
+ scrl += _fnt.getFontHeight();
+ int8 *pixels = (int8 *)_img.getPixels();
+ for (uint16 h = scrl; h < _img.h; h++)
+ memcpy(pixels + _img.pitch * (h - scrl), pixels + _img.pitch * h, _img.pitch);
+
+ _img.fillRect(Common::Rect(0, _img.h - scrl, _img.w, _img.h), 0);
+ _dy -= scrl;
+}
+
+void ttyTextNode::newline() {
+ _dy += _fnt.getFontHeight();
+ _dx = 0;
+}
+
+void ttyTextNode::outchar(uint16 chr) {
+ uint32 clr = _engine->_pixelFormat.RGBToColor(_style.red, _style.green, _style.blue);
+
+ if (_dx + _fnt.getCharWidth(chr) > _r.width())
+ newline();
+
+ if (_dy + _fnt.getFontHeight() >= _r.height())
+ scroll();
+
+ _fnt.drawChar(&_img, chr, _dx, _dy, clr);
+
+ _dx += _fnt.getCharWidth(chr);
+}
+
+} // End of namespace ZVision
diff --git a/engines/zvision/scripting/sidefx/ttytext_node.h b/engines/zvision/scripting/sidefx/ttytext_node.h
new file mode 100644
index 0000000000..a6326c733b
--- /dev/null
+++ b/engines/zvision/scripting/sidefx/ttytext_node.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef ZVISION_TTYTEXT_NODE_H
+#define ZVISION_TTYTEXT_NODE_H
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+#include "zvision/scripting/sidefx.h"
+#include "zvision/text/text.h"
+#include "zvision/fonts/truetype_font.h"
+
+namespace Common {
+class String;
+}
+
+namespace ZVision {
+class ttyTextNode : public SideFX {
+public:
+ ttyTextNode(ZVision *engine, uint32 key, const Common::String &file, const Common::Rect &r, int32 delay);
+ ~ttyTextNode();
+
+ /**
+ * Decrement the timer by the delta time. If the timer is finished, set the status
+ * in _globalState and let this node be deleted
+ *
+ * @param deltaTimeInMillis The number of milliseconds that have passed since last frame
+ * @return If true, the node can be deleted after process() finishes
+ */
+ bool process(uint32 deltaTimeInMillis);
+private:
+ Common::Rect _r;
+ //int16 x;
+ //int16 y;
+ //uint16 w;
+ //uint16 h;
+ cTxtStyle _style;
+ sTTFont _fnt;
+ Common::String _txtbuf;
+ uint32 _txtpos;
+ //int32 txtsize;
+ int32 _delay;
+ int32 _nexttime;
+ Graphics::Surface _img;
+ int16 _dx;
+ int16 _dy;
+private:
+
+ void newline();
+ void scroll();
+ void outchar(uint16 chr);
+};
+
+} // End of namespace ZVision
+
+#endif