[Scummvm-git-logs] scummvm master -> e89c76f63c25e4703a44489d987f1ce481e6d1cf

sev- sev at scummvm.org
Thu Oct 13 23:49:46 CEST 2016


This automated email contains information about 79 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
2e3fd7cf05 BLADERUNNER: Start port to scummvm engine
5c69ed5995 BLADERUNNER: Style
f0432bdf25 BLADERUNNER: Split VQA decoder into player and decoder, add Outtake player
5fd05a41d7 BLADERUNNER: Damn copy/paste...
a67e9e16bd BLADERUNNER: Rebuild VQADecoder on top of Video::VideoDecoder
8217ed6065 BLADERUNNER: Don't base VQADecoder on Video::VideoDecoder anyway
d260f993aa BLADERUNNER: No semicolon after namespace closing brace
5cb4ba9a9b BLADERUNNER: Add basic Scene, Set, and Script support.
25e97d2144 BLADERUNNER: First easter egg, developer commentary
76cfb2c8a9 BLADERUNNER: Remove extra class qualification
ff1df93e9d BLADERUNNER: Rename _vptr to _vpointer
88035e6876 BLADERUNNER: Remove unnecessary semicolon
2189721387 BLADERUNNER: ScriptBase needs a virtual destructor
5b8df8cd8a BLADERUNNER: Resolve argument shadowing
7b6159e095 BLADERUNNER: Fix invalid delete[]
10708f7a8d BLADERUNNER: Fix invalid read
70b154988a BLADERUNNER: Remove unused member variables from OuttakePlayer
8cbfd9ab50 BLADERUNNER: Unshadow variable size in VQADecoder::readMSCI
5a12394a76 BLADERUNNER: Return an error if BladeRunnerEngine::startup() fails
691d0f9888 BLADERUNNER: Avoid global constructor for pixelformat
eefea240c7 BLADERUNNER: Fix memory leaks in BladeRunnerEngine
d93ecabc7a BLADERUNNER: Fix memory leaks in VQADecoder
2a60ddfd75 BLADERUNNER: Fix memory leaks in Image
97207bfc53 BLADERUNNER: Fix memory leaks in Script
86b4850d6c BLADERUNNER: Fix memory leaks in GameInfo
303aba7dd1 BLADERUNNER: tlk_id shouldn't read directly from name
789bb7a281 BLADERUNNER: Add Vector and Matrix classes
7ab0985ca8 COMMON: Add ReadFloatLE to Common::ReadStream
d9453057ab BLADERUNNER: Add View matrix loading
4b181e4bed BLADERUNNER: First pass at slice animation renderer
c8f5ded6d9 BLADERUNNER: SliceAnimation: Avoid using potentially uninitialized variable in destructor
74a8b530f1 BLADERUNNER: Add support for ambient sounds, game flags and variables, and use VQA z-buffer when rendering.
420d7f9ecc BLADERUNNER: Remove commented out code
abf98fca03 BLADERUNNER: Read set objects and walkboxes
b83daefd08 BLADERUNNER: Stub out init script
2d8f421597 BLADERUNNER: Init globals, game flags, and actor clues
35ea84935f BLADERUNNER: Split aud_decoder into aud_stream and adpcm_decoder
eba8ed5c66 BLADERUNNER: Add audio_speech and Actor_Voice_Over
da33169b75 BLADERUNNER: Fix a couple of memory leaks
0fa2191b95 BLADERUNNER: Implement loading and drawing of mouse cursors.
28c55ade89 BLADERUNNER: Add newline at end of file
90f879f5a8 BLADERUNNER: Implement Player_Loses_Control and Player_Gains_Control
02473a16c3 BLADERUNNER: Rearrange startup and shutdown a bit and document TODOs
6715157fad BLADERUNNER: Mismatched array new and delete
a4ba609131 BLADERUNNER: Add beginnings of Actor class and move actor drawing to Scene
6672e443a8 BLADERUNNER: just basic objects description scene stuff - lightning and effects movement track actor clues db actor walk
479d2f5b62 BLADERUNNER: still adding structures... and implementing some of script methods...
de7f961f48 BLADERUNNER: added implementation of more script methods added combat structure (maybe it combat mode??)
2888d0b346 BLADERUNNER: forgotten script files....
b67bca20b5 BLADERUNNER: Pull in changes from madmoose
bf44e97d79 BLADERUNNER: added all scene scripts, esper script, kia script, vk script, completed init script. Added decoding of ligh
c6011c1349 BLADERUNNER: mccoy script completed, walking is now animated
ae03eda3d1 BLADERUNNER: add more logic to actor::tick, added support for looking up scene objects
7e7cf4e748 BLADERUNNER: Fix compilation
cfc8ffed8a BLADERUNNER: fixed exit selection, added footstep sounds, added some debugging display (scene objects, regions, exits, w
f1cb735ee0 BLADERUNNER: added rendering support for lighting and effects, but its not working correctly yet
c7f7341f69 BLADERUNNER: fixed lightning
f5d5f3302f BLADERUNNER: fixed current frame selection for lights
af70a90cbc BLADERUNNER: fixed loading of new set/scene, fixed memoryleak in lights
a6f8a39dd3 BLADERUNNER: Fix warnings
0c7d323921 BLADERUNNER: add support for uncompressed audio, fixed wrong call to gamescript after loading scene
70c10f8243 BLADERUNNER: fixed compiler error in gcc and clang (was working in msvc14)
fe2add5d5f BLADERUNNER: fixed endian issue in uncompressed audio (thx madmoose), fixed some warnings, fixed some scene scripts
2c15b164d7 BLADERUNNER: added support for rendering items in scenes
89d1805b37 BLADERUNNER: added ADQ, fixed some minor memory leaks
77be430824 BLADERUNNER: Added missing copyright headers and normalized the rest
281c19ab03 BLADERUNNER: Code formatting fixes
6547c35e15 BLADERUNNER: trying to figure out walking, added structures for obstacles used for pathfinding, fixed bug in searching f
2b835eb14d BLADERUNNER: added missing license & code formatting
5d1e1131dc BLADERUNNER: code formatting
e0efee2eba BLADERUNNER: added suspects db & fixed crimes db
566da748e1 BLADERUNNER: added support for fonts
c934941e4f BLADERUNNER: fixed some of endianness issues
f30f3c46e3 BLADERUNNER: added item pickup effect
b5c4e09cec BLADERUNNER: Fix compilation
f7acbcb057 BLADERUNNER: fixed speed of pickup effect
8720c3a98f BLADERUNNER: fixed some compilation warnings
577c3b56a5 BLADERUNNER: added picking up of items
e89c76f63c Merge pull request #836 from peterkohaut/bladerunner


Commit: 2e3fd7cf050e24b9f6363b1a38c6ff45847c6d6f
    https://github.com/scummvm/scummvm/commit/2e3fd7cf050e24b9f6363b1a38c6ff45847c6d6f
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:21:00+02:00

Commit Message:
BLADERUNNER: Start port to scummvm engine

Just shows the splash for now. VQA decoder partially ported but without
audio and some minor special features.

Changed paths:
  A engines/bladerunner/archive.cpp
  A engines/bladerunner/archive.h
  A engines/bladerunner/bladerunner.cpp
  A engines/bladerunner/bladerunner.h
  A engines/bladerunner/chapters.cpp
  A engines/bladerunner/chapters.h
  A engines/bladerunner/configure.engine
  A engines/bladerunner/decompress_lcw.cpp
  A engines/bladerunner/decompress_lcw.h
  A engines/bladerunner/decompress_lzo.cpp
  A engines/bladerunner/decompress_lzo.h
  A engines/bladerunner/detection.cpp
  A engines/bladerunner/detection_tables.h
  A engines/bladerunner/gameinfo.cpp
  A engines/bladerunner/gameinfo.h
  A engines/bladerunner/image.cpp
  A engines/bladerunner/image.h
  A engines/bladerunner/module.mk
  A engines/bladerunner/settings.cpp
  A engines/bladerunner/settings.h
  A engines/bladerunner/vqa_decoder.cpp
  A engines/bladerunner/vqa_decoder.h



diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
new file mode 100644
index 0000000..93c122f
--- /dev/null
+++ b/engines/bladerunner/archive.cpp
@@ -0,0 +1,158 @@
+/* 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 "bladerunner/archive.h"
+
+#include "common/debug.h"
+
+namespace BladeRunner {
+
+MIXArchive::MIXArchive() {
+}
+
+MIXArchive::~MIXArchive() {
+	if (_fd.isOpen())
+		debug("~MIXArchive: fd not closed: %s", _fd.getName());
+}
+
+bool MIXArchive::open(const Common::String &filename) {
+	if (!_fd.open(filename)) {
+		debug("MIXArchive::open(): Could not open %s", filename.c_str());
+		return false;
+	}
+
+	_isTLK = filename.hasSuffix(".TLK");
+
+	_entry_count = _fd.readUint16LE();
+	_size        = _fd.readUint32LE();
+
+	_entries.resize(_entry_count);
+	for (uint16 i = 0; i != _entry_count; ++i) {
+		_entries[i].id     = _fd.readSint32LE();
+		_entries[i].offset = _fd.readUint32LE();
+		_entries[i].length = _fd.readUint32LE();
+
+		if (false)
+			debug("%08x %-12d %-12d", _entries[i].id, _entries[i].offset, _entries[i].length);
+
+		// Verify that the entries are sorted by id. Note that id is signed.
+		if (i > 0)
+			assert(_entries[i].id > _entries[i - 1].id);
+	}
+
+	if (_fd.err()) {
+		error("MIXArchive::open(): Error reading entries in %s", filename.c_str());
+		_fd.close();
+		return false;
+	}
+
+	debug("MIXArchive::open: Opened archive %s", filename.c_str());
+
+	return true;
+}
+
+void MIXArchive::close() {
+	return _fd.close();
+}
+
+bool MIXArchive::isOpen() const {
+	return _fd.isOpen();
+}
+
+#define ROL(n) ((n << 1) | ((n >> 31) & 1))
+
+static
+int32 mix_id(const Common::String &name) {
+	char buffer[12] = { 0 };
+
+	for (uint i = 0; i != name.size() && i < 12u; ++i)
+		buffer[i] = (char)toupper(name[i]);
+
+	uint32 id = 0;
+	for (int i = 0; i < 12 && buffer[i]; i += 4)
+	{
+		uint32 t = (uint32)buffer[i + 3] << 24
+		         | (uint32)buffer[i + 2] << 16
+		         | (uint32)buffer[i + 1] <<  8
+		         | (uint32)buffer[i + 0];
+
+		id = ROL(id) + t;
+	}
+
+	return reinterpret_cast<int32&>(id);
+}
+
+static
+int32 tlk_id(const Common::String &name) {
+	char buffer[12] = { 0 };
+
+	for (uint i = 0; i != name.size() && i < 12u; ++i)
+		buffer[i] = (char)toupper(name[i]);
+
+	int actor_id  =   10 * (name[0] - '0') +
+	                       (name[1] - '0');
+
+	int speech_id = 1000 * (name[3] - '0') +
+	                 100 * (name[4] - '0') +
+	                  10 * (name[5] - '0') +
+	                       (name[6] - '0');
+
+	return 10000 * actor_id + speech_id;
+}
+
+uint32 MIXArchive::indexForId(int32 id) const {
+	uint32 lo = 0, hi = _entry_count;
+
+	while (lo < hi)
+	{
+		uint32 mid = lo + (hi - lo) / 2;
+
+		if (id > _entries[mid].id)
+			lo = mid + 1;
+		else if (id < _entries[mid].id)
+			hi = mid;
+		else
+			return mid;
+	}
+	return _entry_count;
+}
+
+Common::SeekableReadStream *MIXArchive::createReadStreamForMember(const Common::String &name) {
+	int32 id;
+
+	if (_isTLK)
+		id = tlk_id(name);
+	else
+		id = mix_id(name);
+
+	uint32 i = indexForId(id);
+
+	if (i == _entry_count)
+		return NULL;
+
+	uint32 start = _entries[i].offset + 6 + 12 * _entry_count;
+	uint32 end   = _entries[i].length + start;
+
+	return new Common::SafeSeekableSubReadStream(&_fd, start, end, DisposeAfterUse::NO);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/archive.h b/engines/bladerunner/archive.h
new file mode 100644
index 0000000..1225c71
--- /dev/null
+++ b/engines/bladerunner/archive.h
@@ -0,0 +1,65 @@
+/* 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 BLADERUNNER_ARCHIVE_H
+#define BLADERUNNER_ARCHIVE_H
+
+#include "common/array.h"
+#include "common/file.h"
+#include "common/substream.h"
+
+namespace BladeRunner {
+
+class MIXArchive {
+public:
+	MIXArchive();
+	~MIXArchive();
+
+	bool open(const Common::String &filename);
+	void close();
+	bool isOpen() const;
+
+	Common::String getName() { return _fd.getName(); }
+
+	Common::SeekableReadStream *createReadStreamForMember(const Common::String &name);
+
+private:
+	Common::File _fd;
+	bool _isTLK;
+
+	uint16 _entry_count;
+	uint32 _size;
+
+	struct ArchiveEntry {
+		int32  id;
+		uint32 offset;
+		uint32 length;
+	};
+
+	Common::Array<ArchiveEntry> _entries;
+
+	uint32 indexForId(int32 id) const;
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
new file mode 100644
index 0000000..3ae0d47
--- /dev/null
+++ b/engines/bladerunner/bladerunner.cpp
@@ -0,0 +1,324 @@
+/* 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 "bladerunner/bladerunner.h"
+
+#include "bladerunner/chapters.h"
+#include "bladerunner/gameinfo.h"
+#include "bladerunner/image.h"
+#include "bladerunner/settings.h"
+#include "bladerunner/vqa_decoder.h"
+
+#include "common/error.h"
+#include "common/events.h"
+#include "common/system.h"
+
+#include "engines/util.h"
+
+#include "graphics/pixelformat.h"
+
+namespace BladeRunner {
+
+BladeRunnerEngine::BladeRunnerEngine(OSystem *syst) : Engine(syst) {
+	_gameInfo = nullptr;
+
+	_windowIsActive = true;
+	_gameIsRunning  = true;
+
+	_chapters = nullptr;
+	_settings = new Settings(this);
+}
+
+bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
+	return f == kSupportsRTL;
+}
+
+Common::Error BladeRunnerEngine::run() {
+	initGraphics(640, 480, true, &RGB555);
+
+	startup();
+
+	if (!warnUserAboutUnsupportedGame())
+		return Common::kNoError;
+
+	init2();
+
+	/* TODO: Check for save games and enter KIA */
+	gameLoop();
+
+	shutdown();
+
+	return Common::kNoError;
+}
+
+bool BladeRunnerEngine::startup() {
+	bool r;
+
+	_surface1.create(640, 480, RGB555);
+
+	r = openArchive("STARTUP.MIX");
+	if (!r)
+		return false;
+
+	loadSplash();
+
+	_gameInfo = new GameInfo(this);
+	if (!_gameInfo)
+		return false;
+
+	r = _gameInfo->open("GAMEINFO.DAT");
+	if (!r)
+		return false;
+
+	_chapters = new Chapters(this);
+	if (!_chapters)
+		return false;
+
+	r = openArchive("MUSIC.MIX");
+	if (!r)
+		return false;
+
+	r = openArchive("SFX.MIX");
+	if (!r)
+		return false;
+
+	r = openArchive("SPCHSFX.TLK");
+	if (!r)
+		return false;
+
+	initActors();
+
+	return true;
+}
+
+void BladeRunnerEngine::initActors() {
+	// TODO: Init actors...
+
+	_settings->setChapter(1);
+	_settings->setNewSetAndScene(_gameInfo->getInitialSetId(), _gameInfo->getInitialSceneId());
+}
+
+void BladeRunnerEngine::shutdown() {
+	if (_chapters) {
+		if (_chapters->hasOpenResources())
+			_chapters->closeResources();
+		delete _chapters;
+		_chapters = 0;
+	}
+
+	if (isArchiveOpen("MUSIC.MIX"))
+		closeArchive("MUSIC.MIX");
+
+	if (isArchiveOpen("SFX.MIX"))
+		closeArchive("SFX.MIX");
+
+	if (isArchiveOpen("SPCHSFX.TLK"))
+		closeArchive("SPCHSFX.TLK");
+
+	if (isArchiveOpen("STARTUP.MIX"))
+		closeArchive("STARTUP.MIX");
+}
+
+void BladeRunnerEngine::loadSplash() {
+	Image img(this);
+	if (!img.open("SPLASH.IMG"))
+		return;
+
+	img.copyToSurface(&_surface1);
+
+	_system->copyRectToScreen(_surface1.getPixels(), _surface1.pitch, 0, 0, _surface1.w, _surface1.h);
+	_system->updateScreen();
+}
+
+bool BladeRunnerEngine::init2() {
+	return true;
+}
+
+void BladeRunnerEngine::gameLoop() {
+	_gameIsRunning = true;
+	do {
+		/* TODO: check player death */
+		gameTick();
+	} while (_gameIsRunning && !shouldQuit());
+}
+
+void BladeRunnerEngine::gameTick() {
+	handleEvents();
+
+	if (_gameIsRunning && _windowIsActive) {
+		// TODO: Only run if not in Kia, script, nor AI
+		_settings->openNewScene();
+
+		// TODO: Autosave
+		// TODO: Kia
+		// TODO: Spinner
+		// TODO: Esper
+		// TODO: VK
+		// TODO: Elevators
+		// TODO: Scores
+		// TODO: Call Script_Player_Walked_In if applicable
+		// TODO: Gun range announcements
+		// TODO: ZBUF repair dirty rects
+		// TODO: Tick Ambient Audio (in Replicant)
+
+		// TODO: Advance frame (in Replicant)
+		// TODO: Render overlays (mostly in Replicant)
+		// TODO: Tick Actor AI and Timers (timers in Replicant)
+
+		if (_settings->getNewScene() == -1 /* || in_script_counter || in_ai */) {
+
+			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
+			// TODO: Draw items (drawing works in Replicant)
+			// TODO: Draw item pickup (understood, drawing works in Replicant)
+			// TODO: Draw dialogue menu
+			// TODO: Draw mouse (understood)
+			// TODO: Process AUD (audio in Replicant)
+			// TODO: Footstep sound
+
+			_system->updateScreen();
+		}
+	}
+}
+
+void BladeRunnerEngine::handleEvents() {
+	Common::Event event;
+	Common::EventManager *eventMan = _system->getEventManager();
+	while (eventMan->pollEvent(event)) {
+	}
+}
+
+void BladeRunnerEngine::playOuttake(int id, bool no_localization) {
+	Common::String name = _gameInfo->getOuttake(id);
+
+	if (no_localization)
+		name += ".VQA";
+	else
+		name += "_E.VQA";
+
+	Common::SeekableReadStream *s = getResourceStream(name);
+	if (!s)
+		return;
+
+	VQADecoder vqa_decoder(s);
+
+	bool b = vqa_decoder.read_header();
+	if (!b) return;
+
+	uint32 frame_count = 0;
+	uint32 start_time = 0;
+	uint32 next_frame_time = 0;
+
+	for (;;)
+	{
+		handleEvents();
+		// TODO: Handle skips
+		if (shouldQuit())
+			break;
+
+		uint32 cur_time = next_frame_time + 1;
+
+		if (next_frame_time <= cur_time)
+		{
+			int frame_number = vqa_decoder.read_frame();
+			debug("frame_number: %d", frame_number);
+
+			if (frame_number < 0)
+				break;
+
+			b = vqa_decoder.decode_frame((uint16*)_surface1.getPixels());
+
+			_system->copyRectToScreen(_surface1.getPixels(), _surface1.pitch, 0, 0, _surface1.w, _surface1.h);
+			_system->updateScreen();
+
+			++frame_count;
+
+			if (!next_frame_time)
+				next_frame_time = cur_time;
+			next_frame_time = next_frame_time + (60 * 1000) / 15;
+		}
+	}
+}
+
+bool BladeRunnerEngine::openArchive(const Common::String &name) {
+	uint i;
+
+	// If archive is already open, return true
+	for (i = 0; i != kArchiveCount; ++i) {
+		if (_archives[i].isOpen() && _archives[i].getName() == name)
+			return true;
+	}
+
+	// Find first available slot
+	for (i = 0; i != kArchiveCount; ++i) {
+		if (!_archives[i].isOpen())
+			break;
+	}
+	if (i == kArchiveCount) {
+		/* TODO: BLADE.EXE retires the least recently used
+		 * archive when it runs out of slots. */
+
+		error("openArchive: No more archive slots");
+		return false;
+	}
+
+	_archives[i].open(name);
+	return _archives[i].isOpen();
+}
+
+bool BladeRunnerEngine::closeArchive(const Common::String &name) {
+	for (uint i = 0; i != 10; ++i) {
+		if (_archives[i].isOpen() &&_archives[i].getName() == name) {
+			_archives[i].close();
+			return true;
+		}
+	}
+
+	debug("closeArchive: Archive %s not open.", name.c_str());
+	return false;
+}
+
+bool BladeRunnerEngine::isArchiveOpen(const Common::String &name) {
+	for (uint i = 0; i != 10; ++i) {
+		if (_archives[i].isOpen() &&_archives[i].getName() == name)
+			return true;
+	}
+
+	return false;
+}
+
+Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::String &name) {
+	for (uint i = 0; i != 10; ++i) {
+		if (!_archives[i].isOpen())
+			continue;
+
+		if (false)
+			debug("getResource: Searching archive %s for %s.", _archives[i].getName().c_str(), name.c_str());
+		Common::SeekableReadStream *stream = _archives[i].createReadStreamForMember(name);
+		if (stream)
+			return stream;
+	}
+
+	debug("getResource: Resource %s not found.", name.c_str());
+	return 0;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
new file mode 100644
index 0000000..c679b80
--- /dev/null
+++ b/engines/bladerunner/bladerunner.h
@@ -0,0 +1,91 @@
+/* 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 BLADERUNNER_BLADERUNNER_H
+#define BLADERUNNER_BLADERUNNER_H
+
+#include "bladerunner/archive.h"
+
+#include "common/array.h"
+#include "common/stream.h"
+#include "common/types.h"
+
+#include "engines/engine.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+const Graphics::PixelFormat RGB555(2, 5, 5, 5, 0, 10, 5, 0, 0);
+
+class Chapters;
+class Settings;
+class GameInfo;
+
+class BladeRunnerEngine : public Engine {
+	GameInfo *_gameInfo;
+
+public:
+	bool      _gameIsRunning;
+	bool      _windowIsActive;
+
+	Chapters *_chapters;
+	Settings *_settings;
+
+	int in_script_counter;
+
+private:
+	static const int kArchiveCount = 10;
+	MIXArchive _archives[kArchiveCount];
+
+	Graphics::Surface _surface1;
+
+public:
+	BladeRunnerEngine(OSystem *syst);
+
+	bool hasFeature(EngineFeature f) const;
+
+	Common::Error BladeRunnerEngine::run();
+
+	bool startup();
+	void initActors();
+	void shutdown();
+
+	void loadSplash();
+	bool init2();
+
+	void gameLoop();
+	void gameTick();
+	void handleEvents();
+
+	void playOuttake(int id, bool no_localization);
+
+	bool openArchive(const Common::String &name);
+	bool closeArchive(const Common::String &name);
+	bool isArchiveOpen(const Common::String &name);
+
+	Common::SeekableReadStream *getResourceStream(const Common::String &name);
+};
+
+} // End of namespace Blade Runner
+
+#endif
diff --git a/engines/bladerunner/chapters.cpp b/engines/bladerunner/chapters.cpp
new file mode 100644
index 0000000..280ce92
--- /dev/null
+++ b/engines/bladerunner/chapters.cpp
@@ -0,0 +1,59 @@
+/* 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 "bladerunner/chapters.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+bool Chapters::enterChapter(int chapter) {
+	int id = _resourceIds[chapter];
+
+	if (!_vm->openArchive("A.TLK"))
+		return false;
+
+	if (!_vm->openArchive(Common::String::format("VQA%d.MIX", MAX(id, 3))))
+		return false;
+
+	if (!_vm->openArchive(Common::String::format("%d.TLK", MAX(id, 3))))
+		return false;
+
+	if (!_vm->openArchive(Common::String::format("OUTTAKE%d.MIX", id)))
+		return false;
+
+	_chapter = chapter;
+	_hasOpenResources = true;
+	return true;
+}
+
+void Chapters::closeResources() {
+	int id = _resourceIds[_chapter];
+
+	_vm->closeArchive("A.TLK");
+	_vm->closeArchive(Common::String::format("VQA%d.MIX", MAX(id, 3)));
+	_vm->closeArchive(Common::String::format("%d.TLK", MAX(id, 3)));
+	_vm->closeArchive(Common::String::format("OUTTAKE%d.MIX", id));
+	_hasOpenResources = false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/chapters.h b/engines/bladerunner/chapters.h
new file mode 100644
index 0000000..9fae487
--- /dev/null
+++ b/engines/bladerunner/chapters.h
@@ -0,0 +1,62 @@
+/* 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 BLADERUNNER_CHAPTERS_H
+#define BLADERUNNER_CHAPTERS_H
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Chapters {
+	BladeRunnerEngine *_vm;
+
+	int  _chapter;
+	int  _resourceIds[6];
+	bool _hasOpenResources;
+
+public:
+	Chapters(BladeRunnerEngine *vm)
+		: _vm(vm), _chapter(0)
+	{
+		_chapter = 0;
+
+		_resourceIds[0] = 1;
+		_resourceIds[1] = 1;
+		_resourceIds[2] = 2;
+		_resourceIds[3] = 2;
+		_resourceIds[4] = 3;
+		_resourceIds[5] = 4;
+
+		_hasOpenResources = false;
+	}
+
+	bool enterChapter(int chapter);
+	void closeResources();
+
+	bool hasOpenResources() { return _hasOpenResources; }
+	int  currentResouceId() { return _chapter ? _resourceIds[_chapter] : -1; }
+};
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/configure.engine b/engines/bladerunner/configure.engine
new file mode 100644
index 0000000..611309f
--- /dev/null
+++ b/engines/bladerunner/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine bladerunner "Blade Runner" no "" "" "16bit"
diff --git a/engines/bladerunner/decompress_lcw.cpp b/engines/bladerunner/decompress_lcw.cpp
new file mode 100644
index 0000000..e632ec7
--- /dev/null
+++ b/engines/bladerunner/decompress_lcw.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.
+ *
+ */
+
+#include "bladerunner/decompress_lcw.h"
+
+#include "common/util.h"
+
+namespace BladeRunner {
+
+uint32 decompress_lcw(uint8 *inBuf, uint32 inLen, uint8 *outBuf, uint32 outLen) {
+	int version = 1;
+	int count, i, color, pos, relpos, out_remain;
+
+	uint8 *src = inBuf;
+	uint8 *dst = outBuf;
+	uint8 *outEnd = dst + outLen;
+
+	if (src[0] == 0)
+	{
+		version = 2;
+		++src;
+	}
+
+	while (src[0] != 0x80 && src < inBuf + inLen && dst < outEnd)
+	{
+		out_remain = (int)(outEnd - dst);
+
+		if (src[0] == 0xff)      // 0b11111111
+		{
+			count = src[1] | (src[2] << 8);
+			pos   = src[3] | (src[4] << 8);
+			src += 5;
+			count = MIN(count, out_remain);
+
+			if (version == 1)
+			{
+				for (i = 0; i < count; i++)
+					dst[i] = outBuf[i + pos];
+			}
+			else
+			{
+				for (i = 0; i < count; i++)
+					dst[i] = *(dst + i - pos);
+			}
+		}
+		else if (src[0] == 0xfe) // 0b11111110
+		{
+			count = src[1] | (src[2] << 8);
+			color = src[3];
+			src += 4;
+			count = MIN(count, out_remain);
+
+			memset(dst, color, count);
+		}
+		else if (src[0] >= 0xc0)  // 0b11??????
+		{
+			count = (src[0] & 0x3f) + 3;
+			pos   = src[1] | (src[2] << 8);
+			src += 3;
+			count = MIN(count, out_remain);
+
+			if (version == 1)
+			{
+				for (i = 0; i < count; i++)
+					dst[i] = outBuf[i + pos];
+			}
+			else
+			{
+				for (i = 0; i < count; i++)
+					dst[i] = *(dst + i - pos);
+			}
+		}
+		else if (src[0] >= 0x80)  // 0b10??????
+		{
+			count = src[0] & 0x3f;
+			++src;
+			count = MIN(count, out_remain);
+
+			memcpy(dst, src, count);
+			src += count;
+		}
+		else                     // 0b0???????
+		{
+			count  = ((src[0] & 0x70) >> 4) + 3;
+			relpos = ((src[0] & 0x0f) << 8) | src[1];
+			src += 2;
+			count = MIN(count, out_remain);
+
+			for (i = 0; i < count; i++)
+			{
+				dst[i] = *(dst + i - relpos);
+			}
+		}
+
+		dst += count;
+	}
+
+	return uint32(dst - outBuf);
+}
+
+uint32 decompress_lcw_output_size(uint8 *inBuf, uint32 inLen) {
+	int count;
+	uint8 *src     = inBuf;
+	uint32 outsize = 0;
+
+	if (src[0] == 0)
+		++src;
+
+	while (src[0] != 0x80 && src < inBuf + inLen)
+	{
+		if (src[0] == 0xff)      // 0b11111111
+		{
+			count = src[1] | (src[2] << 8);
+			src += 5;
+		}
+		else if (src[0] == 0xfe) // 0b11111110
+		{
+			count = src[1] | (src[2] << 8);
+			src += 4;
+		}
+		else if (src[0] >= 0xc0)  // 0b11??????
+		{
+			count = (src[0] & 0x3f) + 3;
+			src += 3;
+		}
+		else if (src[0] & 0x80)  // 0b10??????
+		{
+			count = src[0] & 0x3f;
+			src += count + 1;
+		}
+		else                     // 0b0???????
+		{
+			count  = ((src[0] & 0x70) >> 4) + 3;
+			src += 2;
+		}
+
+		outsize += count;
+	}
+
+	return outsize;
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/decompress_lcw.h b/engines/bladerunner/decompress_lcw.h
new file mode 100644
index 0000000..ea09aab
--- /dev/null
+++ b/engines/bladerunner/decompress_lcw.h
@@ -0,0 +1,35 @@
+/* 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 BLADERUNNER_DECOMPRESS_LCW_H
+#define BLADERUNNER_DECOMPRESS_LCW_H
+
+#include "common/types.h"
+
+namespace BladeRunner {
+
+uint32 decompress_lcw(uint8 *inBuf, uint32 inLen, uint8 *outBuf, uint32 outLen);
+uint32 decompress_lcw_output_size(void *inBuf, uint32 inLen);
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/decompress_lzo.cpp b/engines/bladerunner/decompress_lzo.cpp
new file mode 100644
index 0000000..147d11d
--- /dev/null
+++ b/engines/bladerunner/decompress_lzo.cpp
@@ -0,0 +1,143 @@
+/* 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 "bladerunner/decompress_lzo.h"
+
+namespace BladeRunner {
+
+static inline
+uint32 decode_count(const uint8 **pp) {
+	uint32 v = 0;
+	for (;!**pp;(*pp)++)
+		v += 255;
+
+	v += **pp;
+	(*pp)++;
+
+	return v;
+}
+
+static inline
+void copy(uint8 **dst, const uint8 **src, int count) {
+	assert(count > 0);
+
+	uint8 *d = *dst;
+	const uint8 *s = *src;
+
+	*dst += count;
+	*src += count;
+
+	do { *d++ = *s++; } while (--count);
+}
+
+int decompress_lzo1x(const uint8 *in, size_t inLen, uint8 *out, size_t *outLen) {
+	uint32 t;
+	uint8 *op;
+	const uint8 *ip, *m_pos;
+	const uint8 * const ip_end = in + inLen;
+
+	*outLen = 0;
+
+	op = out;
+	ip = in;
+
+	if (*ip > 17) {
+		t = *ip++ - 17;
+		if (t < 4)
+			goto match_next;
+		copy(&op, &ip, t);
+		goto first_literal_run;
+	}
+
+	for (;;) {
+		t = *ip++;
+		if (t >= 16)
+			goto match;
+
+		if (t == 0)
+			t = 15 + decode_count(&ip);
+		copy(&op, &ip, t + 3);
+
+first_literal_run:
+		t = *ip++;
+		if (t >= 16)
+			goto match;
+		m_pos = op - 0x0801 - (t >> 2) - (*ip++ << 2);
+		copy(&op, &m_pos, 3);
+		goto match_done;
+
+		for (;;) {
+match:
+			if (t >= 64)
+			{
+				m_pos = op - 1 - ((t >> 2) & 7) - (*ip++ << 3);
+				t = (t >> 5) - 1;
+				goto copy_match;
+			}
+			else if (t >= 32)
+			{
+				t &= 31;
+				if (t == 0)
+					t = 31 + decode_count(&ip);
+				m_pos = op - 1 - (ip[0] >> 2) - (ip[1] << 6);
+				ip += 2;
+			}
+			else if (t >= 16)
+			{
+				m_pos = op - ((t & 8) << 11);
+				t &= 7;
+				if (t == 0)
+					t = 7 + decode_count(&ip);
+				m_pos -= (ip[0] >> 2) + (ip[1] << 6);
+				ip += 2;
+				if (m_pos == op)
+					goto eof_found;
+				m_pos -= 0x4000;
+			}
+			else
+			{
+				m_pos = op - 1 - (t >> 2) - (*ip++ << 2);
+				copy(&op, &m_pos, 2);
+				goto match_done;
+			}
+
+copy_match:
+			copy(&op, &m_pos, t + 2);
+
+match_done:
+			t = ip[-2] & 3;
+			if (t == 0)
+				break;
+
+match_next:
+ 			assert(t > 0 && t <= 3);
+			copy(&op, &ip, t);
+			t = *ip++;
+		}
+	}
+
+eof_found:
+	*outLen = op - out;
+	return ip != ip_end;
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/decompress_lzo.h b/engines/bladerunner/decompress_lzo.h
new file mode 100644
index 0000000..20e8581
--- /dev/null
+++ b/engines/bladerunner/decompress_lzo.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.
+ *
+ */
+
+#ifndef BLADERUNNER_DECOMPRESS_LZO_H
+#define BLADERUNNER_DECOMPRESS_LZO_H
+
+#include "common/types.h"
+
+namespace BladeRunner {
+
+int decompress_lzo1x(const uint8 *in, size_t inLen, uint8 *out, size_t *outLen);
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/detection.cpp b/engines/bladerunner/detection.cpp
new file mode 100644
index 0000000..1e40f3d
--- /dev/null
+++ b/engines/bladerunner/detection.cpp
@@ -0,0 +1,66 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/detection_tables.h"
+
+namespace BladeRunner {
+
+static const PlainGameDescriptor bladeRunnerGames[] = {
+	{"bladerunner", "Blade Runner"},
+	{0, 0}
+};
+
+} // End of namespace BladeRunner
+
+class BladeRunnerMetaEngine : public AdvancedMetaEngine {
+public:
+	BladeRunnerMetaEngine() : AdvancedMetaEngine(BladeRunner::gameDescriptions, sizeof(BladeRunner::gameDescriptions[0]), BladeRunner::bladeRunnerGames) {
+	}
+
+	virtual const char *getName() const {
+		return "Blade Runner Engine";
+	}
+
+	virtual const char *getOriginalCopyright() const {
+		return "Blade Runner (C) Westwood Studios.";
+	}
+
+	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+};
+
+bool BladeRunnerMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const
+{
+	*engine = new BladeRunner::BladeRunnerEngine(syst);
+
+	return true;
+}
+
+#if PLUGIN_ENABLED_DYNAMIC(BLADERUNNER)
+	REGISTER_PLUGIN_DYNAMIC(BLADERUNNER, PLUGIN_TYPE_ENGINE, BladeRunnerMetaEngine);
+#else
+	REGISTER_PLUGIN_STATIC(BLADERUNNER, PLUGIN_TYPE_ENGINE, BladeRunnerMetaEngine);
+#endif
diff --git a/engines/bladerunner/detection_tables.h b/engines/bladerunner/detection_tables.h
new file mode 100644
index 0000000..90f27ff
--- /dev/null
+++ b/engines/bladerunner/detection_tables.h
@@ -0,0 +1,47 @@
+/* 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 BLADERUNNER_DETECTION_TABLES_H
+#define BLADERUNNER_DETECTION_TABLES_H
+
+namespace BladeRunner {
+
+static const ADGameDescription gameDescriptions[] = {
+	// BladeRunner
+	{
+		"bladerunner",
+		0,
+		{
+			{"STARTUP.MIX", 0, "5643b53306ca7764cf1ec7b79c9630a3", 2312374},
+			AD_LISTEND
+		},
+		Common::EN_ANY,
+		Common::kPlatformWindows,
+		ADGF_NO_FLAGS,
+		GUIO0()
+	},
+	AD_TABLE_END_MARKER
+};
+
+} // End of namespace Hopkins
+
+#endif
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
new file mode 100644
index 0000000..66a7af8
--- /dev/null
+++ b/engines/bladerunner/gameinfo.cpp
@@ -0,0 +1,112 @@
+/* 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 "bladerunner/gameinfo.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/debug.h"
+#include "common/substream.h"
+
+namespace BladeRunner {
+
+GameInfo::GameInfo(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_set_names    = nullptr;
+	_sfx_tracks   = nullptr;
+	_music_tracks = nullptr;
+	_outtakes     = nullptr;
+}
+
+GameInfo::~GameInfo() {
+	delete[] _set_names;
+	delete[] _sfx_tracks;
+	delete[] _music_tracks;
+	delete[] _outtakes;
+}
+
+bool GameInfo::open(const Common::String &name) {
+	Common::SeekableReadStream *s = _vm->getResourceStream(name);
+
+	if (!s)
+		return false;
+
+	uint32 unk;
+	_actor_count          = s->readUint32LE();   /* 00 */
+	unk                   = s->readUint32LE();   /* 01 */
+	_flag_count           = s->readUint32LE();   /* 02 */
+	unk                   = s->readUint32LE();   /* 03 */
+	_global_var_count     = s->readUint32LE();   /* 04 */
+	_set_names_count      = s->readUint32LE();   /* 05 */
+	_initial_scene_id     = s->readUint32LE();   /* 06 */
+	unk                   = s->readUint32LE();   /* 07 */
+	_initial_set_id       = s->readUint32LE();   /* 08 */
+	unk                   = s->readUint32LE();   /* 09 */
+	_waypoint_count       = s->readUint32LE();   /* 10 */
+	_sfx_track_count      = s->readUint32LE();   /* 11 */
+	_music_track_count    = s->readUint32LE();   /* 12 */
+	_outtake_count        = s->readUint32LE();   /* 13 */
+	unk                   = s->readUint32LE();   /* 14 */
+	unk                   = s->readUint32LE();   /* 15 */
+	_cover_waypoint_count = s->readUint32LE();   /* 16 */
+	_flee_waypoint_count  = s->readUint32LE();   /* 17 */
+
+	(void)unk;
+
+	_set_names = new char[_set_names_count][5];
+	for (uint32 i = 0; i != _set_names_count; ++i)
+		s->read(_set_names[i], 5);
+
+	_sfx_tracks = new char[_sfx_track_count][13];
+	for (uint32 i = 0; i != _sfx_track_count; ++i)
+	{
+		s->read(_sfx_tracks[i], 9);
+		strcat(_sfx_tracks[i], ".AUD");
+	}
+
+	_music_tracks = new char[_music_track_count][13];
+	for (uint32 i = 0; i != _music_track_count; ++i)
+	{
+		s->read(_music_tracks[i], 9);
+		strcat(_music_tracks[i], ".AUD");
+	}
+
+	_outtakes = new char[_outtake_count][13];
+	for (uint32 i = 0; i != _outtake_count; ++i)
+		s->read(_outtakes[i], 9);
+
+	if (false) {
+		for (uint32 i = 0; i != _set_names_count; ++i)
+			debug("%3d: %s", i, _set_names[i]);
+		for (uint32 i = 0; i != _sfx_track_count; ++i)
+			debug("%3d: %s", i, _sfx_tracks[i]);
+		for (uint32 i = 0; i != _music_track_count; ++i)
+			debug("%s", _music_tracks[i]);
+		for (uint32 i = 0; i != _outtake_count; ++i)
+			debug("%2d: %s.VQA", i, _outtakes[i]);
+	}
+
+	return !s->err();
+}
+
+} // End of namespace Blade Runner
diff --git a/engines/bladerunner/gameinfo.h b/engines/bladerunner/gameinfo.h
new file mode 100644
index 0000000..64153be
--- /dev/null
+++ b/engines/bladerunner/gameinfo.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 BLADERUNNER_GAMEINFO_H
+#define BLADERUNNER_GAMEINFO_H
+
+#include "common/str.h"
+
+#include "common/str.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class GameInfo {
+	BladeRunnerEngine *_vm;
+
+	uint32 _actor_count;
+	uint32 _flag_count;
+	uint32 _global_var_count;
+	uint32 _set_names_count;
+	uint32 _initial_scene_id;
+	uint32 _initial_set_id;
+	uint32 _waypoint_count;
+	uint32 _sfx_track_count;
+	uint32 _music_track_count;
+	uint32 _outtake_count;
+	uint32 _cover_waypoint_count;
+	uint32 _flee_waypoint_count;
+
+	char (*_set_names)[5];
+	char (*_sfx_tracks)[13];
+	char (*_music_tracks)[13];
+	char (*_outtakes)[13];
+
+public:
+	GameInfo(BladeRunnerEngine *vm);
+	~GameInfo();
+
+	bool open(const Common::String &name);
+
+	uint32 getActorCount()         { return _actor_count; }
+	uint32 getFlagCount()          { return _flag_count; }
+	uint32 getGlobalVarCount()     { return _global_var_count; }
+	uint32 getSetNamesCount()      { return _set_names_count; }
+	uint32 getInitialSceneId()     { return _initial_scene_id; }
+	uint32 getInitialSetId()       { return _initial_set_id; }
+	uint32 getWaypointCount()      { return _waypoint_count; }
+	uint32 getSfxTrackCount()      { return _sfx_track_count; }
+	uint32 getMusicTrackCount()    { return _music_track_count; }
+	uint32 getOuttakeCount()       { return _outtake_count; }
+	uint32 getCoverWaypointCount() { return _cover_waypoint_count; }
+	uint32 getFleeWaypointCount()  { return _flee_waypoint_count; }
+
+	char *getSetName(int i)        { return _set_names[i]; }
+	char *getSfxTrack(int i)       { return _sfx_tracks[i]; }
+	char *getMusicTrack(int i)     { return _music_tracks[i]; }
+	char *getOuttake(int i)        { return _outtakes[i]; }
+};
+
+} // End of namespace Blade Runner
+
+#endif
diff --git a/engines/bladerunner/image.cpp b/engines/bladerunner/image.cpp
new file mode 100644
index 0000000..fc6b68f
--- /dev/null
+++ b/engines/bladerunner/image.cpp
@@ -0,0 +1,78 @@
+/* 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 "bladerunner/image.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/decompress_lcw.h"
+
+#include "common/rect.h"
+
+namespace BladeRunner {
+
+Image::Image(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+}
+
+bool Image::open(const Common::String &name) {
+	Common::SeekableReadStream *stream = _vm->getResourceStream(name);
+	if (!stream) {
+		debug("Image::open failed to open '%s'\n", name.c_str());
+		return false;
+	}
+
+	char tag[4] = { 0 };
+	stream->read(tag, 3);
+	uint32 width  = stream->readUint32LE();
+	uint32 height = stream->readUint32LE();
+
+	// Enforce a reasonable limit
+	assert(width < 8000 && height < 8000);
+
+	uint32 bufSize = stream->size();
+	uint8 *buf = new uint8[bufSize];
+	stream->read(buf, bufSize);
+
+	uint32 dataSize = 2 * width * height;
+	void *data = malloc(dataSize);
+	assert(data);
+
+	if (strcmp(tag, "LZO") == 0) {
+		debug("LZO");
+	} else if (strcmp(tag, "LCW") == 0) {
+		decompress_lcw(buf, bufSize, (uint8*)data, dataSize);
+	}
+
+	const Graphics::PixelFormat pixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+	_surface.init(width, height, 2*width, data, pixelFormat);
+
+	delete[] buf;
+
+	return true;
+}
+
+void Image::copyToSurface(Graphics::Surface *dst) const {
+	dst->copyRectToSurface(_surface, 0, 0, Common::Rect(_surface.w, _surface.h));
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/image.h b/engines/bladerunner/image.h
new file mode 100644
index 0000000..5d2fa69
--- /dev/null
+++ b/engines/bladerunner/image.h
@@ -0,0 +1,47 @@
+/* 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 BLADERUNNER_IMAGE_H
+#define BLADERUNNER_IMAGE_H
+
+#include "common/debug.h"
+#include "common/substream.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Image {
+	BladeRunnerEngine *_vm;
+	Graphics::Surface  _surface;
+public:
+	Image(BladeRunnerEngine *vm);
+
+	bool open(const Common::String &name);
+	void copyToSurface(Graphics::Surface *surface) const;
+};
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
new file mode 100644
index 0000000..c0d6416
--- /dev/null
+++ b/engines/bladerunner/module.mk
@@ -0,0 +1,21 @@
+MODULE := engines/bladerunner
+
+MODULE_OBJS = \
+	archive.o \
+	bladerunner.o \
+	chapters.o \
+	decompress_lcw.o \
+	decompress_lzo.o \
+	detection.o \
+	gameinfo.o \
+	image.o \
+	settings.o \
+	vqa_decoder.o
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
new file mode 100644
index 0000000..8e46b5d
--- /dev/null
+++ b/engines/bladerunner/settings.cpp
@@ -0,0 +1,99 @@
+/* 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 "bladerunner/settings.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/chapters.h"
+
+namespace BladeRunner {
+
+Settings::Settings(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_chapter = 1;
+	_gamma = 1.0f;
+
+	_chapterChanged;
+	_newChapter;
+	_newScene;
+	_newSet;
+
+	_startingGame;
+	_loadingGame;
+
+	_fullHDFrames;
+	_mst3k;
+
+}
+
+bool Settings::openNewScene() {
+	if (_newSet == -1) {
+		assert(_newScene == -1);
+		return true;
+	}
+	assert(_newScene != -1);
+
+	if (_startingGame) {
+		// Stop ambient audio and music
+	}
+
+	// int currentSet = _vm->scene()->getSet();
+	// int newSet     = _newSet;
+	// int newScene   = _newScene;
+
+	_newSet = -1;
+	_newScene = -1;
+
+	if (_chapterChanged) {
+		if (_vm->_chapters->hasOpenResources())
+			_vm->_chapters->closeResources();
+
+		int newChapter = _newChapter;
+		_chapterChanged = false;
+		_newChapter = 0;
+		if (!_vm->_chapters->enterChapter(newChapter))
+		{
+			_vm->_gameIsRunning = false;
+			return false;
+		}
+		_chapter = newChapter;
+		if (_startingGame)
+			_startingGame = false;
+	}
+
+	// if (!_vm->scene()->open(newSet, newScene, _loadingGame))
+	// {
+	// 	_vm->_gameIsRunning = false;
+	// 	return false;
+	// }
+
+	// if (!_loadingGame && currentSet != newSet) {
+	// 	// TODO: Reset actors for new set
+
+	// }
+
+	_loadingGame = false;
+	return true;
+}
+
+} // End of namespace Blade Runner
diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h
new file mode 100644
index 0000000..cb35285
--- /dev/null
+++ b/engines/bladerunner/settings.h
@@ -0,0 +1,94 @@
+/* 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 BLADERUNNER_SETTINGS_H
+#define BLADERUNNER_SETTINGS_H
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Settings {
+	BladeRunnerEngine *_vm;
+
+	int   _chapter;
+	float _gamma;
+
+	bool  _chapterChanged;
+	int   _newChapter;
+	int   _newScene;
+	int   _newSet;
+
+	bool  _startingGame;
+	bool  _loadingGame;
+
+	int   _fullHDFrames;
+	int   _mst3k;
+
+public:
+	Settings(BladeRunnerEngine *vm);
+
+	void setGamma(float gamma) {
+		_gamma = gamma;
+	}
+
+	void setNewSetAndScene(int set, int scene) {
+		_newSet = set;
+		_newScene = scene;
+	}
+
+	void clearNewSetAndScene() {
+		_newSet = -1;
+		_newScene = -1;
+	}
+
+	int getNewScene() {
+		return _newScene;
+	}
+
+	int getNewSet() {
+		return _newSet;
+	}
+
+	void setChapter(int newChapter) {
+		_chapterChanged = true;
+		_newChapter = newChapter;
+	}
+
+	void setLoadingGame(bool loadingGame) {
+		_loadingGame = loadingGame;
+	}
+
+	bool getLoadingGame() {
+		return _loadingGame;
+	}
+
+	void setStartingGame(bool startingGame) {
+		_startingGame = startingGame;
+	}
+
+	bool openNewScene();
+};
+
+} // End of namespace Blade Runner
+
+#endif
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
new file mode 100644
index 0000000..b717964
--- /dev/null
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -0,0 +1,933 @@
+/* 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 BLADERUNNER_VQA_DECODER_H
+#define BLADERUNNER_VQA_DECODER_H
+
+#include "bladerunner/vqa_decoder.h"
+
+#include "bladerunner/decompress_lcw.h"
+#include "bladerunner/decompress_lzo.h"
+
+#include "common/array.h"
+#include "common/util.h"
+
+namespace BladeRunner {
+
+#define kAESC 0x41455343
+#define kCBFZ 0x4342465A
+#define kCIND 0x43494E44
+#define kCINF 0x43494E46
+#define kCINH 0x43494E48
+#define kCLIP 0x434C4950
+#define kFINF 0x46494E46
+#define kFORM 0x464f524d
+#define kLIND 0x4C494E44
+#define kLINF 0x4C494E46
+#define kLINH 0x4C494E48
+#define kLITE 0x4C495445
+#define kLNID 0x4C4E4944
+#define kLNIH 0x4C4E4948
+#define kLNIN 0x4C4E494E
+#define kLNIO 0x4C4E494F
+#define kMFCD 0x4D464344
+#define kMFCH 0x4D464348
+#define kMFCI 0x4D464349
+#define kMFCT 0x4D464354
+#define kMSCH 0x4D534348
+#define kMSCI 0x4D534349
+#define kMSCT 0x4D534354
+#define kSN2J 0x534e324a
+#define kSND2 0x534e4432
+#define kVIEW 0x56494557
+#define kVPTR 0x56505452
+#define kVQFL 0x5651464C
+#define kVQFR 0x56514652
+#define kVQHD 0x56514844
+#define kWVQA 0x57565141
+#define kZBUF 0x5A425546
+
+VQADecoder::VQADecoder(Common::SeekableReadStream *r)
+	: r(r),
+	  frame(0),
+	  zbuf(0),
+	  codebook(0),
+	  cbfz(0),
+	  vptr(0),
+	  cur_frame(-1),
+	  cur_loop(-1),
+	  loop_special(-1),
+	  loop_default(-1),
+	  has_view(false),
+	  audio_frame(0),
+	  max_view_chunk_size(0),
+	  max_zbuf_chunk_size(0),
+	  max_aesc_chunk_size(0)
+{
+	// debug("Opening VQA: '%s'\n", r->get_name());
+}
+
+VQADecoder::~VQADecoder()
+{
+}
+
+struct iff_chunk_header_s
+{
+	iff_chunk_header_s()
+		: id(0), size(0)
+	{}
+
+	uint32 id;
+	uint32 size;
+};
+
+static inline uint32 roundup(uint32 v)
+{
+	return (v + 1) & ~1u;
+}
+
+const char *str_tag(uint32 tag);
+
+int32 stream_remain(Common::SeekableReadStream *s) {
+	int32 pos = s->pos();
+	if (pos == -1) return -1;
+
+	int32 size = s->size();
+	if (size == -1) return -1;
+
+	return size - pos;
+}
+
+static
+bool read_iff_chunk_header(Common::SeekableReadStream *r, iff_chunk_header_s *ts)
+{
+	if (stream_remain(r) < 8)
+		return false;
+
+	ts->id   = r->readUint32BE();
+	ts->size = r->readUint32BE();
+
+	// if (ts->size != roundup(ts->size))
+	// 	debug("%s: %d\n", str_tag(ts->id), ts->size);
+
+	return true;
+}
+
+const char *str_tag(uint32 tag)
+{
+	static char s[5];
+
+	sprintf(s, "%c%c%c%c",
+		(tag >> 24) & 0xff,
+		(tag >> 16) & 0xff,
+		(tag >>  8) & 0xff,
+		(tag >>  0) & 0xff);
+
+	return s;
+}
+
+bool VQADecoder::read_header()
+{
+	iff_chunk_header_s chd;
+	uint32 type;
+	bool rc;
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kFORM || !chd.size)
+		return false;
+
+	type = r->readUint32BE();
+
+	if (type != kWVQA)
+		return false;
+
+	do {
+		if (!read_iff_chunk_header(r, &chd))
+			return false;
+
+		debug("\t%s : %x\n", str_tag(chd.id), chd.size);
+
+		rc = false;
+		switch (chd.id)
+		{
+			case kCINF: rc = read_cinf(chd.size); break;
+			case kCLIP: rc = read_clip(chd.size); break;
+			case kFINF: rc = read_finf(chd.size); break;
+			case kLINF: rc = read_linf(chd.size); break;
+			case kLNIN: rc = read_lnin(chd.size); break;
+			case kMFCI: rc = read_mfci(chd.size); break;
+			case kMSCI: rc = read_msci(chd.size); break;
+			case kVQHD: rc = read_vqhd(chd.size); break;
+			default:
+				debug("Unhandled chunk '%s'\n", str_tag(chd.id));
+				r->skip(roundup(chd.size));
+				rc = true;
+		}
+
+		if (!rc)
+		{
+			debug("failed to handle chunk %s\n", str_tag(chd.id));
+			return false;
+		}
+
+	} while (chd.id != kFINF);
+
+	for (int i = 0; i != loop_info.loop_count; ++i) {
+		debug("LOOP %2d: %4d %4d %s\n", i,
+			loop_info.loops[i].begin,
+			loop_info.loops[i].end,
+			loop_info.loops[i].name.c_str());
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_vqhd(uint32 size)
+{
+	if (size != 42)
+		return false;
+
+	header.version     = r->readUint16LE();
+	header.flags       = r->readUint16LE();
+	header.numFrames   = r->readUint16LE();
+	header.width       = r->readUint16LE();
+	header.height      = r->readUint16LE();
+	header.blockW      = r->readByte();
+	header.blockH      = r->readByte();
+	header.frameRate   = r->readByte();
+	header.cbParts     = r->readByte();
+	header.colors      = r->readUint16LE();
+	header.maxBlocks   = r->readUint16LE();
+	header.offset_x    = r->readUint16LE();
+	header.offset_y    = r->readUint16LE();
+	header.maxVPTRSize = r->readUint16LE();
+	header.freq        = r->readUint16LE();
+	header.channels    = r->readByte();
+	header.bits        = r->readByte();
+	header.unk3        = r->readUint32LE();
+	header.unk4        = r->readUint16LE();
+	header.maxCBFZSize = r->readUint32LE();
+	header.unk5        = r->readUint32LE();
+
+	if (header.offset_x || header.offset_y)
+	{
+		debug("header.offset_x, header.offset_y: %d %d\n", header.offset_x, header.offset_y);
+	}
+
+	// if (header.unk3 || header.unk4 != 4 || header.unk5 || header.flags != 0x0014)
+	{
+		debug("header.version      %d\n", header.version);
+		debug("header.flags        %04x\n", header.flags);
+		debug("header.numFrames    %d\n", header.numFrames);
+		debug("header.width        %d\n", header.width);
+		debug("header.height       %d\n", header.height);
+		debug("header.blockW       %d\n", header.blockW);
+		debug("header.blockH       %d\n", header.blockH);
+		debug("header.frameRate    %d\n", header.frameRate);
+		debug("header.cbParts      %d\n", header.cbParts);
+		debug("header.colors       %d\n", header.colors);
+		debug("header.maxBlocks    %d\n", header.maxBlocks);
+		debug("header.offsetX      %d\n", header.offset_x);
+		debug("header.offsetY      %d\n", header.offset_y);
+		debug("header.maxVPTRSize  %d\n", header.maxVPTRSize);
+		debug("header.freq         %d\n", header.freq);
+		debug("header.channels     %d\n", header.channels);
+		debug("header.bits         %d\n", header.bits);
+		debug("header.unk3         %d\n", header.unk3);
+		debug("header.unk4         %d\n", header.unk4);
+		debug("header.maxCBFZSize  %d\n", header.maxCBFZSize);
+		debug("header.unk5         %d\n", header.unk5);
+	}
+
+	// exit(-1);
+
+	return true;
+}
+
+bool VQADecoder::read_msci(uint32 size)
+{
+	iff_chunk_header_s chd;
+	read_iff_chunk_header(r, &chd);
+
+	if (chd.id != kMSCH)
+		return false;
+
+	uint32 count, unk0;
+	count = r->readUint32LE();
+	unk0  = r->readUint32LE();
+	assert(unk0 == 0);
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kMSCT || chd.size != count * 0x10)
+		return false;
+
+	for (uint32 i = 0; i < count; ++i)
+	{
+		uint32 tag, size;
+		tag = r->readUint32BE();
+		size = r->readUint32LE();
+
+		switch (tag)
+		{
+		case kVIEW:
+			max_view_chunk_size = size;
+			debug("max VIEW size: %08x\n", max_view_chunk_size);
+			break;
+		case kZBUF:
+			max_zbuf_chunk_size = size;
+			zbuf_chunk = new uint8[roundup(max_zbuf_chunk_size)];
+			debug("max ZBUF size: %08x\n", max_zbuf_chunk_size);
+			break;
+		case kAESC:
+			max_aesc_chunk_size = size;
+			debug("max AESC size: %08x\n", max_aesc_chunk_size);
+			break;
+		default:
+			debug("Unknown tag in MSCT: %s\n", str_tag(tag));
+		}
+
+		uint32 zero;
+		zero = r->readUint32LE(); assert(zero == 0);
+		zero = r->readUint32LE(); assert(zero == 0);
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_linf(uint32 size)
+{
+	iff_chunk_header_s chd;
+	read_iff_chunk_header(r, &chd);
+
+	if (chd.id != kLINH || chd.size != 6)
+		return false;
+
+	loop_info.loop_count = r->readUint16LE();
+	loop_info.flags = r->readUint32LE();
+
+	if ((loop_info.flags & 3) == 0)
+		return false;
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kLIND || chd.size != 4u * loop_info.loop_count)
+		return false;
+
+	loop_info.loops = new Loop[loop_info.loop_count];
+	for (int i = 0; i != loop_info.loop_count; ++i)
+	{
+		loop_info.loops[i].begin = r->readUint16LE();
+		loop_info.loops[i].end = r->readUint16LE();
+
+		// debug("Loop %d: %04x %04x\n", i, loop_info.loops[i].begin, loop_info.loops[i].end);
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_cinf(uint32 size)
+{
+	iff_chunk_header_s chd;
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kCINH || chd.size != 8u)
+		return false;
+
+	clip_info.clip_count = r->readUint16LE();
+	r->skip(6);
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kCIND || chd.size != 6u * clip_info.clip_count)
+		return false;
+
+	for (int i = 0; i != clip_info.clip_count; ++i)
+	{
+		uint16 a;
+		uint32 b;
+		a = r->readUint16LE();
+		b = r->readUint32LE();
+		debug("%4d %08x\n", a, b);
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_finf(uint32 size)
+{
+	if (size != 4u * header.numFrames)
+		return false;
+
+	frame_info = new uint32[header.numFrames];
+
+	for (uint32 i = 0; i != header.numFrames; ++i)
+		frame_info[i] = r->readUint32LE();
+
+	if (false) {
+		uint32 last = 0;
+		for (uint32 i = 0; i != header.numFrames; ++i)
+		{
+			uint32 diff = frame_info[i] - last;
+			debug("frame_info[%4d] = 0x%08x   - %08x\n", i, frame_info[i], diff);
+			last = frame_info[i];
+		}
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_lnin(uint32 size)
+{
+	iff_chunk_header_s chd;
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kLNIH || chd.size != 10)
+		return false;
+
+	uint16 loop_names_count, loop_unk_1, loop_unk_2, loop_unk_3, loop_unk_4;
+
+	loop_names_count = r->readUint16LE();
+	loop_unk_1       = r->readUint16LE();
+	loop_unk_2       = r->readUint16LE();
+	loop_unk_3       = r->readUint16LE();
+	loop_unk_4       = r->readUint16LE();
+
+	if (loop_names_count != loop_info.loop_count)
+		return false;
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kLNIO || chd.size != 4u * loop_names_count)
+		return false;
+
+	uint32 *loop_name_offsets = (uint32*)alloca(loop_names_count * sizeof(uint32));
+	for (int i = 0; i != loop_names_count; ++i) {
+		loop_name_offsets[i] = r->readUint32LE();
+	}
+
+	read_iff_chunk_header(r, &chd);
+	if (chd.id != kLNID)
+		return false;
+
+	char *names = (char*)alloca(roundup(chd.size));
+	r->read(names, roundup(chd.size));
+
+	for (int i = 0; i != loop_names_count; ++i) {
+		char   *begin = names + loop_name_offsets[i];
+		size_t  len   = ((i == loop_names_count) ? chd.size : loop_name_offsets[i+1]) - loop_name_offsets[i];
+
+		loop_info.loops[i].name = Common::String(begin, len);
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_clip(uint32 size)
+{
+	r->skip(roundup(size));
+	return true;
+}
+
+bool VQADecoder::read_mfci(uint32 size)
+{
+	r->skip(roundup(size));
+	return true;
+}
+
+int VQADecoder::read_frame()
+{
+	// debug("VQADecoder::read_frame(): %d, %d, %d, %d\n", loop_default, loop_special, cur_loop, cur_frame);
+
+	if (loop_info.loop_count)
+	{
+		if (loop_special >= 0)
+		{
+			cur_loop = loop_special;
+			loop_special = -1;
+
+			cur_frame = loop_info.loops[cur_loop].begin;
+			seek_to_frame(cur_frame);
+		}
+		else if (cur_loop == -1 && loop_default >= 0)
+		{
+			cur_loop = loop_default;
+			cur_frame = loop_info.loops[cur_loop].begin;
+			seek_to_frame(cur_frame);
+		}
+		else if (cur_loop >= -1 && cur_frame == loop_info.loops[cur_loop].end)
+		{
+			if (loop_default == -1)
+				return -1;
+
+			cur_loop = loop_default;
+			cur_frame = loop_info.loops[cur_loop].begin;
+			seek_to_frame(cur_frame);
+		}
+		else
+			++cur_frame;
+	}
+	else
+		++cur_frame;
+
+	if (cur_frame >= header.numFrames)
+		return -1;
+
+	iff_chunk_header_s chd;
+
+	has_view = false;
+
+	if (stream_remain(r) < 8) {
+		debug("remain: %d\n", stream_remain(r));
+		return -1;
+	}
+
+	do {
+		if (!read_iff_chunk_header(r, &chd)) {
+			debug("Error reading chunk header\n");
+			return -1;
+		}
+
+		// debug("%s ", str_tag(chd.id));
+
+		bool rc = false;
+		switch (chd.id)
+		{
+			case kAESC: rc = read_aesc(chd.size); break;
+			case kLITE: rc = read_lite(chd.size); break;
+			case kSN2J: rc = read_sn2j(chd.size); break;
+			case kSND2: rc = read_snd2(chd.size); break;
+			case kVIEW: rc = read_view(chd.size); break;
+			case kVQFL: rc = read_vqfl(chd.size); break;
+			case kVQFR: rc = read_vqfr(chd.size); break;
+			case kZBUF: rc = read_zbuf(chd.size); break;
+			default:
+				r->skip(roundup(chd.size));
+				rc = true;
+		}
+
+		if (!rc)
+		{
+			debug("Error handling chunk %s\n", str_tag(chd.id));
+			return -1;
+		}
+	} while (chd.id != kVQFR);
+
+	return cur_frame;
+}
+
+
+bool VQADecoder::read_sn2j(uint32 size)
+{
+	if (size != 6)
+		return false;
+
+	uint16 step_index;
+	uint32 predictor;
+
+	step_index = r->readUint16LE();
+	predictor  = r->readUint32LE();
+
+	// ima_adpcm_ws_decoder.set_parameters(step_index >> 5, predictor);
+
+	return true;
+}
+
+bool VQADecoder::read_snd2(uint32 size)
+{
+	if (size != 735)
+	{
+		debug("audio frame size: %d\n", size);
+		return false;
+	}
+
+	if (!audio_frame)
+		audio_frame = new int16[2 * size];
+	memset(audio_frame, 0, 4 * size);
+
+	uint8 *in_frame = new uint8[roundup(size)];
+	r->read(in_frame, roundup(size));
+
+	// ima_adpcm_ws_decoder.decode(in_frame, size, audio_frame);
+
+	delete[] in_frame;
+
+	return true;
+}
+
+bool VQADecoder::read_vqfr(uint32 size)
+{
+	iff_chunk_header_s chd;
+
+	while (size >= 8)
+	{
+		if (!read_iff_chunk_header(r, &chd))
+			return false;
+		size -= roundup(chd.size) + 8;
+
+		// debug("(%s) ", str_tag(chd.id)); fflush(0);
+
+		bool rc = false;
+		switch (chd.id)
+		{
+			case kCBFZ: rc = read_cbfz(chd.size); break;
+			case kVPTR: rc = read_vptr(chd.size); break;
+			default:
+				r->skip(roundup(chd.size));
+		}
+
+		if (!rc)
+		{
+			debug("VQFR: error handling chunk %s\n", str_tag(chd.id));
+			return false;
+		}
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_vqfl(uint32 size)
+{
+	iff_chunk_header_s chd;
+
+	while (size >= 8)
+	{
+		if (!read_iff_chunk_header(r, &chd))
+			return false;
+		size -= roundup(chd.size) + 8;
+
+		bool rc = false;
+		switch (chd.id)
+		{
+			case kCBFZ: rc = read_cbfz(chd.size); break;
+			default:
+				r->skip(roundup(chd.size));
+		}
+
+		if (!rc)
+		{
+			debug("VQFL: error handling chunk %s\n", str_tag(chd.id));
+			return false;
+		}
+	}
+
+	return true;
+}
+
+bool VQADecoder::read_cbfz(uint32 size)
+{
+	if (size > header.maxCBFZSize)
+	{
+		debug("%d > %d\n", size, header.maxCBFZSize);
+		return false;
+	}
+
+	if (!codebook)
+	{
+		codebookSize = 2 * header.maxBlocks * header.blockW * header.blockH;
+		codebook = new uint8[codebookSize];
+	}
+	if (!cbfz)
+		cbfz = new uint8[roundup(header.maxCBFZSize)];
+
+	r->read(cbfz, roundup(size));
+
+	decompress_lcw(cbfz, size, codebook, codebookSize);
+
+	return true;
+}
+
+static
+int decodeZBUF_partial(uint8 *src, uint16 *cur_zbuf, uint32 src_len)
+{
+	uint32 dst_size = 640 * 480; // This is taken from global variables?
+	uint32 dst_remain = dst_size;
+
+	uint16 *curz_p = cur_zbuf;
+	uint16 *in_p = (uint16*)src;
+
+	while (dst_remain && (in_p - (uint16*)src) < (ptrdiff_t)src_len)
+	{
+		uint32 count = FROM_LE_16(*in_p++);
+
+		if (count & 0x8000)
+		{
+			count = MIN(count & 0x7fff, dst_remain);
+			dst_remain -= count;
+
+			while (count--)
+			{
+				uint16 value = FROM_LE_16(*in_p++);
+				if (value)
+					*curz_p = value;
+				++curz_p;
+			}
+		}
+		else
+		{
+			count = MIN(count, dst_remain);
+			dst_remain -= count;
+			uint16 value = FROM_LE_16(*in_p++);
+
+			if (!value)
+				curz_p += count;
+			else
+			{
+				while (count--)
+					*curz_p++ = value;
+			}
+		}
+	}
+	return dst_size - dst_remain;
+}
+
+bool VQADecoder::read_zbuf(uint32 size)
+{
+	if (size > max_zbuf_chunk_size) {
+		debug("VQA ERROR: ZBUF chunk size: %08x > %08x\n", size, max_zbuf_chunk_size);
+		r->skip(roundup(size));
+		return false;
+	}
+
+	uint32 width, height, complete, unk0;
+	width    = r->readUint32LE();
+	height   = r->readUint32LE();
+	complete = r->readUint32LE();
+	unk0     = r->readUint32LE();
+
+	uint32 remain = size - 16;
+
+	if (width != header.width || height != header.height)
+	{
+		debug("%d, %d, %d, %d\n", width, height, complete, unk0);
+		r->skip(roundup(remain));
+		return false;
+	}
+
+	if (!zbuf)
+	{
+		if (!complete) {
+			r->skip(roundup(remain));
+			return false;
+		}
+		zbuf = new uint16[width * height];
+	}
+
+	r->read(zbuf_chunk, roundup(remain));
+
+	if (complete) {
+		size_t zbuf_out_size;
+		decompress_lzo1x(zbuf_chunk, remain, (uint8*)zbuf, &zbuf_out_size);
+	} else {
+		decodeZBUF_partial(zbuf_chunk, zbuf, remain);
+	}
+
+	return true;
+}
+
+bool VQADecoder::get_zbuf(uint16 *a_zbuf)
+{
+	if (!zbuf)
+		return false;
+
+	memcpy(a_zbuf, zbuf, 2 * header.width * header.height);
+	return true;
+}
+
+bool VQADecoder::read_view(uint32 size)
+{
+	if (size != 56)
+		return false;
+
+	r->skip(size);
+	// has_view = true;
+
+	return true;
+}
+
+bool VQADecoder::read_aesc(uint32 size)
+{
+	r->skip(roundup(size));
+	return true;
+}
+
+bool VQADecoder::read_lite(uint32 size)
+{
+	r->skip(roundup(size));
+	return true;
+}
+
+bool VQADecoder::read_vptr(uint32 size)
+{
+	if (size > header.maxVPTRSize)
+		return false;
+
+	if (!vptr)
+		vptr = new uint8[roundup(header.maxVPTRSize)];
+
+	vptrSize = size;
+	r->read(vptr, roundup(size));
+
+	return true;
+}
+
+void VQADecoder::vptr_write_block(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha) const
+{
+	uint16 frame_width  = header.width;
+	uint32 frame_stride = 640;
+	uint16 block_width  = header.blockW;
+	uint16 block_height = header.blockH;
+
+	const uint8 *const block_src =
+		&codebook[2 * src_block * block_width * block_height];
+
+	int blocks_per_line = frame_width / block_width;
+
+	do
+	{
+		uint32 frame_x = dst_block % blocks_per_line * block_width  + header.offset_x / 2;
+		uint32 frame_y = dst_block / blocks_per_line * block_height + header.offset_y;
+
+		uint32 dst_offset = frame_x + frame_y * frame_stride;
+
+		const uint8 *__restrict src = block_src;
+		uint16      *__restrict dst = frame + dst_offset;
+
+		unsigned int block_y;
+		for (block_y = 0; block_y != block_height; ++block_y)
+		{
+			unsigned int block_x;
+			for (block_x = 0; block_x != block_width; ++block_x)
+			{
+				uint16 rgb555 = src[0] | (src[1] << 8);
+				src += 2;
+
+				if (!(alpha && (rgb555 & 0x8000)))
+					*dst = rgb555;
+				++dst;
+			}
+			dst += frame_stride - block_width;
+		}
+
+		++dst_block;
+	}
+	while (--count);
+}
+
+void VQADecoder::set_loop_special(int loop, bool wait)
+{
+	loop_special = loop;
+	if (!wait)
+		cur_loop = -1;
+}
+
+void VQADecoder::set_loop_default(int loop)
+{
+	loop_default = loop;
+}
+
+bool VQADecoder::seek_to_frame(int frame)
+{
+	if (frame < 0 || frame >= header.numFrames)
+		return false;
+
+	r->seek(2 * (frame_info[frame] & 0x0fffffff), SEEK_SET);
+	return true;
+}
+
+bool VQADecoder::decode_frame(uint16 *a_frame)
+{
+	if (!codebook || !vptr)
+		return false;
+
+	if (!frame)
+		frame = new uint16[header.width * header.height];
+
+	uint8 *src = vptr;
+	uint8 *end = vptr + vptrSize;
+
+	uint16 count, src_block, dst_block = 0;
+	(void)src_block;
+
+	while (end - src >= 2)
+	{
+		uint16 command = src[0] | (src[1] << 8);
+		uint8  prefix = command >> 13;
+		src += 2;
+
+		switch (prefix)
+		{
+		case 0:
+			count = command & 0x1fff;
+			dst_block += count;
+			break;
+		case 1:
+			count = 2 * (((command >> 8) & 0x1f) + 1);
+			src_block = command & 0x00ff;
+
+			vptr_write_block(frame, dst_block, src_block, count);
+			dst_block += count;
+			break;
+		case 2:
+			count = 2 * (((command >> 8) & 0x1f) + 1);
+			src_block = command & 0x00ff;
+
+			vptr_write_block(frame, dst_block, src_block, 1);
+			++dst_block;
+
+			for (int i = 0; i < count; ++i)
+			{
+				src_block = *src++;
+				vptr_write_block(frame, dst_block, src_block, 1);
+				++dst_block;
+			}
+			break;
+		case 3:
+		case 4:
+			count = 1;
+			src_block = command & 0x1fff;
+
+			vptr_write_block(frame, dst_block, src_block, count, prefix == 4);
+			++dst_block;
+			break;
+		case 5:
+		case 6:
+			count = *src++;
+			src_block = command & 0x1fff;
+
+			vptr_write_block(frame, dst_block, src_block, count, prefix == 6);
+			dst_block += count;
+			break;
+		default:
+			debug("Undefined case %d\n", command >> 13);
+		}
+	}
+
+	memcpy(a_frame, frame, 2 * 640 * 480);
+
+	return true;
+}
+
+int16 *VQADecoder::get_audio_frame()
+{
+	return audio_frame;
+}
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
new file mode 100644
index 0000000..c4b5974
--- /dev/null
+++ b/engines/bladerunner/vqa_decoder.h
@@ -0,0 +1,165 @@
+/* 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 BLADERUNNER_VQA_H
+#define BLADERUNNER_VQA_H
+
+#include "common/debug.h"
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/types.h"
+
+namespace BladeRunner {
+class VQADecoder
+{
+	struct Header
+	{
+		uint16 version;     // 0x00
+		uint16 flags;       // 0x02
+		uint16 numFrames;   // 0x04
+		uint16 width;       // 0x06
+		uint16 height;      // 0x08
+		uint8  blockW;      // 0x0A
+		uint8  blockH;      // 0x0B
+		uint8  frameRate;   // 0x0C
+		uint8  cbParts;     // 0x0D
+		uint16 colors;      // 0x0E
+		uint16 maxBlocks;   // 0x10
+		uint16 offset_x;    // 0x12
+		uint16 offset_y;    // 0x14
+		uint16 maxVPTRSize; // 0x16
+		uint16 freq;        // 0x18
+		uint8  channels;    // 0x1A
+		uint8  bits;        // 0x1B
+		uint32 unk3;        // 0x1C
+		uint16 unk4;        // 0x20
+		uint32 maxCBFZSize; // 0x22
+		uint32 unk5;        // 0x26
+		                    // 0x2A
+	};
+
+	struct Loop {
+		uint16         begin;
+		uint16         end;
+		Common::String name;
+
+		Loop() :
+			begin(0),
+			end(0)
+		{}
+	};
+
+	struct LoopInfo
+	{
+		uint16  loop_count;
+		uint32  flags;
+		Loop     *loops;
+
+		LoopInfo()
+			: loop_count(0)
+		{}
+	};
+
+	struct ClipInfo
+	{
+		uint16 clip_count;
+	};
+
+	Common::SeekableReadStream *r;
+
+	Header   header;
+	LoopInfo loop_info;
+	ClipInfo clip_info;
+
+	uint16 *frame;
+	uint16 *zbuf;
+
+	size_t  codebookSize;
+	uint8  *codebook;
+	uint8  *cbfz;
+
+	size_t  vptrSize;
+	uint8  *vptr;
+
+	uint32 *frame_info;
+
+	int     cur_frame;
+
+	int     cur_loop;
+	int     loop_special;
+	int     loop_default;
+
+	uint32  max_view_chunk_size;
+	uint32  max_zbuf_chunk_size;
+	uint32  max_aesc_chunk_size;
+	uint8  *zbuf_chunk;
+
+	bool   has_view;
+	// view_t view;
+
+	// ima_adpcm_ws_decoder_t ima_adpcm_ws_decoder;
+	int16 *audio_frame;
+
+	bool read_vqhd(uint32 size);
+	bool read_msci(uint32 size);
+	bool read_mfci(uint32 size);
+	bool read_linf(uint32 size);
+	bool read_cinf(uint32 size);
+	bool read_finf(uint32 size);
+	bool read_lnin(uint32 size);
+	bool read_clip(uint32 size);
+
+	bool read_sn2j(uint32 size);
+	bool read_snd2(uint32 size);
+	bool read_vqfr(uint32 size);
+	bool read_vptr(uint32 size);
+	bool read_vqfl(uint32 size);
+	bool read_cbfz(uint32 size);
+	bool read_zbuf(uint32 size);
+	bool read_view(uint32 size);
+	bool read_aesc(uint32 size);
+	bool read_lite(uint32 size);
+
+public:
+	VQADecoder(Common::SeekableReadStream *r);
+	~VQADecoder();
+
+	bool read_header();
+	int  read_frame();
+
+	void vptr_write_block(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha = false) const;
+
+	void set_loop_special(int loop, bool wait);
+	void set_loop_default(int loop);
+
+	bool seek_to_frame(int frame);
+	bool decode_frame(uint16 *frame);
+
+	int16 *get_audio_frame();
+
+	// bool get_view(view_t *view);
+	bool get_zbuf(uint16 *zbuf);
+};
+
+}; // End of namespace BladeRunner
+
+#endif


Commit: 5c69ed59951c9436c5dd450396fc16dd5ab38f83
    https://github.com/scummvm/scummvm/commit/5c69ed59951c9436c5dd450396fc16dd5ab38f83
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:21:00+02:00

Commit Message:
BLADERUNNER: Style

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 3ae0d47..7e8466c 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -220,7 +220,7 @@ void BladeRunnerEngine::playOuttake(int id, bool no_localization) {
 
 	VQADecoder vqa_decoder(s);
 
-	bool b = vqa_decoder.read_header();
+	bool b = vqa_decoder.readHeader();
 	if (!b) return;
 
 	uint32 frame_count = 0;
@@ -238,13 +238,13 @@ void BladeRunnerEngine::playOuttake(int id, bool no_localization) {
 
 		if (next_frame_time <= cur_time)
 		{
-			int frame_number = vqa_decoder.read_frame();
+			int frame_number = vqa_decoder.readFrame();
 			debug("frame_number: %d", frame_number);
 
 			if (frame_number < 0)
 				break;
 
-			b = vqa_decoder.decode_frame((uint16*)_surface1.getPixels());
+			b = vqa_decoder.decodeFrame((uint16*)_surface1.getPixels());
 
 			_system->copyRectToScreen(_surface1.getPixels(), _surface1.pitch, 0, 0, _surface1.w, _surface1.h);
 			_system->updateScreen();
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index b717964..46e45de 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -66,33 +66,32 @@ namespace BladeRunner {
 #define kWVQA 0x57565141
 #define kZBUF 0x5A425546
 
-VQADecoder::VQADecoder(Common::SeekableReadStream *r)
-	: r(r),
-	  frame(0),
-	  zbuf(0),
-	  codebook(0),
-	  cbfz(0),
-	  vptr(0),
-	  cur_frame(-1),
-	  cur_loop(-1),
-	  loop_special(-1),
-	  loop_default(-1),
-	  has_view(false),
-	  audio_frame(0),
-	  max_view_chunk_size(0),
-	  max_zbuf_chunk_size(0),
-	  max_aesc_chunk_size(0)
-{
-	// debug("Opening VQA: '%s'\n", r->get_name());
+VQADecoder::VQADecoder(Common::SeekableReadStream *s)
+	: _s(s),
+	  _frame(0),
+	  _zbuf(0),
+	  _codebook(0),
+	  _cbfz(0),
+	  _vptr(0),
+	  _curFrame(-1),
+	  _curLoop(-1),
+	  _loopSpecial(-1),
+	  _loopDefault(-1),
+	  _hasView(false),
+	  _audioFrame(0),
+	  _maxVIEWChunkSize(0),
+	  _maxZBUFChunkSize(0),
+	  _maxAESCChunkSize(0)
+{
 }
 
 VQADecoder::~VQADecoder()
 {
 }
 
-struct iff_chunk_header_s
+struct IFFChunkHeader
 {
-	iff_chunk_header_s()
+	IFFChunkHeader()
 		: id(0), size(0)
 	{}
 
@@ -105,9 +104,9 @@ static inline uint32 roundup(uint32 v)
 	return (v + 1) & ~1u;
 }
 
-const char *str_tag(uint32 tag);
+const char *strTag(uint32 tag);
 
-int32 stream_remain(Common::SeekableReadStream *s) {
+int32 remain(Common::SeekableReadStream *s) {
 	int32 pos = s->pos();
 	if (pos == -1) return -1;
 
@@ -118,21 +117,21 @@ int32 stream_remain(Common::SeekableReadStream *s) {
 }
 
 static
-bool read_iff_chunk_header(Common::SeekableReadStream *r, iff_chunk_header_s *ts)
+bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
 {
-	if (stream_remain(r) < 8)
+	if (remain(s) < 8)
 		return false;
 
-	ts->id   = r->readUint32BE();
-	ts->size = r->readUint32BE();
+	ts->id   = s->readUint32BE();
+	ts->size = s->readUint32BE();
 
 	// if (ts->size != roundup(ts->size))
-	// 	debug("%s: %d\n", str_tag(ts->id), ts->size);
+	// 	debug("%s: %d\n", strTag(ts->id), ts->size);
 
 	return true;
 }
 
-const char *str_tag(uint32 tag)
+const char *strTag(uint32 tag)
 {
 	static char s[5];
 
@@ -145,117 +144,117 @@ const char *str_tag(uint32 tag)
 	return s;
 }
 
-bool VQADecoder::read_header()
+bool VQADecoder::readHeader()
 {
-	iff_chunk_header_s chd;
+	IFFChunkHeader chd;
 	uint32 type;
 	bool rc;
 
-	read_iff_chunk_header(r, &chd);
+	readIFFChunkHeader(_s, &chd);
 	if (chd.id != kFORM || !chd.size)
 		return false;
 
-	type = r->readUint32BE();
+	type = _s->readUint32BE();
 
 	if (type != kWVQA)
 		return false;
 
 	do {
-		if (!read_iff_chunk_header(r, &chd))
+		if (!readIFFChunkHeader(_s, &chd))
 			return false;
 
-		debug("\t%s : %x\n", str_tag(chd.id), chd.size);
+		debug("\t%s : %x\n", strTag(chd.id), chd.size);
 
 		rc = false;
 		switch (chd.id)
 		{
-			case kCINF: rc = read_cinf(chd.size); break;
-			case kCLIP: rc = read_clip(chd.size); break;
-			case kFINF: rc = read_finf(chd.size); break;
-			case kLINF: rc = read_linf(chd.size); break;
-			case kLNIN: rc = read_lnin(chd.size); break;
-			case kMFCI: rc = read_mfci(chd.size); break;
-			case kMSCI: rc = read_msci(chd.size); break;
-			case kVQHD: rc = read_vqhd(chd.size); break;
+			case kCINF: rc = readCINF(chd.size); break;
+			case kCLIP: rc = readCLIP(chd.size); break;
+			case kFINF: rc = readFINF(chd.size); break;
+			case kLINF: rc = readLINF(chd.size); break;
+			case kLNIN: rc = readLNIN(chd.size); break;
+			case kMFCI: rc = readMFCI(chd.size); break;
+			case kMSCI: rc = readMSCI(chd.size); break;
+			case kVQHD: rc = readVQHD(chd.size); break;
 			default:
-				debug("Unhandled chunk '%s'\n", str_tag(chd.id));
-				r->skip(roundup(chd.size));
+				debug("Unhandled chunk '%s'\n", strTag(chd.id));
+				_s->skip(roundup(chd.size));
 				rc = true;
 		}
 
 		if (!rc)
 		{
-			debug("failed to handle chunk %s\n", str_tag(chd.id));
+			debug("failed to handle chunk %s\n", strTag(chd.id));
 			return false;
 		}
 
 	} while (chd.id != kFINF);
 
-	for (int i = 0; i != loop_info.loop_count; ++i) {
+	for (int i = 0; i != _loopInfo.loopCount; ++i) {
 		debug("LOOP %2d: %4d %4d %s\n", i,
-			loop_info.loops[i].begin,
-			loop_info.loops[i].end,
-			loop_info.loops[i].name.c_str());
+			_loopInfo.loops[i].begin,
+			_loopInfo.loops[i].end,
+			_loopInfo.loops[i].name.c_str());
 	}
 
 	return true;
 }
 
-bool VQADecoder::read_vqhd(uint32 size)
+bool VQADecoder::readVQHD(uint32 size)
 {
 	if (size != 42)
 		return false;
 
-	header.version     = r->readUint16LE();
-	header.flags       = r->readUint16LE();
-	header.numFrames   = r->readUint16LE();
-	header.width       = r->readUint16LE();
-	header.height      = r->readUint16LE();
-	header.blockW      = r->readByte();
-	header.blockH      = r->readByte();
-	header.frameRate   = r->readByte();
-	header.cbParts     = r->readByte();
-	header.colors      = r->readUint16LE();
-	header.maxBlocks   = r->readUint16LE();
-	header.offset_x    = r->readUint16LE();
-	header.offset_y    = r->readUint16LE();
-	header.maxVPTRSize = r->readUint16LE();
-	header.freq        = r->readUint16LE();
-	header.channels    = r->readByte();
-	header.bits        = r->readByte();
-	header.unk3        = r->readUint32LE();
-	header.unk4        = r->readUint16LE();
-	header.maxCBFZSize = r->readUint32LE();
-	header.unk5        = r->readUint32LE();
-
-	if (header.offset_x || header.offset_y)
+	_header.version     = _s->readUint16LE();
+	_header.flags       = _s->readUint16LE();
+	_header.numFrames   = _s->readUint16LE();
+	_header.width       = _s->readUint16LE();
+	_header.height      = _s->readUint16LE();
+	_header.blockW      = _s->readByte();
+	_header.blockH      = _s->readByte();
+	_header.frameRate   = _s->readByte();
+	_header.cbParts     = _s->readByte();
+	_header.colors      = _s->readUint16LE();
+	_header.maxBlocks   = _s->readUint16LE();
+	_header.offset_x    = _s->readUint16LE();
+	_header.offset_y    = _s->readUint16LE();
+	_header.maxVPTRSize = _s->readUint16LE();
+	_header.freq        = _s->readUint16LE();
+	_header.channels    = _s->readByte();
+	_header.bits        = _s->readByte();
+	_header.unk3        = _s->readUint32LE();
+	_header.unk4        = _s->readUint16LE();
+	_header.maxCBFZSize = _s->readUint32LE();
+	_header.unk5        = _s->readUint32LE();
+
+	if (_header.offset_x || _header.offset_y)
 	{
-		debug("header.offset_x, header.offset_y: %d %d\n", header.offset_x, header.offset_y);
+		debug("_header.offset_x, _header.offset_y: %d %d\n", _header.offset_x, _header.offset_y);
 	}
 
-	// if (header.unk3 || header.unk4 != 4 || header.unk5 || header.flags != 0x0014)
+	// if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014)
 	{
-		debug("header.version      %d\n", header.version);
-		debug("header.flags        %04x\n", header.flags);
-		debug("header.numFrames    %d\n", header.numFrames);
-		debug("header.width        %d\n", header.width);
-		debug("header.height       %d\n", header.height);
-		debug("header.blockW       %d\n", header.blockW);
-		debug("header.blockH       %d\n", header.blockH);
-		debug("header.frameRate    %d\n", header.frameRate);
-		debug("header.cbParts      %d\n", header.cbParts);
-		debug("header.colors       %d\n", header.colors);
-		debug("header.maxBlocks    %d\n", header.maxBlocks);
-		debug("header.offsetX      %d\n", header.offset_x);
-		debug("header.offsetY      %d\n", header.offset_y);
-		debug("header.maxVPTRSize  %d\n", header.maxVPTRSize);
-		debug("header.freq         %d\n", header.freq);
-		debug("header.channels     %d\n", header.channels);
-		debug("header.bits         %d\n", header.bits);
-		debug("header.unk3         %d\n", header.unk3);
-		debug("header.unk4         %d\n", header.unk4);
-		debug("header.maxCBFZSize  %d\n", header.maxCBFZSize);
-		debug("header.unk5         %d\n", header.unk5);
+		debug("_header.version      %d\n", _header.version);
+		debug("_header.flags        %04x\n", _header.flags);
+		debug("_header.numFrames    %d\n", _header.numFrames);
+		debug("_header.width        %d\n", _header.width);
+		debug("_header.height       %d\n", _header.height);
+		debug("_header.blockW       %d\n", _header.blockW);
+		debug("_header.blockH       %d\n", _header.blockH);
+		debug("_header.frameRate    %d\n", _header.frameRate);
+		debug("_header.cbParts      %d\n", _header.cbParts);
+		debug("_header.colors       %d\n", _header.colors);
+		debug("_header.maxBlocks    %d\n", _header.maxBlocks);
+		debug("_header.offsetX      %d\n", _header.offset_x);
+		debug("_header.offsetY      %d\n", _header.offset_y);
+		debug("_header.maxVPTRSize  %d\n", _header.maxVPTRSize);
+		debug("_header.freq         %d\n", _header.freq);
+		debug("_header.channels     %d\n", _header.channels);
+		debug("_header.bits         %d\n", _header.bits);
+		debug("_header.unk3         %d\n", _header.unk3);
+		debug("_header.unk4         %d\n", _header.unk4);
+		debug("_header.maxCBFZSize  %d\n", _header.maxCBFZSize);
+		debug("_header.unk5         %d\n", _header.unk5);
 	}
 
 	// exit(-1);
@@ -263,276 +262,276 @@ bool VQADecoder::read_vqhd(uint32 size)
 	return true;
 }
 
-bool VQADecoder::read_msci(uint32 size)
+bool VQADecoder::readMSCI(uint32 size)
 {
-	iff_chunk_header_s chd;
-	read_iff_chunk_header(r, &chd);
+	IFFChunkHeader chd;
+	readIFFChunkHeader(_s, &chd);
 
 	if (chd.id != kMSCH)
 		return false;
 
 	uint32 count, unk0;
-	count = r->readUint32LE();
-	unk0  = r->readUint32LE();
+	count = _s->readUint32LE();
+	unk0  = _s->readUint32LE();
 	assert(unk0 == 0);
 
-	read_iff_chunk_header(r, &chd);
+	readIFFChunkHeader(_s, &chd);
 	if (chd.id != kMSCT || chd.size != count * 0x10)
 		return false;
 
 	for (uint32 i = 0; i < count; ++i)
 	{
 		uint32 tag, size;
-		tag = r->readUint32BE();
-		size = r->readUint32LE();
+		tag  = _s->readUint32BE();
+		size = _s->readUint32LE();
 
 		switch (tag)
 		{
 		case kVIEW:
-			max_view_chunk_size = size;
-			debug("max VIEW size: %08x\n", max_view_chunk_size);
+			_maxVIEWChunkSize = size;
+			debug("max VIEW size: %08x\n", _maxVIEWChunkSize);
 			break;
 		case kZBUF:
-			max_zbuf_chunk_size = size;
-			zbuf_chunk = new uint8[roundup(max_zbuf_chunk_size)];
-			debug("max ZBUF size: %08x\n", max_zbuf_chunk_size);
+			_maxZBUFChunkSize = size;
+			_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
+			debug("max ZBUF size: %08x\n", _maxZBUFChunkSize);
 			break;
 		case kAESC:
-			max_aesc_chunk_size = size;
-			debug("max AESC size: %08x\n", max_aesc_chunk_size);
+			_maxAESCChunkSize = size;
+			debug("max AESC size: %08x\n", _maxAESCChunkSize);
 			break;
 		default:
-			debug("Unknown tag in MSCT: %s\n", str_tag(tag));
+			debug("Unknown tag in MSCT: %s\n", strTag(tag));
 		}
 
 		uint32 zero;
-		zero = r->readUint32LE(); assert(zero == 0);
-		zero = r->readUint32LE(); assert(zero == 0);
+		zero = _s->readUint32LE(); assert(zero == 0);
+		zero = _s->readUint32LE(); assert(zero == 0);
 	}
 
 	return true;
 }
 
-bool VQADecoder::read_linf(uint32 size)
+bool VQADecoder::readLINF(uint32 size)
 {
-	iff_chunk_header_s chd;
-	read_iff_chunk_header(r, &chd);
+	IFFChunkHeader chd;
+	readIFFChunkHeader(_s, &chd);
 
 	if (chd.id != kLINH || chd.size != 6)
 		return false;
 
-	loop_info.loop_count = r->readUint16LE();
-	loop_info.flags = r->readUint32LE();
+	_loopInfo.loopCount = _s->readUint16LE();
+	_loopInfo.flags = _s->readUint32LE();
 
-	if ((loop_info.flags & 3) == 0)
+	if ((_loopInfo.flags & 3) == 0)
 		return false;
 
-	read_iff_chunk_header(r, &chd);
-	if (chd.id != kLIND || chd.size != 4u * loop_info.loop_count)
+	readIFFChunkHeader(_s, &chd);
+	if (chd.id != kLIND || chd.size != 4u * _loopInfo.loopCount)
 		return false;
 
-	loop_info.loops = new Loop[loop_info.loop_count];
-	for (int i = 0; i != loop_info.loop_count; ++i)
+	_loopInfo.loops = new Loop[_loopInfo.loopCount];
+	for (int i = 0; i != _loopInfo.loopCount; ++i)
 	{
-		loop_info.loops[i].begin = r->readUint16LE();
-		loop_info.loops[i].end = r->readUint16LE();
+		_loopInfo.loops[i].begin = _s->readUint16LE();
+		_loopInfo.loops[i].end   = _s->readUint16LE();
 
-		// debug("Loop %d: %04x %04x\n", i, loop_info.loops[i].begin, loop_info.loops[i].end);
+		// debug("Loop %d: %04x %04x\n", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
 	}
 
 	return true;
 }
 
-bool VQADecoder::read_cinf(uint32 size)
+bool VQADecoder::readCINF(uint32 size)
 {
-	iff_chunk_header_s chd;
+	IFFChunkHeader chd;
 
-	read_iff_chunk_header(r, &chd);
+	readIFFChunkHeader(_s, &chd);
 	if (chd.id != kCINH || chd.size != 8u)
 		return false;
 
-	clip_info.clip_count = r->readUint16LE();
-	r->skip(6);
+	_clipInfo.clipCount = _s->readUint16LE();
+	_s->skip(6);
 
-	read_iff_chunk_header(r, &chd);
-	if (chd.id != kCIND || chd.size != 6u * clip_info.clip_count)
+	readIFFChunkHeader(_s, &chd);
+	if (chd.id != kCIND || chd.size != 6u * _clipInfo.clipCount)
 		return false;
 
-	for (int i = 0; i != clip_info.clip_count; ++i)
+	for (int i = 0; i != _clipInfo.clipCount; ++i)
 	{
 		uint16 a;
 		uint32 b;
-		a = r->readUint16LE();
-		b = r->readUint32LE();
+		a = _s->readUint16LE();
+		b = _s->readUint32LE();
 		debug("%4d %08x\n", a, b);
 	}
 
 	return true;
 }
 
-bool VQADecoder::read_finf(uint32 size)
+bool VQADecoder::readFINF(uint32 size)
 {
-	if (size != 4u * header.numFrames)
+	if (size != 4u * _header.numFrames)
 		return false;
 
-	frame_info = new uint32[header.numFrames];
+	_frameInfo = new uint32[_header.numFrames];
 
-	for (uint32 i = 0; i != header.numFrames; ++i)
-		frame_info[i] = r->readUint32LE();
+	for (uint32 i = 0; i != _header.numFrames; ++i)
+		_frameInfo[i] = _s->readUint32LE();
 
 	if (false) {
 		uint32 last = 0;
-		for (uint32 i = 0; i != header.numFrames; ++i)
+		for (uint32 i = 0; i != _header.numFrames; ++i)
 		{
-			uint32 diff = frame_info[i] - last;
-			debug("frame_info[%4d] = 0x%08x   - %08x\n", i, frame_info[i], diff);
-			last = frame_info[i];
+			uint32 diff = _frameInfo[i] - last;
+			debug("_frameInfo[%4d] = 0x%08x   - %08x\n", i, _frameInfo[i], diff);
+			last = _frameInfo[i];
 		}
 	}
 
 	return true;
 }
 
-bool VQADecoder::read_lnin(uint32 size)
+bool VQADecoder::readLNIN(uint32 size)
 {
-	iff_chunk_header_s chd;
+	IFFChunkHeader chd;
 
-	read_iff_chunk_header(r, &chd);
+	readIFFChunkHeader(_s, &chd);
 	if (chd.id != kLNIH || chd.size != 10)
 		return false;
 
-	uint16 loop_names_count, loop_unk_1, loop_unk_2, loop_unk_3, loop_unk_4;
+	uint16 loopNamesCount, loopUnk1, loopUnk2, loopUnk3, loopUnk4;
 
-	loop_names_count = r->readUint16LE();
-	loop_unk_1       = r->readUint16LE();
-	loop_unk_2       = r->readUint16LE();
-	loop_unk_3       = r->readUint16LE();
-	loop_unk_4       = r->readUint16LE();
+	loopNamesCount = _s->readUint16LE();
+	loopUnk1       = _s->readUint16LE();
+	loopUnk2       = _s->readUint16LE();
+	loopUnk3       = _s->readUint16LE();
+	loopUnk4       = _s->readUint16LE();
 
-	if (loop_names_count != loop_info.loop_count)
+	if (loopNamesCount != _loopInfo.loopCount)
 		return false;
 
-	read_iff_chunk_header(r, &chd);
-	if (chd.id != kLNIO || chd.size != 4u * loop_names_count)
+	readIFFChunkHeader(_s, &chd);
+	if (chd.id != kLNIO || chd.size != 4u * loopNamesCount)
 		return false;
 
-	uint32 *loop_name_offsets = (uint32*)alloca(loop_names_count * sizeof(uint32));
-	for (int i = 0; i != loop_names_count; ++i) {
-		loop_name_offsets[i] = r->readUint32LE();
+	uint32 *loopNameOffsets = (uint32*)alloca(loopNamesCount * sizeof(uint32));
+	for (int i = 0; i != loopNamesCount; ++i) {
+		loopNameOffsets[i] = _s->readUint32LE();
 	}
 
-	read_iff_chunk_header(r, &chd);
+	readIFFChunkHeader(_s, &chd);
 	if (chd.id != kLNID)
 		return false;
 
 	char *names = (char*)alloca(roundup(chd.size));
-	r->read(names, roundup(chd.size));
+	_s->read(names, roundup(chd.size));
 
-	for (int i = 0; i != loop_names_count; ++i) {
-		char   *begin = names + loop_name_offsets[i];
-		size_t  len   = ((i == loop_names_count) ? chd.size : loop_name_offsets[i+1]) - loop_name_offsets[i];
+	for (int i = 0; i != loopNamesCount; ++i) {
+		char   *begin = names + loopNameOffsets[i];
+		size_t  len   = ((i == loopNamesCount) ? chd.size : loopNameOffsets[i+1]) - loopNameOffsets[i];
 
-		loop_info.loops[i].name = Common::String(begin, len);
+		_loopInfo.loops[i].name = Common::String(begin, len);
 	}
 
 	return true;
 }
 
-bool VQADecoder::read_clip(uint32 size)
+bool VQADecoder::readCLIP(uint32 size)
 {
-	r->skip(roundup(size));
+	_s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::read_mfci(uint32 size)
+bool VQADecoder::readMFCI(uint32 size)
 {
-	r->skip(roundup(size));
+	_s->skip(roundup(size));
 	return true;
 }
 
-int VQADecoder::read_frame()
+int VQADecoder::readFrame()
 {
-	// debug("VQADecoder::read_frame(): %d, %d, %d, %d\n", loop_default, loop_special, cur_loop, cur_frame);
+	// debug("VQADecoder::readFrame(): %d, %d, %d, %d\n", _loopDefault, _loopSpecial, _curLoop, _curFrame);
 
-	if (loop_info.loop_count)
+	if (_loopInfo.loopCount)
 	{
-		if (loop_special >= 0)
+		if (_loopSpecial >= 0)
 		{
-			cur_loop = loop_special;
-			loop_special = -1;
+			_curLoop = _loopSpecial;
+			_loopSpecial = -1;
 
-			cur_frame = loop_info.loops[cur_loop].begin;
-			seek_to_frame(cur_frame);
+			_curFrame = _loopInfo.loops[_curLoop].begin;
+			seekToFrame(_curFrame);
 		}
-		else if (cur_loop == -1 && loop_default >= 0)
+		else if (_curLoop == -1 && _loopDefault >= 0)
 		{
-			cur_loop = loop_default;
-			cur_frame = loop_info.loops[cur_loop].begin;
-			seek_to_frame(cur_frame);
+			_curLoop = _loopDefault;
+			_curFrame = _loopInfo.loops[_curLoop].begin;
+			seekToFrame(_curFrame);
 		}
-		else if (cur_loop >= -1 && cur_frame == loop_info.loops[cur_loop].end)
+		else if (_curLoop >= -1 && _curFrame == _loopInfo.loops[_curLoop].end)
 		{
-			if (loop_default == -1)
+			if (_loopDefault == -1)
 				return -1;
 
-			cur_loop = loop_default;
-			cur_frame = loop_info.loops[cur_loop].begin;
-			seek_to_frame(cur_frame);
+			_curLoop = _loopDefault;
+			_curFrame = _loopInfo.loops[_curLoop].begin;
+			seekToFrame(_curFrame);
 		}
 		else
-			++cur_frame;
+			++_curFrame;
 	}
 	else
-		++cur_frame;
+		++_curFrame;
 
-	if (cur_frame >= header.numFrames)
+	if (_curFrame >= _header.numFrames)
 		return -1;
 
-	iff_chunk_header_s chd;
+	IFFChunkHeader chd;
 
-	has_view = false;
+	_hasView = false;
 
-	if (stream_remain(r) < 8) {
-		debug("remain: %d\n", stream_remain(r));
+	if (remain(_s) < 8) {
+		debug("remain: %d\n", remain(_s));
 		return -1;
 	}
 
 	do {
-		if (!read_iff_chunk_header(r, &chd)) {
+		if (!readIFFChunkHeader(_s, &chd)) {
 			debug("Error reading chunk header\n");
 			return -1;
 		}
 
-		// debug("%s ", str_tag(chd.id));
+		// debug("%s ", strTag(chd.id));
 
 		bool rc = false;
 		switch (chd.id)
 		{
-			case kAESC: rc = read_aesc(chd.size); break;
-			case kLITE: rc = read_lite(chd.size); break;
-			case kSN2J: rc = read_sn2j(chd.size); break;
-			case kSND2: rc = read_snd2(chd.size); break;
-			case kVIEW: rc = read_view(chd.size); break;
-			case kVQFL: rc = read_vqfl(chd.size); break;
-			case kVQFR: rc = read_vqfr(chd.size); break;
-			case kZBUF: rc = read_zbuf(chd.size); break;
+			case kAESC: rc = readAESC(chd.size); break;
+			case kLITE: rc = readLITE(chd.size); break;
+			case kSN2J: rc = readSN2J(chd.size); break;
+			case kSND2: rc = readSND2(chd.size); break;
+			case kVIEW: rc = readVIEW(chd.size); break;
+			case kVQFL: rc = readVQFL(chd.size); break;
+			case kVQFR: rc = readVQFR(chd.size); break;
+			case kZBUF: rc = readZBUF(chd.size); break;
 			default:
-				r->skip(roundup(chd.size));
+				_s->skip(roundup(chd.size));
 				rc = true;
 		}
 
 		if (!rc)
 		{
-			debug("Error handling chunk %s\n", str_tag(chd.id));
+			debug("Error handling chunk %s\n", strTag(chd.id));
 			return -1;
 		}
 	} while (chd.id != kVQFR);
 
-	return cur_frame;
+	return _curFrame;
 }
 
 
-bool VQADecoder::read_sn2j(uint32 size)
+bool VQADecoder::readSN2J(uint32 size)
 {
 	if (size != 6)
 		return false;
@@ -540,15 +539,15 @@ bool VQADecoder::read_sn2j(uint32 size)
 	uint16 step_index;
 	uint32 predictor;
 
-	step_index = r->readUint16LE();
-	predictor  = r->readUint32LE();
+	step_index = _s->readUint16LE();
+	predictor  = _s->readUint32LE();
 
 	// ima_adpcm_ws_decoder.set_parameters(step_index >> 5, predictor);
 
 	return true;
 }
 
-bool VQADecoder::read_snd2(uint32 size)
+bool VQADecoder::readSND2(uint32 size)
 {
 	if (size != 735)
 	{
@@ -556,44 +555,44 @@ bool VQADecoder::read_snd2(uint32 size)
 		return false;
 	}
 
-	if (!audio_frame)
-		audio_frame = new int16[2 * size];
-	memset(audio_frame, 0, 4 * size);
+	if (!_audioFrame)
+		_audioFrame = new int16[2 * size];
+	memset(_audioFrame, 0, 4 * size);
 
-	uint8 *in_frame = new uint8[roundup(size)];
-	r->read(in_frame, roundup(size));
+	uint8 *inFrame = new uint8[roundup(size)];
+	_s->read(inFrame, roundup(size));
 
-	// ima_adpcm_ws_decoder.decode(in_frame, size, audio_frame);
+	// ima_adpcm_ws_decoder.decode(inFrame, size, _audioFrame);
 
-	delete[] in_frame;
+	delete[] inFrame;
 
 	return true;
 }
 
-bool VQADecoder::read_vqfr(uint32 size)
+bool VQADecoder::readVQFR(uint32 size)
 {
-	iff_chunk_header_s chd;
+	IFFChunkHeader chd;
 
 	while (size >= 8)
 	{
-		if (!read_iff_chunk_header(r, &chd))
+		if (!readIFFChunkHeader(_s, &chd))
 			return false;
 		size -= roundup(chd.size) + 8;
 
-		// debug("(%s) ", str_tag(chd.id)); fflush(0);
+		// debug("(%s) ", strTag(chd.id)); fflush(0);
 
 		bool rc = false;
 		switch (chd.id)
 		{
-			case kCBFZ: rc = read_cbfz(chd.size); break;
-			case kVPTR: rc = read_vptr(chd.size); break;
+			case kCBFZ: rc = readCBFZ(chd.size); break;
+			case kVPTR: rc = readVPTR(chd.size); break;
 			default:
-				r->skip(roundup(chd.size));
+				_s->skip(roundup(chd.size));
 		}
 
 		if (!rc)
 		{
-			debug("VQFR: error handling chunk %s\n", str_tag(chd.id));
+			debug("VQFR: error handling chunk %s\n", strTag(chd.id));
 			return false;
 		}
 	}
@@ -601,27 +600,27 @@ bool VQADecoder::read_vqfr(uint32 size)
 	return true;
 }
 
-bool VQADecoder::read_vqfl(uint32 size)
+bool VQADecoder::readVQFL(uint32 size)
 {
-	iff_chunk_header_s chd;
+	IFFChunkHeader chd;
 
 	while (size >= 8)
 	{
-		if (!read_iff_chunk_header(r, &chd))
+		if (!readIFFChunkHeader(_s, &chd))
 			return false;
 		size -= roundup(chd.size) + 8;
 
 		bool rc = false;
 		switch (chd.id)
 		{
-			case kCBFZ: rc = read_cbfz(chd.size); break;
+			case kCBFZ: rc = readCBFZ(chd.size); break;
 			default:
-				r->skip(roundup(chd.size));
+				_s->skip(roundup(chd.size));
 		}
 
 		if (!rc)
 		{
-			debug("VQFL: error handling chunk %s\n", str_tag(chd.id));
+			debug("VQFL: error handling chunk %s\n", strTag(chd.id));
 			return false;
 		}
 	}
@@ -629,179 +628,179 @@ bool VQADecoder::read_vqfl(uint32 size)
 	return true;
 }
 
-bool VQADecoder::read_cbfz(uint32 size)
+bool VQADecoder::readCBFZ(uint32 size)
 {
-	if (size > header.maxCBFZSize)
+	if (size > _header.maxCBFZSize)
 	{
-		debug("%d > %d\n", size, header.maxCBFZSize);
+		debug("%d > %d\n", size, _header.maxCBFZSize);
 		return false;
 	}
 
-	if (!codebook)
+	if (!_codebook)
 	{
-		codebookSize = 2 * header.maxBlocks * header.blockW * header.blockH;
-		codebook = new uint8[codebookSize];
+		_codebookSize = 2 * _header.maxBlocks * _header.blockW * _header.blockH;
+		_codebook = new uint8[_codebookSize];
 	}
-	if (!cbfz)
-		cbfz = new uint8[roundup(header.maxCBFZSize)];
+	if (!_cbfz)
+		_cbfz = new uint8[roundup(_header.maxCBFZSize)];
 
-	r->read(cbfz, roundup(size));
+	_s->read(_cbfz, roundup(size));
 
-	decompress_lcw(cbfz, size, codebook, codebookSize);
+	decompress_lcw(_cbfz, size, _codebook, _codebookSize);
 
 	return true;
 }
 
 static
-int decodeZBUF_partial(uint8 *src, uint16 *cur_zbuf, uint32 src_len)
+int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 {
-	uint32 dst_size = 640 * 480; // This is taken from global variables?
-	uint32 dst_remain = dst_size;
+	uint32 dstSize = 640 * 480; // This is taken from global variables?
+	uint32 dstRemain = dstSize;
 
-	uint16 *curz_p = cur_zbuf;
-	uint16 *in_p = (uint16*)src;
+	uint16 *curzp = curZBUF;
+	uint16 *inp = (uint16*)src;
 
-	while (dst_remain && (in_p - (uint16*)src) < (ptrdiff_t)src_len)
+	while (dstRemain && (inp - (uint16*)src) < (ptrdiff_t)srcLen)
 	{
-		uint32 count = FROM_LE_16(*in_p++);
+		uint32 count = FROM_LE_16(*inp++);
 
 		if (count & 0x8000)
 		{
-			count = MIN(count & 0x7fff, dst_remain);
-			dst_remain -= count;
+			count = MIN(count & 0x7fff, dstRemain);
+			dstRemain -= count;
 
 			while (count--)
 			{
-				uint16 value = FROM_LE_16(*in_p++);
+				uint16 value = FROM_LE_16(*inp++);
 				if (value)
-					*curz_p = value;
-				++curz_p;
+					*curzp = value;
+				++curzp;
 			}
 		}
 		else
 		{
-			count = MIN(count, dst_remain);
-			dst_remain -= count;
-			uint16 value = FROM_LE_16(*in_p++);
+			count = MIN(count, dstRemain);
+			dstRemain -= count;
+			uint16 value = FROM_LE_16(*inp++);
 
 			if (!value)
-				curz_p += count;
+				curzp += count;
 			else
 			{
 				while (count--)
-					*curz_p++ = value;
+					*curzp++ = value;
 			}
 		}
 	}
-	return dst_size - dst_remain;
+	return dstSize - dstRemain;
 }
 
-bool VQADecoder::read_zbuf(uint32 size)
+bool VQADecoder::readZBUF(uint32 size)
 {
-	if (size > max_zbuf_chunk_size) {
-		debug("VQA ERROR: ZBUF chunk size: %08x > %08x\n", size, max_zbuf_chunk_size);
-		r->skip(roundup(size));
+	if (size > _maxZBUFChunkSize) {
+		debug("VQA ERROR: ZBUF chunk size: %08x > %08x\n", size, _maxZBUFChunkSize);
+		_s->skip(roundup(size));
 		return false;
 	}
 
 	uint32 width, height, complete, unk0;
-	width    = r->readUint32LE();
-	height   = r->readUint32LE();
-	complete = r->readUint32LE();
-	unk0     = r->readUint32LE();
+	width    = _s->readUint32LE();
+	height   = _s->readUint32LE();
+	complete = _s->readUint32LE();
+	unk0     = _s->readUint32LE();
 
 	uint32 remain = size - 16;
 
-	if (width != header.width || height != header.height)
+	if (width != _header.width || height != _header.height)
 	{
 		debug("%d, %d, %d, %d\n", width, height, complete, unk0);
-		r->skip(roundup(remain));
+		_s->skip(roundup(remain));
 		return false;
 	}
 
-	if (!zbuf)
+	if (!_zbuf)
 	{
 		if (!complete) {
-			r->skip(roundup(remain));
+			_s->skip(roundup(remain));
 			return false;
 		}
-		zbuf = new uint16[width * height];
+		_zbuf = new uint16[width * height];
 	}
 
-	r->read(zbuf_chunk, roundup(remain));
+	_s->read(_zbufChunk, roundup(remain));
 
 	if (complete) {
-		size_t zbuf_out_size;
-		decompress_lzo1x(zbuf_chunk, remain, (uint8*)zbuf, &zbuf_out_size);
+		size_t zbufOutSize;
+		decompress_lzo1x(_zbufChunk, remain, (uint8*)_zbuf, &zbufOutSize);
 	} else {
-		decodeZBUF_partial(zbuf_chunk, zbuf, remain);
+		decodeZBUF_partial(_zbufChunk, _zbuf, remain);
 	}
 
 	return true;
 }
 
-bool VQADecoder::get_zbuf(uint16 *a_zbuf)
+bool VQADecoder::getZBUF(uint16 *zbuf)
 {
-	if (!zbuf)
+	if (!_zbuf)
 		return false;
 
-	memcpy(a_zbuf, zbuf, 2 * header.width * header.height);
+	memcpy(zbuf, _zbuf, 2 * _header.width * _header.height);
 	return true;
 }
 
-bool VQADecoder::read_view(uint32 size)
+bool VQADecoder::readVIEW(uint32 size)
 {
 	if (size != 56)
 		return false;
 
-	r->skip(size);
-	// has_view = true;
+	_s->skip(size);
+	// _hasView = true;
 
 	return true;
 }
 
-bool VQADecoder::read_aesc(uint32 size)
+bool VQADecoder::readAESC(uint32 size)
 {
-	r->skip(roundup(size));
+	_s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::read_lite(uint32 size)
+bool VQADecoder::readLITE(uint32 size)
 {
-	r->skip(roundup(size));
+	_s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::read_vptr(uint32 size)
+bool VQADecoder::readVPTR(uint32 size)
 {
-	if (size > header.maxVPTRSize)
+	if (size > _header.maxVPTRSize)
 		return false;
 
-	if (!vptr)
-		vptr = new uint8[roundup(header.maxVPTRSize)];
+	if (!_vptr)
+		_vptr = new uint8[roundup(_header.maxVPTRSize)];
 
-	vptrSize = size;
-	r->read(vptr, roundup(size));
+	_vptrSize = size;
+	_s->read(_vptr, roundup(size));
 
 	return true;
 }
 
-void VQADecoder::vptr_write_block(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha) const
+void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha) const
 {
-	uint16 frame_width  = header.width;
+	uint16 frame_width  = _header.width;
 	uint32 frame_stride = 640;
-	uint16 block_width  = header.blockW;
-	uint16 block_height = header.blockH;
+	uint16 block_width  = _header.blockW;
+	uint16 block_height = _header.blockH;
 
 	const uint8 *const block_src =
-		&codebook[2 * src_block * block_width * block_height];
+		&_codebook[2 * srcBlock * block_width * block_height];
 
 	int blocks_per_line = frame_width / block_width;
 
 	do
 	{
-		uint32 frame_x = dst_block % blocks_per_line * block_width  + header.offset_x / 2;
-		uint32 frame_y = dst_block / blocks_per_line * block_height + header.offset_y;
+		uint32 frame_x = dstBlock % blocks_per_line * block_width  + _header.offset_x / 2;
+		uint32 frame_y = dstBlock / blocks_per_line * block_height + _header.offset_y;
 
 		uint32 dst_offset = frame_x + frame_y * frame_stride;
 
@@ -824,45 +823,45 @@ void VQADecoder::vptr_write_block(uint16 *frame, unsigned int dst_block, unsigne
 			dst += frame_stride - block_width;
 		}
 
-		++dst_block;
+		++dstBlock;
 	}
 	while (--count);
 }
 
-void VQADecoder::set_loop_special(int loop, bool wait)
+void VQADecoder::setLoopSpecial(int loop, bool wait)
 {
-	loop_special = loop;
+	_loopSpecial = loop;
 	if (!wait)
-		cur_loop = -1;
+		_curLoop = -1;
 }
 
-void VQADecoder::set_loop_default(int loop)
+void VQADecoder::setLoopDefault(int loop)
 {
-	loop_default = loop;
+	_loopDefault = loop;
 }
 
-bool VQADecoder::seek_to_frame(int frame)
+bool VQADecoder::seekToFrame(int frame)
 {
-	if (frame < 0 || frame >= header.numFrames)
+	if (frame < 0 || frame >= _header.numFrames)
 		return false;
 
-	r->seek(2 * (frame_info[frame] & 0x0fffffff), SEEK_SET);
+	_s->seek(2 * (_frameInfo[frame] & 0x0fffffff), SEEK_SET);
 	return true;
 }
 
-bool VQADecoder::decode_frame(uint16 *a_frame)
+bool VQADecoder::decodeFrame(uint16 *frame)
 {
-	if (!codebook || !vptr)
+	if (!_codebook || !_vptr)
 		return false;
 
-	if (!frame)
-		frame = new uint16[header.width * header.height];
+	if (!_frame)
+		_frame = new uint16[_header.width * _header.height];
 
-	uint8 *src = vptr;
-	uint8 *end = vptr + vptrSize;
+	uint8 *src = _vptr;
+	uint8 *end = _vptr + _vptrSize;
 
-	uint16 count, src_block, dst_block = 0;
-	(void)src_block;
+	uint16 count, srcBlock, dstBlock = 0;
+	(void)srcBlock;
 
 	while (end - src >= 2)
 	{
@@ -874,58 +873,58 @@ bool VQADecoder::decode_frame(uint16 *a_frame)
 		{
 		case 0:
 			count = command & 0x1fff;
-			dst_block += count;
+			dstBlock += count;
 			break;
 		case 1:
 			count = 2 * (((command >> 8) & 0x1f) + 1);
-			src_block = command & 0x00ff;
+			srcBlock = command & 0x00ff;
 
-			vptr_write_block(frame, dst_block, src_block, count);
-			dst_block += count;
+			VPTRWriteBlock(_frame, dstBlock, srcBlock, count);
+			dstBlock += count;
 			break;
 		case 2:
 			count = 2 * (((command >> 8) & 0x1f) + 1);
-			src_block = command & 0x00ff;
+			srcBlock = command & 0x00ff;
 
-			vptr_write_block(frame, dst_block, src_block, 1);
-			++dst_block;
+			VPTRWriteBlock(_frame, dstBlock, srcBlock, 1);
+			++dstBlock;
 
 			for (int i = 0; i < count; ++i)
 			{
-				src_block = *src++;
-				vptr_write_block(frame, dst_block, src_block, 1);
-				++dst_block;
+				srcBlock = *src++;
+				VPTRWriteBlock(_frame, dstBlock, srcBlock, 1);
+				++dstBlock;
 			}
 			break;
 		case 3:
 		case 4:
 			count = 1;
-			src_block = command & 0x1fff;
+			srcBlock = command & 0x1fff;
 
-			vptr_write_block(frame, dst_block, src_block, count, prefix == 4);
-			++dst_block;
+			VPTRWriteBlock(_frame, dstBlock, srcBlock, count, prefix == 4);
+			++dstBlock;
 			break;
 		case 5:
 		case 6:
 			count = *src++;
-			src_block = command & 0x1fff;
+			srcBlock = command & 0x1fff;
 
-			vptr_write_block(frame, dst_block, src_block, count, prefix == 6);
-			dst_block += count;
+			VPTRWriteBlock(_frame, dstBlock, srcBlock, count, prefix == 6);
+			dstBlock += count;
 			break;
 		default:
 			debug("Undefined case %d\n", command >> 13);
 		}
 	}
 
-	memcpy(a_frame, frame, 2 * 640 * 480);
+	memcpy(frame, _frame, 2 * 640 * 480);
 
 	return true;
 }
 
-int16 *VQADecoder::get_audio_frame()
+int16 *VQADecoder::getAudioFrame()
 {
-	return audio_frame;
+	return _audioFrame;
 }
 
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index c4b5974..cd0123e 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -29,6 +29,7 @@
 #include "common/types.h"
 
 namespace BladeRunner {
+
 class VQADecoder
 {
 	struct Header
@@ -70,94 +71,93 @@ class VQADecoder
 
 	struct LoopInfo
 	{
-		uint16  loop_count;
+		uint16  loopCount;
 		uint32  flags;
-		Loop     *loops;
+		Loop   *loops;
 
 		LoopInfo()
-			: loop_count(0)
+			: loopCount(0)
 		{}
 	};
 
 	struct ClipInfo
 	{
-		uint16 clip_count;
+		uint16 clipCount;
 	};
 
-	Common::SeekableReadStream *r;
-
-	Header   header;
-	LoopInfo loop_info;
-	ClipInfo clip_info;
+	Common::SeekableReadStream *_s;
 
-	uint16 *frame;
-	uint16 *zbuf;
+	Header   _header;
+	LoopInfo _loopInfo;
+	ClipInfo _clipInfo;
 
-	size_t  codebookSize;
-	uint8  *codebook;
-	uint8  *cbfz;
+	uint16  *_frame;
+	uint16  *_zbuf;
 
-	size_t  vptrSize;
-	uint8  *vptr;
+	size_t   _codebookSize;
+	uint8   *_codebook;
+	uint8   *_cbfz;
 
-	uint32 *frame_info;
+	size_t   _vptrSize;
+	uint8   *_vptr;
 
-	int     cur_frame;
+	uint32  *_frameInfo;
 
-	int     cur_loop;
-	int     loop_special;
-	int     loop_default;
+	int      _curFrame;
+	int      _curLoop;
+	int      _loopSpecial;
+	int      _loopDefault;
 
-	uint32  max_view_chunk_size;
-	uint32  max_zbuf_chunk_size;
-	uint32  max_aesc_chunk_size;
-	uint8  *zbuf_chunk;
+	uint32   _maxVIEWChunkSize;
+	uint32   _maxZBUFChunkSize;
+	uint32   _maxAESCChunkSize;
+	uint8   *_zbufChunk;
 
-	bool   has_view;
+	bool   _hasView;
 	// view_t view;
 
 	// ima_adpcm_ws_decoder_t ima_adpcm_ws_decoder;
-	int16 *audio_frame;
-
-	bool read_vqhd(uint32 size);
-	bool read_msci(uint32 size);
-	bool read_mfci(uint32 size);
-	bool read_linf(uint32 size);
-	bool read_cinf(uint32 size);
-	bool read_finf(uint32 size);
-	bool read_lnin(uint32 size);
-	bool read_clip(uint32 size);
-
-	bool read_sn2j(uint32 size);
-	bool read_snd2(uint32 size);
-	bool read_vqfr(uint32 size);
-	bool read_vptr(uint32 size);
-	bool read_vqfl(uint32 size);
-	bool read_cbfz(uint32 size);
-	bool read_zbuf(uint32 size);
-	bool read_view(uint32 size);
-	bool read_aesc(uint32 size);
-	bool read_lite(uint32 size);
+	int16 *_audioFrame;
+
+	bool readVQHD(uint32 size);
+	bool readMSCI(uint32 size);
+	bool readMFCI(uint32 size);
+	bool readLINF(uint32 size);
+	bool readCINF(uint32 size);
+	bool readFINF(uint32 size);
+	bool readLNIN(uint32 size);
+	bool readCLIP(uint32 size);
+
+	bool readSN2J(uint32 size);
+	bool readSND2(uint32 size);
+	bool readVQFR(uint32 size);
+	bool readVPTR(uint32 size);
+	bool readVQFL(uint32 size);
+	bool readCBFZ(uint32 size);
+	bool readZBUF(uint32 size);
+	bool readVIEW(uint32 size);
+	bool readAESC(uint32 size);
+	bool readLITE(uint32 size);
 
 public:
 	VQADecoder(Common::SeekableReadStream *r);
 	~VQADecoder();
 
-	bool read_header();
-	int  read_frame();
+	bool readHeader();
+	int  readFrame();
 
-	void vptr_write_block(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha = false) const;
+	void VPTRWriteBlock(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha = false) const;
 
-	void set_loop_special(int loop, bool wait);
-	void set_loop_default(int loop);
+	void setLoopSpecial(int loop, bool wait);
+	void setLoopDefault(int loop);
 
-	bool seek_to_frame(int frame);
-	bool decode_frame(uint16 *frame);
+	bool seekToFrame(int frame);
+	bool decodeFrame(uint16 *frame);
 
-	int16 *get_audio_frame();
+	int16 *getAudioFrame();
 
 	// bool get_view(view_t *view);
-	bool get_zbuf(uint16 *zbuf);
+	bool getZBUF(uint16 *zbuf);
 };
 
 }; // End of namespace BladeRunner


Commit: f0432bdf2568a0390e02ff18dd73ea5296a007e2
    https://github.com/scummvm/scummvm/commit/f0432bdf2568a0390e02ff18dd73ea5296a007e2
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:21:00+02:00

Commit Message:
BLADERUNNER: Split VQA decoder into player and decoder, add Outtake player

Changed paths:
  A engines/bladerunner/outtake.cpp
  A engines/bladerunner/outtake.h
  A engines/bladerunner/vqa_player.cpp
  A engines/bladerunner/vqa_player.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/module.mk
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 7e8466c..bcf8c09 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -25,6 +25,7 @@
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
+#include "bladerunner/outtake.h"
 #include "bladerunner/settings.h"
 #include "bladerunner/vqa_decoder.h"
 
@@ -206,56 +207,12 @@ void BladeRunnerEngine::handleEvents() {
 	}
 }
 
-void BladeRunnerEngine::playOuttake(int id, bool no_localization) {
+void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
 	Common::String name = _gameInfo->getOuttake(id);
 
-	if (no_localization)
-		name += ".VQA";
-	else
-		name += "_E.VQA";
+	OuttakePlayer player(this);
 
-	Common::SeekableReadStream *s = getResourceStream(name);
-	if (!s)
-		return;
-
-	VQADecoder vqa_decoder(s);
-
-	bool b = vqa_decoder.readHeader();
-	if (!b) return;
-
-	uint32 frame_count = 0;
-	uint32 start_time = 0;
-	uint32 next_frame_time = 0;
-
-	for (;;)
-	{
-		handleEvents();
-		// TODO: Handle skips
-		if (shouldQuit())
-			break;
-
-		uint32 cur_time = next_frame_time + 1;
-
-		if (next_frame_time <= cur_time)
-		{
-			int frame_number = vqa_decoder.readFrame();
-			debug("frame_number: %d", frame_number);
-
-			if (frame_number < 0)
-				break;
-
-			b = vqa_decoder.decodeFrame((uint16*)_surface1.getPixels());
-
-			_system->copyRectToScreen(_surface1.getPixels(), _surface1.pitch, 0, 0, _surface1.w, _surface1.h);
-			_system->updateScreen();
-
-			++frame_count;
-
-			if (!next_frame_time)
-				next_frame_time = cur_time;
-			next_frame_time = next_frame_time + (60 * 1000) / 15;
-		}
-	}
+	player.play(name, noLocalization, -1);
 }
 
 bool BladeRunnerEngine::openArchive(const Common::String &name) {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index c679b80..bf95ca7 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -53,12 +53,12 @@ public:
 
 	int in_script_counter;
 
+	Graphics::Surface _surface1;
+
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
 
-	Graphics::Surface _surface1;
-
 public:
 	BladeRunnerEngine(OSystem *syst);
 
@@ -77,7 +77,7 @@ public:
 	void gameTick();
 	void handleEvents();
 
-	void playOuttake(int id, bool no_localization);
+	void outtakePlay(int id, bool no_localization, int container = -1);
 
 	bool openArchive(const Common::String &name);
 	bool closeArchive(const Common::String &name);
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index c0d6416..44e681a 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -9,8 +9,10 @@ MODULE_OBJS = \
 	detection.o \
 	gameinfo.o \
 	image.o \
+	outtake.o \
 	settings.o \
-	vqa_decoder.o
+	vqa_decoder.o \
+	vqa_player.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
new file mode 100644
index 0000000..01ceefa
--- /dev/null
+++ b/engines/bladerunner/outtake.cpp
@@ -0,0 +1,67 @@
+/* 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 "bladerunner/outtake.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/vqa_player.h"
+
+#include "common/system.h"
+
+namespace BladeRunner {
+
+void OuttakePlayer::play(const Common::String &name, bool noLocalization, int container) {
+	if (container > 0) {
+		debug("OuttakePlayer::play TODO");
+		return;
+	}
+
+	Common::String resName;
+	if (noLocalization)
+		resName = name + ".VQA";
+	else
+		resName = name + "_E.VQA";
+
+	_vqaPlayer = new VQAPlayer(_vm, &_vm->_surface1);
+	_vqaPlayer->open(resName);
+
+	for (;;) {
+		_vm->handleEvents();
+		if (_vm->shouldQuit())
+			break;
+
+		int r = _vqaPlayer->update();
+		if (r == -3)
+			break;
+
+		if (r >= 0) {
+			_vm->_system->copyRectToScreen(_vm->_surface1.getPixels(), _vm->_surface1.pitch, 0, 0, _vm->_surface1.w, _vm->_surface1.h);
+			_vm->_system->updateScreen();
+			_vm->_system->delayMillis(10);
+		}
+	}
+
+	delete _vqaPlayer;
+	_vqaPlayer = nullptr;
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/outtake.h b/engines/bladerunner/outtake.h
new file mode 100644
index 0000000..4e97b1b
--- /dev/null
+++ b/engines/bladerunner/outtake.h
@@ -0,0 +1,54 @@
+/* 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 BLADERUNNER_OUTTAKE_H
+#define BLADERUNNER_OUTTAKE_H
+
+#include "common/str.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class VQAPlayer;
+
+class OuttakePlayer {
+	BladeRunnerEngine *_vm;
+
+	bool               _isVQAOpen;
+	VQAPlayer         *_vqaPlayer;
+	Graphics::Surface *_surface;
+
+public:
+	OuttakePlayer(BladeRunnerEngine *vm) :
+		_vm(vm),
+		_isVQAOpen(false),
+		_vqaPlayer(nullptr)
+	{}
+
+	void play(const Common::String &name, bool noLocalization, int container);
+};
+
+}; // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 46e45de..c297935 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -66,17 +66,13 @@ namespace BladeRunner {
 #define kWVQA 0x57565141
 #define kZBUF 0x5A425546
 
-VQADecoder::VQADecoder(Common::SeekableReadStream *s)
-	: _s(s),
+VQADecoder::VQADecoder()
+	: _s(nullptr),
 	  _frame(0),
 	  _zbuf(0),
 	  _codebook(0),
 	  _cbfz(0),
 	  _vptr(0),
-	  _curFrame(-1),
-	  _curLoop(-1),
-	  _loopSpecial(-1),
-	  _loopDefault(-1),
 	  _hasView(false),
 	  _audioFrame(0),
 	  _maxVIEWChunkSize(0),
@@ -126,7 +122,7 @@ bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
 	ts->size = s->readUint32BE();
 
 	// if (ts->size != roundup(ts->size))
-	// 	debug("%s: %d\n", strTag(ts->id), ts->size);
+	// 	debug("%s: %d", strTag(ts->id), ts->size);
 
 	return true;
 }
@@ -144,26 +140,27 @@ const char *strTag(uint32 tag)
 	return s;
 }
 
-bool VQADecoder::readHeader()
+bool VQADecoder::open(Common::SeekableReadStream *s)
 {
 	IFFChunkHeader chd;
 	uint32 type;
 	bool rc;
 
-	readIFFChunkHeader(_s, &chd);
+	readIFFChunkHeader(s, &chd);
 	if (chd.id != kFORM || !chd.size)
 		return false;
 
-	type = _s->readUint32BE();
+	type = s->readUint32BE();
 
 	if (type != kWVQA)
 		return false;
 
+	_s = s;
 	do {
 		if (!readIFFChunkHeader(_s, &chd))
 			return false;
 
-		debug("\t%s : %x\n", strTag(chd.id), chd.size);
+		debug("\t%s : %x", strTag(chd.id), chd.size);
 
 		rc = false;
 		switch (chd.id)
@@ -177,21 +174,21 @@ bool VQADecoder::readHeader()
 			case kMSCI: rc = readMSCI(chd.size); break;
 			case kVQHD: rc = readVQHD(chd.size); break;
 			default:
-				debug("Unhandled chunk '%s'\n", strTag(chd.id));
+				debug("Unhandled chunk '%s'", strTag(chd.id));
 				_s->skip(roundup(chd.size));
 				rc = true;
 		}
 
 		if (!rc)
 		{
-			debug("failed to handle chunk %s\n", strTag(chd.id));
-			return false;
+			debug("failed to handle chunk %s", strTag(chd.id));
+			return -1;
 		}
 
 	} while (chd.id != kFINF);
 
 	for (int i = 0; i != _loopInfo.loopCount; ++i) {
-		debug("LOOP %2d: %4d %4d %s\n", i,
+		debug("LOOP %2d: %4d %4d %s", i,
 			_loopInfo.loops[i].begin,
 			_loopInfo.loops[i].end,
 			_loopInfo.loops[i].name.c_str());
@@ -229,32 +226,32 @@ bool VQADecoder::readVQHD(uint32 size)
 
 	if (_header.offset_x || _header.offset_y)
 	{
-		debug("_header.offset_x, _header.offset_y: %d %d\n", _header.offset_x, _header.offset_y);
+		debug("_header.offset_x, _header.offset_y: %d %d", _header.offset_x, _header.offset_y);
 	}
 
 	// if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014)
 	{
-		debug("_header.version      %d\n", _header.version);
-		debug("_header.flags        %04x\n", _header.flags);
-		debug("_header.numFrames    %d\n", _header.numFrames);
-		debug("_header.width        %d\n", _header.width);
-		debug("_header.height       %d\n", _header.height);
-		debug("_header.blockW       %d\n", _header.blockW);
-		debug("_header.blockH       %d\n", _header.blockH);
-		debug("_header.frameRate    %d\n", _header.frameRate);
-		debug("_header.cbParts      %d\n", _header.cbParts);
-		debug("_header.colors       %d\n", _header.colors);
-		debug("_header.maxBlocks    %d\n", _header.maxBlocks);
-		debug("_header.offsetX      %d\n", _header.offset_x);
-		debug("_header.offsetY      %d\n", _header.offset_y);
-		debug("_header.maxVPTRSize  %d\n", _header.maxVPTRSize);
-		debug("_header.freq         %d\n", _header.freq);
-		debug("_header.channels     %d\n", _header.channels);
-		debug("_header.bits         %d\n", _header.bits);
-		debug("_header.unk3         %d\n", _header.unk3);
-		debug("_header.unk4         %d\n", _header.unk4);
-		debug("_header.maxCBFZSize  %d\n", _header.maxCBFZSize);
-		debug("_header.unk5         %d\n", _header.unk5);
+		debug("_header.version      %d", _header.version);
+		debug("_header.flags        %04x", _header.flags);
+		debug("_header.numFrames    %d", _header.numFrames);
+		debug("_header.width        %d", _header.width);
+		debug("_header.height       %d", _header.height);
+		debug("_header.blockW       %d", _header.blockW);
+		debug("_header.blockH       %d", _header.blockH);
+		debug("_header.frameRate    %d", _header.frameRate);
+		debug("_header.cbParts      %d", _header.cbParts);
+		debug("_header.colors       %d", _header.colors);
+		debug("_header.maxBlocks    %d", _header.maxBlocks);
+		debug("_header.offsetX      %d", _header.offset_x);
+		debug("_header.offsetY      %d", _header.offset_y);
+		debug("_header.maxVPTRSize  %d", _header.maxVPTRSize);
+		debug("_header.freq         %d", _header.freq);
+		debug("_header.channels     %d", _header.channels);
+		debug("_header.bits         %d", _header.bits);
+		debug("_header.unk3         %d", _header.unk3);
+		debug("_header.unk4         %d", _header.unk4);
+		debug("_header.maxCBFZSize  %d", _header.maxCBFZSize);
+		debug("_header.unk5         %d", _header.unk5);
 	}
 
 	// exit(-1);
@@ -289,19 +286,19 @@ bool VQADecoder::readMSCI(uint32 size)
 		{
 		case kVIEW:
 			_maxVIEWChunkSize = size;
-			debug("max VIEW size: %08x\n", _maxVIEWChunkSize);
+			debug("max VIEW size: %08x", _maxVIEWChunkSize);
 			break;
 		case kZBUF:
 			_maxZBUFChunkSize = size;
 			_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
-			debug("max ZBUF size: %08x\n", _maxZBUFChunkSize);
+			debug("max ZBUF size: %08x", _maxZBUFChunkSize);
 			break;
 		case kAESC:
 			_maxAESCChunkSize = size;
-			debug("max AESC size: %08x\n", _maxAESCChunkSize);
+			debug("max AESC size: %08x", _maxAESCChunkSize);
 			break;
 		default:
-			debug("Unknown tag in MSCT: %s\n", strTag(tag));
+			debug("Unknown tag in MSCT: %s", strTag(tag));
 		}
 
 		uint32 zero;
@@ -336,7 +333,7 @@ bool VQADecoder::readLINF(uint32 size)
 		_loopInfo.loops[i].begin = _s->readUint16LE();
 		_loopInfo.loops[i].end   = _s->readUint16LE();
 
-		// debug("Loop %d: %04x %04x\n", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
+		// debug("Loop %d: %04x %04x", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
 	}
 
 	return true;
@@ -363,7 +360,7 @@ bool VQADecoder::readCINF(uint32 size)
 		uint32 b;
 		a = _s->readUint16LE();
 		b = _s->readUint32LE();
-		debug("%4d %08x\n", a, b);
+		debug("%4d %08x", a, b);
 	}
 
 	return true;
@@ -384,7 +381,7 @@ bool VQADecoder::readFINF(uint32 size)
 		for (uint32 i = 0; i != _header.numFrames; ++i)
 		{
 			uint32 diff = _frameInfo[i] - last;
-			debug("_frameInfo[%4d] = 0x%08x   - %08x\n", i, _frameInfo[i], diff);
+			debug("_frameInfo[%4d] = 0x%08x   - %08x", i, _frameInfo[i], diff);
 			last = _frameInfo[i];
 		}
 	}
@@ -449,57 +446,24 @@ bool VQADecoder::readMFCI(uint32 size)
 	return true;
 }
 
-int VQADecoder::readFrame()
+bool VQADecoder::readFrame()
 {
-	// debug("VQADecoder::readFrame(): %d, %d, %d, %d\n", _loopDefault, _loopSpecial, _curLoop, _curFrame);
-
-	if (_loopInfo.loopCount)
-	{
-		if (_loopSpecial >= 0)
-		{
-			_curLoop = _loopSpecial;
-			_loopSpecial = -1;
-
-			_curFrame = _loopInfo.loops[_curLoop].begin;
-			seekToFrame(_curFrame);
-		}
-		else if (_curLoop == -1 && _loopDefault >= 0)
-		{
-			_curLoop = _loopDefault;
-			_curFrame = _loopInfo.loops[_curLoop].begin;
-			seekToFrame(_curFrame);
-		}
-		else if (_curLoop >= -1 && _curFrame == _loopInfo.loops[_curLoop].end)
-		{
-			if (_loopDefault == -1)
-				return -1;
-
-			_curLoop = _loopDefault;
-			_curFrame = _loopInfo.loops[_curLoop].begin;
-			seekToFrame(_curFrame);
-		}
-		else
-			++_curFrame;
-	}
-	else
-		++_curFrame;
-
-	if (_curFrame >= _header.numFrames)
-		return -1;
-
 	IFFChunkHeader chd;
 
+	if (!_s)
+		return false;
+
 	_hasView = false;
 
 	if (remain(_s) < 8) {
-		debug("remain: %d\n", remain(_s));
-		return -1;
+		debug("remain: %d", remain(_s));
+		return false;
 	}
 
 	do {
 		if (!readIFFChunkHeader(_s, &chd)) {
-			debug("Error reading chunk header\n");
-			return -1;
+			debug("Error reading chunk header");
+			return false;
 		}
 
 		// debug("%s ", strTag(chd.id));
@@ -522,12 +486,12 @@ int VQADecoder::readFrame()
 
 		if (!rc)
 		{
-			debug("Error handling chunk %s\n", strTag(chd.id));
-			return -1;
+			debug("Error handling chunk %s", strTag(chd.id));
+			return false;
 		}
 	} while (chd.id != kVQFR);
 
-	return _curFrame;
+	return true;
 }
 
 
@@ -551,7 +515,7 @@ bool VQADecoder::readSND2(uint32 size)
 {
 	if (size != 735)
 	{
-		debug("audio frame size: %d\n", size);
+		debug("audio frame size: %d", size);
 		return false;
 	}
 
@@ -592,7 +556,7 @@ bool VQADecoder::readVQFR(uint32 size)
 
 		if (!rc)
 		{
-			debug("VQFR: error handling chunk %s\n", strTag(chd.id));
+			debug("VQFR: error handling chunk %s", strTag(chd.id));
 			return false;
 		}
 	}
@@ -620,7 +584,7 @@ bool VQADecoder::readVQFL(uint32 size)
 
 		if (!rc)
 		{
-			debug("VQFL: error handling chunk %s\n", strTag(chd.id));
+			debug("VQFL: error handling chunk %s", strTag(chd.id));
 			return false;
 		}
 	}
@@ -632,7 +596,7 @@ bool VQADecoder::readCBFZ(uint32 size)
 {
 	if (size > _header.maxCBFZSize)
 	{
-		debug("%d > %d\n", size, _header.maxCBFZSize);
+		debug("%d > %d", size, _header.maxCBFZSize);
 		return false;
 	}
 
@@ -698,7 +662,7 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 bool VQADecoder::readZBUF(uint32 size)
 {
 	if (size > _maxZBUFChunkSize) {
-		debug("VQA ERROR: ZBUF chunk size: %08x > %08x\n", size, _maxZBUFChunkSize);
+		debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
 		_s->skip(roundup(size));
 		return false;
 	}
@@ -713,7 +677,7 @@ bool VQADecoder::readZBUF(uint32 size)
 
 	if (width != _header.width || height != _header.height)
 	{
-		debug("%d, %d, %d, %d\n", width, height, complete, unk0);
+		debug("%d, %d, %d, %d", width, height, complete, unk0);
 		_s->skip(roundup(remain));
 		return false;
 	}
@@ -828,18 +792,6 @@ void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned i
 	while (--count);
 }
 
-void VQADecoder::setLoopSpecial(int loop, bool wait)
-{
-	_loopSpecial = loop;
-	if (!wait)
-		_curLoop = -1;
-}
-
-void VQADecoder::setLoopDefault(int loop)
-{
-	_loopDefault = loop;
-}
-
 bool VQADecoder::seekToFrame(int frame)
 {
 	if (frame < 0 || frame >= _header.numFrames)
@@ -913,7 +865,7 @@ bool VQADecoder::decodeFrame(uint16 *frame)
 			dstBlock += count;
 			break;
 		default:
-			debug("Undefined case %d\n", command >> 13);
+			debug("Undefined case %d", command >> 13);
 		}
 	}
 
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index cd0123e..ab1f9ef 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef BLADERUNNER_VQA_H
-#define BLADERUNNER_VQA_H
+#ifndef BLADERUNNER_VQA_DECODER_H
+#define BLADERUNNER_VQA_DECODER_H
 
 #include "common/debug.h"
 #include "common/str.h"
@@ -103,11 +103,6 @@ class VQADecoder
 
 	uint32  *_frameInfo;
 
-	int      _curFrame;
-	int      _curLoop;
-	int      _loopSpecial;
-	int      _loopDefault;
-
 	uint32   _maxVIEWChunkSize;
 	uint32   _maxZBUFChunkSize;
 	uint32   _maxAESCChunkSize;
@@ -140,16 +135,15 @@ class VQADecoder
 	bool readLITE(uint32 size);
 
 public:
-	VQADecoder(Common::SeekableReadStream *r);
+	VQADecoder();
 	~VQADecoder();
 
-	bool readHeader();
-	int  readFrame();
+	bool open(Common::SeekableReadStream *s);
+	bool readFrame();
 
-	void VPTRWriteBlock(uint16 *frame, unsigned int dst_block, unsigned int src_block, int count, bool alpha = false) const;
+	int getFrameTime() { return 1000 / _header.frameRate; }
 
-	void setLoopSpecial(int loop, bool wait);
-	void setLoopDefault(int loop);
+	void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false) const;
 
 	bool seekToFrame(int frame);
 	bool decodeFrame(uint16 *frame);
@@ -158,6 +152,8 @@ public:
 
 	// bool get_view(view_t *view);
 	bool getZBUF(uint16 *zbuf);
+
+	friend class VQAPlayer;
 };
 
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
new file mode 100644
index 0000000..8b61481
--- /dev/null
+++ b/engines/bladerunner/vqa_player.cpp
@@ -0,0 +1,102 @@
+/* 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 "bladerunner/vqa_player.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/system.h"
+
+namespace BladeRunner {
+
+bool VQAPlayer::open(const Common::String &name) {
+	_s = _vm->getResourceStream(name);
+	if (!_s)
+		return false;
+
+	if(!_decoder.open(_s)) {
+		delete _s;
+		_s = nullptr;
+		return false;
+	}
+
+	return true;
+}
+
+int VQAPlayer::update() {
+	uint32 now = _vm->_system->getMillis();
+
+	if (_nextFrameTime == 0)
+		_nextFrameTime = now;
+
+	if (now < _nextFrameTime)
+		return -1;
+
+	_nextFrameTime += 1000 / _decoder._header.frameRate;
+
+	if (_decoder._loopInfo.loopCount) {
+		if (_loopSpecial >= 0) {
+			_curLoop = _loopSpecial;
+			_loopSpecial = -3;
+
+			_curFrame = _decoder._loopInfo.loops[_curLoop].begin;
+			_decoder.seekToFrame(_curFrame);
+		} else if (_curLoop == -1 && _loopDefault >= 0) {
+			_curLoop = _loopDefault;
+			_curFrame = _decoder._loopInfo.loops[_curLoop].begin;
+			_decoder.seekToFrame(_curFrame);
+		} else if (_curLoop >= 0 && _curFrame == _decoder._loopInfo.loops[_curLoop].end) {
+			if (_loopDefault == -1)
+				return -3;
+
+			_curLoop = _loopDefault;
+			_curFrame = _decoder._loopInfo.loops[_curLoop].begin;
+			_decoder.seekToFrame(_curFrame);
+		}
+		else
+			++_curFrame;
+	}
+	else
+		++_curFrame;
+
+	if (_curFrame >= _decoder._header.numFrames)
+		return -3;
+
+	_decoder.readFrame();
+	_decoder.decodeFrame((uint16*)_surface->getPixels());
+
+	return _curFrame;
+}
+
+void VQAPlayer::setLoopSpecial(int loop, bool wait)
+{
+	_loopSpecial = loop;
+	if (!wait)
+		_curLoop = -1;
+}
+
+void VQAPlayer::setLoopDefault(int loop)
+{
+	_loopDefault = loop;
+}
+
+}; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
new file mode 100644
index 0000000..2d7d682
--- /dev/null
+++ b/engines/bladerunner/vqa_player.h
@@ -0,0 +1,73 @@
+/* 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 BLADERUNNER_VQA_PLAYER_H
+#define BLADERUNNER_VQA_PLAYER_H
+
+#include "bladerunner/vqa_decoder.h"
+
+#include "audio/audiostream.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class VQAPlayer {
+	BladeRunnerEngine           *_vm;
+	Common::SeekableReadStream  *_s;
+	VQADecoder                   _decoder;
+	Graphics::Surface           *_surface;
+	Audio::QueuingAudioStream   *_audioStream;
+
+	int _curFrame;
+	int _curLoop;
+	int _loopSpecial;
+	int _loopDefault;
+
+	uint32 _nextFrameTime;
+
+public:
+
+	VQAPlayer(BladeRunnerEngine *vm, Graphics::Surface *surface)
+		: _vm(vm),
+		  _s(nullptr),
+		  _surface(surface),
+		  _audioStream(nullptr),
+		  _curFrame(-1),
+		  _curLoop(-1),
+		  _loopSpecial(-1),
+		  _loopDefault(-1),
+		  _nextFrameTime(0)
+	{}
+
+	bool open(const Common::String &name);
+	int  update();
+
+	void setLoopSpecial(int loop, bool wait);
+	void setLoopDefault(int loop);
+};
+
+}; // End of namespace BladeRunner
+
+#endif


Commit: 5fd05a41d7908dd63420c91134965b7d14c4b3ae
    https://github.com/scummvm/scummvm/commit/5fd05a41d7908dd63420c91134965b7d14c4b3ae
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:04+02:00

Commit Message:
BLADERUNNER: Damn copy/paste...

Changed paths:
    engines/bladerunner/vqa_decoder.cpp



diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index c297935..f4676d3 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -20,9 +20,6 @@
  *
  */
 
-#ifndef BLADERUNNER_VQA_DECODER_H
-#define BLADERUNNER_VQA_DECODER_H
-
 #include "bladerunner/vqa_decoder.h"
 
 #include "bladerunner/decompress_lcw.h"
@@ -880,5 +877,3 @@ int16 *VQADecoder::getAudioFrame()
 }
 
 }; // End of namespace BladeRunner
-
-#endif


Commit: a67e9e16bdbb5acbb2d1eb52a87c3eb2d128c44d
    https://github.com/scummvm/scummvm/commit/a67e9e16bdbb5acbb2d1eb52a87c3eb2d128c44d
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:11+02:00

Commit Message:
BLADERUNNER: Rebuild VQADecoder on top of Video::VideoDecoder

Changed paths:
  A engines/bladerunner/aud_decoder.cpp
  A engines/bladerunner/aud_decoder.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/module.mk
    engines/bladerunner/outtake.cpp
    engines/bladerunner/outtake.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/aud_decoder.cpp b/engines/bladerunner/aud_decoder.cpp
new file mode 100644
index 0000000..d11a90e
--- /dev/null
+++ b/engines/bladerunner/aud_decoder.cpp
@@ -0,0 +1,167 @@
+/* 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 "bladerunner/aud_decoder.h"
+
+#include "common/util.h"
+
+namespace BladeRunner {
+
+static const
+int16 imaIndexTable[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
+
+static const
+uint16 imaStepTable[712] =
+{
+ 0x0000,0x0001,0x0003,0x0004,0x0007,0x0008,0x000a,0x000b,
+ 0x0001,0x0003,0x0005,0x0007,0x0009,0x000b,0x000d,0x000f,
+ 0x0001,0x0003,0x0005,0x0007,0x000a,0x000c,0x000e,0x0010,
+ 0x0001,0x0003,0x0006,0x0008,0x000b,0x000d,0x0010,0x0012,
+ 0x0001,0x0003,0x0006,0x0008,0x000c,0x000e,0x0011,0x0013,
+ 0x0001,0x0004,0x0007,0x000a,0x000d,0x0010,0x0013,0x0016,
+ 0x0001,0x0004,0x0007,0x000a,0x000e,0x0011,0x0014,0x0017,
+ 0x0001,0x0004,0x0008,0x000b,0x000f,0x0012,0x0016,0x0019,
+ 0x0002,0x0006,0x000a,0x000e,0x0012,0x0016,0x001a,0x001e,
+ 0x0002,0x0006,0x000a,0x000e,0x0013,0x0017,0x001b,0x001f,
+ 0x0002,0x0006,0x000b,0x000f,0x0015,0x0019,0x001e,0x0022,
+ 0x0002,0x0007,0x000c,0x0011,0x0017,0x001c,0x0021,0x0026,
+ 0x0002,0x0007,0x000d,0x0012,0x0019,0x001e,0x0024,0x0029,
+ 0x0003,0x0009,0x000f,0x0015,0x001c,0x0022,0x0028,0x002e,
+ 0x0003,0x000a,0x0011,0x0018,0x001f,0x0026,0x002d,0x0034,
+ 0x0003,0x000a,0x0012,0x0019,0x0022,0x0029,0x0031,0x0038,
+ 0x0004,0x000c,0x0015,0x001d,0x0026,0x002e,0x0037,0x003f,
+ 0x0004,0x000d,0x0016,0x001f,0x0029,0x0032,0x003b,0x0044,
+ 0x0005,0x000f,0x0019,0x0023,0x002e,0x0038,0x0042,0x004c,
+ 0x0005,0x0010,0x001b,0x0026,0x0032,0x003d,0x0048,0x0053,
+ 0x0006,0x0012,0x001f,0x002b,0x0038,0x0044,0x0051,0x005d,
+ 0x0006,0x0013,0x0021,0x002e,0x003d,0x004a,0x0058,0x0065,
+ 0x0007,0x0016,0x0025,0x0034,0x0043,0x0052,0x0061,0x0070,
+ 0x0008,0x0018,0x0029,0x0039,0x004a,0x005a,0x006b,0x007b,
+ 0x0009,0x001b,0x002d,0x003f,0x0052,0x0064,0x0076,0x0088,
+ 0x000a,0x001e,0x0032,0x0046,0x005a,0x006e,0x0082,0x0096,
+ 0x000b,0x0021,0x0037,0x004d,0x0063,0x0079,0x008f,0x00a5,
+ 0x000c,0x0024,0x003c,0x0054,0x006d,0x0085,0x009d,0x00b5,
+ 0x000d,0x0027,0x0042,0x005c,0x0078,0x0092,0x00ad,0x00c7,
+ 0x000e,0x002b,0x0049,0x0066,0x0084,0x00a1,0x00bf,0x00dc,
+ 0x0010,0x0030,0x0051,0x0071,0x0092,0x00b2,0x00d3,0x00f3,
+ 0x0011,0x0034,0x0058,0x007b,0x00a0,0x00c3,0x00e7,0x010a,
+ 0x0013,0x003a,0x0061,0x0088,0x00b0,0x00d7,0x00fe,0x0125,
+ 0x0015,0x0040,0x006b,0x0096,0x00c2,0x00ed,0x0118,0x0143,
+ 0x0017,0x0046,0x0076,0x00a5,0x00d5,0x0104,0x0134,0x0163,
+ 0x001a,0x004e,0x0082,0x00b6,0x00eb,0x011f,0x0153,0x0187,
+ 0x001c,0x0055,0x008f,0x00c8,0x0102,0x013b,0x0175,0x01ae,
+ 0x001f,0x005e,0x009d,0x00dc,0x011c,0x015b,0x019a,0x01d9,
+ 0x0022,0x0067,0x00ad,0x00f2,0x0139,0x017e,0x01c4,0x0209,
+ 0x0026,0x0072,0x00bf,0x010b,0x0159,0x01a5,0x01f2,0x023e,
+ 0x002a,0x007e,0x00d2,0x0126,0x017b,0x01cf,0x0223,0x0277,
+ 0x002e,0x008a,0x00e7,0x0143,0x01a1,0x01fd,0x025a,0x02b6,
+ 0x0033,0x0099,0x00ff,0x0165,0x01cb,0x0231,0x0297,0x02fd,
+ 0x0038,0x00a8,0x0118,0x0188,0x01f9,0x0269,0x02d9,0x0349,
+ 0x003d,0x00b8,0x0134,0x01af,0x022b,0x02a6,0x0322,0x039d,
+ 0x0044,0x00cc,0x0154,0x01dc,0x0264,0x02ec,0x0374,0x03fc,
+ 0x004a,0x00df,0x0175,0x020a,0x02a0,0x0335,0x03cb,0x0460,
+ 0x0052,0x00f6,0x019b,0x023f,0x02e4,0x0388,0x042d,0x04d1,
+ 0x005a,0x010f,0x01c4,0x0279,0x032e,0x03e3,0x0498,0x054d,
+ 0x0063,0x012a,0x01f1,0x02b8,0x037f,0x0446,0x050d,0x05d4,
+ 0x006d,0x0148,0x0223,0x02fe,0x03d9,0x04b4,0x058f,0x066a,
+ 0x0078,0x0168,0x0259,0x0349,0x043b,0x052b,0x061c,0x070c,
+ 0x0084,0x018d,0x0296,0x039f,0x04a8,0x05b1,0x06ba,0x07c3,
+ 0x0091,0x01b4,0x02d8,0x03fb,0x051f,0x0642,0x0766,0x0889,
+ 0x00a0,0x01e0,0x0321,0x0461,0x05a2,0x06e2,0x0823,0x0963,
+ 0x00b0,0x0210,0x0371,0x04d1,0x0633,0x0793,0x08f4,0x0a54,
+ 0x00c2,0x0246,0x03ca,0x054e,0x06d2,0x0856,0x09da,0x0b5e,
+ 0x00d5,0x027f,0x042a,0x05d4,0x0780,0x092a,0x0ad5,0x0c7f,
+ 0x00ea,0x02bf,0x0495,0x066a,0x0840,0x0a15,0x0beb,0x0dc0,
+ 0x0102,0x0306,0x050b,0x070f,0x0914,0x0b18,0x0d1d,0x0f21,
+ 0x011c,0x0354,0x058c,0x07c4,0x09fc,0x0c34,0x0e6c,0x10a4,
+ 0x0138,0x03a8,0x0619,0x0889,0x0afb,0x0d6b,0x0fdc,0x124c,
+ 0x0157,0x0406,0x06b5,0x0964,0x0c14,0x0ec3,0x1172,0x1421,
+ 0x017a,0x046e,0x0762,0x0a56,0x0d4a,0x103e,0x1332,0x1626,
+ 0x019f,0x04de,0x081e,0x0b5d,0x0e9e,0x11dd,0x151d,0x185c,
+ 0x01c9,0x055c,0x08ef,0x0c82,0x1015,0x13a8,0x173b,0x1ace,
+ 0x01f7,0x05e5,0x09d4,0x0dc2,0x11b1,0x159f,0x198e,0x1d7c,
+ 0x0229,0x067c,0x0acf,0x0f22,0x1375,0x17c8,0x1c1b,0x206e,
+ 0x0260,0x0721,0x0be3,0x10a4,0x1567,0x1a28,0x1eea,0x23ab,
+ 0x029d,0x07d8,0x0d14,0x124f,0x178b,0x1cc6,0x2202,0x273d,
+ 0x02e0,0x08a1,0x0e63,0x1424,0x19e6,0x1fa7,0x2569,0x2b2a,
+ 0x032a,0x097f,0x0fd4,0x1629,0x1c7e,0x22d3,0x2928,0x2f7d,
+ 0x037b,0x0a72,0x1169,0x1860,0x1f57,0x264e,0x2d45,0x343c,
+ 0x03d4,0x0b7d,0x1326,0x1acf,0x2279,0x2a22,0x31cb,0x3974,
+ 0x0436,0x0ca3,0x1511,0x1d7e,0x25ec,0x2e59,0x36c7,0x3f34,
+ 0x04a2,0x0de7,0x172c,0x2071,0x29b7,0x32fc,0x3c41,0x4586,
+ 0x0519,0x0f4b,0x197e,0x23b0,0x2de3,0x3815,0x4248,0x4c7a,
+ 0x059b,0x10d2,0x1c0a,0x2741,0x327a,0x3db1,0x48e9,0x5420,
+ 0x062b,0x1281,0x1ed8,0x2b2e,0x3786,0x43dc,0x5033,0x5c89,
+ 0x06c9,0x145b,0x21ee,0x2f80,0x3d14,0x4aa6,0x5839,0x65cb,
+ 0x0777,0x1665,0x2553,0x3441,0x4330,0x521e,0x610c,0x6ffa,
+ 0x0836,0x18a2,0x290f,0x397b,0x49e8,0x5a54,0x6ac1,0x7b2d,
+ 0x0908,0x1b19,0x2d2a,0x3f3b,0x514c,0x635d,0x756e,0x877f,
+ 0x09ef,0x1dce,0x31ae,0x458d,0x596d,0x6d4c,0x812c,0x950b,
+ 0x0aee,0x20ca,0x36a6,0x4c82,0x625f,0x783b,0x8e17,0xa3f3,
+ 0x0c05,0x2410,0x3c1c,0x5427,0x6c34,0x843f,0x9c4b,0xb456,
+ 0x0d39,0x27ac,0x4220,0x5c93,0x7707,0x917a,0xabee,0xc661,
+ 0x0e8c,0x2ba4,0x48bd,0x65d5,0x82ee,0xa006,0xbd1f,0xda37,
+ 0x0fff,0x2ffe,0x4ffe,0x6ffd,0x8ffe,0xaffd,0xcffd,0xeffc
+};
+
+void ADPCMWestwoodDecoder::decode(uint8 *in, size_t size, int16 *out)
+{
+	uint8 *end = in + size;
+
+	int16 stepIndex = _stepIndex;
+	int32 predictor = _predictor;
+
+	while (in != end)
+	{
+		uint16 bl = *in++;
+
+		for (int n = 0; n != 2; ++n)
+		{
+			uint8 nibble = (bl >> (4 * n)) & 0x0f;
+			uint8 code = nibble & 0x07;
+			uint8 sign = nibble & 0x08;
+
+			int diff = imaStepTable[(stepIndex << 3) | code];
+
+			// Westwood's IMA ADPCM differs from the below standard implementation
+			// in the LSB in a couple of places.
+			//int diff = imaStepTable_std[stepIndex] * code / 4 + imaStepTable_std[stepIndex] / 8;
+
+			if (sign)
+				predictor -= diff;
+			else
+				predictor += diff;
+
+			predictor = CLIP<int32>(predictor, -32768, 32767);
+
+			*out++ = (int16)predictor;
+
+			stepIndex = imaIndexTable[code] + stepIndex;
+			stepIndex = CLIP<int16>(stepIndex, 0, 88);
+		}
+	}
+
+	_stepIndex = stepIndex;
+	_predictor = predictor;
+}
+
+};
diff --git a/engines/bladerunner/aud_decoder.h b/engines/bladerunner/aud_decoder.h
new file mode 100644
index 0000000..dbf7ca1
--- /dev/null
+++ b/engines/bladerunner/aud_decoder.h
@@ -0,0 +1,50 @@
+/* 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 BLADERUNNER_AUD_DECODER_H
+#define BLADERUNNER_AUD_DECODER_H
+
+#include "common/types.h"
+
+namespace BladeRunner {
+
+class ADPCMWestwoodDecoder {
+	int16 _stepIndex;
+	int32 _predictor;
+
+public:
+	ADPCMWestwoodDecoder()
+		: _stepIndex(0), _predictor(0)
+	{}
+
+	void setParameters(int16 stepIndex, int32 predictor)
+	{
+		_stepIndex = stepIndex;
+		_predictor = predictor;
+	}
+
+	void decode(uint8 *in, size_t size, int16 *out);
+};
+
+};
+
+#endif
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index bcf8c09..e914f1c 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -58,13 +58,12 @@ Common::Error BladeRunnerEngine::run() {
 
 	startup();
 
-	if (!warnUserAboutUnsupportedGame())
-		return Common::kNoError;
+	if (warnUserAboutUnsupportedGame()) {
+		init2();
 
-	init2();
-
-	/* TODO: Check for save games and enter KIA */
-	gameLoop();
+		/* TODO: Check for save games and enter KIA */
+		gameLoop();
+	}
 
 	shutdown();
 
@@ -169,6 +168,10 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: Only run if not in Kia, script, nor AI
 		_settings->openNewScene();
 
+		outtakePlay(28, true);
+		outtakePlay(41, true);
+		outtakePlay( 0, false);
+
 		// TODO: Autosave
 		// TODO: Kia
 		// TODO: Spinner
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 44e681a..23113a9 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/bladerunner
 
 MODULE_OBJS = \
 	archive.o \
+	aud_decoder.o \
 	bladerunner.o \
 	chapters.o \
 	decompress_lcw.o \
@@ -11,8 +12,7 @@ MODULE_OBJS = \
 	image.o \
 	outtake.o \
 	settings.o \
-	vqa_decoder.o \
-	vqa_player.o
+	vqa_decoder.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index 01ceefa..6ebede5 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -23,8 +23,10 @@
 #include "bladerunner/outtake.h"
 
 #include "bladerunner/bladerunner.h"
-#include "bladerunner/vqa_player.h"
+#include "bladerunner/vqa_decoder.h"
 
+#include "common/debug.h"
+#include "common/events.h"
 #include "common/system.h"
 
 namespace BladeRunner {
@@ -41,27 +43,33 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
 	else
 		resName = name + "_E.VQA";
 
-	_vqaPlayer = new VQAPlayer(_vm, &_vm->_surface1);
-	_vqaPlayer->open(resName);
+	Common::SeekableReadStream *s = _vm->getResourceStream(resName);
 
-	for (;;) {
-		_vm->handleEvents();
-		if (_vm->shouldQuit())
-			break;
+	_vqaDecoder = new VQADecoder();
+	_vqaDecoder->loadStream(s);
 
-		int r = _vqaPlayer->update();
-		if (r == -3)
-			break;
+	_vqaDecoder->start();
 
-		if (r >= 0) {
-			_vm->_system->copyRectToScreen(_vm->_surface1.getPixels(), _vm->_surface1.pitch, 0, 0, _vm->_surface1.w, _vm->_surface1.h);
+	uint32 last = _vm->_system->getMillis();
+
+	while (!_vqaDecoder->endOfVideo() && !_vm->shouldQuit()) {
+		if (_vqaDecoder->needsUpdate()) {
+			uint32 now = _vm->_system->getMillis();
+			debug("delta: %d", now - last);
+			last = now;
+
+			const Graphics::Surface *surface = _vqaDecoder->decodeNextFrame();
+			_vm->_system->copyRectToScreen((const byte *)surface->getBasePtr(0, 0), surface->pitch, 0, 0, 640, 480);
 			_vm->_system->updateScreen();
-			_vm->_system->delayMillis(10);
 		}
-	}
 
-	delete _vqaPlayer;
-	_vqaPlayer = nullptr;
+		Common::Event event;
+		while (_vm->_system->getEventManager()->pollEvent(event))
+			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+				return;
+
+		_vm->_system->delayMillis(10);
+	}
 }
 
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/outtake.h b/engines/bladerunner/outtake.h
index 4e97b1b..9182b87 100644
--- a/engines/bladerunner/outtake.h
+++ b/engines/bladerunner/outtake.h
@@ -30,20 +30,20 @@
 namespace BladeRunner {
 
 class BladeRunnerEngine;
-class VQAPlayer;
+class VQADecoder;
 
 class OuttakePlayer {
 	BladeRunnerEngine *_vm;
 
 	bool               _isVQAOpen;
-	VQAPlayer         *_vqaPlayer;
+	VQADecoder        *_vqaDecoder;
 	Graphics::Surface *_surface;
 
 public:
 	OuttakePlayer(BladeRunnerEngine *vm) :
 		_vm(vm),
 		_isVQAOpen(false),
-		_vqaPlayer(nullptr)
+		_vqaDecoder(nullptr)
 	{}
 
 	void play(const Common::String &name, bool noLocalization, int container);
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index f4676d3..bd898bc 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -22,9 +22,12 @@
 
 #include "bladerunner/vqa_decoder.h"
 
+#include "bladerunner/bladerunner.h"
 #include "bladerunner/decompress_lcw.h"
 #include "bladerunner/decompress_lzo.h"
 
+#include "audio/decoders/raw.h"
+
 #include "common/array.h"
 #include "common/util.h"
 
@@ -63,23 +66,14 @@ namespace BladeRunner {
 #define kWVQA 0x57565141
 #define kZBUF 0x5A425546
 
-VQADecoder::VQADecoder()
-	: _s(nullptr),
-	  _frame(0),
-	  _zbuf(0),
-	  _codebook(0),
-	  _cbfz(0),
-	  _vptr(0),
-	  _hasView(false),
-	  _audioFrame(0),
-	  _maxVIEWChunkSize(0),
-	  _maxZBUFChunkSize(0),
-	  _maxAESCChunkSize(0)
-{
-}
+int32 remain(Common::SeekableReadStream *s) {
+	int32 pos = s->pos();
+	if (pos == -1) return -1;
 
-VQADecoder::~VQADecoder()
-{
+	int32 size = s->size();
+	if (size == -1) return -1;
+
+	return size - pos;
 }
 
 struct IFFChunkHeader
@@ -92,23 +86,6 @@ struct IFFChunkHeader
 	uint32 size;
 };
 
-static inline uint32 roundup(uint32 v)
-{
-	return (v + 1) & ~1u;
-}
-
-const char *strTag(uint32 tag);
-
-int32 remain(Common::SeekableReadStream *s) {
-	int32 pos = s->pos();
-	if (pos == -1) return -1;
-
-	int32 size = s->size();
-	if (size == -1) return -1;
-
-	return size - pos;
-}
-
 static
 bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
 {
@@ -118,12 +95,14 @@ bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
 	ts->id   = s->readUint32BE();
 	ts->size = s->readUint32BE();
 
-	// if (ts->size != roundup(ts->size))
-	// 	debug("%s: %d", strTag(ts->id), ts->size);
-
 	return true;
 }
 
+static inline uint32 roundup(uint32 v)
+{
+	return (v + 1) & ~1u;
+}
+
 const char *strTag(uint32 tag)
 {
 	static char s[5];
@@ -137,8 +116,21 @@ const char *strTag(uint32 tag)
 	return s;
 }
 
-bool VQADecoder::open(Common::SeekableReadStream *s)
+VQADecoder::VQADecoder()
+	: _s(nullptr),
+	  _maxVIEWChunkSize(0),
+	  _maxZBUFChunkSize(0),
+	  _maxAESCChunkSize(0)
 {
+}
+
+VQADecoder::~VQADecoder() {
+}
+
+bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
+	close();
+	_s = s;
+
 	IFFChunkHeader chd;
 	uint32 type;
 	bool rc;
@@ -152,81 +144,124 @@ bool VQADecoder::open(Common::SeekableReadStream *s)
 	if (type != kWVQA)
 		return false;
 
-	_s = s;
 	do {
 		if (!readIFFChunkHeader(_s, &chd))
 			return false;
 
-		debug("\t%s : %x", strTag(chd.id), chd.size);
-
 		rc = false;
 		switch (chd.id)
 		{
-			case kCINF: rc = readCINF(chd.size); break;
-			case kCLIP: rc = readCLIP(chd.size); break;
-			case kFINF: rc = readFINF(chd.size); break;
-			case kLINF: rc = readLINF(chd.size); break;
-			case kLNIN: rc = readLNIN(chd.size); break;
-			case kMFCI: rc = readMFCI(chd.size); break;
-			case kMSCI: rc = readMSCI(chd.size); break;
-			case kVQHD: rc = readVQHD(chd.size); break;
+			case kCINF: rc = readCINF(s, chd.size); break;
+			case kCLIP: rc = readCLIP(s, chd.size); break;
+			case kFINF: rc = readFINF(s, chd.size); break;
+			case kLINF: rc = readLINF(s, chd.size); break;
+			case kLNIN: rc = readLNIN(s, chd.size); break;
+			case kMFCI: rc = readMFCI(s, chd.size); break;
+			case kMSCI: rc = readMSCI(s, chd.size); break;
+			case kVQHD: rc = readVQHD(s, chd.size); break;
 			default:
 				debug("Unhandled chunk '%s'", strTag(chd.id));
-				_s->skip(roundup(chd.size));
+				s->skip(roundup(chd.size));
 				rc = true;
 		}
 
-		if (!rc)
-		{
+		if (!rc) {
 			debug("failed to handle chunk %s", strTag(chd.id));
-			return -1;
+			return false;
 		}
-
 	} while (chd.id != kFINF);
 
+	_videoTrack = new VQAVideoTrack(this);
+	addTrack(_videoTrack);
+
+	_audioTrack = new VQAAudioTrack(this);
+	addTrack(_audioTrack);
+
+	/*
 	for (int i = 0; i != _loopInfo.loopCount; ++i) {
 		debug("LOOP %2d: %4d %4d %s", i,
 			_loopInfo.loops[i].begin,
 			_loopInfo.loops[i].end,
 			_loopInfo.loops[i].name.c_str());
 	}
+	*/
 
 	return true;
 }
 
-bool VQADecoder::readVQHD(uint32 size)
+void VQADecoder::readNextPacket() {
+	IFFChunkHeader chd;
+
+	if (remain(_s) < 8) {
+		warning("remain: %d", remain(_s));
+		assert(remain(_s) < 8);
+	}
+
+	do {
+		if (!readIFFChunkHeader(_s, &chd)) {
+			warning("Error reading chunk header");
+			return;
+		}
+
+		bool rc = false;
+		switch (chd.id) {
+			// Video track
+			case kAESC: rc = _videoTrack->readAESC(_s, chd.size); break;
+			case kLITE: rc = _videoTrack->readLITE(_s, chd.size); break;
+			case kVIEW: rc = _videoTrack->readVIEW(_s, chd.size); break;
+			case kVQFL: rc = _videoTrack->readVQFL(_s, chd.size); break;
+			case kVQFR: rc = _videoTrack->readVQFR(_s, chd.size); break;
+			case kZBUF: rc = _videoTrack->readZBUF(_s, chd.size); break;
+			// Sound track
+			case kSN2J: rc = _audioTrack->readSN2J(_s, chd.size); break;
+			case kSND2: rc = _audioTrack->readSND2(_s, chd.size); break;
+
+			default:
+				_s->skip(roundup(chd.size));
+				rc = false;
+		}
+
+		if (!rc) {
+			warning("Error handling chunk %s", strTag(chd.id));
+			return;
+		}
+	} while (chd.id != kVQFR);
+}
+
+bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 42)
 		return false;
 
-	_header.version     = _s->readUint16LE();
-	_header.flags       = _s->readUint16LE();
-	_header.numFrames   = _s->readUint16LE();
-	_header.width       = _s->readUint16LE();
-	_header.height      = _s->readUint16LE();
-	_header.blockW      = _s->readByte();
-	_header.blockH      = _s->readByte();
-	_header.frameRate   = _s->readByte();
-	_header.cbParts     = _s->readByte();
-	_header.colors      = _s->readUint16LE();
-	_header.maxBlocks   = _s->readUint16LE();
-	_header.offset_x    = _s->readUint16LE();
-	_header.offset_y    = _s->readUint16LE();
-	_header.maxVPTRSize = _s->readUint16LE();
-	_header.freq        = _s->readUint16LE();
-	_header.channels    = _s->readByte();
-	_header.bits        = _s->readByte();
-	_header.unk3        = _s->readUint32LE();
-	_header.unk4        = _s->readUint16LE();
-	_header.maxCBFZSize = _s->readUint32LE();
-	_header.unk5        = _s->readUint32LE();
-
-	if (_header.offset_x || _header.offset_y)
+	_header.version     = s->readUint16LE();
+	_header.flags       = s->readUint16LE();
+	_header.numFrames   = s->readUint16LE();
+	_header.width       = s->readUint16LE();
+	_header.height      = s->readUint16LE();
+	_header.blockW      = s->readByte();
+	_header.blockH      = s->readByte();
+	_header.frameRate   = s->readByte();
+	_header.cbParts     = s->readByte();
+	_header.colors      = s->readUint16LE();
+	_header.maxBlocks   = s->readUint16LE();
+	_header.offsetX     = s->readUint16LE();
+	_header.offsetY     = s->readUint16LE();
+	_header.maxVPTRSize = s->readUint16LE();
+	_header.freq        = s->readUint16LE();
+	_header.channels    = s->readByte();
+	_header.bits        = s->readByte();
+	_header.unk3        = s->readUint32LE();
+	_header.unk4        = s->readUint16LE();
+	_header.maxCBFZSize = s->readUint32LE();
+	_header.unk5        = s->readUint32LE();
+
+	if (_header.offsetX || _header.offsetY)
 	{
-		debug("_header.offset_x, _header.offset_y: %d %d", _header.offset_x, _header.offset_y);
+		debug("_header.offsetX, _header.offsetY: %d %d", _header.offsetX, _header.offsetY);
 	}
 
 	// if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014)
+	if (false)
 	{
 		debug("_header.version      %d", _header.version);
 		debug("_header.flags        %04x", _header.flags);
@@ -239,8 +274,8 @@ bool VQADecoder::readVQHD(uint32 size)
 		debug("_header.cbParts      %d", _header.cbParts);
 		debug("_header.colors       %d", _header.colors);
 		debug("_header.maxBlocks    %d", _header.maxBlocks);
-		debug("_header.offsetX      %d", _header.offset_x);
-		debug("_header.offsetY      %d", _header.offset_y);
+		debug("_header.offsetX      %d", _header.offsetX);
+		debug("_header.offsetY      %d", _header.offsetY);
 		debug("_header.maxVPTRSize  %d", _header.maxVPTRSize);
 		debug("_header.freq         %d", _header.freq);
 		debug("_header.channels     %d", _header.channels);
@@ -251,12 +286,39 @@ bool VQADecoder::readVQHD(uint32 size)
 		debug("_header.unk5         %d", _header.unk5);
 	}
 
-	// exit(-1);
+	return true;
+}
+
+bool VQADecoder::VQAVideoTrack::readVQFR(Common::SeekableReadStream *s, uint32 size)
+{
+	IFFChunkHeader chd;
+
+	while (size >= 8)
+	{
+		if (!readIFFChunkHeader(s, &chd))
+			return false;
+		size -= roundup(chd.size) + 8;
+
+		bool rc = false;
+		switch (chd.id)
+		{
+		case kCBFZ: rc = readCBFZ(s, chd.size); break;
+		case kVPTR: rc = readVPTR(s, chd.size); break;
+		default:
+			s->skip(roundup(chd.size));
+		}
+
+		if (!rc)
+		{
+			debug("VQFR: error handling chunk %s", strTag(chd.id));
+			return false;
+		}
+	}
 
 	return true;
 }
 
-bool VQADecoder::readMSCI(uint32 size)
+bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
 {
 	IFFChunkHeader chd;
 	readIFFChunkHeader(_s, &chd);
@@ -265,8 +327,8 @@ bool VQADecoder::readMSCI(uint32 size)
 		return false;
 
 	uint32 count, unk0;
-	count = _s->readUint32LE();
-	unk0  = _s->readUint32LE();
+	count = s->readUint32LE();
+	unk0  = s->readUint32LE();
 	assert(unk0 == 0);
 
 	readIFFChunkHeader(_s, &chd);
@@ -276,8 +338,8 @@ bool VQADecoder::readMSCI(uint32 size)
 	for (uint32 i = 0; i < count; ++i)
 	{
 		uint32 tag, size;
-		tag  = _s->readUint32BE();
-		size = _s->readUint32LE();
+		tag  = s->readUint32BE();
+		size = s->readUint32LE();
 
 		switch (tag)
 		{
@@ -287,7 +349,6 @@ bool VQADecoder::readMSCI(uint32 size)
 			break;
 		case kZBUF:
 			_maxZBUFChunkSize = size;
-			_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
 			debug("max ZBUF size: %08x", _maxZBUFChunkSize);
 			break;
 		case kAESC:
@@ -299,14 +360,14 @@ bool VQADecoder::readMSCI(uint32 size)
 		}
 
 		uint32 zero;
-		zero = _s->readUint32LE(); assert(zero == 0);
-		zero = _s->readUint32LE(); assert(zero == 0);
+		zero = s->readUint32LE(); assert(zero == 0);
+		zero = s->readUint32LE(); assert(zero == 0);
 	}
 
 	return true;
 }
 
-bool VQADecoder::readLINF(uint32 size)
+bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size)
 {
 	IFFChunkHeader chd;
 	readIFFChunkHeader(_s, &chd);
@@ -314,8 +375,8 @@ bool VQADecoder::readLINF(uint32 size)
 	if (chd.id != kLINH || chd.size != 6)
 		return false;
 
-	_loopInfo.loopCount = _s->readUint16LE();
-	_loopInfo.flags = _s->readUint32LE();
+	_loopInfo.loopCount = s->readUint16LE();
+	_loopInfo.flags = s->readUint32LE();
 
 	if ((_loopInfo.flags & 3) == 0)
 		return false;
@@ -327,8 +388,8 @@ bool VQADecoder::readLINF(uint32 size)
 	_loopInfo.loops = new Loop[_loopInfo.loopCount];
 	for (int i = 0; i != _loopInfo.loopCount; ++i)
 	{
-		_loopInfo.loops[i].begin = _s->readUint16LE();
-		_loopInfo.loops[i].end   = _s->readUint16LE();
+		_loopInfo.loops[i].begin = s->readUint16LE();
+		_loopInfo.loops[i].end   = s->readUint16LE();
 
 		// debug("Loop %d: %04x %04x", i, _loopInfo.loops[i].begin, _loopInfo.loops[i].end);
 	}
@@ -336,7 +397,7 @@ bool VQADecoder::readLINF(uint32 size)
 	return true;
 }
 
-bool VQADecoder::readCINF(uint32 size)
+bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size)
 {
 	IFFChunkHeader chd;
 
@@ -344,8 +405,8 @@ bool VQADecoder::readCINF(uint32 size)
 	if (chd.id != kCINH || chd.size != 8u)
 		return false;
 
-	_clipInfo.clipCount = _s->readUint16LE();
-	_s->skip(6);
+	_clipInfo.clipCount = s->readUint16LE();
+	s->skip(6);
 
 	readIFFChunkHeader(_s, &chd);
 	if (chd.id != kCIND || chd.size != 6u * _clipInfo.clipCount)
@@ -355,15 +416,14 @@ bool VQADecoder::readCINF(uint32 size)
 	{
 		uint16 a;
 		uint32 b;
-		a = _s->readUint16LE();
-		b = _s->readUint32LE();
-		debug("%4d %08x", a, b);
+		a = s->readUint16LE();
+		b = s->readUint32LE();
 	}
 
 	return true;
 }
 
-bool VQADecoder::readFINF(uint32 size)
+bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 4u * _header.numFrames)
 		return false;
@@ -371,7 +431,7 @@ bool VQADecoder::readFINF(uint32 size)
 	_frameInfo = new uint32[_header.numFrames];
 
 	for (uint32 i = 0; i != _header.numFrames; ++i)
-		_frameInfo[i] = _s->readUint32LE();
+		_frameInfo[i] = s->readUint32LE();
 
 	if (false) {
 		uint32 last = 0;
@@ -386,7 +446,7 @@ bool VQADecoder::readFINF(uint32 size)
 	return true;
 }
 
-bool VQADecoder::readLNIN(uint32 size)
+bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size)
 {
 	IFFChunkHeader chd;
 
@@ -396,11 +456,11 @@ bool VQADecoder::readLNIN(uint32 size)
 
 	uint16 loopNamesCount, loopUnk1, loopUnk2, loopUnk3, loopUnk4;
 
-	loopNamesCount = _s->readUint16LE();
-	loopUnk1       = _s->readUint16LE();
-	loopUnk2       = _s->readUint16LE();
-	loopUnk3       = _s->readUint16LE();
-	loopUnk4       = _s->readUint16LE();
+	loopNamesCount = s->readUint16LE();
+	loopUnk1       = s->readUint16LE();
+	loopUnk2       = s->readUint16LE();
+	loopUnk3       = s->readUint16LE();
+	loopUnk4       = s->readUint16LE();
 
 	if (loopNamesCount != _loopInfo.loopCount)
 		return false;
@@ -411,7 +471,7 @@ bool VQADecoder::readLNIN(uint32 size)
 
 	uint32 *loopNameOffsets = (uint32*)alloca(loopNamesCount * sizeof(uint32));
 	for (int i = 0; i != loopNamesCount; ++i) {
-		loopNameOffsets[i] = _s->readUint32LE();
+		loopNameOffsets[i] = s->readUint32LE();
 	}
 
 	readIFFChunkHeader(_s, &chd);
@@ -419,7 +479,7 @@ bool VQADecoder::readLNIN(uint32 size)
 		return false;
 
 	char *names = (char*)alloca(roundup(chd.size));
-	_s->read(names, roundup(chd.size));
+	s->read(names, roundup(chd.size));
 
 	for (int i = 0; i != loopNamesCount; ++i) {
 		char   *begin = names + loopNameOffsets[i];
@@ -431,157 +491,113 @@ bool VQADecoder::readLNIN(uint32 size)
 	return true;
 }
 
-bool VQADecoder::readCLIP(uint32 size)
-{
-	_s->skip(roundup(size));
+bool VQADecoder::readCLIP(Common::SeekableReadStream *s, uint32 size) {
+	s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::readMFCI(uint32 size)
-{
-	_s->skip(roundup(size));
+bool VQADecoder::readMFCI(Common::SeekableReadStream *s, uint32 size) {
+	s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::readFrame()
-{
-	IFFChunkHeader chd;
-
-	if (!_s)
-		return false;
-
-	_hasView = false;
+VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
+	VQADecoder::Header *header = &vqaDecoder->_header;
 
-	if (remain(_s) < 8) {
-		debug("remain: %d", remain(_s));
-		return false;
-	}
+	_surface = nullptr;
+	_hasNewFrame = false;
 
-	do {
-		if (!readIFFChunkHeader(_s, &chd)) {
-			debug("Error reading chunk header");
-			return false;
-		}
+	_numFrames = header->numFrames;
+	_width     = header->width;
+	_height    = header->height;
+	_blockW    = header->blockW;
+	_blockH    = header->blockH;
+	_frameRate = header->frameRate;
+	_maxBlocks = header->maxBlocks;
+	_offsetX   = header->offsetX;
+	_offsetY   = header->offsetY;
 
-		// debug("%s ", strTag(chd.id));
+	_maxVPTRSize = header->maxVPTRSize;
+	_maxCBFZSize = header->maxCBFZSize;
+	_maxZBUFChunkSize = vqaDecoder->_maxZBUFChunkSize;
 
-		bool rc = false;
-		switch (chd.id)
-		{
-			case kAESC: rc = readAESC(chd.size); break;
-			case kLITE: rc = readLITE(chd.size); break;
-			case kSN2J: rc = readSN2J(chd.size); break;
-			case kSND2: rc = readSND2(chd.size); break;
-			case kVIEW: rc = readVIEW(chd.size); break;
-			case kVQFL: rc = readVQFL(chd.size); break;
-			case kVQFR: rc = readVQFR(chd.size); break;
-			case kZBUF: rc = readZBUF(chd.size); break;
-			default:
-				_s->skip(roundup(chd.size));
-				rc = true;
-		}
+	_codebookSize = 0;
+	_codebook  = nullptr;
+	_cbfz      = nullptr;
+	_zbufChunk = nullptr;
 
-		if (!rc)
-		{
-			debug("Error handling chunk %s", strTag(chd.id));
-			return false;
-		}
-	} while (chd.id != kVQFR);
-
-	return true;
-}
-
-
-bool VQADecoder::readSN2J(uint32 size)
-{
-	if (size != 6)
-		return false;
+	_vptrSize = 0;
+	_vptr = nullptr;
 
-	uint16 step_index;
-	uint32 predictor;
+	_curFrame = -1;
 
-	step_index = _s->readUint16LE();
-	predictor  = _s->readUint32LE();
 
-	// ima_adpcm_ws_decoder.set_parameters(step_index >> 5, predictor);
+	_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
 
-	return true;
+	_surface = new Graphics::Surface();
+	_surface->create(_width, _height, RGB555);
 }
 
-bool VQADecoder::readSND2(uint32 size)
-{
-	if (size != 735)
-	{
-		debug("audio frame size: %d", size);
-		return false;
-	}
-
-	if (!_audioFrame)
-		_audioFrame = new int16[2 * size];
-	memset(_audioFrame, 0, 4 * size);
-
-	uint8 *inFrame = new uint8[roundup(size)];
-	_s->read(inFrame, roundup(size));
+VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
+	delete[] _codebook;
+	delete[] _cbfz;
+	delete[] _zbufChunk;
+	delete[] _vptr;
 
-	// ima_adpcm_ws_decoder.decode(inFrame, size, _audioFrame);
+	delete _surface;
+}
 
-	delete[] inFrame;
+uint16 VQADecoder::VQAVideoTrack::getWidth() const {
+	return _width;
+}
 
-	return true;
+uint16 VQADecoder::VQAVideoTrack::getHeight() const {
+	return _height;
 }
 
-bool VQADecoder::readVQFR(uint32 size)
-{
-	IFFChunkHeader chd;
+Graphics::PixelFormat VQADecoder::VQAVideoTrack::getPixelFormat() const {
+	return _surface->format;
+}
 
-	while (size >= 8)
-	{
-		if (!readIFFChunkHeader(_s, &chd))
-			return false;
-		size -= roundup(chd.size) + 8;
+int VQADecoder::VQAVideoTrack::getCurFrame() const {
+	return _curFrame;
+}
 
-		// debug("(%s) ", strTag(chd.id)); fflush(0);
+int VQADecoder::VQAVideoTrack::getFrameCount() const {
+	return _numFrames;
+}
 
-		bool rc = false;
-		switch (chd.id)
-		{
-			case kCBFZ: rc = readCBFZ(chd.size); break;
-			case kVPTR: rc = readVPTR(chd.size); break;
-			default:
-				_s->skip(roundup(chd.size));
-		}
+Common::Rational VQADecoder::VQAVideoTrack::getFrameRate() const {
+	return _frameRate;
+}
 
-		if (!rc)
-		{
-			debug("VQFR: error handling chunk %s", strTag(chd.id));
-			return false;
-		}
+const Graphics::Surface *VQADecoder::VQAVideoTrack::decodeNextFrame() {
+	debug("_curFrame: %d", _curFrame);
+	if (_hasNewFrame) {
+		decodeFrame((uint16*)_surface->getPixels());
+		_curFrame++;
+		_hasNewFrame = false;
 	}
-
-	return true;
+	return _surface;
 }
 
-bool VQADecoder::readVQFL(uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readVQFL(Common::SeekableReadStream *s, uint32 size) {
 	IFFChunkHeader chd;
 
-	while (size >= 8)
-	{
-		if (!readIFFChunkHeader(_s, &chd))
+	while (size >= 8) {
+		if (!readIFFChunkHeader(s, &chd))
 			return false;
 		size -= roundup(chd.size) + 8;
 
 		bool rc = false;
-		switch (chd.id)
-		{
-			case kCBFZ: rc = readCBFZ(chd.size); break;
+		switch (chd.id) {
+			case kCBFZ: rc = readCBFZ(s, chd.size); break;
 			default:
-				_s->skip(roundup(chd.size));
+				s->skip(roundup(chd.size));
 		}
 
-		if (!rc)
-		{
-			debug("VQFL: error handling chunk %s", strTag(chd.id));
+		if (!rc) {
+			warning("VQFL: error handling chunk %s", strTag(chd.id));
 			return false;
 		}
 	}
@@ -589,29 +605,27 @@ bool VQADecoder::readVQFL(uint32 size)
 	return true;
 }
 
-bool VQADecoder::readCBFZ(uint32 size)
-{
-	if (size > _header.maxCBFZSize)
-	{
-		debug("%d > %d", size, _header.maxCBFZSize);
+bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 size) {
+	if (size > _maxCBFZSize) {
+		debug("%d > %d", size, _maxCBFZSize);
 		return false;
 	}
 
-	if (!_codebook)
-	{
-		_codebookSize = 2 * _header.maxBlocks * _header.blockW * _header.blockH;
+	if (!_codebook) {
+		_codebookSize = 2 * _maxBlocks * _blockW * _blockH;
 		_codebook = new uint8[_codebookSize];
 	}
 	if (!_cbfz)
-		_cbfz = new uint8[roundup(_header.maxCBFZSize)];
+		_cbfz = new uint8[roundup(_maxCBFZSize)];
 
-	_s->read(_cbfz, roundup(size));
+	s->read(_cbfz, roundup(size));
 
 	decompress_lcw(_cbfz, size, _codebook, _codebookSize);
 
 	return true;
 }
 
+#if 0
 static
 int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 {
@@ -655,52 +669,58 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 	}
 	return dstSize - dstRemain;
 }
+#endif
 
-bool VQADecoder::readZBUF(uint32 size)
+bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size)
 {
+	s->skip(roundup(size));
+	return true;
+#if 0
 	if (size > _maxZBUFChunkSize) {
 		debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
-		_s->skip(roundup(size));
+		s->skip(roundup(size));
 		return false;
 	}
 
 	uint32 width, height, complete, unk0;
-	width    = _s->readUint32LE();
-	height   = _s->readUint32LE();
-	complete = _s->readUint32LE();
-	unk0     = _s->readUint32LE();
+	width    = s->readUint32LE();
+	height   = s->readUint32LE();
+	complete = s->readUint32LE();
+	unk0     = s->readUint32LE();
 
 	uint32 remain = size - 16;
 
-	if (width != _header.width || height != _header.height)
+	if (width != width || height != height)
 	{
 		debug("%d, %d, %d, %d", width, height, complete, unk0);
-		_s->skip(roundup(remain));
+		s->skip(roundup(remain));
 		return false;
 	}
 
+	s->read(_zbufChunk, roundup(remain));
+
 	if (!_zbuf)
 	{
 		if (!complete) {
-			_s->skip(roundup(remain));
+			s->skip(roundup(remain));
 			return false;
 		}
 		_zbuf = new uint16[width * height];
 	}
 
-	_s->read(_zbufChunk, roundup(remain));
-
 	if (complete) {
 		size_t zbufOutSize;
 		decompress_lzo1x(_zbufChunk, remain, (uint8*)_zbuf, &zbufOutSize);
 	} else {
 		decodeZBUF_partial(_zbufChunk, _zbuf, remain);
 	}
+#endif
 
 	return true;
 }
 
-bool VQADecoder::getZBUF(uint16 *zbuf)
+#if 0
+bool VQADecoder::VQAVideoTrack::getZBUF(uint16 *zbuf)
 {
 	if (!_zbuf)
 		return false;
@@ -708,50 +728,51 @@ bool VQADecoder::getZBUF(uint16 *zbuf)
 	memcpy(zbuf, _zbuf, 2 * _header.width * _header.height);
 	return true;
 }
+#endif
 
-bool VQADecoder::readVIEW(uint32 size)
+bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 56)
 		return false;
 
-	_s->skip(size);
-	// _hasView = true;
-
+	s->skip(size);
 	return true;
 }
 
-bool VQADecoder::readAESC(uint32 size)
+bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size)
 {
-	_s->skip(roundup(size));
+	s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::readLITE(uint32 size)
+bool VQADecoder::VQAVideoTrack::readLITE(Common::SeekableReadStream *s, uint32 size)
 {
-	_s->skip(roundup(size));
+	s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::readVPTR(uint32 size)
+bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 size)
 {
-	if (size > _header.maxVPTRSize)
+	if (size > _maxVPTRSize)
 		return false;
 
 	if (!_vptr)
-		_vptr = new uint8[roundup(_header.maxVPTRSize)];
+		_vptr = new uint8[roundup(_maxVPTRSize)];
 
 	_vptrSize = size;
-	_s->read(_vptr, roundup(size));
+	s->read(_vptr, roundup(size));
+
+	_hasNewFrame = true;
 
 	return true;
 }
 
-void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha) const
+void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha)
 {
-	uint16 frame_width  = _header.width;
+	uint16 frame_width  = _width;
 	uint32 frame_stride = 640;
-	uint16 block_width  = _header.blockW;
-	uint16 block_height = _header.blockH;
+	uint16 block_width  = _blockW;
+	uint16 block_height = _blockH;
 
 	const uint8 *const block_src =
 		&_codebook[2 * srcBlock * block_width * block_height];
@@ -760,8 +781,8 @@ void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned i
 
 	do
 	{
-		uint32 frame_x = dstBlock % blocks_per_line * block_width  + _header.offset_x / 2;
-		uint32 frame_y = dstBlock / blocks_per_line * block_height + _header.offset_y;
+		uint32 frame_x = dstBlock % blocks_per_line * block_width  + _offsetX / 2;
+		uint32 frame_y = dstBlock / blocks_per_line * block_height + _offsetY;
 
 		uint32 dst_offset = frame_x + frame_y * frame_stride;
 
@@ -789,23 +810,11 @@ void VQADecoder::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned i
 	while (--count);
 }
 
-bool VQADecoder::seekToFrame(int frame)
-{
-	if (frame < 0 || frame >= _header.numFrames)
-		return false;
-
-	_s->seek(2 * (_frameInfo[frame] & 0x0fffffff), SEEK_SET);
-	return true;
-}
-
-bool VQADecoder::decodeFrame(uint16 *frame)
+bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
 {
 	if (!_codebook || !_vptr)
 		return false;
 
-	if (!_frame)
-		_frame = new uint16[_header.width * _header.height];
-
 	uint8 *src = _vptr;
 	uint8 *end = _vptr + _vptrSize;
 
@@ -828,20 +837,20 @@ bool VQADecoder::decodeFrame(uint16 *frame)
 			count = 2 * (((command >> 8) & 0x1f) + 1);
 			srcBlock = command & 0x00ff;
 
-			VPTRWriteBlock(_frame, dstBlock, srcBlock, count);
+			VPTRWriteBlock(frame, dstBlock, srcBlock, count);
 			dstBlock += count;
 			break;
 		case 2:
 			count = 2 * (((command >> 8) & 0x1f) + 1);
 			srcBlock = command & 0x00ff;
 
-			VPTRWriteBlock(_frame, dstBlock, srcBlock, 1);
+			VPTRWriteBlock(frame, dstBlock, srcBlock, 1);
 			++dstBlock;
 
 			for (int i = 0; i < count; ++i)
 			{
 				srcBlock = *src++;
-				VPTRWriteBlock(_frame, dstBlock, srcBlock, 1);
+				VPTRWriteBlock(frame, dstBlock, srcBlock, 1);
 				++dstBlock;
 			}
 			break;
@@ -850,7 +859,7 @@ bool VQADecoder::decodeFrame(uint16 *frame)
 			count = 1;
 			srcBlock = command & 0x1fff;
 
-			VPTRWriteBlock(_frame, dstBlock, srcBlock, count, prefix == 4);
+			VPTRWriteBlock(frame, dstBlock, srcBlock, count, prefix == 4);
 			++dstBlock;
 			break;
 		case 5:
@@ -858,7 +867,7 @@ bool VQADecoder::decodeFrame(uint16 *frame)
 			count = *src++;
 			srcBlock = command & 0x1fff;
 
-			VPTRWriteBlock(_frame, dstBlock, srcBlock, count, prefix == 6);
+			VPTRWriteBlock(frame, dstBlock, srcBlock, count, prefix == 6);
 			dstBlock += count;
 			break;
 		default:
@@ -866,14 +875,51 @@ bool VQADecoder::decodeFrame(uint16 *frame)
 		}
 	}
 
-	memcpy(frame, _frame, 2 * 640 * 480);
+	return true;
+}
+
+VQADecoder::VQAAudioTrack::VQAAudioTrack(VQADecoder *vqaDecoder) {
+	_audioStream = Audio::makeQueuingAudioStream(vqaDecoder->_header.freq, false);
+}
+
+VQADecoder::VQAAudioTrack::~VQAAudioTrack() {
+	delete _audioStream;
+}
+
+Audio::AudioStream *VQADecoder::VQAAudioTrack::getAudioStream() const {
+	return _audioStream;
+}
+
+bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 size)
+{
+	if (size != 735) {
+		error("audio frame size: %d", size);
+		return false;
+	}
+
+	s->read(_compressedAudioFrame, roundup(size));
+
+	int16 *audioFrame = (int16*)malloc(4 * size);
+	memset(audioFrame, 0, 4 * size);
+
+	_adpcmDecoder.decode(_compressedAudioFrame, size, audioFrame);
+
+	_audioStream->queueBuffer((byte*)audioFrame, 4 * size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
 
 	return true;
 }
 
-int16 *VQADecoder::getAudioFrame()
+bool VQADecoder::VQAAudioTrack::readSN2J(Common::SeekableReadStream *s, uint32 size)
 {
-	return _audioFrame;
+	if (size != 6)
+		return false;
+
+	uint16 stepIndex = s->readUint16LE();
+	uint32 predictor = s->readUint32LE();
+
+	_adpcmDecoder.setParameters(stepIndex >> 5, predictor);
+
+	return true;
 }
 
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index ab1f9ef..a2237cc 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -23,15 +23,33 @@
 #ifndef BLADERUNNER_VQA_DECODER_H
 #define BLADERUNNER_VQA_DECODER_H
 
+#include "bladerunner/aud_decoder.h"
+
+#include "audio/audiostream.h"
+
 #include "common/debug.h"
 #include "common/str.h"
 #include "common/stream.h"
 #include "common/types.h"
 
+#include "graphics/surface.h"
+
+#include "video/video_decoder.h"
+
 namespace BladeRunner {
 
-class VQADecoder
+class VQADecoder : public Video::VideoDecoder
 {
+public:
+	VQADecoder();
+	~VQADecoder();
+
+	bool loadStream(Common::SeekableReadStream *s);
+
+protected:
+	void readNextPacket();
+
+private:
 	struct Header
 	{
 		uint16 version;     // 0x00
@@ -45,8 +63,8 @@ class VQADecoder
 		uint8  cbParts;     // 0x0D
 		uint16 colors;      // 0x0E
 		uint16 maxBlocks;   // 0x10
-		uint16 offset_x;    // 0x12
-		uint16 offset_y;    // 0x14
+		uint16 offsetX;     // 0x12
+		uint16 offsetY;     // 0x14
 		uint16 maxVPTRSize; // 0x16
 		uint16 freq;        // 0x18
 		uint8  channels;    // 0x1A
@@ -85,60 +103,109 @@ class VQADecoder
 		uint16 clipCount;
 	};
 
+	class VQAVideoTrack;
+	class VQAAudioTrack;
+
 	Common::SeekableReadStream *_s;
 
 	Header   _header;
 	LoopInfo _loopInfo;
 	ClipInfo _clipInfo;
 
-	uint16  *_frame;
-	uint16  *_zbuf;
-
-	size_t   _codebookSize;
-	uint8   *_codebook;
-	uint8   *_cbfz;
-
-	size_t   _vptrSize;
-	uint8   *_vptr;
-
 	uint32  *_frameInfo;
 
 	uint32   _maxVIEWChunkSize;
 	uint32   _maxZBUFChunkSize;
 	uint32   _maxAESCChunkSize;
-	uint8   *_zbufChunk;
 
-	bool   _hasView;
+	VQAVideoTrack *_videoTrack;
+	VQAAudioTrack *_audioTrack;
+
+	// bool   _hasView;
 	// view_t view;
 
-	// ima_adpcm_ws_decoder_t ima_adpcm_ws_decoder;
-	int16 *_audioFrame;
-
-	bool readVQHD(uint32 size);
-	bool readMSCI(uint32 size);
-	bool readMFCI(uint32 size);
-	bool readLINF(uint32 size);
-	bool readCINF(uint32 size);
-	bool readFINF(uint32 size);
-	bool readLNIN(uint32 size);
-	bool readCLIP(uint32 size);
-
-	bool readSN2J(uint32 size);
-	bool readSND2(uint32 size);
-	bool readVQFR(uint32 size);
-	bool readVPTR(uint32 size);
-	bool readVQFL(uint32 size);
-	bool readCBFZ(uint32 size);
-	bool readZBUF(uint32 size);
-	bool readVIEW(uint32 size);
-	bool readAESC(uint32 size);
-	bool readLITE(uint32 size);
+	bool readVQHD(Common::SeekableReadStream *s, uint32 size);
+	bool readMSCI(Common::SeekableReadStream *s, uint32 size);
+	bool readMFCI(Common::SeekableReadStream *s, uint32 size);
+	bool readLINF(Common::SeekableReadStream *s, uint32 size);
+	bool readCINF(Common::SeekableReadStream *s, uint32 size);
+	bool readFINF(Common::SeekableReadStream *s, uint32 size);
+	bool readLNIN(Common::SeekableReadStream *s, uint32 size);
+	bool readCLIP(Common::SeekableReadStream *s, uint32 size);
+
+	class VQAVideoTrack : public FixedRateVideoTrack {
+	public:
+		VQAVideoTrack(VQADecoder *vqaDecoder);
+		~VQAVideoTrack();
+
+		uint16 getWidth() const;
+		uint16 getHeight() const;
+		Graphics::PixelFormat getPixelFormat() const;
+		int getCurFrame() const;
+		int getFrameCount() const;
+		const Graphics::Surface *decodeNextFrame();
+
+		bool readVQFR(Common::SeekableReadStream *s, uint32 size);
+		bool readVPTR(Common::SeekableReadStream *s, uint32 size);
+		bool readVQFL(Common::SeekableReadStream *s, uint32 size);
+		bool readCBFZ(Common::SeekableReadStream *s, uint32 size);
+		bool readZBUF(Common::SeekableReadStream *s, uint32 size);
+		bool readVIEW(Common::SeekableReadStream *s, uint32 size);
+		bool readAESC(Common::SeekableReadStream *s, uint32 size);
+		bool readLITE(Common::SeekableReadStream *s, uint32 size);
+
+	protected:
+		Common::Rational getFrameRate() const;
+
+	private:
+		Graphics::Surface *_surface;
+		bool     _hasNewFrame;
+
+		uint16 _numFrames;
+		uint16 _width, _height;
+		uint8  _blockW, _blockH;
+		uint8  _frameRate;
+		uint16 _maxBlocks;
+		uint16 _offsetX, _offsetY;
+
+		uint16  _maxVPTRSize;
+		uint32  _maxCBFZSize;
+		uint32  _maxZBUFChunkSize;
+
+		size_t   _codebookSize;
+		uint8   *_codebook;
+		uint8   *_cbfz;
+		uint8   *_zbufChunk;
+
+		size_t   _vptrSize;
+		uint8   *_vptr;
+
+		int      _curFrame;
+
+
+		void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false);
+		bool decodeFrame(uint16 *frame);
+	};
 
-public:
-	VQADecoder();
-	~VQADecoder();
+	class VQAAudioTrack : public AudioTrack {
+	public:
+		VQAAudioTrack(VQADecoder *vqaDecoder);
+		~VQAAudioTrack();
+
+		bool readSND2(Common::SeekableReadStream *s, uint32 size);
+		bool readSN2J(Common::SeekableReadStream *s, uint32 size);
+
+	protected:
+		Audio::AudioStream *getAudioStream() const;
+
+	private:
+		Audio::QueuingAudioStream *_audioStream;
+
+		ADPCMWestwoodDecoder _adpcmDecoder;
+		uint8                _compressedAudioFrame[735];
+	};
 
-	bool open(Common::SeekableReadStream *s);
+/*
 	bool readFrame();
 
 	int getFrameTime() { return 1000 / _header.frameRate; }
@@ -154,6 +221,7 @@ public:
 	bool getZBUF(uint16 *zbuf);
 
 	friend class VQAPlayer;
+*/
 };
 
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 8b61481..f05e14b 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -24,6 +24,8 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "audio/decoders/raw.h"
+
 #include "common/system.h"
 
 namespace BladeRunner {
@@ -39,6 +41,8 @@ bool VQAPlayer::open(const Common::String &name) {
 		return false;
 	}
 
+	_audioStream = Audio::makeQueuingAudioStream(_decoder._header.freq, _decoder._header.channels == 2);
+
 	return true;
 }
 
@@ -78,12 +82,31 @@ int VQAPlayer::update() {
 	else
 		++_curFrame;
 
-	if (_curFrame >= _decoder._header.numFrames)
+	if (_curFrame >= _decoder._header.numFrames) {
+		if (_audioStream)
+			_audioStream->finish();
 		return -3;
+	}
 
 	_decoder.readFrame();
 	_decoder.decodeFrame((uint16*)_surface->getPixels());
 
+	if (_audioStream) {
+		int16 *audioFrame = (int16*)malloc(2940);
+		memcpy(audioFrame, _decoder.getAudioFrame(), 2940);
+		_audioStream->queueBuffer((byte*)audioFrame, 2940, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
+
+		if (!_audioStarted)
+			_vm->_mixer->playStream(
+				Audio::Mixer::kPlainSoundType,
+				&_soundHandle,
+				_audioStream,
+				-1
+			);
+
+		_audioStarted = true;
+	}
+
 	return _curFrame;
 }
 
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 2d7d682..7e7fab5 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -26,6 +26,7 @@
 #include "bladerunner/vqa_decoder.h"
 
 #include "audio/audiostream.h"
+#include "audio/mixer.h"
 
 #include "graphics/surface.h"
 
@@ -46,6 +47,8 @@ class VQAPlayer {
 	int _loopDefault;
 
 	uint32 _nextFrameTime;
+	bool   _audioStarted;
+	Audio::SoundHandle _soundHandle;
 
 public:
 
@@ -58,7 +61,8 @@ public:
 		  _curLoop(-1),
 		  _loopSpecial(-1),
 		  _loopDefault(-1),
-		  _nextFrameTime(0)
+		  _nextFrameTime(0),
+		  _audioStarted(false)
 	{}
 
 	bool open(const Common::String &name);


Commit: 8217ed6065ac0c45edaeb672908da7e91a068c4f
    https://github.com/scummvm/scummvm/commit/8217ed6065ac0c45edaeb672908da7e91a068c4f
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:17+02:00

Commit Message:
BLADERUNNER: Don't base VQADecoder on Video::VideoDecoder anyway

VideoDecoder doesn't handle audio underflow very well,
and Blade Runner's VQA files don't have any audio prebuffer.

VQAPlayer doesn't handle it perfectly either, but underflow
happens a lot less. To be improved.

Changed paths:
    engines/bladerunner/module.mk
    engines/bladerunner/outtake.cpp
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 23113a9..b1de94d 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -12,7 +12,8 @@ MODULE_OBJS = \
 	image.o \
 	outtake.o \
 	settings.o \
-	vqa_decoder.o
+	vqa_decoder.o \
+	vqa_player.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index 6ebede5..3bbcb6b 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -23,7 +23,9 @@
 #include "bladerunner/outtake.h"
 
 #include "bladerunner/bladerunner.h"
-#include "bladerunner/vqa_decoder.h"
+#include "bladerunner/vqa_player.h"
+
+#include "audio/audiostream.h"
 
 #include "common/debug.h"
 #include "common/events.h"
@@ -43,31 +45,27 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
 	else
 		resName = name + "_E.VQA";
 
-	Common::SeekableReadStream *s = _vm->getResourceStream(resName);
-
-	_vqaDecoder = new VQADecoder();
-	_vqaDecoder->loadStream(s);
+	VQAPlayer vqa_player(_vm);
 
-	_vqaDecoder->start();
+	vqa_player.open(resName);
 
-	uint32 last = _vm->_system->getMillis();
+	_vm->_mixer->stopAll();
+	while (!_vm->shouldQuit()) {
+		Common::Event event;
+		while (_vm->_system->getEventManager()->pollEvent(event))
+			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+				return;
 
-	while (!_vqaDecoder->endOfVideo() && !_vm->shouldQuit()) {
-		if (_vqaDecoder->needsUpdate()) {
-			uint32 now = _vm->_system->getMillis();
-			debug("delta: %d", now - last);
-			last = now;
+		int frame = vqa_player.update();
+		if (frame == -3)
+			break;
 
-			const Graphics::Surface *surface = _vqaDecoder->decodeNextFrame();
+		if (frame >= 0) {
+			const Graphics::Surface *surface = vqa_player.getSurface();
 			_vm->_system->copyRectToScreen((const byte *)surface->getBasePtr(0, 0), surface->pitch, 0, 0, 640, 480);
 			_vm->_system->updateScreen();
 		}
 
-		Common::Event event;
-		while (_vm->_system->getEventManager()->pollEvent(event))
-			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
-				return;
-
 		_vm->_system->delayMillis(10);
 	}
 }
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index bd898bc..bcba7d0 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -128,7 +128,7 @@ VQADecoder::~VQADecoder() {
 }
 
 bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
-	close();
+	// close();
 	_s = s;
 
 	IFFChunkHeader chd;
@@ -160,22 +160,22 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
 			case kMSCI: rc = readMSCI(s, chd.size); break;
 			case kVQHD: rc = readVQHD(s, chd.size); break;
 			default:
-				debug("Unhandled chunk '%s'", strTag(chd.id));
+				warning("Unhandled chunk '%s'", strTag(chd.id));
 				s->skip(roundup(chd.size));
 				rc = true;
 		}
 
 		if (!rc) {
-			debug("failed to handle chunk %s", strTag(chd.id));
+			warning("failed to handle chunk %s", strTag(chd.id));
 			return false;
 		}
 	} while (chd.id != kFINF);
 
 	_videoTrack = new VQAVideoTrack(this);
-	addTrack(_videoTrack);
+	// addTrack(_videoTrack);
 
 	_audioTrack = new VQAAudioTrack(this);
-	addTrack(_audioTrack);
+	// addTrack(_audioTrack);
 
 	/*
 	for (int i = 0; i != _loopInfo.loopCount; ++i) {
@@ -189,6 +189,14 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
 	return true;
 }
 
+const Graphics::Surface *VQADecoder::decodeVideoFrame() {
+	return _videoTrack->decodeVideoFrame();
+}
+
+Audio::SeekableAudioStream *VQADecoder::decodeAudioFrame() {
+	return _audioTrack->decodeAudioFrame();
+}
+
 void VQADecoder::readNextPacket() {
 	IFFChunkHeader chd;
 
@@ -286,6 +294,12 @@ bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 		debug("_header.unk5         %d", _header.unk5);
 	}
 
+	assert(_header.version == 2);
+	assert(_header.freq == 22050);
+	assert(_header.channels == 1);
+	assert(_header.bits == 16);
+	assert(_header.colors == 0);
+
 	return true;
 }
 
@@ -345,18 +359,18 @@ bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
 		{
 		case kVIEW:
 			_maxVIEWChunkSize = size;
-			debug("max VIEW size: %08x", _maxVIEWChunkSize);
+			// debug("max VIEW size: %08x", _maxVIEWChunkSize);
 			break;
 		case kZBUF:
 			_maxZBUFChunkSize = size;
-			debug("max ZBUF size: %08x", _maxZBUFChunkSize);
+			// debug("max ZBUF size: %08x", _maxZBUFChunkSize);
 			break;
 		case kAESC:
 			_maxAESCChunkSize = size;
-			debug("max AESC size: %08x", _maxAESCChunkSize);
+			// debug("max AESC size: %08x", _maxAESCChunkSize);
 			break;
 		default:
-			debug("Unknown tag in MSCT: %s", strTag(tag));
+			warning("Unknown tag in MSCT: %s", strTag(tag));
 		}
 
 		uint32 zero;
@@ -483,7 +497,7 @@ bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size)
 
 	for (int i = 0; i != loopNamesCount; ++i) {
 		char   *begin = names + loopNameOffsets[i];
-		size_t  len   = ((i == loopNamesCount) ? chd.size : loopNameOffsets[i+1]) - loopNameOffsets[i];
+		uint32  len   = ((i == loopNamesCount) ? chd.size : loopNameOffsets[i+1]) - loopNameOffsets[i];
 
 		_loopInfo.loops[i].name = Common::String(begin, len);
 	}
@@ -571,8 +585,7 @@ Common::Rational VQADecoder::VQAVideoTrack::getFrameRate() const {
 	return _frameRate;
 }
 
-const Graphics::Surface *VQADecoder::VQAVideoTrack::decodeNextFrame() {
-	debug("_curFrame: %d", _curFrame);
+const Graphics::Surface *VQADecoder::VQAVideoTrack::decodeVideoFrame() {
 	if (_hasNewFrame) {
 		decodeFrame((uint16*)_surface->getPixels());
 		_curFrame++;
@@ -607,7 +620,7 @@ bool VQADecoder::VQAVideoTrack::readVQFL(Common::SeekableReadStream *s, uint32 s
 
 bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 size) {
 	if (size > _maxCBFZSize) {
-		debug("%d > %d", size, _maxCBFZSize);
+		warning("readCBFZ: chunk too large: %d > %d", size, _maxCBFZSize);
 		return false;
 	}
 
@@ -871,7 +884,7 @@ bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
 			dstBlock += count;
 			break;
 		default:
-			debug("Undefined case %d", command >> 13);
+			warning("VQAVideoTrack::decodeFrame: Undefined case %d", command >> 13);
 		}
 	}
 
@@ -879,33 +892,32 @@ bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
 }
 
 VQADecoder::VQAAudioTrack::VQAAudioTrack(VQADecoder *vqaDecoder) {
-	_audioStream = Audio::makeQueuingAudioStream(vqaDecoder->_header.freq, false);
+	_frequency = vqaDecoder->_header.freq;
 }
 
 VQADecoder::VQAAudioTrack::~VQAAudioTrack() {
-	delete _audioStream;
 }
 
-Audio::AudioStream *VQADecoder::VQAAudioTrack::getAudioStream() const {
-	return _audioStream;
+Audio::SeekableAudioStream *VQADecoder::VQAAudioTrack::decodeAudioFrame() {
+	int16 *audioFrame = (int16*)malloc(4 * 735);
+	memset(audioFrame, 0, 4 * 735);
+
+	_adpcmDecoder.decode(_compressedAudioFrame, 735, audioFrame);
+
+	uint flags = Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
+
+	return Audio::makeRawStream((byte*)audioFrame, 4 * 735, _frequency, flags, DisposeAfterUse::YES);
 }
 
 bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 735) {
-		error("audio frame size: %d", size);
+		warning("audio frame size: %d", size);
 		return false;
 	}
 
 	s->read(_compressedAudioFrame, roundup(size));
 
-	int16 *audioFrame = (int16*)malloc(4 * size);
-	memset(audioFrame, 0, 4 * size);
-
-	_adpcmDecoder.decode(_compressedAudioFrame, size, audioFrame);
-
-	_audioStream->queueBuffer((byte*)audioFrame, 4 * size, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
-
 	return true;
 }
 
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index a2237cc..13097c6 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -38,7 +38,7 @@
 
 namespace BladeRunner {
 
-class VQADecoder : public Video::VideoDecoder
+class VQADecoder
 {
 public:
 	VQADecoder();
@@ -46,9 +46,21 @@ public:
 
 	bool loadStream(Common::SeekableReadStream *s);
 
-protected:
 	void readNextPacket();
 
+	const Graphics::Surface    *decodeVideoFrame();
+	Audio::SeekableAudioStream *decodeAudioFrame();
+
+	uint16 numFrames() const { return _header.numFrames; }
+	uint8  frameRate() const { return _header.frameRate; }
+
+	uint16 offsetX() const { return _header.offsetX; }
+	uint16 offsetY() const { return _header.offsetY; }
+
+	uint16 frequency() const { return _header.freq; }
+
+protected:
+
 private:
 	struct Header
 	{
@@ -121,9 +133,6 @@ private:
 	VQAVideoTrack *_videoTrack;
 	VQAAudioTrack *_audioTrack;
 
-	// bool   _hasView;
-	// view_t view;
-
 	bool readVQHD(Common::SeekableReadStream *s, uint32 size);
 	bool readMSCI(Common::SeekableReadStream *s, uint32 size);
 	bool readMFCI(Common::SeekableReadStream *s, uint32 size);
@@ -133,7 +142,7 @@ private:
 	bool readLNIN(Common::SeekableReadStream *s, uint32 size);
 	bool readCLIP(Common::SeekableReadStream *s, uint32 size);
 
-	class VQAVideoTrack : public FixedRateVideoTrack {
+	class VQAVideoTrack {
 	public:
 		VQAVideoTrack(VQADecoder *vqaDecoder);
 		~VQAVideoTrack();
@@ -143,7 +152,7 @@ private:
 		Graphics::PixelFormat getPixelFormat() const;
 		int getCurFrame() const;
 		int getFrameCount() const;
-		const Graphics::Surface *decodeNextFrame();
+		const Graphics::Surface *decodeVideoFrame();
 
 		bool readVQFR(Common::SeekableReadStream *s, uint32 size);
 		bool readVPTR(Common::SeekableReadStream *s, uint32 size);
@@ -157,6 +166,8 @@ private:
 	protected:
 		Common::Rational getFrameRate() const;
 
+		bool useAudioSync() const { return false; }
+
 	private:
 		Graphics::Surface *_surface;
 		bool     _hasNewFrame;
@@ -172,22 +183,21 @@ private:
 		uint32  _maxCBFZSize;
 		uint32  _maxZBUFChunkSize;
 
-		size_t   _codebookSize;
+		uint32   _codebookSize;
 		uint8   *_codebook;
 		uint8   *_cbfz;
 		uint8   *_zbufChunk;
 
-		size_t   _vptrSize;
+		uint32   _vptrSize;
 		uint8   *_vptr;
 
 		int      _curFrame;
 
-
 		void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false);
 		bool decodeFrame(uint16 *frame);
 	};
 
-	class VQAAudioTrack : public AudioTrack {
+	class VQAAudioTrack {
 	public:
 		VQAAudioTrack(VQADecoder *vqaDecoder);
 		~VQAAudioTrack();
@@ -195,33 +205,14 @@ private:
 		bool readSND2(Common::SeekableReadStream *s, uint32 size);
 		bool readSN2J(Common::SeekableReadStream *s, uint32 size);
 
+		Audio::SeekableAudioStream *decodeAudioFrame();
 	protected:
-		Audio::AudioStream *getAudioStream() const;
 
 	private:
-		Audio::QueuingAudioStream *_audioStream;
-
+		uint16               _frequency;
 		ADPCMWestwoodDecoder _adpcmDecoder;
 		uint8                _compressedAudioFrame[735];
 	};
-
-/*
-	bool readFrame();
-
-	int getFrameTime() { return 1000 / _header.frameRate; }
-
-	void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false) const;
-
-	bool seekToFrame(int frame);
-	bool decodeFrame(uint16 *frame);
-
-	int16 *getAudioFrame();
-
-	// bool get_view(view_t *view);
-	bool getZBUF(uint16 *zbuf);
-
-	friend class VQAPlayer;
-*/
 };
 
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index f05e14b..4c83079 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -35,91 +35,98 @@ bool VQAPlayer::open(const Common::String &name) {
 	if (!_s)
 		return false;
 
-	if(!_decoder.open(_s)) {
+	if(!_decoder.loadStream(_s)) {
 		delete _s;
 		_s = nullptr;
 		return false;
 	}
 
-	_audioStream = Audio::makeQueuingAudioStream(_decoder._header.freq, _decoder._header.channels == 2);
+	_audioStream = Audio::makeQueuingAudioStream(_decoder.frequency(), false);
 
 	return true;
 }
 
+void VQAPlayer::close() {
+	_vm->_mixer->stopHandle(_soundHandle);
+	delete[] _s;
+	_s = nullptr;
+}
+
 int VQAPlayer::update() {
-	uint32 now = _vm->_system->getMillis();
-
-	if (_nextFrameTime == 0)
-		_nextFrameTime = now;
-
-	if (now < _nextFrameTime)
-		return -1;
-
-	_nextFrameTime += 1000 / _decoder._header.frameRate;
-
-	if (_decoder._loopInfo.loopCount) {
-		if (_loopSpecial >= 0) {
-			_curLoop = _loopSpecial;
-			_loopSpecial = -3;
-
-			_curFrame = _decoder._loopInfo.loops[_curLoop].begin;
-			_decoder.seekToFrame(_curFrame);
-		} else if (_curLoop == -1 && _loopDefault >= 0) {
-			_curLoop = _loopDefault;
-			_curFrame = _decoder._loopInfo.loops[_curLoop].begin;
-			_decoder.seekToFrame(_curFrame);
-		} else if (_curLoop >= 0 && _curFrame == _decoder._loopInfo.loops[_curLoop].end) {
-			if (_loopDefault == -1)
-				return -3;
-
-			_curLoop = _loopDefault;
-			_curFrame = _decoder._loopInfo.loops[_curLoop].begin;
-			_decoder.seekToFrame(_curFrame);
+	uint32 now = 60 * _vm->_system->getMillis();
+
+	if (_curFrame == -1) {
+		_curFrame = 0;
+		if (_curFrame >= 0) {
+			_decoder.readNextPacket();
+			queueAudioFrame(_decoder.decodeAudioFrame());
+			_surface = _decoder.decodeVideoFrame();
 		}
-		else
-			++_curFrame;
-	}
-	else
-		++_curFrame;
 
-	if (_curFrame >= _decoder._header.numFrames) {
-		if (_audioStream)
-			_audioStream->finish();
-		return -3;
-	}
+		_decodedFrame = calcNextFrame(_curFrame);
+		if (_decodedFrame >= 0) {
+			_decoder.readNextPacket();
+			queueAudioFrame(_decoder.decodeAudioFrame());
+		}
 
-	_decoder.readFrame();
-	_decoder.decodeFrame((uint16*)_surface->getPixels());
+		_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, _audioStream);
+		_audioStarted = true;
 
-	if (_audioStream) {
-		int16 *audioFrame = (int16*)malloc(2940);
-		memcpy(audioFrame, _decoder.getAudioFrame(), 2940);
-		_audioStream->queueBuffer((byte*)audioFrame, 2940, DisposeAfterUse::YES, Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
+		_nextFrameTime = now + 60000 / 15;
+		return _curFrame;
+	}
 
-		if (!_audioStarted)
-			_vm->_mixer->playStream(
-				Audio::Mixer::kPlainSoundType,
-				&_soundHandle,
-				_audioStream,
-				-1
-			);
+	if (now >= _nextFrameTime) {
+		_curFrame = _decodedFrame;
+		if (_curFrame >= 0) {
+			_surface = _decoder.decodeVideoFrame();
+		}
 
-		_audioStarted = true;
+		_decodedFrame = calcNextFrame(_curFrame);
+		if (_decodedFrame >= 0) {
+			_decoder.readNextPacket();
+			queueAudioFrame(_decoder.decodeAudioFrame());
+		}
+
+		_nextFrameTime += 60000 / 15;
+		return _curFrame;
 	}
 
-	return _curFrame;
+	_surface = nullptr;
+	return -1;
+}
+
+const Graphics::Surface *VQAPlayer::getSurface() const {
+	return _surface;
 }
 
-void VQAPlayer::setLoopSpecial(int loop, bool wait)
-{
+void VQAPlayer::setLoopSpecial(int loop, bool wait) {
 	_loopSpecial = loop;
 	if (!wait)
 		_curLoop = -1;
 }
 
-void VQAPlayer::setLoopDefault(int loop)
-{
+void VQAPlayer::setLoopDefault(int loop) {
 	_loopDefault = loop;
 }
 
+int VQAPlayer::calcNextFrame(int frame) const {
+	if (frame < 0)
+		return -3;
+
+	frame += 1;
+
+	if (frame == _decoder.numFrames())
+		frame = -3;
+
+	return frame;
+}
+
+void VQAPlayer::queueAudioFrame(Audio::AudioStream *audioStream) {
+	int n = _audioStream->numQueuedStreams();
+	if (n == 0)
+		warning("numQueuedStreams: %d", n);
+	_audioStream->queueAudioStream(audioStream, DisposeAfterUse::YES);
+}
+
 }; // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 7e7fab5..e38a274 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -38,10 +38,11 @@ class VQAPlayer {
 	BladeRunnerEngine           *_vm;
 	Common::SeekableReadStream  *_s;
 	VQADecoder                   _decoder;
-	Graphics::Surface           *_surface;
+	const Graphics::Surface     *_surface;
 	Audio::QueuingAudioStream   *_audioStream;
 
 	int _curFrame;
+	int _decodedFrame;
 	int _curLoop;
 	int _loopSpecial;
 	int _loopDefault;
@@ -52,12 +53,13 @@ class VQAPlayer {
 
 public:
 
-	VQAPlayer(BladeRunnerEngine *vm, Graphics::Surface *surface)
+	VQAPlayer(BladeRunnerEngine *vm)
 		: _vm(vm),
 		  _s(nullptr),
-		  _surface(surface),
+		  _surface(nullptr),
 		  _audioStream(nullptr),
 		  _curFrame(-1),
+		  _decodedFrame(-1),
 		  _curLoop(-1),
 		  _loopSpecial(-1),
 		  _loopDefault(-1),
@@ -65,11 +67,22 @@ public:
 		  _audioStarted(false)
 	{}
 
+	~VQAPlayer() {
+		close();
+	}
+
 	bool open(const Common::String &name);
+	void close();
+
 	int  update();
+	const Graphics::Surface *getSurface() const;
 
 	void setLoopSpecial(int loop, bool wait);
 	void setLoopDefault(int loop);
+
+private:
+	int calcNextFrame(int frame) const;
+	void queueAudioFrame(Audio::AudioStream *audioStream);
 };
 
 }; // End of namespace BladeRunner


Commit: d260f993aad56cf699d8ba298c84e603650edf8f
    https://github.com/scummvm/scummvm/commit/d260f993aad56cf699d8ba298c84e603650edf8f
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:23+02:00

Commit Message:
BLADERUNNER: No semicolon after namespace closing brace

Changed paths:
    engines/bladerunner/aud_decoder.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/chapters.h
    engines/bladerunner/decompress_lcw.cpp
    engines/bladerunner/decompress_lcw.h
    engines/bladerunner/decompress_lzo.cpp
    engines/bladerunner/decompress_lzo.h
    engines/bladerunner/gameinfo.cpp
    engines/bladerunner/gameinfo.h
    engines/bladerunner/image.cpp
    engines/bladerunner/image.h
    engines/bladerunner/outtake.cpp
    engines/bladerunner/outtake.h
    engines/bladerunner/settings.cpp
    engines/bladerunner/settings.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/aud_decoder.cpp b/engines/bladerunner/aud_decoder.cpp
index d11a90e..3123ddd 100644
--- a/engines/bladerunner/aud_decoder.cpp
+++ b/engines/bladerunner/aud_decoder.cpp
@@ -164,4 +164,4 @@ void ADPCMWestwoodDecoder::decode(uint8 *in, size_t size, int16 *out)
 	_predictor = predictor;
 }
 
-};
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index bf95ca7..836450f 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -86,6 +86,6 @@ public:
 	Common::SeekableReadStream *getResourceStream(const Common::String &name);
 };
 
-} // End of namespace Blade Runner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/chapters.h b/engines/bladerunner/chapters.h
index 9fae487..f167e1b 100644
--- a/engines/bladerunner/chapters.h
+++ b/engines/bladerunner/chapters.h
@@ -57,6 +57,6 @@ public:
 	int  currentResouceId() { return _chapter ? _resourceIds[_chapter] : -1; }
 };
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/decompress_lcw.cpp b/engines/bladerunner/decompress_lcw.cpp
index e632ec7..15e28bf 100644
--- a/engines/bladerunner/decompress_lcw.cpp
+++ b/engines/bladerunner/decompress_lcw.cpp
@@ -159,4 +159,4 @@ uint32 decompress_lcw_output_size(uint8 *inBuf, uint32 inLen) {
 	return outsize;
 }
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/decompress_lcw.h b/engines/bladerunner/decompress_lcw.h
index ea09aab..dbb0e04 100644
--- a/engines/bladerunner/decompress_lcw.h
+++ b/engines/bladerunner/decompress_lcw.h
@@ -30,6 +30,6 @@ namespace BladeRunner {
 uint32 decompress_lcw(uint8 *inBuf, uint32 inLen, uint8 *outBuf, uint32 outLen);
 uint32 decompress_lcw_output_size(void *inBuf, uint32 inLen);
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/decompress_lzo.cpp b/engines/bladerunner/decompress_lzo.cpp
index 147d11d..aa4ebc7 100644
--- a/engines/bladerunner/decompress_lzo.cpp
+++ b/engines/bladerunner/decompress_lzo.cpp
@@ -140,4 +140,4 @@ eof_found:
 	return ip != ip_end;
 }
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/decompress_lzo.h b/engines/bladerunner/decompress_lzo.h
index 20e8581..e6404c6 100644
--- a/engines/bladerunner/decompress_lzo.h
+++ b/engines/bladerunner/decompress_lzo.h
@@ -29,6 +29,6 @@ namespace BladeRunner {
 
 int decompress_lzo1x(const uint8 *in, size_t inLen, uint8 *out, size_t *outLen);
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index 66a7af8..2d5879d 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -109,4 +109,4 @@ bool GameInfo::open(const Common::String &name) {
 	return !s->err();
 }
 
-} // End of namespace Blade Runner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/gameinfo.h b/engines/bladerunner/gameinfo.h
index 64153be..094d157 100644
--- a/engines/bladerunner/gameinfo.h
+++ b/engines/bladerunner/gameinfo.h
@@ -77,6 +77,6 @@ public:
 	char *getOuttake(int i)        { return _outtakes[i]; }
 };
 
-} // End of namespace Blade Runner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/image.cpp b/engines/bladerunner/image.cpp
index fc6b68f..42070bc 100644
--- a/engines/bladerunner/image.cpp
+++ b/engines/bladerunner/image.cpp
@@ -75,4 +75,4 @@ void Image::copyToSurface(Graphics::Surface *dst) const {
 	dst->copyRectToSurface(_surface, 0, 0, Common::Rect(_surface.w, _surface.h));
 }
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/image.h b/engines/bladerunner/image.h
index 5d2fa69..3980ff4 100644
--- a/engines/bladerunner/image.h
+++ b/engines/bladerunner/image.h
@@ -42,6 +42,6 @@ public:
 	void copyToSurface(Graphics::Surface *surface) const;
 };
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index 3bbcb6b..092dc51 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -70,4 +70,4 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
 	}
 }
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/outtake.h b/engines/bladerunner/outtake.h
index 9182b87..7ef3552 100644
--- a/engines/bladerunner/outtake.h
+++ b/engines/bladerunner/outtake.h
@@ -49,6 +49,6 @@ public:
 	void play(const Common::String &name, bool noLocalization, int container);
 };
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index 8e46b5d..c31d4a3 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -96,4 +96,4 @@ bool Settings::openNewScene() {
 	return true;
 }
 
-} // End of namespace Blade Runner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h
index cb35285..61ac420 100644
--- a/engines/bladerunner/settings.h
+++ b/engines/bladerunner/settings.h
@@ -89,6 +89,6 @@ public:
 	bool openNewScene();
 };
 
-} // End of namespace Blade Runner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index bcba7d0..d97c1d8 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -934,4 +934,4 @@ bool VQADecoder::VQAAudioTrack::readSN2J(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 13097c6..f5b00f5 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -215,6 +215,6 @@ private:
 	};
 };
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 4c83079..ad269ef 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -129,4 +129,4 @@ void VQAPlayer::queueAudioFrame(Audio::AudioStream *audioStream) {
 	_audioStream->queueAudioStream(audioStream, DisposeAfterUse::YES);
 }
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index e38a274..128bbe6 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -85,6 +85,6 @@ private:
 	void queueAudioFrame(Audio::AudioStream *audioStream);
 };
 
-}; // End of namespace BladeRunner
+} // End of namespace BladeRunner
 
 #endif


Commit: 5cb4ba9a9b52705d84e30b07de1badb780e4b02e
    https://github.com/scummvm/scummvm/commit/5cb4ba9a9b52705d84e30b07de1badb780e4b02e
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:28+02:00

Commit Message:
BLADERUNNER: Add basic Scene, Set, and Script support.

Changed paths:
  A engines/bladerunner/scene.cpp
  A engines/bladerunner/scene.h
  A engines/bladerunner/script/rc01.cpp
  A engines/bladerunner/script/script.cpp
  A engines/bladerunner/script/script.h
  A engines/bladerunner/set.cpp
  A engines/bladerunner/set.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/chapters.cpp
    engines/bladerunner/chapters.h
    engines/bladerunner/module.mk
    engines/bladerunner/outtake.cpp
    engines/bladerunner/settings.cpp
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index e914f1c..ff8ea28 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -26,6 +26,8 @@
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
 #include "bladerunner/outtake.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/script/script.h"
 #include "bladerunner/settings.h"
 #include "bladerunner/vqa_decoder.h"
 
@@ -46,6 +48,8 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst) : Engine(syst) {
 	_gameIsRunning  = true;
 
 	_chapters = nullptr;
+	_scene = new Scene(this);
+	_script = new Script(this);
 	_settings = new Settings(this);
 }
 
@@ -105,12 +109,12 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
-	initActors();
+	initChapterAndScene();
 
 	return true;
 }
 
-void BladeRunnerEngine::initActors() {
+void BladeRunnerEngine::initChapterAndScene() {
 	// TODO: Init actors...
 
 	_settings->setChapter(1);
@@ -168,10 +172,6 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: Only run if not in Kia, script, nor AI
 		_settings->openNewScene();
 
-		outtakePlay(28, true);
-		outtakePlay(41, true);
-		outtakePlay( 0, false);
-
 		// TODO: Autosave
 		// TODO: Kia
 		// TODO: Spinner
@@ -184,11 +184,17 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: ZBUF repair dirty rects
 		// TODO: Tick Ambient Audio (in Replicant)
 
-		// TODO: Advance frame (in Replicant)
+		bool backgroundChanged = false;
+		int frame = _scene->advanceFrame(_surface1);
+		if (frame >= 0) {
+			_script->SceneFrameAdvanced(frame);
+			backgroundChanged = true;
+		}
+
 		// TODO: Render overlays (mostly in Replicant)
 		// TODO: Tick Actor AI and Timers (timers in Replicant)
 
-		if (_settings->getNewScene() == -1 /* || in_script_counter || in_ai */) {
+		if (_settings->getNewScene() == -1 || _script->_inScriptCounter /* || in_ai */) {
 
 			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
 			// TODO: Draw items (drawing works in Replicant)
@@ -198,7 +204,9 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Process AUD (audio in Replicant)
 			// TODO: Footstep sound
 
+			_system->copyRectToScreen((const byte *) _surface1.getBasePtr(0, 0), _surface1.pitch, 0, 0, 640, 480);
 			_system->updateScreen();
+			_system->delayMillis(10);
 		}
 	}
 }
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 836450f..c13f6a8 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -38,17 +38,20 @@ namespace BladeRunner {
 const Graphics::PixelFormat RGB555(2, 5, 5, 5, 0, 10, 5, 0, 0);
 
 class Chapters;
+class Scene;
+class Script;
 class Settings;
 class GameInfo;
 
 class BladeRunnerEngine : public Engine {
-	GameInfo *_gameInfo;
-
 public:
 	bool      _gameIsRunning;
 	bool      _windowIsActive;
 
 	Chapters *_chapters;
+	GameInfo *_gameInfo;
+	Scene    *_scene;
+	Script   *_script;
 	Settings *_settings;
 
 	int in_script_counter;
@@ -67,7 +70,7 @@ public:
 	Common::Error BladeRunnerEngine::run();
 
 	bool startup();
-	void initActors();
+	void initChapterAndScene();
 	void shutdown();
 
 	void loadSplash();
diff --git a/engines/bladerunner/chapters.cpp b/engines/bladerunner/chapters.cpp
index 280ce92..a573fff 100644
--- a/engines/bladerunner/chapters.cpp
+++ b/engines/bladerunner/chapters.cpp
@@ -32,10 +32,10 @@ bool Chapters::enterChapter(int chapter) {
 	if (!_vm->openArchive("A.TLK"))
 		return false;
 
-	if (!_vm->openArchive(Common::String::format("VQA%d.MIX", MAX(id, 3))))
+	if (!_vm->openArchive(Common::String::format("VQA%d.MIX", MIN(id, 3))))
 		return false;
 
-	if (!_vm->openArchive(Common::String::format("%d.TLK", MAX(id, 3))))
+	if (!_vm->openArchive(Common::String::format("%d.TLK", MIN(id, 3))))
 		return false;
 
 	if (!_vm->openArchive(Common::String::format("OUTTAKE%d.MIX", id)))
@@ -50,8 +50,8 @@ void Chapters::closeResources() {
 	int id = _resourceIds[_chapter];
 
 	_vm->closeArchive("A.TLK");
-	_vm->closeArchive(Common::String::format("VQA%d.MIX", MAX(id, 3)));
-	_vm->closeArchive(Common::String::format("%d.TLK", MAX(id, 3)));
+	_vm->closeArchive(Common::String::format("VQA%d.MIX", MIN(id, 3)));
+	_vm->closeArchive(Common::String::format("%d.TLK", MIN(id, 3)));
 	_vm->closeArchive(Common::String::format("OUTTAKE%d.MIX", id));
 	_hasOpenResources = false;
 }
diff --git a/engines/bladerunner/chapters.h b/engines/bladerunner/chapters.h
index f167e1b..9778209 100644
--- a/engines/bladerunner/chapters.h
+++ b/engines/bladerunner/chapters.h
@@ -54,7 +54,7 @@ public:
 	void closeResources();
 
 	bool hasOpenResources() { return _hasOpenResources; }
-	int  currentResouceId() { return _chapter ? _resourceIds[_chapter] : -1; }
+	int  currentResourceId() { return _chapter ? _resourceIds[_chapter] : -1; }
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index b1de94d..752543b 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -11,6 +11,10 @@ MODULE_OBJS = \
 	gameinfo.o \
 	image.o \
 	outtake.o \
+	scene.o \
+	script/rc01.o \
+	script/script.o \
+	set.o \
 	settings.o \
 	vqa_decoder.o \
 	vqa_player.o
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index 092dc51..5bb6394 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -53,7 +53,7 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
 	while (!_vm->shouldQuit()) {
 		Common::Event event;
 		while (_vm->_system->getEventManager()->pollEvent(event))
-			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+			if (event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE)
 				return;
 
 		int frame = vqa_player.update();
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
new file mode 100644
index 0000000..7cb3b01
--- /dev/null
+++ b/engines/bladerunner/scene.cpp
@@ -0,0 +1,112 @@
+/* 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 "bladerunner/scene.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/chapters.h"
+#include "bladerunner/gameinfo.h"
+#include "bladerunner/script/script.h"
+
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace BladeRunner {
+
+bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
+	if (!isLoadingGame) {
+		// flush ADQ
+	}
+
+	_setId = setId;
+	_sceneId = sceneId;
+
+	const Common::String setName = _vm->_gameInfo->getSetName(_sceneId);
+
+	if (isLoadingGame) {
+		// TODO: Set up overlays
+	} else {
+		// TODO: Clear regions
+		// TODO: Destroy all overlays
+		_defaultLoop = 0;
+		_frame = -1;
+	}
+
+	Common::String vqaName;
+	int currentResourceId = _vm->_chapters->currentResourceId();
+	if (currentResourceId == 1) {
+		vqaName = Common::String::format("%s.VQA", setName.c_str());
+	} else {
+		vqaName = Common::String::format("%s_%d.VQA", setName.c_str(), MIN(currentResourceId, 3));
+	}
+
+	if (!_vqaPlayer.open(vqaName))
+		return false;
+
+	Common::String sceneName = _vm->_gameInfo->getSetName(sceneId);
+	if (!_vm->_script->open(sceneName))
+		return false;
+
+	if (!isLoadingGame)
+		_vm->_script->InitializeScene();
+
+	Common::String setResourceName = Common::String::format("%s-MIN.SET", sceneName.c_str());
+	// if (!_set->open(setResourceName))
+	// 	return false;
+
+	// TODO: Set view
+	if (isLoadingGame) {
+		if (sceneId >= 73 && sceneId <= 76)
+			_vm->_script->InitializeScene();
+		return true;
+	}
+
+	// TODO: set VQADecoder parameters
+	// TODO: Set actor position from scene info
+	// TODO: Set actor set
+	// TODO: call SCRIPT_Scene_Loaded
+	_vm->_script->SceneLoaded();
+
+#if 0
+	// Init click map
+	int actorCount = _vm->_gameInfo->getActorCount();
+	for (int i = 0; i != actorCount; ++i) {
+		Actor *actor = _vm->_actors[i];
+		if (actor->getSet() == setId) {
+
+		}
+	}
+	// TODO: Update click map for set, items
+#endif
+
+	return true;
+}
+
+int Scene::advanceFrame(Graphics::Surface &surface) {
+	int frame = _vqaPlayer.update();
+	if (frame >= 0) {
+		surface.copyFrom(*_vqaPlayer.getSurface());
+	}
+	return frame;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
new file mode 100644
index 0000000..b69d99d
--- /dev/null
+++ b/engines/bladerunner/scene.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.
+ *
+ */
+
+#ifndef BLADERUNNER_SCENE_H
+#define BLADERUNNER_SCENE_H
+
+#include "bladerunner/vqa_player.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Scene {
+	BladeRunnerEngine *_vm;
+
+public:
+	int         _setId;
+	int         _sceneId;
+	VQAPlayer   _vqaPlayer;
+	int         _defaultLoop;
+	int         _nextSetId;
+	int         _nextSceneId;
+	int         _frame;
+	bool        _playerWalkedIn;
+
+public:
+	Scene(BladeRunnerEngine *vm)
+		: _vm(vm),
+		  _setId(-1),
+		  _sceneId(-1),
+		  _vqaPlayer(vm),
+		  _defaultLoop(0),
+		  _nextSetId(-1),
+		  _nextSceneId(-1),
+		  _playerWalkedIn(false)
+	{
+	}
+
+	bool open(int setId, int sceneId, bool isLoadingGame);
+	int advanceFrame(Graphics::Surface &surface);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
new file mode 100644
index 0000000..24cb27c
--- /dev/null
+++ b/engines/bladerunner/script/rc01.cpp
@@ -0,0 +1,43 @@
+/* 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 "bladerunner/script/script.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+void ScriptRC01::InitializeScene() {
+	_vm->outtakePlay(28, true);
+	_vm->outtakePlay(41, true);
+	_vm->outtakePlay( 0, false);
+}
+
+void ScriptRC01::SceneLoaded() {
+
+}
+
+void ScriptRC01::SceneFrameAdvanced(int frame) {
+
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
new file mode 100644
index 0000000..948e8b8
--- /dev/null
+++ b/engines/bladerunner/script/script.cpp
@@ -0,0 +1,55 @@
+/* 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 "bladerunner/script/script.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+bool Script::open(const Common::String &name) {
+	delete _currentScript;
+
+	if (name == "RC01") { _currentScript = new ScriptRC01(_vm); return true; }
+
+	return false;
+}
+
+void Script::InitializeScene() {
+	_inScriptCounter++;
+	_currentScript->InitializeScene();
+	_inScriptCounter--;
+}
+
+void Script::SceneLoaded() {
+	_inScriptCounter++;
+	_currentScript->SceneLoaded();
+	_inScriptCounter--;
+}
+
+void Script::SceneFrameAdvanced(int frame) {
+	_inScriptCounter++;
+	_currentScript->SceneFrameAdvanced(frame);
+	_inScriptCounter--;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
new file mode 100644
index 0000000..b958035
--- /dev/null
+++ b/engines/bladerunner/script/script.h
@@ -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.
+ *
+ */
+
+#ifndef BLADERUNNER_SCRIPT_H
+#define BLADERUNNER_SCRIPT_H
+
+#include "common/str.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class ScriptBase;
+
+class Script {
+public:
+	BladeRunnerEngine *_vm;
+	int                _inScriptCounter;
+	ScriptBase        *_currentScript;
+
+	Script(BladeRunnerEngine *vm)
+		: _vm(vm),
+		  _inScriptCounter(0),
+		  _currentScript(nullptr)
+	{}
+
+	bool open(const Common::String &name);
+
+	void InitializeScene();
+	void SceneLoaded();
+	void SceneFrameAdvanced(int frame);
+};
+
+class ScriptBase {
+protected:
+	BladeRunnerEngine *_vm;
+
+	ScriptBase(BladeRunnerEngine *vm)
+		: _vm(vm)
+	{}
+
+public:
+	virtual void InitializeScene() = 0;
+	virtual void SceneLoaded() = 0;
+	virtual void SceneFrameAdvanced(int frame) = 0;
+};
+
+#define DECLARE_SCRIPT(name) \
+class Script##name : public ScriptBase { \
+public: \
+	Script##name(BladeRunnerEngine *_vm) \
+		: ScriptBase(_vm) \
+	{} \
+	void InitializeScene(); \
+	void SceneLoaded(); \
+	void SceneFrameAdvanced(int frame); \
+};
+
+DECLARE_SCRIPT(RC01)
+
+#undef DECLARE_SCRIPT
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
new file mode 100644
index 0000000..2751c1d
--- /dev/null
+++ b/engines/bladerunner/set.cpp
@@ -0,0 +1,45 @@
+/* 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 "bladerunner/set.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/ptr.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace BladeRunner {
+
+#define kSet0 0x53657430
+
+bool Set::open(const Common::String &name) {
+	Common::ScopedPtr<Common::SeekableReadStream> s(_vm->getResourceStream(name));
+
+	uint32 sig = s->readUint32BE();
+	if (sig != kSet0)
+		return false;
+
+	return true;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
new file mode 100644
index 0000000..b298278
--- /dev/null
+++ b/engines/bladerunner/set.h
@@ -0,0 +1,47 @@
+/* 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 BLADERUNNER_SET_H
+#define BLADERUNNER_SET_H
+
+#include "common/str.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class VQADecoder;
+
+class Set {
+	BladeRunnerEngine *_vm;
+
+public:
+	Set(BladeRunnerEngine *vm)
+	{
+	}
+
+	bool open(const Common::String &name);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index c31d4a3..0759762 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -24,6 +24,9 @@
 
 #include "bladerunner/bladerunner.h"
 #include "bladerunner/chapters.h"
+#include "bladerunner/scene.h"
+
+#include "common/debug.h"
 
 namespace BladeRunner {
 
@@ -33,17 +36,16 @@ Settings::Settings(BladeRunnerEngine *vm)
 	_chapter = 1;
 	_gamma = 1.0f;
 
-	_chapterChanged;
-	_newChapter;
-	_newScene;
-	_newSet;
-
-	_startingGame;
-	_loadingGame;
+	_chapterChanged = false;
+	_newChapter = -1;
+	_newScene = -1;
+	_newSet = -1;
 
-	_fullHDFrames;
-	_mst3k;
+	_startingGame = true;
+	_loadingGame = false;
 
+	_fullHDFrames = true;
+	_mst3k = false;
 }
 
 bool Settings::openNewScene() {
@@ -57,9 +59,9 @@ bool Settings::openNewScene() {
 		// Stop ambient audio and music
 	}
 
-	// int currentSet = _vm->scene()->getSet();
-	// int newSet     = _newSet;
-	// int newScene   = _newScene;
+	int currentSet = _vm->_scene->_setId;
+	int newSet     = _newSet;
+	int newScene   = _newScene;
 
 	_newSet = -1;
 	_newScene = -1;
@@ -71,8 +73,7 @@ bool Settings::openNewScene() {
 		int newChapter = _newChapter;
 		_chapterChanged = false;
 		_newChapter = 0;
-		if (!_vm->_chapters->enterChapter(newChapter))
-		{
+		if (!_vm->_chapters->enterChapter(newChapter)) {
 			_vm->_gameIsRunning = false;
 			return false;
 		}
@@ -81,16 +82,14 @@ bool Settings::openNewScene() {
 			_startingGame = false;
 	}
 
-	// if (!_vm->scene()->open(newSet, newScene, _loadingGame))
-	// {
-	// 	_vm->_gameIsRunning = false;
-	// 	return false;
-	// }
-
-	// if (!_loadingGame && currentSet != newSet) {
-	// 	// TODO: Reset actors for new set
+	if (!_vm->_scene->open(newSet, newScene, _loadingGame)) {
+		_vm->_gameIsRunning = false;
+		return false;
+	}
 
-	// }
+	if (!_loadingGame && currentSet != newSet) {
+		// TODO: Reset actors for new set
+	}
 
 	_loadingGame = false;
 	return true;
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index d97c1d8..4f484ca 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -295,9 +295,11 @@ bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 	}
 
 	assert(_header.version == 2);
-	assert(_header.freq == 22050);
-	assert(_header.channels == 1);
-	assert(_header.bits == 16);
+	if (_header.channels != 0) {
+		assert(_header.freq == 22050);
+		assert(_header.channels == 1);
+		assert(_header.bits == 16);
+	}
 	assert(_header.colors == 0);
 
 	return true;
@@ -497,9 +499,11 @@ bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size)
 
 	for (int i = 0; i != loopNamesCount; ++i) {
 		char   *begin = names + loopNameOffsets[i];
-		uint32  len   = ((i == loopNamesCount) ? chd.size : loopNameOffsets[i+1]) - loopNameOffsets[i];
+		uint32  len   = ((i == loopNamesCount - 1) ? chd.size : loopNameOffsets[i+1]) - loopNameOffsets[i];
 
 		_loopInfo.loops[i].name = Common::String(begin, len);
+
+		// debug("%2d: %s", i, _loopInfo.loops[i].name.c_str());
 	}
 
 	return true;
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index f5b00f5..d07d73f 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -57,6 +57,7 @@ public:
 	uint16 offsetX() const { return _header.offsetX; }
 	uint16 offsetY() const { return _header.offsetY; }
 
+	bool   hasAudio() const { return _header.channels != 0; }
 	uint16 frequency() const { return _header.freq; }
 
 protected:
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index ad269ef..8259625 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -41,7 +41,9 @@ bool VQAPlayer::open(const Common::String &name) {
 		return false;
 	}
 
-	_audioStream = Audio::makeQueuingAudioStream(_decoder.frequency(), false);
+	_hasAudio = _decoder.hasAudio();
+	if (_hasAudio)
+		_audioStream = Audio::makeQueuingAudioStream(_decoder.frequency(), false);
 
 	return true;
 }
@@ -59,18 +61,22 @@ int VQAPlayer::update() {
 		_curFrame = 0;
 		if (_curFrame >= 0) {
 			_decoder.readNextPacket();
-			queueAudioFrame(_decoder.decodeAudioFrame());
+			if (_hasAudio)
+				queueAudioFrame(_decoder.decodeAudioFrame());
 			_surface = _decoder.decodeVideoFrame();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
 		if (_decodedFrame >= 0) {
 			_decoder.readNextPacket();
-			queueAudioFrame(_decoder.decodeAudioFrame());
+			if (_hasAudio)
+				queueAudioFrame(_decoder.decodeAudioFrame());
 		}
 
-		_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, _audioStream);
-		_audioStarted = true;
+		if (_hasAudio) {
+			_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, _audioStream);
+			_audioStarted = true;
+		}
 
 		_nextFrameTime = now + 60000 / 15;
 		return _curFrame;
@@ -85,7 +91,8 @@ int VQAPlayer::update() {
 		_decodedFrame = calcNextFrame(_curFrame);
 		if (_decodedFrame >= 0) {
 			_decoder.readNextPacket();
-			queueAudioFrame(_decoder.decodeAudioFrame());
+			if (_hasAudio)
+				queueAudioFrame(_decoder.decodeAudioFrame());
 		}
 
 		_nextFrameTime += 60000 / 15;
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 128bbe6..9e9266e 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -48,6 +48,7 @@ class VQAPlayer {
 	int _loopDefault;
 
 	uint32 _nextFrameTime;
+	bool   _hasAudio;
 	bool   _audioStarted;
 	Audio::SoundHandle _soundHandle;
 
@@ -64,6 +65,7 @@ public:
 		  _loopSpecial(-1),
 		  _loopDefault(-1),
 		  _nextFrameTime(0),
+		  _hasAudio(false),
 		  _audioStarted(false)
 	{}
 


Commit: 25e97d21446418a4303652c749aac2118d04984c
    https://github.com/scummvm/scummvm/commit/25e97d21446418a4303652c749aac2118d04984c
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:33+02:00

Commit Message:
BLADERUNNER: First easter egg, developer commentary

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/script/rc01.cpp



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index ff8ea28..70f61e7 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -289,4 +289,9 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
 	return 0;
 }
 
+void BladeRunnerEngine::ISez(const char *str) {
+	debug("\t%s", str);
+}
+
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index c13f6a8..a2b2c89 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -87,6 +87,8 @@ public:
 	bool isArchiveOpen(const Common::String &name);
 
 	Common::SeekableReadStream *getResourceStream(const Common::String &name);
+
+	void ISez(const char *str);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 24cb27c..560eb24 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -30,6 +30,27 @@ void ScriptRC01::InitializeScene() {
 	_vm->outtakePlay(28, true);
 	_vm->outtakePlay(41, true);
 	_vm->outtakePlay( 0, false);
+
+	_vm->ISez("Blade Runner");
+	_vm->ISez("");
+	_vm->ISez("From the dark recesses of David Leary's imagination comes a game unlike any");
+	_vm->ISez("other. Blade Runner immerses you in the underbelly of future Los Angeles. Right");
+	_vm->ISez("from the start, the story pulls you in with graphic descriptions of a");
+	_vm->ISez("grandmother doing the shimmy in her underwear, child molestation, brutal");
+	_vm->ISez("cold-blooded slaying of innocent animals, vomiting on desks, staring at a");
+	_vm->ISez("woman's ass, the list goes on. And when the game starts, the real fun begins -");
+	_vm->ISez("shoot down-on-their-luck homeless people and toss them into a dumpster. Watch");
+	_vm->ISez("with sadistic glee as a dog gets blown into chunky, bloody, bits by an");
+	_vm->ISez("explosive, and even murder a shy little girl who loves you. If you think David");
+	_vm->ISez("Leary is sick, and you like sick, this is THE game for you.");
+	_vm->ISez("");
+	_vm->ISez("JW: Don't forget the wasting of helpless mutated cripples in the underground.");
+	_vm->ISez("It's such a beautiful thing!");
+	_vm->ISez("");
+	_vm->ISez("DL: Go ahead.  Just keep beating that snarling pit bull...ignore the foam");
+	_vm->ISez("around his jaws. There's room on the top shelf of my fridge for at least one");
+	_vm->ISez("more head... - Psychotic Dave");
+	_vm->ISez("");
 }
 
 void ScriptRC01::SceneLoaded() {


Commit: 76cfb2c8a9fbdc56dfcdca9d1fcfe82eac0ba9ee
    https://github.com/scummvm/scummvm/commit/76cfb2c8a9fbdc56dfcdca9d1fcfe82eac0ba9ee
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:33+02:00

Commit Message:
BLADERUNNER: Remove extra class qualification

MSVC allows it, but it's against the standard.

Changed paths:
    engines/bladerunner/bladerunner.h



diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index a2b2c89..5a02d94 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -67,7 +67,7 @@ public:
 
 	bool hasFeature(EngineFeature f) const;
 
-	Common::Error BladeRunnerEngine::run();
+	Common::Error run();
 
 	bool startup();
 	void initChapterAndScene();


Commit: ff1df93e9d6b16d2d3eab0933a3019a80fb00abb
    https://github.com/scummvm/scummvm/commit/ff1df93e9d6b16d2d3eab0933a3019a80fb00abb
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:33+02:00

Commit Message:
BLADERUNNER: Rename _vptr to _vpointer

_vptr is a reserved keyword!

Changed paths:
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h



diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 4f484ca..04c3137 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -544,8 +544,8 @@ VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
 	_cbfz      = nullptr;
 	_zbufChunk = nullptr;
 
-	_vptrSize = 0;
-	_vptr = nullptr;
+	_vpointerSize = 0;
+	_vpointer = nullptr;
 
 	_curFrame = -1;
 
@@ -560,7 +560,7 @@ VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
 	delete[] _codebook;
 	delete[] _cbfz;
 	delete[] _zbufChunk;
-	delete[] _vptr;
+	delete[] _vpointer;
 
 	delete _surface;
 }
@@ -773,11 +773,11 @@ bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 s
 	if (size > _maxVPTRSize)
 		return false;
 
-	if (!_vptr)
-		_vptr = new uint8[roundup(_maxVPTRSize)];
+	if (!_vpointer)
+		_vpointer = new uint8[roundup(_maxVPTRSize)];
 
-	_vptrSize = size;
-	s->read(_vptr, roundup(size));
+	_vpointerSize = size;
+	s->read(_vpointer, roundup(size));
 
 	_hasNewFrame = true;
 
@@ -829,11 +829,11 @@ void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBl
 
 bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
 {
-	if (!_codebook || !_vptr)
+	if (!_codebook || !_vpointer)
 		return false;
 
-	uint8 *src = _vptr;
-	uint8 *end = _vptr + _vptrSize;
+	uint8 *src = _vpointer;
+	uint8 *end = _vpointer + _vpointerSize;
 
 	uint16 count, srcBlock, dstBlock = 0;
 	(void)srcBlock;
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index d07d73f..110ca70 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -189,8 +189,8 @@ private:
 		uint8   *_cbfz;
 		uint8   *_zbufChunk;
 
-		uint32   _vptrSize;
-		uint8   *_vptr;
+		uint32   _vpointerSize;
+		uint8   *_vpointer;
 
 		int      _curFrame;
 


Commit: 88035e68767d89da3e7e83ef1733eba09e621cd5
    https://github.com/scummvm/scummvm/commit/88035e68767d89da3e7e83ef1733eba09e621cd5
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:34+02:00

Commit Message:
BLADERUNNER: Remove unnecessary semicolon

Changed paths:
    engines/bladerunner/aud_decoder.h



diff --git a/engines/bladerunner/aud_decoder.h b/engines/bladerunner/aud_decoder.h
index dbf7ca1..c09b5fa 100644
--- a/engines/bladerunner/aud_decoder.h
+++ b/engines/bladerunner/aud_decoder.h
@@ -45,6 +45,6 @@ public:
 	void decode(uint8 *in, size_t size, int16 *out);
 };
 
-};
+}
 
 #endif


Commit: 2189721387c1607d63e05401f1a27990b13c2a94
    https://github.com/scummvm/scummvm/commit/2189721387c1607d63e05401f1a27990b13c2a94
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:34+02:00

Commit Message:
BLADERUNNER: ScriptBase needs a virtual destructor

Changed paths:
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index b958035..28b49f3 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -58,6 +58,9 @@ protected:
 	{}
 
 public:
+	virtual ~ScriptBase()
+	{}
+
 	virtual void InitializeScene() = 0;
 	virtual void SceneLoaded() = 0;
 	virtual void SceneFrameAdvanced(int frame) = 0;


Commit: 5b8df8cd8ad54c3d464bb3e2121131a8577f3b56
    https://github.com/scummvm/scummvm/commit/5b8df8cd8ad54c3d464bb3e2121131a8577f3b56
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:34+02:00

Commit Message:
BLADERUNNER: Resolve argument shadowing

Changed paths:
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 28b49f3..2bb52a8 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -69,8 +69,8 @@ public:
 #define DECLARE_SCRIPT(name) \
 class Script##name : public ScriptBase { \
 public: \
-	Script##name(BladeRunnerEngine *_vm) \
-		: ScriptBase(_vm) \
+	Script##name(BladeRunnerEngine *vm) \
+		: ScriptBase(vm) \
 	{} \
 	void InitializeScene(); \
 	void SceneLoaded(); \


Commit: 7b6159e0957a61135e9636b1c7a28f3e343cbb7e
    https://github.com/scummvm/scummvm/commit/7b6159e0957a61135e9636b1c7a28f3e343cbb7e
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:34+02:00

Commit Message:
BLADERUNNER: Fix invalid delete[]

delete[] -> delete. It's a single pointer, not an array.

Changed paths:
    engines/bladerunner/vqa_player.cpp



diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 8259625..9d96154 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -50,7 +50,7 @@ bool VQAPlayer::open(const Common::String &name) {
 
 void VQAPlayer::close() {
 	_vm->_mixer->stopHandle(_soundHandle);
-	delete[] _s;
+	delete _s;
 	_s = nullptr;
 }
 


Commit: 10708f7a8d267ffaa89d739d42686fe12d26e92c
    https://github.com/scummvm/scummvm/commit/10708f7a8d267ffaa89d739d42686fe12d26e92c
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2016-09-29T22:33:34+02:00

Commit Message:
BLADERUNNER: Fix invalid read

Conditions are evaluated left to right. If you want short-
circuiting to protect from invalid read, you have to do the
range checks before the pointer dereferencing.

Changed paths:
    engines/bladerunner/decompress_lcw.cpp



diff --git a/engines/bladerunner/decompress_lcw.cpp b/engines/bladerunner/decompress_lcw.cpp
index 15e28bf..8d20e23 100644
--- a/engines/bladerunner/decompress_lcw.cpp
+++ b/engines/bladerunner/decompress_lcw.cpp
@@ -40,7 +40,7 @@ uint32 decompress_lcw(uint8 *inBuf, uint32 inLen, uint8 *outBuf, uint32 outLen)
 		++src;
 	}
 
-	while (src[0] != 0x80 && src < inBuf + inLen && dst < outEnd)
+	while (src < inBuf + inLen && dst < outEnd && src[0] != 0x80)
 	{
 		out_remain = (int)(outEnd - dst);
 


Commit: 70b154988a433e801c8aa633204e85076d433767
    https://github.com/scummvm/scummvm/commit/70b154988a433e801c8aa633204e85076d433767
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:34+02:00

Commit Message:
BLADERUNNER: Remove unused member variables from OuttakePlayer

Changed paths:
    engines/bladerunner/outtake.cpp
    engines/bladerunner/outtake.h



diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index 5bb6394..b81b212 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -25,8 +25,6 @@
 #include "bladerunner/bladerunner.h"
 #include "bladerunner/vqa_player.h"
 
-#include "audio/audiostream.h"
-
 #include "common/debug.h"
 #include "common/events.h"
 #include "common/system.h"
diff --git a/engines/bladerunner/outtake.h b/engines/bladerunner/outtake.h
index 7ef3552..872656e 100644
--- a/engines/bladerunner/outtake.h
+++ b/engines/bladerunner/outtake.h
@@ -30,20 +30,13 @@
 namespace BladeRunner {
 
 class BladeRunnerEngine;
-class VQADecoder;
 
 class OuttakePlayer {
 	BladeRunnerEngine *_vm;
 
-	bool               _isVQAOpen;
-	VQADecoder        *_vqaDecoder;
-	Graphics::Surface *_surface;
-
 public:
 	OuttakePlayer(BladeRunnerEngine *vm) :
-		_vm(vm),
-		_isVQAOpen(false),
-		_vqaDecoder(nullptr)
+		_vm(vm)
 	{}
 
 	void play(const Common::String &name, bool noLocalization, int container);


Commit: 8cbfd9ab50064456e1aac1e08c2c98661e756ebc
    https://github.com/scummvm/scummvm/commit/8cbfd9ab50064456e1aac1e08c2c98661e756ebc
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:35+02:00

Commit Message:
BLADERUNNER: Unshadow variable size in VQADecoder::readMSCI

Changed paths:
    engines/bladerunner/vqa_decoder.cpp



diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 04c3137..345fc2c 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -353,23 +353,20 @@ bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
 
 	for (uint32 i = 0; i < count; ++i)
 	{
-		uint32 tag, size;
+		uint32 tag, max_size;
 		tag  = s->readUint32BE();
-		size = s->readUint32LE();
+		max_size = s->readUint32LE();
 
 		switch (tag)
 		{
 		case kVIEW:
-			_maxVIEWChunkSize = size;
-			// debug("max VIEW size: %08x", _maxVIEWChunkSize);
+			_maxVIEWChunkSize = max_size;
 			break;
 		case kZBUF:
-			_maxZBUFChunkSize = size;
-			// debug("max ZBUF size: %08x", _maxZBUFChunkSize);
+			_maxZBUFChunkSize = max_size;
 			break;
 		case kAESC:
-			_maxAESCChunkSize = size;
-			// debug("max AESC size: %08x", _maxAESCChunkSize);
+			_maxAESCChunkSize = max_size;
 			break;
 		default:
 			warning("Unknown tag in MSCT: %s", strTag(tag));


Commit: 5a12394a763b569977c697dca0ec8e1e428b6db4
    https://github.com/scummvm/scummvm/commit/5a12394a763b569977c697dca0ec8e1e428b6db4
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:35+02:00

Commit Message:
BLADERUNNER: Return an error if BladeRunnerEngine::startup() fails

Changed paths:
    engines/bladerunner/bladerunner.cpp



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 70f61e7..6f6b2f2 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -60,7 +60,8 @@ bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
 Common::Error BladeRunnerEngine::run() {
 	initGraphics(640, 480, true, &RGB555);
 
-	startup();
+	if (!startup())
+		return Common::Error(Common::kUnknownError, "Failed to initialize resources");
 
 	if (warnUserAboutUnsupportedGame()) {
 		init2();


Commit: 691d0f9888830699861a9406a4c5fc6bff5c5aef
    https://github.com/scummvm/scummvm/commit/691d0f9888830699861a9406a4c5fc6bff5c5aef
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:35+02:00

Commit Message:
BLADERUNNER: Avoid global constructor for pixelformat

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/vqa_decoder.cpp



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 6f6b2f2..b8bfce9 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -58,7 +58,8 @@ bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
 }
 
 Common::Error BladeRunnerEngine::run() {
-	initGraphics(640, 480, true, &RGB555);
+	Graphics::PixelFormat format = createRGB555();
+	initGraphics(640, 480, true, &format);
 
 	if (!startup())
 		return Common::Error(Common::kUnknownError, "Failed to initialize resources");
@@ -78,7 +79,7 @@ Common::Error BladeRunnerEngine::run() {
 bool BladeRunnerEngine::startup() {
 	bool r;
 
-	_surface1.create(640, 480, RGB555);
+	_surface1.create(640, 480, createRGB555());
 
 	r = openArchive("STARTUP.MIX");
 	if (!r)
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 5a02d94..353a003 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -35,8 +35,6 @@
 
 namespace BladeRunner {
 
-const Graphics::PixelFormat RGB555(2, 5, 5, 5, 0, 10, 5, 0, 0);
-
 class Chapters;
 class Scene;
 class Script;
@@ -91,6 +89,11 @@ public:
 	void ISez(const char *str);
 };
 
+static inline
+const Graphics::PixelFormat createRGB555() {
+	return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+}
+
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 345fc2c..ba30e73 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -550,7 +550,7 @@ VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
 	_zbufChunk = new uint8[roundup(_maxZBUFChunkSize)];
 
 	_surface = new Graphics::Surface();
-	_surface->create(_width, _height, RGB555);
+	_surface->create(_width, _height, createRGB555());
 }
 
 VQADecoder::VQAVideoTrack::~VQAVideoTrack() {


Commit: eefea240c72a464857fbe463b8604c6ffa112e8f
    https://github.com/scummvm/scummvm/commit/eefea240c72a464857fbe463b8604c6ffa112e8f
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:35+02:00

Commit Message:
BLADERUNNER: Fix memory leaks in BladeRunnerEngine

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index b8bfce9..4791be9 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -42,17 +42,26 @@
 namespace BladeRunner {
 
 BladeRunnerEngine::BladeRunnerEngine(OSystem *syst) : Engine(syst) {
-	_gameInfo = nullptr;
-
 	_windowIsActive = true;
 	_gameIsRunning  = true;
 
 	_chapters = nullptr;
+	_gameInfo = nullptr;
 	_scene = new Scene(this);
 	_script = new Script(this);
 	_settings = new Settings(this);
 }
 
+BladeRunnerEngine::~BladeRunnerEngine() {
+	delete _settings;
+	delete _script;
+	delete _scene;
+	delete _gameInfo;
+	delete _chapters;
+
+	_surface1.free();
+}
+
 bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
 	return f == kSupportsRTL;
 }
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 353a003..60d87ef 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -62,6 +62,7 @@ private:
 
 public:
 	BladeRunnerEngine(OSystem *syst);
+	~BladeRunnerEngine();
 
 	bool hasFeature(EngineFeature f) const;
 


Commit: d93ecabc7ae5a24dabc4e21a6fcb5ec37e74566d
    https://github.com/scummvm/scummvm/commit/d93ecabc7ae5a24dabc4e21a6fcb5ec37e74566d
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:35+02:00

Commit Message:
BLADERUNNER: Fix memory leaks in VQADecoder

Changed paths:
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h



diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index ba30e73..f2aee5d 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -118,6 +118,9 @@ const char *strTag(uint32 tag)
 
 VQADecoder::VQADecoder()
 	: _s(nullptr),
+	  _frameInfo(nullptr),
+	  _videoTrack(nullptr),
+	  _audioTrack(nullptr),
 	  _maxVIEWChunkSize(0),
 	  _maxZBUFChunkSize(0),
 	  _maxAESCChunkSize(0)
@@ -125,6 +128,9 @@ VQADecoder::VQADecoder()
 }
 
 VQADecoder::~VQADecoder() {
+	delete _audioTrack;
+	delete _videoTrack;
+	delete[] _frameInfo;
 }
 
 bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
@@ -172,10 +178,7 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
 	} while (chd.id != kFINF);
 
 	_videoTrack = new VQAVideoTrack(this);
-	// addTrack(_videoTrack);
-
 	_audioTrack = new VQAAudioTrack(this);
-	// addTrack(_audioTrack);
 
 	/*
 	for (int i = 0; i != _loopInfo.loopCount; ++i) {
@@ -559,6 +562,8 @@ VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
 	delete[] _zbufChunk;
 	delete[] _vpointer;
 
+	if (_surface)
+		_surface->free();
 	delete _surface;
 }
 
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 110ca70..ca7e067 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -107,8 +107,12 @@ private:
 		Loop   *loops;
 
 		LoopInfo()
-			: loopCount(0)
+			: loopCount(0),
+			  loops(nullptr)
 		{}
+		~LoopInfo() {
+			delete[] loops;
+		}
 	};
 
 	struct ClipInfo


Commit: 2a60ddfd750a720a99a040f0094afa67f9de8429
    https://github.com/scummvm/scummvm/commit/2a60ddfd750a720a99a040f0094afa67f9de8429
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:35+02:00

Commit Message:
BLADERUNNER: Fix memory leaks in Image

Changed paths:
    engines/bladerunner/image.cpp
    engines/bladerunner/image.h



diff --git a/engines/bladerunner/image.cpp b/engines/bladerunner/image.cpp
index 42070bc..157e443 100644
--- a/engines/bladerunner/image.cpp
+++ b/engines/bladerunner/image.cpp
@@ -34,6 +34,10 @@ Image::Image(BladeRunnerEngine *vm)
 {
 }
 
+Image::~Image() {
+	_surface.free();
+}
+
 bool Image::open(const Common::String &name) {
 	Common::SeekableReadStream *stream = _vm->getResourceStream(name);
 	if (!stream) {
@@ -67,6 +71,7 @@ bool Image::open(const Common::String &name) {
 	_surface.init(width, height, 2*width, data, pixelFormat);
 
 	delete[] buf;
+	delete stream;
 
 	return true;
 }
diff --git a/engines/bladerunner/image.h b/engines/bladerunner/image.h
index 3980ff4..75991d0 100644
--- a/engines/bladerunner/image.h
+++ b/engines/bladerunner/image.h
@@ -37,6 +37,7 @@ class Image {
 	Graphics::Surface  _surface;
 public:
 	Image(BladeRunnerEngine *vm);
+	~Image();
 
 	bool open(const Common::String &name);
 	void copyToSurface(Graphics::Surface *surface) const;


Commit: 97207bfc532f3d17140a9e0767e5431c0e79da70
    https://github.com/scummvm/scummvm/commit/97207bfc532f3d17140a9e0767e5431c0e79da70
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:36+02:00

Commit Message:
BLADERUNNER: Fix memory leaks in Script

Changed paths:
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 948e8b8..540d431 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -34,6 +34,10 @@ bool Script::open(const Common::String &name) {
 	return false;
 }
 
+Script::~Script() {
+	delete _currentScript;
+}
+
 void Script::InitializeScene() {
 	_inScriptCounter++;
 	_currentScript->InitializeScene();
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 2bb52a8..83fd78d 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -41,6 +41,7 @@ public:
 		  _inScriptCounter(0),
 		  _currentScript(nullptr)
 	{}
+	~Script();
 
 	bool open(const Common::String &name);
 


Commit: 86b4850d6c64487f7eb15a7cd4cb78daaa58526d
    https://github.com/scummvm/scummvm/commit/86b4850d6c64487f7eb15a7cd4cb78daaa58526d
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:36+02:00

Commit Message:
BLADERUNNER: Fix memory leaks in GameInfo

Changed paths:
    engines/bladerunner/gameinfo.cpp



diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index 2d5879d..712d548 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -106,7 +106,9 @@ bool GameInfo::open(const Common::String &name) {
 			debug("%2d: %s.VQA", i, _outtakes[i]);
 	}
 
-	return !s->err();
+	bool err = s->err();
+	delete s;
+	return !err;
 }
 
 } // End of namespace BladeRunner


Commit: 303aba7dd109a3a6dfde34fd0191b53a5d6d7f67
    https://github.com/scummvm/scummvm/commit/303aba7dd109a3a6dfde34fd0191b53a5d6d7f67
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:36+02:00

Commit Message:
BLADERUNNER: tlk_id shouldn't read directly from name

Changed paths:
    engines/bladerunner/archive.cpp



diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
index 93c122f..4e355e8 100644
--- a/engines/bladerunner/archive.cpp
+++ b/engines/bladerunner/archive.cpp
@@ -108,13 +108,13 @@ int32 tlk_id(const Common::String &name) {
 	for (uint i = 0; i != name.size() && i < 12u; ++i)
 		buffer[i] = (char)toupper(name[i]);
 
-	int actor_id  =   10 * (name[0] - '0') +
-	                       (name[1] - '0');
+	int actor_id  =   10 * (buffer[0] - '0') +
+	                       (buffer[1] - '0');
 
-	int speech_id = 1000 * (name[3] - '0') +
-	                 100 * (name[4] - '0') +
-	                  10 * (name[5] - '0') +
-	                       (name[6] - '0');
+	int speech_id = 1000 * (buffer[3] - '0') +
+	                 100 * (buffer[4] - '0') +
+	                  10 * (buffer[5] - '0') +
+	                       (buffer[6] - '0');
 
 	return 10000 * actor_id + speech_id;
 }


Commit: 789bb7a2810a1bee537229862037e1f11396e2e6
    https://github.com/scummvm/scummvm/commit/789bb7a2810a1bee537229862037e1f11396e2e6
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:36+02:00

Commit Message:
BLADERUNNER: Add Vector and Matrix classes

Changed paths:
  A engines/bladerunner/matrix.cpp
  A engines/bladerunner/matrix.h
  A engines/bladerunner/vector.h
    engines/bladerunner/module.mk



diff --git a/engines/bladerunner/matrix.cpp b/engines/bladerunner/matrix.cpp
new file mode 100644
index 0000000..a55271e
--- /dev/null
+++ b/engines/bladerunner/matrix.cpp
@@ -0,0 +1,169 @@
+/* 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 "bladerunner/matrix.h"
+
+#include "common/scummsys.h"
+
+namespace BladeRunner {
+
+Matrix3x2::Matrix3x2()
+{
+	for (int r = 0; r != 2; ++r)
+		for (int c = 0; c != 3; ++c)
+			_m[r][c] = (r == c) ? 1.0f : 0.0f;
+}
+
+Matrix3x2::Matrix3x2(float d[6])
+{
+	for (int r = 0; r != 2; ++r)
+		for (int c = 0; c != 3; ++c)
+			_m[r][c] = d[r*3+c];
+}
+
+Matrix3x2::Matrix3x2(
+	float m00, float m01, float m02,
+	float m10, float m11, float m12)
+{
+	_m[0][0] = m00;
+	_m[0][1] = m01;
+	_m[0][2] = m02;
+	_m[1][0] = m10;
+	_m[1][1] = m11;
+	_m[1][2] = m12;
+}
+
+Matrix4x3::Matrix4x3()
+{
+	for (int r = 0; r != 3; ++r)
+		for (int c = 0; c != 4; ++c)
+			_m[r][c] = (r == c) ? 1.0f : 0.0f;
+}
+
+Matrix4x3::Matrix4x3(float d[12])
+{
+	for (int r = 0; r != 3; ++r)
+		for (int c = 0; c != 4; ++c)
+			_m[r][c] = d[r*4+c];
+}
+
+Matrix4x3::Matrix4x3(
+	float m00, float m01, float m02, float m03,
+	float m10, float m11, float m12, float m13,
+	float m20, float m21, float m22, float m23)
+{
+	_m[0][0] = m00;
+	_m[0][1] = m01;
+	_m[0][2] = m02;
+	_m[0][3] = m03;
+	_m[1][0] = m10;
+	_m[1][1] = m11;
+	_m[1][2] = m12;
+	_m[1][3] = m13;
+	_m[2][0] = m20;
+	_m[2][1] = m21;
+	_m[2][2] = m22;
+	_m[2][3] = m23;
+}
+
+Matrix4x3 rotationMatrixX(float angle)
+{
+	float ca = cos(angle);
+	float sa = sin(angle);
+
+	return Matrix4x3( 1.0f, 0.0f, 0.0f, 0.0f,
+	                  0.0f,   ca,   sa, 0.0f,
+	                  0.0f,  -sa,   ca, 0.0f );
+}
+
+static inline
+void swapRows(double *r1, double *r2)
+{
+	for (int c = 0; c != 8; ++c)
+	{
+		double t = r1[c];
+		r1[c] = r2[c];
+		r2[c] = t;
+	}
+}
+
+static inline
+void subtractRow(double *r1, double factor, double *r2)
+{
+	for (int c = 0; c != 8; ++c)
+		r1[c] -= factor * r2[c];
+}
+
+static inline
+void divideRow(double *r1, double d)
+{
+	for (int c = 0; c != 8; ++c)
+		r1[c] /= d;
+}
+
+Matrix4x3 invertMatrix(const Matrix4x3 &m)
+{
+	double w[3][8];
+
+	for (int r = 0; r != 3; ++r) {
+		for (int c = 0; c != 4; ++c) {
+			w[r][c] = m(r, c);
+			w[r][c+4] = (r == c) ? 1.0 : 0.0;
+		}
+	}
+
+	if (w[0][0] == 0.0) {
+		if (w[1][0] != 0.0)
+			swapRows(w[0], w[1]);
+		else
+			swapRows(w[0], w[2]);
+	}
+	divideRow(w[0], w[0][0]);
+	subtractRow(w[1], w[1][0], w[0]);
+	subtractRow(w[2], w[2][0], w[0]);
+
+	if (w[1][1] == 0.0)
+		swapRows(w[1], w[2]);
+
+	divideRow(w[1], w[1][1]);
+	subtractRow(w[0], w[0][1], w[1]);
+	subtractRow(w[2], w[2][1], w[1]);
+
+	divideRow(w[2], w[2][2]);
+	subtractRow(w[0], w[0][2], w[2]);
+	subtractRow(w[1], w[1][2], w[2]);
+
+	for (int r = 0; r != 3; ++r) {
+		w[r][7] = -w[r][3];
+		w[r][3] = 0.0;
+	}
+
+	Matrix4x3 result;
+
+	for (int r = 0; r != 3; ++r)
+		for (int c = 0; c != 4; ++c)
+			result(r, c) = float(w[r][c+4]);
+
+	return result;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/matrix.h b/engines/bladerunner/matrix.h
new file mode 100644
index 0000000..64c3070
--- /dev/null
+++ b/engines/bladerunner/matrix.h
@@ -0,0 +1,133 @@
+/* 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 BLADERUNNER_MATRIX_H
+#define BLADERUNNER_MATRIX_H
+
+#include "bladerunner/vector.h"
+
+namespace BladeRunner {
+
+class Matrix3x2
+{
+public:
+	float _m[2][3];
+
+	Matrix3x2();
+	Matrix3x2(float d[6]);
+	Matrix3x2(
+		float m00, float m01, float m02,
+		float m10, float m11, float m12);
+
+	      float &operator()(int r, int c)       { assert(r >= 0 && r < 2); assert(c >= 0 && c < 3); return _m[r][c]; }
+	const float &operator()(int r, int c) const { assert(r >= 0 && r < 2); assert(c >= 0 && c < 3); return _m[r][c]; }
+};
+
+inline
+Matrix3x2 operator*(const Matrix3x2 &a, const Matrix3x2 &b)
+{
+	Matrix3x2 t;
+
+	t(0,0) = a(0,0)*b(0,0) + a(0,1)*b(1,0);
+	t(0,1) = a(0,0)*b(0,1) + a(0,1)*b(1,1);
+	t(0,2) = a(0,0)*b(0,2) + a(0,1)*b(1,2) + a(0,2);
+	t(1,0) = a(1,0)*b(0,0) + a(1,1)*b(1,0);
+	t(1,1) = a(1,0)*b(0,1) + a(1,1)*b(1,1);
+	t(1,2) = a(1,0)*b(0,2) + a(1,1)*b(1,2) + a(1,2);
+
+	return t;
+}
+
+inline
+Matrix3x2 operator+(const Matrix3x2 &a, Vector2 b)
+{
+	Matrix3x2 t(a);
+
+	t(0,2) += b.x;
+	t(1,2) += b.y;
+
+	return t;
+}
+
+inline
+Vector2 operator*(const Matrix3x2 &a, Vector2 b)
+{
+	Vector2 t;
+
+	t.x = a(0,0) * b.x + a(0,1) * b.y + a(0,2);
+	t.y = a(1,0) * b.x + a(1,1) * b.y + a(1,2);
+
+	return t;
+}
+
+class Matrix4x3
+{
+public:
+	float _m[3][4];
+
+	Matrix4x3();
+	Matrix4x3(float d[12]);
+	Matrix4x3(
+		float m00, float m01, float m02, float m03,
+		float m10, float m11, float m12, float m13,
+		float m20, float m21, float m22, float m23);
+
+	      float &operator()(int r, int c)       { assert(r >= 0 && r < 3); assert(c >= 0 && c < 4); return _m[r][c]; }
+	const float &operator()(int r, int c) const { assert(r >= 0 && r < 3); assert(c >= 0 && c < 4); return _m[r][c]; }
+
+};
+
+Matrix4x3 invertMatrix(const Matrix4x3 &m);
+Matrix4x3 rotationMatrixX(float angle);
+
+inline
+Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b)
+{
+	Matrix4x3 t;
+
+	for (int i = 0; i !=3; ++i)
+	{
+		// printf("t(%d,0) = %7.2f*%7.2f + %7.2f*%7.2f + %7.2f*%7.2f\n", i, a(i,0), b(0,0), a(i,0), b(1,0), a(i,0), b(2,0));
+		t(i,0) = a(i,0)*b(0,0) + a(i,1)*b(1,0) + a(i,2)*b(2,0);
+		t(i,1) = a(i,0)*b(0,1) + a(i,1)*b(1,1) + a(i,2)*b(2,1);
+		t(i,2) = a(i,0)*b(0,2) + a(i,1)*b(1,2) + a(i,2)*b(2,2);
+		t(i,3) = a(i,0)*b(0,3) + a(i,1)*b(1,3) + a(i,2)*b(2,3) + a(i,3);
+	}
+
+	return t;
+}
+
+inline
+Vector3 operator*(const Matrix4x3 &m, const Vector3 &v)
+{
+	Vector3 r;
+
+	r.x = m(0, 0) * v.x + m(0, 1) * v.y + m(0, 2) * v.z + m(0, 3);
+	r.y = m(1, 0) * v.x + m(1, 1) * v.y + m(1, 2) * v.z + m(1, 3);
+	r.z = m(2, 0) * v.x + m(2, 1) * v.y + m(2, 2) * v.z + m(2, 3);
+
+	return r;
+}
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 752543b..3d01448 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -10,6 +10,7 @@ MODULE_OBJS = \
 	detection.o \
 	gameinfo.o \
 	image.o \
+	matrix.o \
 	outtake.o \
 	scene.o \
 	script/rc01.o \
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
new file mode 100644
index 0000000..3b85da4
--- /dev/null
+++ b/engines/bladerunner/vector.h
@@ -0,0 +1,128 @@
+/* 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 BLADERUNNER_VECTOR_H
+#define BLADERUNNER_VECTOR_H
+
+#include "common/types.h"
+
+namespace BladeRunner {
+
+class Vector2
+{
+public:
+	float x;
+	float y;
+
+	Vector2()
+		: x(0.0), y(0.0)
+	{}
+
+	Vector2(float ax, float ay)
+		: x(ax), y(ay)
+	{}
+};
+
+class Vector3
+{
+public:
+	float x;
+	float y;
+	float z;
+
+	Vector3()
+		: x(0.0), y(0.0), z(0.0)
+	{}
+
+	Vector3(float ax, float ay, float az)
+		: x(ax), y(ay), z(az)
+	{}
+};
+
+inline
+Vector3 operator+(Vector3 a, Vector3 b)
+{
+	return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
+}
+
+inline
+Vector3 operator-(Vector3 a, Vector3 b)
+{
+	return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
+}
+
+inline
+Vector3 operator*(float f, Vector3 v)
+{
+	return Vector3(f * v.x, f * v.y, f * v.z);
+}
+
+class Vector4
+{
+public:
+	float x;
+	float y;
+	float z;
+	float w;
+
+	Vector4()
+		: x(0.0), y(0.0), z(0.0), w(0.0)
+	{}
+
+	Vector4(float ax, float ay, float az, float aw)
+		: x(ax), y(ay), z(az), w(aw)
+	{}
+};
+
+inline
+Vector4 operator+(Vector4 a, Vector4 b)
+{
+	return Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
+}
+
+inline
+Vector4 operator-(Vector4 a, Vector4 b)
+{
+	return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
+}
+
+inline
+Vector4 operator*(float f, Vector4 v)
+{
+	return Vector4(f * v.x, f * v.y, f * v.z, f * v.w);
+}
+
+inline
+Vector4 operator*(Vector4 v, float f)
+{
+	return Vector4(f * v.x, f * v.y, f * v.z, f * v.w);
+}
+
+inline
+Vector4 operator/(Vector4 a, Vector4 b)
+{
+	return Vector4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
+}
+
+} // End of namespace BladeRunner
+
+#endif


Commit: 7ab0985ca8526d29c0d7f076746045b39267a23c
    https://github.com/scummvm/scummvm/commit/7ab0985ca8526d29c0d7f076746045b39267a23c
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-09-29T22:33:36+02:00

Commit Message:
COMMON: Add ReadFloatLE to Common::ReadStream

Changed paths:
    common/stream.h



diff --git a/common/stream.h b/common/stream.h
index c6c300f..e0ffc47 100644
--- a/common/stream.h
+++ b/common/stream.h
@@ -402,6 +402,22 @@ public:
 #endif
 
 	/**
+	 * Read a 32-bit floating point value stored in little endian (LSB first)
+	 * order from the stream and return it.
+	 * Performs no error checking. The return value is undefined
+	 * if a read error occurred (for which client code can check by
+	 * calling err() and eos() ).
+	 */
+	FORCEINLINE float readFloatLE() {
+		uint32 n = readUint32LE();
+		float f;
+
+		memcpy(&f, &n, 4);
+
+		return f;
+	}
+
+	/**
 	 * Read the specified amount of data into a malloc'ed buffer
 	 * which then is wrapped into a MemoryReadStream.
 	 * The returned stream might contain less data than requested,


Commit: d9453057abff91a30ff4fb427cadc21b5666c350
    https://github.com/scummvm/scummvm/commit/d9453057abff91a30ff4fb427cadc21b5666c350
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:37+02:00

Commit Message:
BLADERUNNER: Add View matrix loading

Changed paths:
  A engines/bladerunner/view.cpp
  A engines/bladerunner/view.h
    engines/bladerunner/module.mk
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 3d01448..eae0d95 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS = \
 	script/script.o \
 	set.o \
 	settings.o \
+	view.o \
 	vqa_decoder.o \
 	vqa_player.o
 
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 7cb3b01..2f357e2 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -105,6 +105,7 @@ int Scene::advanceFrame(Graphics::Surface &surface) {
 	int frame = _vqaPlayer.update();
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer.getSurface());
+		_view = _vqaPlayer.getView();
 	}
 	return frame;
 }
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index b69d99d..d7904f2 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -23,6 +23,7 @@
 #ifndef BLADERUNNER_SCENE_H
 #define BLADERUNNER_SCENE_H
 
+#include "bladerunner/view.h"
 #include "bladerunner/vqa_player.h"
 
 namespace BladeRunner {
@@ -41,6 +42,7 @@ public:
 	int         _nextSceneId;
 	int         _frame;
 	bool        _playerWalkedIn;
+	View        _view;
 
 public:
 	Scene(BladeRunnerEngine *vm)
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
new file mode 100644
index 0000000..b3b6ad8
--- /dev/null
+++ b/engines/bladerunner/view.cpp
@@ -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.
+ *
+ */
+
+#include "bladerunner/view.h"
+
+#include "common/debug.h"
+#include "common/stream.h"
+
+namespace BladeRunner {
+
+bool View::read(Common::ReadStream *stream) {
+	uint32 frame;
+	frame = stream->readUint32LE();
+
+	float d[12];
+	for (int i = 0; i != 12; ++i)
+		d[i] = stream->readFloatLE();
+
+	_frameViewMatrix = Matrix4x3(d);
+
+	float fovX = stream->readFloatLE();
+
+	setFovX(fovX);
+	calculateSliceViewMatrix();
+	calculateCameraPosition();
+
+	return true;
+}
+
+void View::setFovX(float fovX) {
+	_fovX = fovX;
+
+	_viewportHalfWidth  = 320.0f;
+	_viewportHalfHeight = 240.0f;
+
+	_viewportDistance = 320.0f / tanf(_fovX / 2.0f);
+}
+
+void View::calculateSliceViewMatrix() {
+	Matrix4x3 m = _frameViewMatrix;
+
+	m = m * rotationMatrixX(float(M_PI) / 2.0f);
+
+	Matrix4x3 a( -1.0f,  0.0f,  0.0f,  0.0f,
+	              0.0f, -1.0f,  0.0f,  0.0f,
+	              0.0f,  0.0f,  1.0f,  0.0f);
+
+	m = a * m;
+
+	_sliceViewMatrix = m;
+}
+
+void View::calculateCameraPosition()
+{
+	Matrix4x3 invertedMatrix = invertMatrix(_sliceViewMatrix);
+
+	_cameraPosition.x = invertedMatrix(0, 3);
+	_cameraPosition.y = invertedMatrix(1, 3);
+	_cameraPosition.z = invertedMatrix(2, 3);
+}
+
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
new file mode 100644
index 0000000..511ea66
--- /dev/null
+++ b/engines/bladerunner/view.h
@@ -0,0 +1,57 @@
+/* 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 BLADERUNNER_VIEW_H
+#define BLADERUNNER_VIEW_H
+
+#include "matrix.h"
+
+namespace Common {
+	class ReadStream;
+}
+
+namespace BladeRunner {
+
+class View {
+public:
+	float     _fovX;
+	Matrix4x3 _frameViewMatrix;
+	Matrix4x3 _sliceViewMatrix;
+	uint32    _frame;
+
+	Vector3   _cameraPosition;
+
+	float     _viewportHalfWidth;
+	float     _viewportHalfHeight;
+	float     _viewportDistance;
+
+	bool read(Common::ReadStream *stream);
+
+private:
+	void setFovX(float fovX);
+	void calculateSliceViewMatrix();
+	void calculateCameraPosition();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index f2aee5d..f5b8c80 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -754,7 +754,8 @@ bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 s
 	if (size != 56)
 		return false;
 
-	s->skip(size);
+	_view.read(s);
+
 	return true;
 }
 
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index ca7e067..132c18a 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -24,6 +24,7 @@
 #define BLADERUNNER_VQA_DECODER_H
 
 #include "bladerunner/aud_decoder.h"
+#include "bladerunner/view.h"
 
 #include "audio/audiostream.h"
 
@@ -51,6 +52,8 @@ public:
 	const Graphics::Surface    *decodeVideoFrame();
 	Audio::SeekableAudioStream *decodeAudioFrame();
 
+	const View &getView() { return _videoTrack->getView(); }
+
 	uint16 numFrames() const { return _header.numFrames; }
 	uint8  frameRate() const { return _header.frameRate; }
 
@@ -158,6 +161,7 @@ private:
 		int getCurFrame() const;
 		int getFrameCount() const;
 		const Graphics::Surface *decodeVideoFrame();
+		const View &getView() { return _view; }
 
 		bool readVQFR(Common::SeekableReadStream *s, uint32 size);
 		bool readVPTR(Common::SeekableReadStream *s, uint32 size);
@@ -198,6 +202,8 @@ private:
 
 		int      _curFrame;
 
+		View     _view;
+
 		void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false);
 		bool decodeFrame(uint16 *frame);
 	};
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 9d96154..2b79ac7 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -64,6 +64,7 @@ int VQAPlayer::update() {
 			if (_hasAudio)
 				queueAudioFrame(_decoder.decodeAudioFrame());
 			_surface = _decoder.decodeVideoFrame();
+			_view = _decoder.getView();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
@@ -86,6 +87,7 @@ int VQAPlayer::update() {
 		_curFrame = _decodedFrame;
 		if (_curFrame >= 0) {
 			_surface = _decoder.decodeVideoFrame();
+			_view = _decoder.getView();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 9e9266e..4d87b59 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -47,6 +47,8 @@ class VQAPlayer {
 	int _loopSpecial;
 	int _loopDefault;
 
+	View _view;
+
 	uint32 _nextFrameTime;
 	bool   _hasAudio;
 	bool   _audioStarted;
@@ -78,6 +80,7 @@ public:
 
 	int  update();
 	const Graphics::Surface *getSurface() const;
+	const View &getView() const { return _view; }
 
 	void setLoopSpecial(int loop, bool wait);
 	void setLoopDefault(int loop);


Commit: 4b181e4bed3af7b7e32a8d4c9209d81ece366554
    https://github.com/scummvm/scummvm/commit/4b181e4bed3af7b7e32a8d4c9209d81ece366554
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:37+02:00

Commit Message:
BLADERUNNER: First pass at slice animation renderer

Z-buffers are not being read from the VQA background yet, so z-buffer
handling is faked for now.

Changed paths:
  A engines/bladerunner/slice_animations.cpp
  A engines/bladerunner/slice_animations.h
  A engines/bladerunner/slice_renderer.cpp
  A engines/bladerunner/slice_renderer.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/module.mk



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 4791be9..7da46f1 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -29,6 +29,8 @@
 #include "bladerunner/scene.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/settings.h"
+#include "bladerunner/slice_animations.h"
+#include "bladerunner/slice_renderer.h"
 #include "bladerunner/vqa_decoder.h"
 
 #include "common/error.h"
@@ -50,9 +52,13 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst) : Engine(syst) {
 	_scene = new Scene(this);
 	_script = new Script(this);
 	_settings = new Settings(this);
+	_sliceAnimations = new SliceAnimations(this);
+	_sliceRenderer = new SliceRenderer(this);
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
+	delete _sliceRenderer;
+	delete _sliceAnimations;
 	delete _settings;
 	delete _script;
 	delete _scene;
@@ -60,6 +66,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	delete _chapters;
 
 	_surface1.free();
+	_surface2.free();
 }
 
 bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
@@ -120,6 +127,18 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
+	r = _sliceAnimations->open("INDEX.DAT");
+	if (!r)
+		return false;
+
+	r = _sliceAnimations->openCoreAnim();
+	if (!r)
+		return false;
+
+	r = _sliceAnimations->openHDFrames();
+	if (!r)
+		return false;
+
 	initChapterAndScene();
 
 	return true;
@@ -201,6 +220,7 @@ void BladeRunnerEngine::gameTick() {
 			_script->SceneFrameAdvanced(frame);
 			backgroundChanged = true;
 		}
+		_surface2.copyFrom(_surface1);
 
 		// TODO: Render overlays (mostly in Replicant)
 		// TODO: Tick Actor AI and Timers (timers in Replicant)
@@ -208,6 +228,16 @@ void BladeRunnerEngine::gameTick() {
 		if (_settings->getNewScene() == -1 || _script->_inScriptCounter /* || in_ai */) {
 
 			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
+
+			// Hardcode McCoy in place to test the slice renderer
+			Vector3 pos(-151.98f, -0.30f, 318.15f);
+			Vector3 draw_pos(pos.x, -pos.z, pos.y + 2);
+			float facing = -1.570796f;
+
+			_sliceRenderer->setView(_scene->_view);
+			_sliceRenderer->setupFrame(19, 1, draw_pos, facing);
+			_sliceRenderer->drawFrame(_surface2);
+
 			// TODO: Draw items (drawing works in Replicant)
 			// TODO: Draw item pickup (understood, drawing works in Replicant)
 			// TODO: Draw dialogue menu
@@ -215,7 +245,7 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Process AUD (audio in Replicant)
 			// TODO: Footstep sound
 
-			_system->copyRectToScreen((const byte *) _surface1.getBasePtr(0, 0), _surface1.pitch, 0, 0, 640, 480);
+			_system->copyRectToScreen((const byte *)_surface2.getBasePtr(0, 0), _surface2.pitch, 0, 0, 640, 480);
 			_system->updateScreen();
 			_system->delayMillis(10);
 		}
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 60d87ef..c3f7eac 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -36,25 +36,30 @@
 namespace BladeRunner {
 
 class Chapters;
+class GameInfo;
 class Scene;
 class Script;
 class Settings;
-class GameInfo;
+class SliceAnimations;
+class SliceRenderer;
 
 class BladeRunnerEngine : public Engine {
 public:
 	bool      _gameIsRunning;
 	bool      _windowIsActive;
 
-	Chapters *_chapters;
-	GameInfo *_gameInfo;
-	Scene    *_scene;
-	Script   *_script;
-	Settings *_settings;
+	Chapters        *_chapters;
+	GameInfo        *_gameInfo;
+	Scene           *_scene;
+	Script          *_script;
+	Settings        *_settings;
+	SliceAnimations *_sliceAnimations;
+	SliceRenderer   *_sliceRenderer;
 
 	int in_script_counter;
 
 	Graphics::Surface _surface1;
+	Graphics::Surface _surface2;
 
 private:
 	static const int kArchiveCount = 10;
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index eae0d95..37ba70b 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -17,6 +17,8 @@ MODULE_OBJS = \
 	script/script.o \
 	set.o \
 	settings.o \
+	slice_animations.o \
+	slice_renderer.o \
 	view.o \
 	vqa_decoder.o \
 	vqa_player.o
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
new file mode 100644
index 0000000..b17e517
--- /dev/null
+++ b/engines/bladerunner/slice_animations.cpp
@@ -0,0 +1,173 @@
+/* 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 "bladerunner/slice_animations.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/debug.h"
+#include "common/file.h"
+#include "common/system.h"
+
+namespace BladeRunner {
+
+bool SliceAnimations::open(const Common::String &name) {
+	Common::File file;
+	if (!file.open(_vm->getResourceStream(name), name))
+		return false;
+
+	_timestamp    = file.readUint32LE();
+	_pageSize     = file.readUint32LE();
+	_pageCount    = file.readUint32LE();
+	_paletteCount = file.readUint32LE();
+
+	if (_timestamp != 0x3457b6f6) // Timestamp: Wed, 29 Oct 1997 22:21:42 GMT
+		return false;
+
+	_palettes.resize(_paletteCount);
+
+	for (uint32 i = 0; i != _paletteCount; ++i) {
+		for (uint32 j = 0; j != 256; ++j) {
+			uint8 color_r = file.readByte();
+			uint8 color_g = file.readByte();
+			uint8 color_b = file.readByte();
+
+			uint16 rgb555 = ((uint16)color_r << 10) |
+			                ((uint16)color_g <<  5) |
+			                 (uint16)color_b;
+
+			_palettes[i][j] = rgb555;
+		}
+	}
+
+	uint32 animationCount = file.readUint32LE();
+	_animations.resize(animationCount);
+
+	for (uint32 i = 0; i != animationCount; ++i) {
+		_animations[i].frameCount = file.readUint32LE();
+		_animations[i].frameSize  = file.readUint32LE();
+		_animations[i].fps        = file.readFloatLE();
+		_animations[i].unk0       = file.readFloatLE();
+		_animations[i].unk1       = file.readFloatLE();
+		_animations[i].unk2       = file.readFloatLE();
+		_animations[i].unk3       = file.readFloatLE();
+		_animations[i].offset     = file.readUint32LE();
+
+#if 0
+		debug("%4d  %6d %6x  %7.2g %7.2g %7.2g %7.2g %7.2g %8x",
+			i,
+			_animations[i].frameCount,
+			_animations[i].frameSize,
+			_animations[i].fps,
+			_animations[i].unk0,
+			_animations[i].unk1,
+			_animations[i].unk2,
+			_animations[i].unk3,
+			_animations[i].offset);
+#endif
+	}
+
+	_pages.resize(_pageCount);
+	for (uint32 i = 0; i != _pageCount; ++i)
+		_pages[i]._data = nullptr;
+
+	return true;
+}
+
+SliceAnimations::~SliceAnimations() {
+	for (uint32 i = 0; i != _pageCount; ++i)
+		free(_pages[i]._data);
+}
+
+bool SliceAnimations::openCoreAnim() {
+	return _coreAnimPageFile.open("COREANIM.DAT");
+}
+
+bool SliceAnimations::openHDFrames() {
+	return _framesPageFile.open("HDFRAMES.DAT");
+}
+
+bool SliceAnimations::PageFile::open(const Common::String &name) {
+	if (!_file.open(name))
+		return false;
+
+	uint32 timestamp = _file.readUint32LE();
+	if (timestamp != _sliceAnimations->_timestamp)
+		return false;
+
+	_pageOffsets.resize(_sliceAnimations->_pageCount);
+	for (uint32 i = 0; i != _sliceAnimations->_pageCount; ++i)
+		_pageOffsets[i] = -1;
+
+	uint32 pageCount  = _file.readUint32LE();
+	uint32 dataOffset = 8 + 4 * pageCount;
+
+	for (uint32 i = 0; i != pageCount; ++i) {
+		uint32 pageNumber = _file.readUint32LE();
+		if (pageNumber == 0xffffffff)
+			continue;
+		_pageOffsets[pageNumber] = dataOffset + i * _sliceAnimations->_pageSize;
+	}
+
+	debug("PageFile::Open: page file \"%s\" opened with %d pages", name.c_str(), pageCount);
+
+	return true;
+}
+
+void *SliceAnimations::PageFile::loadPage(uint32 pageNumber) {
+	if (_pageOffsets[pageNumber] == -1)
+		return nullptr;
+
+	uint32 pageSize = _sliceAnimations->_pageSize;
+
+	// TODO: Retire oldest pages if we exceed some memory limit
+
+	void *data = malloc(pageSize);
+	_file.seek(_pageOffsets[pageNumber], SEEK_SET);
+	uint32 r = _file.read(data, pageSize);
+	assert(r == pageSize);
+
+	return data;
+}
+
+void *SliceAnimations::getFramePtr(uint32 animation, uint32 frame) {
+	assert(frame < _animations[animation].frameCount);
+
+	uint32 frameOffset = _animations[animation].offset + frame * _animations[animation].frameSize;
+	uint32 page        = frameOffset / _pageSize;
+	uint32 pageOffset  = frameOffset % _pageSize;
+
+	if (!_pages[page]._data)
+		_pages[page]._data = _coreAnimPageFile.loadPage(page);
+
+	if (!_pages[page]._data)
+		_pages[page]._data = _framesPageFile.loadPage(page);
+
+	if (!_pages[page]._data)
+		error("Unable to locate page %d for animation %d frame %d", page, animation, frame);
+
+	_pages[page]._lastAccess = _vm->_system->getMillis();
+
+	return (byte*)_pages[page]._data + pageOffset;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
new file mode 100644
index 0000000..cc07b57
--- /dev/null
+++ b/engines/bladerunner/slice_animations.h
@@ -0,0 +1,111 @@
+/* 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 BLADERUNNER_SLICE_ANIMATIONS_H
+#define BLADERUNNER_SLICE_ANIMATIONS_H
+
+#include "common/array.h"
+#include "common/file.h"
+#include "common/str.h"
+#include "common/types.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+struct SlicePalette {
+	uint16 color[256];
+
+	uint16 &operator[](size_t i) { return color[i]; }
+};
+
+class SliceAnimations {
+	friend class SliceRenderer;
+
+	struct Animation
+	{
+		uint32 frameCount;
+		uint32 frameSize;
+		float  fps;
+		float  unk0;
+		float  unk1;
+		float  unk2;
+		float  unk3;
+		uint32 offset;
+	};
+
+	struct Page {
+		void   *_data;
+		uint32 _lastAccess;
+
+		Page()
+			: _data(nullptr)
+		{}
+	};
+
+	struct PageFile {
+		SliceAnimations     *_sliceAnimations;
+		Common::File         _file;
+		Common::Array<int32> _pageOffsets;
+
+		PageFile(SliceAnimations *sliceAnimations)
+			: _sliceAnimations(sliceAnimations)
+		{}
+
+		bool  open(const Common::String &name);
+		void *loadPage(uint32 page);
+	};
+
+	BladeRunnerEngine *_vm;
+
+	uint32 _timestamp;
+	uint32 _pageSize;
+	uint32 _pageCount;
+	uint32 _paletteCount;
+
+	Common::Array<SlicePalette> _palettes;
+	Common::Array<Animation>    _animations;
+	Common::Array<Page>         _pages;
+
+	PageFile _coreAnimPageFile;
+	PageFile _framesPageFile;
+
+public:
+	SliceAnimations(BladeRunnerEngine *vm)
+		: _vm(vm),
+		  _coreAnimPageFile(this),
+		  _framesPageFile(this)
+	{}
+	~SliceAnimations();
+
+	bool open(const Common::String &name);
+
+	bool openCoreAnim();
+	bool openHDFrames();
+
+	SlicePalette &getPalette(int i) { return _palettes[i]; };
+	void *getFramePtr(uint32 animation, uint32 frame);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
new file mode 100644
index 0000000..e8e3ecf
--- /dev/null
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -0,0 +1,412 @@
+/* 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 "bladerunner/slice_renderer.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/slice_animations.h"
+
+#include "common/debug.h"
+#include "common/memstream.h"
+#include "common/rect.h"
+#include "common/util.h"
+
+namespace BladeRunner {
+
+#if 0
+void dump(const char *str, Vector3 v) {
+	debug("%s %g %g %g", str, v.x, v.y, v.z);
+}
+
+void dump(const char *str, Matrix3x2 m) {
+	debug("%s", str);
+	debug("%11.6g %11.6g %11.6g", m(0, 0), m(0, 1), m(0, 2));
+	debug("%11.6g %11.6g %11.6g", m(1, 0), m(1, 1), m(1, 2));
+}
+
+void dump(const char *str, Matrix4x3 m) {
+	debug("%s", str);
+	debug("%11.6g %11.6g %11.6g %11.6g", m(0, 0), m(0, 1), m(0, 2), m(0, 3));
+	debug("%11.6g %11.6g %11.6g %11.6g", m(1, 0), m(1, 1), m(1, 2), m(1, 3));
+	debug("%11.6g %11.6g %11.6g %11.6g", m(2, 0), m(2, 1), m(2, 2), m(2, 3));
+}
+#endif
+
+SliceRenderer::~SliceRenderer() {
+}
+
+void SliceRenderer::setView(const View &view) {
+	_view = view;
+}
+
+void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float facing, float scale) {
+	_animation = animation;
+	_frame = frame;
+	_position = position;
+	_facing = facing;
+	_scale = scale;
+
+	_sliceFramePtr = _vm->_sliceAnimations->getFramePtr(_animation, _frame);
+
+	Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[_animation].frameSize);
+
+	_frameFront.x      = stream.readFloatLE();
+	_frameFront.y      = stream.readFloatLE();
+	_frameSliceHeight  = stream.readFloatLE();
+	_framePos.x        = stream.readFloatLE();
+	_framePos.y        = stream.readFloatLE();
+	_frameBottomZ      = stream.readFloatLE();
+	_framePaletteIndex = stream.readUint32LE();
+	_frameSliceCount   = stream.readUint32LE();
+
+	calculateBoundingRect();
+}
+
+Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
+	assert(_sliceFramePtr);
+
+	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
+	Vector3 viewPos = viewMatrix * _position;
+	float dir = atan2f(viewPos.x, viewPos.z) + _facing;
+	float s = sinf(dir);
+	float c = cosf(dir);
+
+	Matrix3x2 rotation( c, -s, 0.0f,
+	                    s,  c, 0.0f);
+
+	Matrix3x2 viewRotation(viewMatrix(0,0), viewMatrix(0,1), 0.0f,
+	                       viewMatrix(2,0), viewMatrix(2,1), 0.0f);
+
+	return viewRotation * rotation;
+}
+
+void SliceRenderer::calculateBoundingRect() {
+	assert(_sliceFramePtr);
+
+	_minX = 0.0f;
+	_maxX = 0.0f;
+	_minY = 0.0f;
+	_maxY = 0.0f;
+
+	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
+
+	Vector3 frameBottom = Vector3(0.0f, 0.0f, _frameBottomZ);
+	Vector3 frameTop    = Vector3(0.0f, 0.0f, _frameBottomZ + _frameSliceCount * _frameSliceHeight);
+
+	Vector3 bottom = viewMatrix * (_position + frameBottom);
+	Vector3 top    = viewMatrix * (_position + frameTop);
+
+	top = bottom + _scale * (top - bottom);
+
+	if (bottom.z < 0.0f || top.z < 0.0f)
+		return;
+
+	Matrix3x2 facingRotation = calculateFacingRotationMatrix();
+
+	Matrix3x2 m4(_view._viewportDistance / bottom.z,  0.0f, 0.0f,
+	                                           0.0f, 25.5f, 0.0f);
+
+	Matrix3x2 m2(_frameFront.x,          0.0f, _framePos.x,
+	                      0.0f, _frameFront.y, _framePos.y);
+
+	_field_109E = m4 * (facingRotation * m2);
+
+	Vector4 B6(_view._viewportHalfWidth   + top.x / top.z * _view._viewportDistance,
+	           _view._viewportHalfHeight  + top.y / top.z * _view._viewportDistance,
+	           1.0f / top.z,
+	           _frameSliceCount * (1.0f / top.z));
+
+	Vector4 C2(_view._viewportHalfWidth   + bottom.x / bottom.z * _view._viewportDistance,
+	           _view._viewportHalfHeight  + bottom.y / bottom.z * _view._viewportDistance,
+	           1.0f / bottom.z,
+	           0.0f);
+
+	_field_10B6.x = B6.x;
+	_field_10B6.y = B6.y;
+	_field_10B6.z = B6.z;
+	_field_10C2.x = C2.x;
+	_field_10C2.y = C2.y;
+	_field_10C2.z = C2.z;
+	_field_10CE   = B6.w;
+	_field_10D2   = C2.w;
+
+	Vector4 delta = C2 - B6;
+
+	if (delta.y == 0.0f)
+		return;
+
+	/*
+	 * Calculate min and max Y
+	 */
+
+	float screenMinY =   0.0f;
+	float screenMaxY = 479.0f;
+
+	if (B6.y < screenMinY) {
+		if (C2.y < screenMinY)
+			return;
+
+		float f = (screenMinY - B6.y) / delta.y;
+		B6 = B6 + f * delta;
+	} else if (B6.y > screenMaxY) {
+		if (C2.y >= screenMaxY)
+			return;
+
+		float f = (screenMaxY - B6.y) / delta.y;
+		B6 = B6 + f * delta;
+	}
+
+	if (C2.y < screenMinY) {
+		float f = (screenMinY - C2.y) / delta.y;
+		C2 = C2 + f * delta;
+	} else if (C2.y > screenMaxY) {
+		float f = (screenMaxY - C2.y) / delta.y;
+		C2 = C2 + f * delta;
+	}
+
+	int bbox_min_y = (int)MIN(B6.y, C2.y);
+	int bbox_max_y = (int)MAX(B6.y, C2.y) + 1;
+
+	/*
+	 * Calculate min and max X
+	 */
+
+	Matrix3x2 mB6 = _field_109E + Vector2(B6.x, 25.5f / B6.z);
+	Matrix3x2 mC2 = _field_109E + Vector2(C2.x, 25.5f / C2.z);
+
+	float min_x =  640.0f;
+	float max_x =    0.0f;
+
+	for (float i = 0.0f; i <= 256.0f; i += 255.0f)
+	{
+		for (float j = 0.0f; j <= 256.0f; j += 255.0f)
+		{
+			Vector2 v1 = mB6 * Vector2(i, j);
+
+			min_x = MIN(min_x, v1.x);
+			max_x = MAX(max_x, v1.x);
+
+			Vector2 v2 = mC2 * Vector2(i, j);
+
+			min_x = MIN(min_x, v2.x);
+			max_x = MAX(max_x, v2.x);
+		}
+	}
+
+	int bbox_min_x = MIN(MAX((int)min_x,     0), 640);
+	int bbox_max_x = MIN(MAX((int)max_x + 1, 0), 640);
+
+	_field_10B6.x = B6.x;
+	_field_10B6.y = B6.y;
+	_field_10B6.z = B6.z;
+	_field_10C2.x = C2.x;
+	_field_10C2.y = C2.y;
+	_field_10C2.z = C2.z;
+	_field_10CE   = B6.w;
+	_field_10D2   = C2.w;
+
+	_minX = bbox_min_x;
+	_minY = bbox_min_y;
+	_maxX = bbox_max_x;
+	_maxY = bbox_max_y;
+}
+
+struct SliceLineIterator {
+	int _field_00[2][3];
+	int _field_18;
+	int _field_1C;
+
+	float _field_20;
+	float _field_24;
+	float _field_28;
+	float _field_2C;
+	float _field_30;
+	float _field_34;
+	int   _field_38;
+	int   _field_3C;
+
+	void setup(float arg_1,  float arg_2,  float arg_3,
+	           float arg_4,  float arg_5,  float arg_6,
+	           float arg_7,  float arg_8,
+	           Matrix3x2 arg_9);
+	float line();
+	void advance();
+};
+
+void SliceLineIterator::setup(
+	float arg_1,  float arg_2,  float arg_3,
+	float arg_4,  float arg_5,  float arg_6,
+	float arg_7,  float arg_8,
+	Matrix3x2 arg_9)
+{
+	_field_18 = (int)arg_5;
+	_field_1C = (int)arg_2;
+
+	float var_3 = arg_2 - arg_5;
+
+	if (var_3 <= 0.0f || arg_6 <= 0.0f)
+		_field_3C = _field_1C + 1;
+
+	_field_20 = arg_6;
+	_field_24 = (arg_3 - arg_6) / var_3;
+	_field_2C = (arg_7 - arg_8) / var_3;
+	_field_28 = arg_8 - (arg_5 - floor(arg_5) - 1.0f) * _field_2C;
+
+	_field_30 = arg_4;
+	_field_34 = (arg_1 - arg_4) / var_3;
+	_field_38 = (int)((25.5f / var_3) * (1.0f / arg_3 - 1.0f / arg_6) * 64.0);
+	_field_3C = _field_18;
+
+	float var_54 =         _field_30;
+	float var_55 = 25.5f / _field_20;
+
+	Matrix3x2 translate_matrix = Matrix3x2(1.0f, 0.0f, var_54,
+	                                       0.0f, 1.0f, var_55);
+
+	Matrix3x2 scale_matrix = Matrix3x2(65536.0f,  0.0f, 0.0f,
+	                                       0.0f, 64.0f, 0.0f);
+
+	arg_9 = scale_matrix * (translate_matrix * arg_9);
+
+	for (int r = 0; r != 2; ++r)
+		for (int c = 0; c != 3; ++c)
+			_field_00[r][c] = arg_9(r, c);
+}
+
+float SliceLineIterator::line() {
+	float var_0 = 0.0f;
+
+	if (_field_20 != 0.0f)
+		var_0 = _field_28 / _field_20;
+
+	if (var_0 < 0.0)
+		var_0 = 0.0f;
+
+	return var_0;
+}
+
+void SliceLineIterator::advance() {
+	_field_20 += _field_24;
+	_field_28 += _field_2C;
+	_field_30 += _field_34;
+	_field_3C += 1;
+	_field_00[0][2] += (int)(65536.0f * _field_34);
+	_field_00[1][2] += _field_38;
+}
+
+static
+void setupLookupTable(int t[256], int inc) {
+	int v = 0;
+	for (int i = 0; i != 256; ++i) {
+		t[i] = v;
+		v += inc;
+	}
+}
+
+void SliceRenderer::drawFrame(Graphics::Surface &surface) {
+	assert(_sliceFramePtr);
+
+	SliceLineIterator sliceLineIterator;
+	sliceLineIterator.setup(
+		_field_10C2.x, _field_10C2.y, _field_10C2.z,
+		_field_10B6.x, _field_10B6.y, _field_10B6.z,
+		_field_10D2, _field_10CE, // 2 floats
+		_field_109E              // 3x2 matrix
+		);
+
+	setupLookupTable(_t1, sliceLineIterator._field_00[0][0]);
+	setupLookupTable(_t2, sliceLineIterator._field_00[0][1]);
+	setupLookupTable(_t4, sliceLineIterator._field_00[1][0]);
+	setupLookupTable(_t5, sliceLineIterator._field_00[1][1]);
+
+	int frameY = sliceLineIterator._field_18;
+
+	uint16 *frameLinePtr = (uint16*)surface.getPixels() + 640 * frameY;
+
+	while (sliceLineIterator._field_3C <= sliceLineIterator._field_1C) {
+		_c3 = sliceLineIterator._field_00[0][2];
+		_c6 = sliceLineIterator._field_00[1][2];
+
+		float sliceLine = sliceLineIterator.line();
+
+		if (frameY >= 0 && frameY < 480)
+			drawSlice((int)sliceLine, frameLinePtr);
+
+		sliceLineIterator.advance();
+		frameY += 1;
+		frameLinePtr += 640;
+	}
+}
+
+void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr) {
+	if (slice < 0 || slice >= _frameSliceCount)
+		return;
+
+	SlicePalette &palette = _vm->_sliceAnimations->getPalette(_framePaletteIndex);
+
+	byte *p = (byte*)_sliceFramePtr + 0x20 + 4 * slice;
+
+	uint32 polyOffset = READ_LE_UINT32(p);
+
+	p = (byte*)_sliceFramePtr + polyOffset;
+
+	uint32 polyCount = READ_LE_UINT32(p);
+	p += 4;
+
+	int zbufLinePtr[640];
+	for (int i = 0; i != 640; ++i)
+		zbufLinePtr[i] = 65535;
+
+	while (polyCount--) {
+		uint32 vertexCount = READ_LE_UINT32(p);
+		p += 4;
+
+		if (vertexCount == 0)
+			continue;
+
+		uint32 lastVertex = vertexCount - 1;
+		int lastVertexX = MAX((_t1[p[3*lastVertex]] + _t2[p[3*lastVertex+1]] + _c3) >> 16, 0);
+
+		int previousVertexX = lastVertexX;
+
+		while (vertexCount--) {
+			int vertexX = CLIP((_t1[p[0]] + _t2[p[1]] + _c3) >> 16, 0, 640);
+
+			if (vertexX > previousVertexX) {
+				int vertexZ = (_t4[p[0]] + _t5[p[1]] + _c6) >> 6;
+
+				if (vertexZ >= 0 && vertexZ < 65536) {
+					for (int x = previousVertexX; x != vertexX; ++x) {
+						if (vertexZ < zbufLinePtr[x]) {
+							frameLinePtr[x] = palette[p[2]];
+							zbufLinePtr[x] = (int16)vertexZ;
+						}
+					}
+				}
+			}
+			p += 3;
+			previousVertexX = vertexX;
+		}
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
new file mode 100644
index 0000000..2e0fe93
--- /dev/null
+++ b/engines/bladerunner/slice_renderer.h
@@ -0,0 +1,96 @@
+/* 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 BLADERUNNER_SLICE_RENDERER_H
+#define BLADERUNNER_SLICE_RENDERER_H
+
+#include "bladerunner/vector.h"
+#include "bladerunner/view.h"
+#include "bladerunner/matrix.h"
+
+#include "graphics/surface.h"
+
+namespace Common {
+	class MemoryReadStream;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class SliceRenderer {
+	BladeRunnerEngine *_vm;
+
+	int       _animation;
+	int       _frame;
+	Vector3   _position;
+	float     _facing;
+	float     _scale;
+
+	View      _view;
+
+	void                     *_sliceFramePtr;
+
+	// Animation frame data
+	Vector2 _frameFront;
+	float   _frameBottomZ;
+	Vector2 _framePos;
+	float   _frameSliceHeight;
+	uint32  _framePaletteIndex;
+	uint32  _frameSliceCount;
+
+	Matrix3x2 _field_109E;
+	Vector3   _field_10B6;
+	Vector3   _field_10C2;
+	float     _field_10CE;
+	float     _field_10D2;
+	int       _minX;
+	int       _maxX;
+	int       _minY;
+	int       _maxY;
+
+	int _t1[256];
+	int _t2[256];
+	int _c3;
+	int _t4[256];
+	int _t5[256];
+	int _c6;
+
+	Matrix3x2 calculateFacingRotationMatrix();
+	void drawSlice(int slice, uint16 *frameLinePtr);
+
+public:
+	SliceRenderer(BladeRunnerEngine *vm)
+		: _vm(vm)
+	{}
+	~SliceRenderer();
+
+	void setView(const View &view);
+	void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f);
+	void calculateBoundingRect();
+
+	void drawFrame(Graphics::Surface &surface);
+};
+
+} // End of namespace BladeRunner
+
+#endif


Commit: c8f5ded6d94863e3c1deb58961e543703bc934f8
    https://github.com/scummvm/scummvm/commit/c8f5ded6d94863e3c1deb58961e543703bc934f8
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:37+02:00

Commit Message:
BLADERUNNER: SliceAnimation: Avoid using potentially uninitialized variable in destructor

Changed paths:
    engines/bladerunner/slice_animations.cpp



diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index b17e517..6d0347c 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -94,7 +94,7 @@ bool SliceAnimations::open(const Common::String &name) {
 }
 
 SliceAnimations::~SliceAnimations() {
-	for (uint32 i = 0; i != _pageCount; ++i)
+	for (uint32 i = 0; i != _pages.size(); ++i)
 		free(_pages[i]._data);
 }
 


Commit: 74a8b530f196233b287c9775e9c80774c4811058
    https://github.com/scummvm/scummvm/commit/74a8b530f196233b287c9775e9c80774c4811058
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:37+02:00

Commit Message:
BLADERUNNER: Add support for ambient sounds, game flags and variables, and use VQA z-buffer when rendering.

Changed paths:
  A engines/bladerunner/ambient_sounds.cpp
  A engines/bladerunner/ambient_sounds.h
  A engines/bladerunner/audio_player.cpp
  A engines/bladerunner/audio_player.h
  A engines/bladerunner/gameflags.cpp
  A engines/bladerunner/gameflags.h
    engines/bladerunner/archive.cpp
    engines/bladerunner/archive.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/gameinfo.cpp
    engines/bladerunner/gameinfo.h
    engines/bladerunner/module.mk
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/ambient_sounds.cpp b/engines/bladerunner/ambient_sounds.cpp
new file mode 100644
index 0000000..77b8195
--- /dev/null
+++ b/engines/bladerunner/ambient_sounds.cpp
@@ -0,0 +1,216 @@
+/* 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 "bladerunner/ambient_sounds.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/gameinfo.h"
+
+#include "common/debug.h"
+#include "common/system.h"
+
+namespace BladeRunner {
+
+#define NON_LOOPING_SOUNDS 25
+#define LOOPING_SOUNDS      3
+
+AmbientSounds::AmbientSounds(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_nonLoopingSounds = new NonLoopingSound[NON_LOOPING_SOUNDS];
+	_loopingSounds = new LoopingSound[LOOPING_SOUNDS];
+	_ambientVolume = 65;
+
+	for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
+		NonLoopingSound &track = _nonLoopingSounds[i];
+		track.isActive = false;
+	}
+
+	for (int i = 0; i != LOOPING_SOUNDS; ++i) {
+		LoopingSound &track = _loopingSounds[i];
+		track.isActive = false;
+	}
+}
+
+AmbientSounds::~AmbientSounds() {
+	delete[] _nonLoopingSounds;
+	delete[] _loopingSounds;
+}
+
+static inline void sort(int &a, int &b) {
+	if (a > b) {
+		int t = a;
+		a = b;
+		b = t;
+	}
+}
+
+void AmbientSounds::addSound(
+	int id,
+	int timeRangeBegin, int timeRangeEnd,
+	int volumeRangeBegin, int volumeRangeEnd,
+	int unk1RangeBegin, int unk1RangeEnd,
+	int unk2RangeBegin, int unk2RangeEnd,
+	int priority, int unk3)
+{
+	const char *name = _vm->_gameInfo->getSfxTrack(id);
+
+	sort(volumeRangeBegin, volumeRangeEnd);
+	sort(unk1RangeBegin, unk1RangeEnd);
+	sort(unk2RangeBegin, unk2RangeEnd);
+
+	addSoundByName(
+		name,
+		timeRangeBegin, timeRangeEnd,
+		volumeRangeBegin, volumeRangeEnd,
+		unk1RangeBegin, unk1RangeEnd,
+		unk2RangeBegin, unk2RangeEnd,
+		priority, unk3
+	);
+}
+
+void AmbientSounds::addLoopingSound(int sfx_id, int volume, int unk, int fadeInTime) {
+	const char *name = _vm->_gameInfo->getSfxTrack(sfx_id);
+
+	int32 hash = mix_id(name);
+
+	if (findLoopingTrackByHash(hash) >= 0)
+		return;
+
+	int i = findAvailableLoopingTrack();
+	if (i == -1)
+		return;
+
+	int actualVolume = volume * _ambientVolume / 100;
+
+	int balance = 0;
+
+	_vm->_audioPlayer->playAud(name, actualVolume, balance, balance, 100, AudioPlayer::LOOP | AudioPlayer::OVERRIDE_VOLUME);
+}
+
+void AmbientSounds::tick() {
+	uint32 now = g_system->getMillis();
+
+	for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
+		NonLoopingSound &track = _nonLoopingSounds[i];
+
+		if (!track.isActive || track.nextPlayTime > now)
+			continue;
+
+		int pan1, pan2;
+
+		pan1 = _vm->_rnd.getRandomNumberRng(track.pan1begin, track.pan1end);
+		if (track.pan2begin == -101) {
+			pan2 = pan1;
+		} else {
+			pan2 = _vm->_rnd.getRandomNumberRng(track.pan2begin, track.pan2end);
+		}
+
+		track.volume = _vm->_rnd.getRandomNumberRng(track.volume1, track.volume2);
+
+		track.audio_player_track = _vm->_audioPlayer->playAud(
+			track.name,
+			track.volume * _ambientVolume / 100,
+			pan1, pan2,
+			track.priority,
+			AudioPlayer::OVERRIDE_VOLUME
+		);
+
+		track.nextPlayTime = now + _vm->_rnd.getRandomNumberRng(track.time1, track.time2);
+
+	}
+}
+
+int AmbientSounds::findAvailableNonLoopingTrack() {
+	for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
+		if (!_nonLoopingSounds[i].isActive)
+			return i;
+	}
+
+	return -1;
+}
+
+int AmbientSounds::findNonLoopingTrackByHash(int32 hash) {
+	for (int i = 0; i != NON_LOOPING_SOUNDS; ++i) {
+		NonLoopingSound &track = _nonLoopingSounds[i];
+
+		if (track.isActive && track.hash == hash)
+			return i;
+	}
+
+	return -1;
+}
+
+int AmbientSounds::findAvailableLoopingTrack() {
+	for (int i = 0; i != LOOPING_SOUNDS; ++i) {
+		if (!_loopingSounds[i].isActive)
+			return i;
+	}
+
+	return -1;
+}
+
+int AmbientSounds::findLoopingTrackByHash(int32 hash) {
+	for (int i = 0; i != LOOPING_SOUNDS; ++i) {
+		LoopingSound &track = _loopingSounds[i];
+
+		if (track.isActive && track.hash == hash)
+			return i;
+	}
+
+	return -1;
+}
+
+void AmbientSounds::addSoundByName(
+		const char *name,
+		int timeRangeBegin, int timeRangeEnd,
+		int volumeRangeBegin, int volumeRangeEnd,
+		int pan1begin, int pan1end,
+		int pan2begin, int pan2end,
+		int priority, int unk3)
+{
+	int i = findAvailableNonLoopingTrack();
+	if (i < 0)
+		return;
+
+	NonLoopingSound &track = _nonLoopingSounds[i];
+
+	uint32 now = g_system->getMillis();
+
+	track.isActive      = true;
+	strcpy(track.name, name);
+	track.hash          = mix_id(name);
+	track.time1         = 1000 * timeRangeBegin;
+	track.time2         = 1000 * timeRangeEnd;
+	track.nextPlayTime  = now + _vm->_rnd.getRandomNumberRng(track.time1, track.time2);
+	track.volume1       = volumeRangeBegin;
+	track.volume2       = volumeRangeEnd;
+	track.volume        = 0;
+	track.pan1begin     = pan1begin;
+	track.pan1end       = pan1end;
+	track.pan2begin     = pan2begin;
+	track.pan2end       = pan2end;
+	track.priority      = priority;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/ambient_sounds.h b/engines/bladerunner/ambient_sounds.h
new file mode 100644
index 0000000..e5428e9
--- /dev/null
+++ b/engines/bladerunner/ambient_sounds.h
@@ -0,0 +1,120 @@
+/* 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 BLADERUNNER_AMBIENT_SOUNDS_H
+#define BLADERUNNER_AMBIENT_SOUNDS_H
+
+#include "audio/audiostream.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class AmbientSounds {
+	BladeRunnerEngine *_vm;
+
+	struct NonLoopingSound {
+		bool   isActive;
+		char   name[13];
+		int32  hash;
+		int32  audio_player_track;
+		int32  time1;
+		int32  time2;
+		uint32 nextPlayTime;
+		int32  volume1;
+		int32  volume2;
+		int32  volume;
+		int32  pan1begin;
+		int32  pan1end;
+		int32  pan2begin;
+		int32  pan2end;
+		int32  priority;
+	};
+
+	struct LoopingSound {
+		bool  isActive;
+		char  name[13];
+		int32 hash;
+		int32 volume;
+	};
+
+	NonLoopingSound *_nonLoopingSounds;
+	LoopingSound    *_loopingSounds;
+	int              _ambientVolume;
+
+public:
+	AmbientSounds(BladeRunnerEngine *vm);
+	~AmbientSounds();
+
+	void addSound(
+		int id,
+		int timeRangeBegin, int timeRangeEnd,
+		int volumeRangeBegin, int volumeRangeEnd,
+		int pan1begin, int pan1end,
+		int pan2begin, int pan2end,
+		int priority, int unk3
+	);
+	// removeSound
+	// addSpeechSound
+	// removeSpeechSound
+	// playSound
+	// playSpeech
+	// removeAllNonLoopingSounds
+
+	// addLoopingSound
+	void addLoopingSound(int sfx_id, int volume, int unk, int fadeInTime);
+	// adjustLoopingSound
+	// removeLoopingSound
+	// removeAllLoopingSounds
+
+	void tick();
+
+	// setVolume
+	// getVolume
+
+private:
+	int findAvailableNonLoopingTrack();
+	int findNonLoopingTrackByHash(int32 hash);
+
+	int findAvailableLoopingTrack();
+	int findLoopingTrackByHash(int32 hash);
+
+	// stopNonLoopingTrack
+	// stopLoopingTrack
+
+	// saveToSaveGame
+	// initFromSaveGame
+	// addSoundByName
+	// playVolumeAdjustSound
+
+	void addSoundByName(
+		const char *name,
+		int timeRangeBegin, int timeRangeEnd,
+		int volumeRangeBegin, int volumeRangeEnd,
+		int unk1RangeBegin, int unk1RangeEnd,
+		int unk2RangeBegin, int unk2RangeEnd,
+		int priority, int unk3);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
index 4e355e8..051fcd8 100644
--- a/engines/bladerunner/archive.cpp
+++ b/engines/bladerunner/archive.cpp
@@ -80,7 +80,6 @@ bool MIXArchive::isOpen() const {
 
 #define ROL(n) ((n << 1) | ((n >> 31) & 1))
 
-static
 int32 mix_id(const Common::String &name) {
 	char buffer[12] = { 0 };
 
diff --git a/engines/bladerunner/archive.h b/engines/bladerunner/archive.h
index 1225c71..03eda4e 100644
--- a/engines/bladerunner/archive.h
+++ b/engines/bladerunner/archive.h
@@ -60,6 +60,8 @@ private:
 	uint32 indexForId(int32 id) const;
 };
 
+int32 mix_id(const Common::String &name);
+
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
new file mode 100644
index 0000000..293fc56
--- /dev/null
+++ b/engines/bladerunner/audio_player.cpp
@@ -0,0 +1,368 @@
+/* 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 "audio_player.h"
+
+#include "bladerunner/archive.h"
+#include "bladerunner/aud_decoder.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+
+#include "common/array.h"
+#include "common/debug.h"
+#include "common/mutex.h"
+#include "common/stream.h"
+
+namespace Common {
+	class MemoryReadStream;
+}
+
+namespace BladeRunner {
+
+/*
+ * This is a poor imitation of Bladerunner's resource cache
+ */
+class AudioCache {
+	struct cacheItem {
+		int32   hash;
+		int     refs;
+		uint    lastAccess;
+		byte   *data;
+		uint32  size;
+	};
+
+	Common::Mutex            _mutex;
+	Common::Array<cacheItem> _cacheItems;
+
+	uint32 _totalSize;
+	uint32 _maxSize;
+	uint32 _accessCounter;
+public:
+	AudioCache() :
+		_totalSize(0),
+		_maxSize(2457600),
+		_accessCounter(0)
+	{}
+	~AudioCache();
+
+	bool  canAllocate(uint32 size);
+	bool  dropOldest();
+	byte *findByHash(int32 hash);
+	void  storeByHash(int32 hash, Common::SeekableReadStream *stream);
+
+	void  incRef(int32 hash);
+	void  decRef(int32 hash);
+};
+
+AudioCache::~AudioCache() {
+	for (uint i = 0; i != _cacheItems.size(); ++i) {
+		free(_cacheItems[i].data);
+	}
+}
+
+bool AudioCache::canAllocate(uint32 size) {
+	Common::StackLock lock(_mutex);
+
+	return _maxSize - _totalSize >= size;
+}
+
+bool AudioCache::dropOldest() {
+	Common::StackLock lock(_mutex);
+
+	if (_cacheItems.size() == 0)
+		return false;
+
+	uint oldest = 0;
+	for (uint i = 1; i != _cacheItems.size(); ++i) {
+		if (_cacheItems[i].refs == 0 && _cacheItems[i].lastAccess < _cacheItems[oldest].lastAccess)
+			oldest = i;
+	}
+
+	free(_cacheItems[oldest].data);
+	_totalSize -= _cacheItems[oldest].size;
+	_cacheItems.remove_at(oldest);
+	return true;
+}
+
+byte *AudioCache::findByHash(int32 hash) {
+	Common::StackLock lock(_mutex);
+
+	for (uint i = 0; i != _cacheItems.size(); ++i) {
+		if (_cacheItems[i].hash == hash) {
+			_cacheItems[i].lastAccess = _accessCounter++;
+			return _cacheItems[i].data;
+		}
+	}
+
+	return NULL;
+}
+
+void AudioCache::storeByHash(int32 hash, Common::SeekableReadStream *stream) {
+	Common::StackLock lock(_mutex);
+
+	uint32 size = stream->size();
+	byte *data = (byte*)malloc(size);
+	stream->read(data, size);
+
+	cacheItem item = {
+		hash,
+		0,
+		_accessCounter++,
+		data,
+		size
+	};
+
+	_cacheItems.push_back(item);
+	_totalSize += size;
+}
+
+void AudioCache::incRef(int32 hash) {
+	Common::StackLock lock(_mutex);
+
+	for (uint i = 0; i != _cacheItems.size(); ++i) {
+		if (_cacheItems[i].hash == hash) {
+			_cacheItems[i].refs++;
+			return;
+		}
+	}
+	assert(0 && "AudioCache::incRef: hash not found");
+}
+
+void AudioCache::decRef(int32 hash) {
+	Common::StackLock lock(_mutex);
+
+	for (uint i = 0; i != _cacheItems.size(); ++i) {
+		if (_cacheItems[i].hash == hash) {
+			assert(_cacheItems[i].refs > 0);
+			_cacheItems[i].refs--;
+			return;
+		}
+	}
+	assert(0 && "AudioCache::decRef: hash not found");
+}
+
+class AudStream : public Audio::RewindableAudioStream {
+	byte       *_data;
+	byte       *_p;
+	byte       *_end;
+	AudioCache *_cache;
+	int32       _hash;
+	byte        _compressionType;
+	uint16      _deafBlockRemain;
+
+	ADPCMWestwoodDecoder _decoder;
+
+public:
+	AudStream(AudioCache *cache, int32 hash)
+		: _cache(cache), _hash(hash)
+	{
+		_data = _cache->findByHash(_hash);
+		_end = _data + READ_LE_UINT32(_data + 2) + 12;
+		_cache->incRef(_hash);
+
+		assert(_end - _data >= 12);
+
+		_compressionType = *(_data + 11);
+
+		_deafBlockRemain = 0;
+		_p = _data + 12;
+	}
+	~AudStream() {
+		_cache->decRef(_hash);
+	}
+
+	int readBuffer(int16 *buffer, const int numSamples);
+	bool isStereo() const { return false; }
+	int getRate() const { return READ_LE_UINT16(_data); };
+	bool endOfData() const { return _p == _end; }
+	bool rewind();
+};
+
+int AudStream::readBuffer(int16 *buffer, const int numSamples) {
+	int samplesRead = 0;
+
+	assert(numSamples % 2 == 0);
+
+	if (_compressionType == 99) {
+		while (samplesRead < numSamples) {
+			if (_deafBlockRemain == 0) {
+				if (_end - _p == 0)
+					break;
+
+				assert(_end - _p >= 6);
+
+				uint16 blockSize     = READ_LE_UINT16(_p);
+				uint16 blockOutSize  = READ_LE_UINT16(_p + 2);
+				uint32 sig           = READ_LE_UINT32(_p + 4);
+				_p += 8;
+
+				assert(sig == 0xdeaf);
+				assert(_end - _p >= blockSize);
+				assert(blockOutSize = 4 * blockSize);
+
+				_deafBlockRemain = blockSize;
+			}
+
+			assert(_end - _p >= _deafBlockRemain);
+
+			int bytesConsumed = MIN<int>(_deafBlockRemain, (numSamples - samplesRead) / 2);
+
+			_decoder.decode(_p, bytesConsumed, buffer + samplesRead);
+			_p += bytesConsumed;
+			_deafBlockRemain -= bytesConsumed;
+
+			samplesRead += 2 * bytesConsumed;
+		}
+	} else {
+		assert(0 && "readBuffer: Unimplemented");
+	}
+
+	return samplesRead;
+}
+
+bool AudStream::rewind() {
+	_p = _data + 12;
+	_decoder.setParameters(0, 0);
+	return true;
+}
+
+AudioPlayer::AudioPlayer(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_cache = new AudioCache();
+
+	for (int i = 0; i != 6; ++i) {
+		_tracks[i].hash = 0;
+		_tracks[i].priority = 0;
+	}
+}
+
+AudioPlayer::~AudioPlayer() {
+	delete _cache;
+}
+
+bool AudioPlayer::isTrackActive(Track *track)
+{
+	if (!track->isMaybeActive)
+		return false;
+
+	return track->isMaybeActive = _vm->_mixer->isSoundHandleActive(track->soundHandle);
+}
+
+void AudioPlayer::stopAll()
+{
+	for (int i = 0; i != TRACKS; ++i) {
+		_vm->_mixer->stopHandle(_tracks[i].soundHandle);
+	}
+}
+
+void AudioPlayer::fadeAndStopTrack(Track *track, int time)
+{
+	(void)time;
+
+	_vm->_mixer->stopHandle(track->soundHandle);
+}
+
+int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, int panTo, int priority, byte flags) {
+	/* Find first available track or, alternatively, the lowest priority playing track */
+	int    trackId;
+	Track *track = NULL;
+	int    lowestPriority = 100;
+	Track *lowestPriorityTrack = NULL;
+
+	for (int i = 0; i != 6; ++i) {
+		track = &_tracks[i];
+		if (!isTrackActive(track)) {
+			trackId = 1;
+			break;
+		}
+
+		if (track->priority < lowestPriority) {
+			lowestPriority = track->priority;
+			lowestPriorityTrack = track;
+		}
+	}
+
+	/* If there's no available track, stop the lowest priority track if it's lower than
+	 * the new priority
+	 */
+	if (track == NULL && lowestPriority < priority) {
+		fadeAndStopTrack(lowestPriorityTrack, 1);
+		track = lowestPriorityTrack;
+	}
+
+	/* If there's still no available track, give up */
+	if (track == NULL)
+		return -1;
+
+	/* Load audio resource and store in cache. Playback will happen directly from there. */
+	int32 hash = mix_id(name);
+	if (!_cache->findByHash(hash)) {
+		Common::SeekableReadStream *r = _vm->getResourceStream(name);
+		if (!r)
+			return -1;
+
+		int32 size = r->size();
+		while (!_cache->canAllocate(size)) {
+			if (!_cache->dropOldest()) {
+				delete r;
+				return -1;
+			}
+		}
+		_cache->storeByHash(hash, r);
+		delete r;
+	}
+
+	AudStream *audStream = new AudStream(_cache, hash);
+
+	Audio::AudioStream *audioStream = audStream;
+	if (flags & LOOP) {
+		audioStream = new Audio::LoopingAudioStream(audStream, 0, DisposeAfterUse::YES);
+	}
+
+	Audio::SoundHandle soundHandle;
+
+	debug("PlayStream: %s", name.c_str());
+
+	int balance = panFrom;
+
+	_vm->_mixer->playStream(
+		Audio::Mixer::kPlainSoundType,
+		&soundHandle,
+		audioStream,
+		-1,
+		volume * 255 / 100,
+		balance);
+
+	track->isMaybeActive = true;
+	track->soundHandle   = soundHandle;
+	track->priority      = priority;
+	track->hash          = hash;
+	track->volume        = volume;
+
+	return trackId;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/audio_player.h b/engines/bladerunner/audio_player.h
new file mode 100644
index 0000000..32c7dbb
--- /dev/null
+++ b/engines/bladerunner/audio_player.h
@@ -0,0 +1,74 @@
+/* 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 BLADERUNNER_AUDIO_H
+#define BLADERUNNER_AUDIO_H
+
+#include "audio/mixer.h"
+#include "common/str.h"
+#include "common/types.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class AudioCache;
+
+#define TRACKS 6
+
+class AudioPlayer {
+	BladeRunnerEngine *_vm;
+	AudioCache *_cache;
+
+	struct Track {
+		bool               isMaybeActive;
+		Audio::SoundHandle soundHandle;
+		int                priority;
+		int32              hash;
+		int                volume;
+
+		Track()
+			: isMaybeActive(false)
+		{}
+	};
+
+	Track _tracks[TRACKS];
+
+	bool isTrackActive(Track *track);
+	void fadeAndStopTrack(Track *track, int time);
+
+public:
+	AudioPlayer(BladeRunnerEngine *vm);
+	~AudioPlayer();
+
+	enum {
+		LOOP = 1,
+		OVERRIDE_VOLUME = 2
+	};
+
+	int playAud(const Common::String &name, int volume, int panFrom, int panTo, int priority, byte flags = 0);
+
+	void stopAll();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 7da46f1..c1c6574 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -1,3 +1,4 @@
+
 /* ScummVM - Graphic Adventure Engine
  *
  * ScummVM is the legal property of its developers, whose names
@@ -22,8 +23,11 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/audio_player.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
+#include "bladerunner/gameflags.h"
 #include "bladerunner/image.h"
 #include "bladerunner/outtake.h"
 #include "bladerunner/scene.h"
@@ -43,12 +47,19 @@
 
 namespace BladeRunner {
 
-BladeRunnerEngine::BladeRunnerEngine(OSystem *syst) : Engine(syst) {
+BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
+	: Engine(syst),
+	  _rnd("bladerunner")
+{
 	_windowIsActive = true;
 	_gameIsRunning  = true;
 
+	_ambientSounds = new AmbientSounds(this);
+	_audioPlayer = new AudioPlayer(this);
 	_chapters = nullptr;
 	_gameInfo = nullptr;
+	_gameFlags = new GameFlags();
+	_gameVars = nullptr;
 	_scene = new Scene(this);
 	_script = new Script(this);
 	_settings = new Settings(this);
@@ -62,8 +73,12 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	delete _settings;
 	delete _script;
 	delete _scene;
+	delete _gameVars;
+	delete _gameFlags;
 	delete _gameInfo;
 	delete _chapters;
+	delete _audioPlayer;
+	delete _ambientSounds;
 
 	_surface1.free();
 	_surface2.free();
@@ -77,6 +92,8 @@ Common::Error BladeRunnerEngine::run() {
 	Graphics::PixelFormat format = createRGB555();
 	initGraphics(640, 480, true, &format);
 
+	_system->showMouse(true);
+
 	if (!startup())
 		return Common::Error(Common::kUnknownError, "Failed to initialize resources");
 
@@ -111,6 +128,10 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
+	_gameFlags->setFlagCount(_gameInfo->getFlagCount());
+
+	_gameVars = new int[_gameInfo->getGlobalVarCount()];
+
 	_chapters = new Chapters(this);
 	if (!_chapters)
 		return false;
@@ -139,6 +160,9 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
+	_zBuffer1 = new uint16[640 * 480];
+	_zBuffer2 = new uint16[640 * 480];
+
 	initChapterAndScene();
 
 	return true;
@@ -152,6 +176,8 @@ void BladeRunnerEngine::initChapterAndScene() {
 }
 
 void BladeRunnerEngine::shutdown() {
+	_mixer->stopAll();
+
 	if (_chapters) {
 		if (_chapters->hasOpenResources())
 			_chapters->closeResources();
@@ -212,15 +238,18 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: Call Script_Player_Walked_In if applicable
 		// TODO: Gun range announcements
 		// TODO: ZBUF repair dirty rects
-		// TODO: Tick Ambient Audio (in Replicant)
+
+		_ambientSounds->tick();
 
 		bool backgroundChanged = false;
-		int frame = _scene->advanceFrame(_surface1);
+		int frame = _scene->advanceFrame(_surface1, _zBuffer1);
 		if (frame >= 0) {
 			_script->SceneFrameAdvanced(frame);
 			backgroundChanged = true;
 		}
+		(void)backgroundChanged;
 		_surface2.copyFrom(_surface1);
+		memcpy(_zBuffer2, _zBuffer1, 640*480*2);
 
 		// TODO: Render overlays (mostly in Replicant)
 		// TODO: Tick Actor AI and Timers (timers in Replicant)
@@ -230,13 +259,13 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
 
 			// Hardcode McCoy in place to test the slice renderer
-			Vector3 pos(-151.98f, -0.30f, 318.15f);
+			Vector3 pos = _scene->_actorStartPosition;
 			Vector3 draw_pos(pos.x, -pos.z, pos.y + 2);
 			float facing = -1.570796f;
 
 			_sliceRenderer->setView(_scene->_view);
 			_sliceRenderer->setupFrame(19, 1, draw_pos, facing);
-			_sliceRenderer->drawFrame(_surface2);
+			_sliceRenderer->drawFrame(_surface2, _zBuffer2);
 
 			// TODO: Draw items (drawing works in Replicant)
 			// TODO: Draw item pickup (understood, drawing works in Replicant)
@@ -264,7 +293,7 @@ void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container)
 
 	OuttakePlayer player(this);
 
-	player.play(name, noLocalization, -1);
+	player.play(name, noLocalization, container);
 }
 
 bool BladeRunnerEngine::openArchive(const Common::String &name) {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index c3f7eac..5ef2310 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -26,6 +26,7 @@
 #include "bladerunner/archive.h"
 
 #include "common/array.h"
+#include "common/random.h"
 #include "common/stream.h"
 #include "common/types.h"
 
@@ -35,8 +36,11 @@
 
 namespace BladeRunner {
 
+class AmbientSounds;
+class AudioPlayer;
 class Chapters;
 class GameInfo;
+class GameFlags;
 class Scene;
 class Script;
 class Settings;
@@ -48,18 +52,26 @@ public:
 	bool      _gameIsRunning;
 	bool      _windowIsActive;
 
+	AmbientSounds   *_ambientSounds;
+	AudioPlayer     *_audioPlayer;
 	Chapters        *_chapters;
 	GameInfo        *_gameInfo;
+	GameFlags       *_gameFlags;
 	Scene           *_scene;
 	Script          *_script;
 	Settings        *_settings;
 	SliceAnimations *_sliceAnimations;
 	SliceRenderer   *_sliceRenderer;
+	int             *_gameVars;
 
 	int in_script_counter;
 
-	Graphics::Surface _surface1;
-	Graphics::Surface _surface2;
+	Graphics::Surface  _surface1;
+	Graphics::Surface  _surface2;
+	uint16            *_zBuffer1;
+	uint16            *_zBuffer2;
+
+	Common::RandomSource _rnd;
 
 private:
 	static const int kArchiveCount = 10;
diff --git a/engines/bladerunner/gameflags.cpp b/engines/bladerunner/gameflags.cpp
new file mode 100644
index 0000000..3704271
--- /dev/null
+++ b/engines/bladerunner/gameflags.cpp
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/gameflags.h"
+
+#include "common/debug.h"
+
+namespace BladeRunner {
+
+GameFlags::GameFlags()
+	: flags(NULL), flagCount(0)
+{
+}
+
+GameFlags::~GameFlags() {
+	delete[] flags;
+}
+
+void GameFlags::setFlagCount(int count) {
+	assert(count > 0);
+
+	debug("flagCount: %d", count);
+
+	flagCount = count;
+	flags = new uint32[count / 32 + 1];
+
+	for (int i = 0; i <= flagCount; ++i)
+		reset(i);
+}
+
+void GameFlags::set(int flag) {
+	assert(flag >= 0 && flag <= flagCount);
+
+	flags[flag / 32] |= (1 << (flag % 32));
+}
+
+void GameFlags::reset(int flag) {
+	assert(flag >= 0 && flag <= flagCount);
+
+	flags[flag / 32] &= ~(1 << (flag % 32));
+}
+
+bool GameFlags::query(int flag) {
+	assert(flag >= 0 && flag <= flagCount);
+
+	return !!(flags[flag / 32] & (1 << (flag % 32)));
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/gameflags.h b/engines/bladerunner/gameflags.h
new file mode 100644
index 0000000..4df9e5a
--- /dev/null
+++ b/engines/bladerunner/gameflags.h
@@ -0,0 +1,47 @@
+/* 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 BLADERUNNER_GAMEFLAGS_H
+#define BLADERUNNER_GAMEFLAGS_H
+
+#include <common/scummsys.h>
+
+namespace BladeRunner {
+
+class GameFlags {
+	uint32 *flags;
+	int     flagCount;
+
+public:
+	GameFlags();
+	~GameFlags();
+
+	void setFlagCount(int count);
+
+	void set(int flag);
+	void reset(int flag);
+	bool query(int flag);
+};
+
+} // End of namespace BladeRunner
+
+#endif
\ No newline at end of file
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index 712d548..15058c8 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -53,7 +53,7 @@ bool GameInfo::open(const Common::String &name) {
 
 	uint32 unk;
 	_actor_count          = s->readUint32LE();   /* 00 */
-	unk                   = s->readUint32LE();   /* 01 */
+	_player_id            = s->readUint32LE();   /* 01 */
 	_flag_count           = s->readUint32LE();   /* 02 */
 	unk                   = s->readUint32LE();   /* 03 */
 	_global_var_count     = s->readUint32LE();   /* 04 */
diff --git a/engines/bladerunner/gameinfo.h b/engines/bladerunner/gameinfo.h
index 094d157..8c8202b 100644
--- a/engines/bladerunner/gameinfo.h
+++ b/engines/bladerunner/gameinfo.h
@@ -35,6 +35,7 @@ class GameInfo {
 	BladeRunnerEngine *_vm;
 
 	uint32 _actor_count;
+	uint32 _player_id;
 	uint32 _flag_count;
 	uint32 _global_var_count;
 	uint32 _set_names_count;
@@ -59,6 +60,7 @@ public:
 	bool open(const Common::String &name);
 
 	uint32 getActorCount()         { return _actor_count; }
+	uint32 getPlayerId()           { return _player_id; }
 	uint32 getFlagCount()          { return _flag_count; }
 	uint32 getGlobalVarCount()     { return _global_var_count; }
 	uint32 getSetNamesCount()      { return _set_names_count; }
@@ -71,10 +73,10 @@ public:
 	uint32 getCoverWaypointCount() { return _cover_waypoint_count; }
 	uint32 getFleeWaypointCount()  { return _flee_waypoint_count; }
 
-	char *getSetName(int i)        { return _set_names[i]; }
-	char *getSfxTrack(int i)       { return _sfx_tracks[i]; }
-	char *getMusicTrack(int i)     { return _music_tracks[i]; }
-	char *getOuttake(int i)        { return _outtakes[i]; }
+	const char *getSetName(int i)    { return _set_names[i]; }
+	const char *getSfxTrack(int i)   { return _sfx_tracks[i]; }
+	const char *getMusicTrack(int i) { return _music_tracks[i]; }
+	const char *getOuttake(int i)    { return _outtakes[i]; }
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 37ba70b..080eda9 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -1,13 +1,16 @@
 MODULE := engines/bladerunner
 
 MODULE_OBJS = \
+	ambient_sounds.o \
 	archive.o \
 	aud_decoder.o \
+	audio_player.o \
 	bladerunner.o \
 	chapters.o \
 	decompress_lcw.o \
 	decompress_lzo.o \
 	detection.o \
+	gameflags.o \
 	gameinfo.o \
 	image.o \
 	matrix.o \
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 2f357e2..8a5870d 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -101,13 +101,19 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	return true;
 }
 
-int Scene::advanceFrame(Graphics::Surface &surface) {
+int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	int frame = _vqaPlayer.update();
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer.getSurface());
+		memcpy(zBuffer, _vqaPlayer.getZBuffer(), 640*480*2);
 		_view = _vqaPlayer.getView();
 	}
 	return frame;
 }
 
+void Scene::setActorStart(Vector3 position, int facing) {
+	_actorStartPosition = position;
+	_actorStartFacing = facing;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index d7904f2..5856e0b 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -41,6 +41,8 @@ public:
 	int         _nextSetId;
 	int         _nextSceneId;
 	int         _frame;
+	Vector3     _actorStartPosition;
+	int         _actorStartFacing;
 	bool        _playerWalkedIn;
 	View        _view;
 
@@ -58,7 +60,8 @@ public:
 	}
 
 	bool open(int setId, int sceneId, bool isLoadingGame);
-	int advanceFrame(Graphics::Surface &surface);
+	int  advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer);
+	void setActorStart(Vector3 position, int facing);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 560eb24..2fa5778 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -22,35 +22,99 @@
 
 #include "bladerunner/script/script.h"
 
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/audio_player.h"
 #include "bladerunner/bladerunner.h"
 
 namespace BladeRunner {
 
 void ScriptRC01::InitializeScene() {
-	_vm->outtakePlay(28, true);
-	_vm->outtakePlay(41, true);
-	_vm->outtakePlay( 0, false);
-
-	_vm->ISez("Blade Runner");
-	_vm->ISez("");
-	_vm->ISez("From the dark recesses of David Leary's imagination comes a game unlike any");
-	_vm->ISez("other. Blade Runner immerses you in the underbelly of future Los Angeles. Right");
-	_vm->ISez("from the start, the story pulls you in with graphic descriptions of a");
-	_vm->ISez("grandmother doing the shimmy in her underwear, child molestation, brutal");
-	_vm->ISez("cold-blooded slaying of innocent animals, vomiting on desks, staring at a");
-	_vm->ISez("woman's ass, the list goes on. And when the game starts, the real fun begins -");
-	_vm->ISez("shoot down-on-their-luck homeless people and toss them into a dumpster. Watch");
-	_vm->ISez("with sadistic glee as a dog gets blown into chunky, bloody, bits by an");
-	_vm->ISez("explosive, and even murder a shy little girl who loves you. If you think David");
-	_vm->ISez("Leary is sick, and you like sick, this is THE game for you.");
-	_vm->ISez("");
-	_vm->ISez("JW: Don't forget the wasting of helpless mutated cripples in the underground.");
-	_vm->ISez("It's such a beautiful thing!");
-	_vm->ISez("");
-	_vm->ISez("DL: Go ahead.  Just keep beating that snarling pit bull...ignore the foam");
-	_vm->ISez("around his jaws. There's room on the top shelf of my fridge for at least one");
-	_vm->ISez("more head... - Psychotic Dave");
-	_vm->ISez("");
+	if (!Game_Flag_Query(24)) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Outtake_Play(28, 1); // WSTLGO_E.VQA
+		Outtake_Play(41, 1); // BRLOGO_E.VQA
+		Outtake_Play( 0, 0); // INTRO_E.VQA
+		Outtake_Play(33, 1); // DSCENT_E.VQA
+	}
+
+	Game_Flag_Set(9); // Force flag 9 so McCoy will be in view
+	if (Game_Flag_Query(9)) {
+		Setup_Scene_Information(-171.16,  5.55,  27.28, 616);
+	} else if (Game_Flag_Query(114)) {
+		Setup_Scene_Information(-471.98, -0.30, 258.15, 616);
+	} else {
+		Setup_Scene_Information( -10.98, -0.30, 318.15, 616);
+	}
+
+	Scene_Exit_Add_2D_Exit(0, 314, 145, 340, 255, 0);
+	if (Game_Flag_Query(249))
+		Scene_Exit_Add_2D_Exit(1, 482, 226, 639, 280, 2);
+	if (Global_Variable_Query(1) > 1 && Game_Flag_Query(710))
+		Scene_Exit_Add_2D_Exit(2, 0, 0, 10, 479, 3);
+	if (!Game_Flag_Query(186))
+		Scene_2D_Region_Add(0, 0, 294, 296, 479);
+
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(0);
+	Ambient_Sounds_Add_Looping_Sound(54, 30, 0, 1); // CTRAIN1.AUD
+
+	if (!Game_Flag_Query(186)) {
+		Ambient_Sounds_Add_Sound(181, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0470R.AUD
+		Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0480R.AUD
+		Ambient_Sounds_Add_Sound(183, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0500R.AUD
+		Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0540R.AUD
+		Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0560R.AUD
+		Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0870R.AUD
+		Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0900R.AUD
+		Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0940R.AUD
+		Ambient_Sounds_Add_Sound(190, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_0960R.AUD
+		Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_1070R.AUD
+		Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_1080R.AUD
+		Ambient_Sounds_Add_Sound(193, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_1100R.AUD
+		Ambient_Sounds_Add_Sound(194, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_1140R.AUD
+		Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0); // 67_1160R.AUD
+	}
+
+	Ambient_Sounds_Add_Looping_Sound(81, 60, 100, 1); // RCAMBR1.AUD
+	Ambient_Sounds_Add_Sound(82, 5, 30, 30, 50, -100, 100, -101, -101, 0, 0);  // RCCARBY1.AUD
+	Ambient_Sounds_Add_Sound(83, 5, 30, 30, 55, -100, 100, -101, -101, 0, 0);  // RCCARBY2.AUD
+	Ambient_Sounds_Add_Sound(84, 5, 30, 30, 50, -100, 100, -101, -101, 0, 0);  // RCCARBY3.AUD
+	Ambient_Sounds_Add_Sound(67, 10, 50, 30, 50, -100, 100, -101, -101, 0, 0); // SPIN2A.AUD
+	Ambient_Sounds_Add_Sound(87, 20, 80, 20, 40, -100, 100, -101, -101, 0, 0); // SIREN2.AUD
+
+	if (Game_Flag_Query(186)) {
+		if (!Game_Flag_Query(9) && !Game_Flag_Query(114))
+			Scene_Loop_Start_Special(0, 5, 0);
+		if (Game_Flag_Query(249))
+			Scene_Loop_Set_Default(6);
+		else
+			Scene_Loop_Set_Default(10);
+	} else {
+		if (!Game_Flag_Query(9) && !Game_Flag_Query(114))
+			Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+	}
+
+	I_Sez("Blade Runner");
+	I_Sez("");
+	I_Sez("From the dark recesses of David Leary's imagination comes a game unlike any");
+	I_Sez("other. Blade Runner immerses you in the underbelly of future Los Angeles. Right");
+	I_Sez("from the start, the story pulls you in with graphic descriptions of a");
+	I_Sez("grandmother doing the shimmy in her underwear, child molestation, brutal");
+	I_Sez("cold-blooded slaying of innocent animals, vomiting on desks, staring at a");
+	I_Sez("woman's ass, the list goes on. And when the game starts, the real fun begins -");
+	I_Sez("shoot down-on-their-luck homeless people and toss them into a dumpster. Watch");
+	I_Sez("with sadistic glee as a dog gets blown into chunky, bloody, bits by an");
+	I_Sez("explosive, and even murder a shy little girl who loves you. If you think David");
+	I_Sez("Leary is sick, and you like sick, this is THE game for you.");
+	I_Sez("");
+	I_Sez("JW: Don't forget the wasting of helpless mutated cripples in the underground.");
+	I_Sez("It's such a beautiful thing!");
+	I_Sez("");
+	I_Sez("DL: Go ahead.  Just keep beating that snarling pit bull...ignore the foam");
+	I_Sez("around his jaws. There's room on the top shelf of my fridge for at least one");
+	I_Sez("more head... - Psychotic Dave");
+	I_Sez("");
 }
 
 void ScriptRC01::SceneLoaded() {
@@ -58,7 +122,26 @@ void ScriptRC01::SceneLoaded() {
 }
 
 void ScriptRC01::SceneFrameAdvanced(int frame) {
+	if (frame == 1)
+		Sound_Play(118, 40, 0, 0, 50);    // CARDOWN3.AUD
+
+	if (frame == 61 || frame == 362)
+		Sound_Play(116, 100, 80, 80, 50); // SPINOPN4.AUD
+
+	if (frame == 108 || frame == 409)
+		Sound_Play(119, 100, 80, 80, 50); // SPINCLS1.AUD
+
+	if (frame == 183 || frame == 484)
+		Sound_Play(116, 100, 80, 80, 50); // SPINOPN4.AUD
+
+	if (frame == 228 || frame == 523)
+		Sound_Play(119, 100, 80, 80, 50); // SPINCLS1.AUD
+
+	if (frame == 243 || frame == 545)
+		Sound_Play(117, 40, 80, 80, 50);  // CARUP3.AUD
 
+	if (frame == 315)
+		Sound_Play(118, 40, 80, 80, 50);  // CARDOWN3.AUD
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 540d431..9aca48f 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -24,6 +24,13 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/ambient_sounds.h"
+#include "bladerunner/audio_player.h"
+#include "bladerunner/gameinfo.h"
+#include "bladerunner/gameflags.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/vector.h"
+
 namespace BladeRunner {
 
 bool Script::open(const Common::String &name) {
@@ -56,4 +63,86 @@ void Script::SceneFrameAdvanced(int frame) {
 	_inScriptCounter--;
 }
 
+void ScriptBase::Game_Flag_Set(int flag) {
+	_vm->_gameFlags->set(flag);
+}
+
+void ScriptBase::Game_Flag_Reset(int flag) {
+	_vm->_gameFlags->reset(flag);
+}
+
+bool ScriptBase::Game_Flag_Query(int flag) {
+	return _vm->_gameFlags->query(flag);
+}
+
+int ScriptBase::Global_Variable_Set(int var, int value) {
+	return _vm->_gameVars[var] = value;
+}
+
+int ScriptBase::Global_Variable_Reset(int var) {
+	return _vm->_gameVars[var] = 0;
+}
+
+int ScriptBase::Global_Variable_Query(int var) {
+	return _vm->_gameVars[var];
+}
+
+int ScriptBase::Global_Variable_Increment(int var, int inc) {
+	return _vm->_gameVars[var] += inc;
+}
+
+int ScriptBase::Global_Variable_Decrement(int var, int dec) {
+	return _vm->_gameVars[var] -= dec;
+}
+
+void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int priority) {
+	const char *name = _vm->_gameInfo->getSfxTrack(id);
+	_vm->_audioPlayer->playAud(name, volume, panFrom, panTo, priority);
+}
+
+void ScriptBase::Scene_Loop_Set_Default(int a) {
+	debug("Scene_Loop_Set_Default(%d)", a);
+}
+
+void ScriptBase::Scene_Loop_Start_Special(int a, int b, int c) {
+	debug("Scene_Loop_Start_Special(%d, %d, %d)", a, b, c);
+}
+
+void ScriptBase::Outtake_Play(int id, int noLocalization, int container) {
+	_vm->outtakePlay(id, noLocalization, container);
+}
+
+void ScriptBase::Ambient_Sounds_Add_Sound(int id, int time1, int time2, int volume1, int volume2, int pan1begin, int pan1end, int pan2begin, int pan2end, int priority, int unk) {
+	_vm->_ambientSounds->addSound(id, time1, time2, volume1, volume2, pan1begin, pan1end, pan2begin, pan2end, priority, unk);
+}
+
+void ScriptBase::Ambient_Sounds_Remove_All_Non_Looping_Sounds(int time) {
+	// _vm->_ambientSounds->removeAllNonLoopingSounds(time);
+}
+
+void ScriptBase::Ambient_Sounds_Add_Looping_Sound(int id, int volume, int pan, int fadeInTime) {
+	_vm->_ambientSounds->addLoopingSound(id, volume, pan, fadeInTime);
+}
+
+void ScriptBase::Ambient_Sounds_Remove_All_Looping_Sounds(int time) {
+	// _vm->_ambientSounds->removeAllLoopingSounds(time);
+}
+
+void ScriptBase::Setup_Scene_Information(float actorX, float actorY, float actorZ, int actorFacing) {
+	_vm->_scene->setActorStart(Vector3(actorX, actorY, actorZ), actorFacing);
+}
+
+void ScriptBase::Scene_Exit_Add_2D_Exit(int a, int b, int c, int d, int e, int f) {
+	debug("Scene_Exit_Add_2D_Exit(%d, %d, %d, %d, %d, %d)", a, b, c, d, e, f);
+}
+
+void ScriptBase::Scene_2D_Region_Add(int a, int b, int c, int d, int e) {
+	debug("Scene_2D_Region_Add(%d, %d, %d, %d, %d)", a, b, c, d, e);
+}
+
+void ScriptBase::I_Sez(const char *str) {
+	_vm->ISez(str);
+}
+
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 83fd78d..e8bf1c0 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -65,6 +65,42 @@ public:
 	virtual void InitializeScene() = 0;
 	virtual void SceneLoaded() = 0;
 	virtual void SceneFrameAdvanced(int frame) = 0;
+
+protected:
+
+	void Game_Flag_Set(int flag);
+	void Game_Flag_Reset(int flag);
+	bool Game_Flag_Query(int flag);
+
+	int Global_Variable_Set(int, int);
+	int Global_Variable_Reset(int);
+	int Global_Variable_Query(int);
+	int Global_Variable_Increment(int, int);
+	int Global_Variable_Decrement(int, int);
+
+	void Sound_Play(int id, int volume, int panFrom, int panTo, int priority);
+
+	void Scene_Loop_Set_Default(int);
+	void Scene_Loop_Start_Special(int, int, int);
+
+	void Outtake_Play(int id, int noLocalization = false, int container = -1);
+	void Ambient_Sounds_Add_Sound(int id, int time1, int time2, int volume1, int volume2, int pan1begin, int pan1end, int pan2begin, int pan2end, int priority, int unk);
+	// Ambient_Sounds_Remove_Sound
+	// Ambient_Sounds_Add_Speech_Sound
+	// Ambient_Sounds_Remove_Speech_Sound
+	// Ambient_Sounds_Play_Sound
+	// Ambient_Sounds_Play_Speech_Sound
+	void Ambient_Sounds_Remove_All_Non_Looping_Sounds(int time);
+	void Ambient_Sounds_Add_Looping_Sound(int id, int volume, int pan, int fadeInTime);
+	// Ambient_Sounds_Adjust_Looping_Sound
+	// Ambient_Sounds_Remove_Looping_Sound
+	void Ambient_Sounds_Remove_All_Looping_Sounds(int time);
+	void Setup_Scene_Information(float actorX, float actorY, float actorZ, int actorFacing);
+
+	void Scene_Exit_Add_2D_Exit(int, int, int, int, int, int);
+	void Scene_2D_Region_Add(int, int, int, int, int);
+
+	void I_Sez(const char *str);
 };
 
 #define DECLARE_SCRIPT(name) \
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index e8e3ecf..4e2300e 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -322,7 +322,7 @@ void setupLookupTable(int t[256], int inc) {
 	}
 }
 
-void SliceRenderer::drawFrame(Graphics::Surface &surface) {
+void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) {
 	assert(_sliceFramePtr);
 
 	SliceLineIterator sliceLineIterator;
@@ -340,7 +340,8 @@ void SliceRenderer::drawFrame(Graphics::Surface &surface) {
 
 	int frameY = sliceLineIterator._field_18;
 
-	uint16 *frameLinePtr = (uint16*)surface.getPixels() + 640 * frameY;
+	uint16 *frameLinePtr  = (uint16*)surface.getPixels() + 640 * frameY;
+	uint16 *zBufferLinePtr = zbuffer + 640 * frameY;
 
 	while (sliceLineIterator._field_3C <= sliceLineIterator._field_1C) {
 		_c3 = sliceLineIterator._field_00[0][2];
@@ -349,16 +350,17 @@ void SliceRenderer::drawFrame(Graphics::Surface &surface) {
 		float sliceLine = sliceLineIterator.line();
 
 		if (frameY >= 0 && frameY < 480)
-			drawSlice((int)sliceLine, frameLinePtr);
+			drawSlice((int)sliceLine, frameLinePtr, zBufferLinePtr);
 
 		sliceLineIterator.advance();
 		frameY += 1;
 		frameLinePtr += 640;
+		zBufferLinePtr += 640;
 	}
 }
 
-void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr) {
-	if (slice < 0 || slice >= _frameSliceCount)
+void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr) {
+	if (slice < 0 || (uint32)slice >= _frameSliceCount)
 		return;
 
 	SlicePalette &palette = _vm->_sliceAnimations->getPalette(_framePaletteIndex);
@@ -371,11 +373,6 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr) {
 
 	uint32 polyCount = READ_LE_UINT32(p);
 	p += 4;
-
-	int zbufLinePtr[640];
-	for (int i = 0; i != 640; ++i)
-		zbufLinePtr[i] = 65535;
-
 	while (polyCount--) {
 		uint32 vertexCount = READ_LE_UINT32(p);
 		p += 4;
@@ -396,9 +393,10 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr) {
 
 				if (vertexZ >= 0 && vertexZ < 65536) {
 					for (int x = previousVertexX; x != vertexX; ++x) {
+						// debug("\t%04x < %04x", vertexZ, zbufLinePtr[x]);
 						if (vertexZ < zbufLinePtr[x]) {
 							frameLinePtr[x] = palette[p[2]];
-							zbufLinePtr[x] = (int16)vertexZ;
+							zbufLinePtr[x] = (uint16)vertexZ;
 						}
 					}
 				}
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index 2e0fe93..79ebdd8 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -76,7 +76,7 @@ class SliceRenderer {
 	int _c6;
 
 	Matrix3x2 calculateFacingRotationMatrix();
-	void drawSlice(int slice, uint16 *frameLinePtr);
+	void drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr);
 
 public:
 	SliceRenderer(BladeRunnerEngine *vm)
@@ -88,7 +88,7 @@ public:
 	void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f);
 	void calculateBoundingRect();
 
-	void drawFrame(Graphics::Surface &surface);
+	void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index f5b8c80..5c08284 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -196,6 +196,10 @@ const Graphics::Surface *VQADecoder::decodeVideoFrame() {
 	return _videoTrack->decodeVideoFrame();
 }
 
+const uint16 *VQADecoder::decodeZBuffer() {
+	return _videoTrack->decodeZBuffer();
+}
+
 Audio::SeekableAudioStream *VQADecoder::decodeAudioFrame() {
 	return _audioTrack->decodeAudioFrame();
 }
@@ -295,6 +299,7 @@ bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 		debug("_header.unk4         %d", _header.unk4);
 		debug("_header.maxCBFZSize  %d", _header.maxCBFZSize);
 		debug("_header.unk5         %d", _header.unk5);
+		debug("\n");
 	}
 
 	assert(_header.version == 2);
@@ -538,6 +543,7 @@ VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
 	_maxVPTRSize = header->maxVPTRSize;
 	_maxCBFZSize = header->maxCBFZSize;
 	_maxZBUFChunkSize = vqaDecoder->_maxZBUFChunkSize;
+	_zbuffer = nullptr;
 
 	_codebookSize = 0;
 	_codebook  = nullptr;
@@ -644,7 +650,7 @@ bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-#if 0
+#if 1
 static
 int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 {
@@ -654,7 +660,7 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 	uint16 *curzp = curZBUF;
 	uint16 *inp = (uint16*)src;
 
-	while (dstRemain && (inp - (uint16*)src) < (ptrdiff_t)srcLen)
+	while (dstRemain && (inp - (uint16*)src) < (std::ptrdiff_t)srcLen)
 	{
 		uint32 count = FROM_LE_16(*inp++);
 
@@ -692,9 +698,9 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 
 bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size)
 {
-	s->skip(roundup(size));
-	return true;
-#if 0
+	// s->skip(roundup(size));
+	// return true;
+#if 1
 	if (size > _maxZBUFChunkSize) {
 		debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
 		s->skip(roundup(size));
@@ -709,43 +715,47 @@ bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 s
 
 	uint32 remain = size - 16;
 
-	if (width != width || height != height)
+	if (_width != width || _height != height)
 	{
 		debug("%d, %d, %d, %d", width, height, complete, unk0);
 		s->skip(roundup(remain));
 		return false;
 	}
 
+	_zbufChunkComplete = complete;
+	_zbufChunkSize = remain;
 	s->read(_zbufChunk, roundup(remain));
-
-	if (!_zbuf)
-	{
-		if (!complete) {
-			s->skip(roundup(remain));
-			return false;
-		}
-		_zbuf = new uint16[width * height];
-	}
-
-	if (complete) {
-		size_t zbufOutSize;
-		decompress_lzo1x(_zbufChunk, remain, (uint8*)_zbuf, &zbufOutSize);
-	} else {
-		decodeZBUF_partial(_zbufChunk, _zbuf, remain);
-	}
 #endif
 
 	return true;
 }
 
-#if 0
-bool VQADecoder::VQAVideoTrack::getZBUF(uint16 *zbuf)
+#if 1
+const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 {
-	if (!_zbuf)
-		return false;
+	if (_maxZBUFChunkSize == 0)
+		return nullptr;
+
+	if (!_zbuffer)
+		_zbuffer = new uint16[_width * _height];
+	// {
+		// if (!complete) {
+		// 	return false;
+		// }
+	// }
+
+	if (_zbufChunkComplete) {
+		size_t zbufOutSize;
+		decompress_lzo1x(_zbufChunk, _zbufChunkSize, (uint8*)_zbuffer, &zbufOutSize);
+	} else {
+		decodeZBUF_partial(_zbufChunk, _zbuffer, _zbufChunkSize);
+	}
 
-	memcpy(zbuf, _zbuf, 2 * _header.width * _header.height);
-	return true;
+	// if (!_zbuf)
+	// 	return false;
+
+	// memcpy(zbuf, _zbuffer, 2 * _width * _height);
+	return _zbuffer;
 }
 #endif
 
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 132c18a..8b4293d 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -50,6 +50,7 @@ public:
 	void readNextPacket();
 
 	const Graphics::Surface    *decodeVideoFrame();
+	const uint16               *decodeZBuffer();
 	Audio::SeekableAudioStream *decodeAudioFrame();
 
 	const View &getView() { return _videoTrack->getView(); }
@@ -161,6 +162,7 @@ private:
 		int getCurFrame() const;
 		int getFrameCount() const;
 		const Graphics::Surface *decodeVideoFrame();
+		const uint16 *decodeZBuffer();
 		const View &getView() { return _view; }
 
 		bool readVQFR(Common::SeekableReadStream *s, uint32 size);
@@ -179,6 +181,7 @@ private:
 
 	private:
 		Graphics::Surface *_surface;
+		uint16            *_zbuffer;
 		bool     _hasNewFrame;
 
 		uint16 _numFrames;
@@ -195,6 +198,8 @@ private:
 		uint32   _codebookSize;
 		uint8   *_codebook;
 		uint8   *_cbfz;
+		bool     _zbufChunkComplete;
+		uint32   _zbufChunkSize;
 		uint8   *_zbufChunk;
 
 		uint32   _vpointerSize;
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 2b79ac7..8146c1a 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -64,6 +64,7 @@ int VQAPlayer::update() {
 			if (_hasAudio)
 				queueAudioFrame(_decoder.decodeAudioFrame());
 			_surface = _decoder.decodeVideoFrame();
+			_zBuffer = _decoder.decodeZBuffer();
 			_view = _decoder.getView();
 		}
 
@@ -87,6 +88,7 @@ int VQAPlayer::update() {
 		_curFrame = _decodedFrame;
 		if (_curFrame >= 0) {
 			_surface = _decoder.decodeVideoFrame();
+			_zBuffer = _decoder.decodeZBuffer();
 			_view = _decoder.getView();
 		}
 
@@ -109,6 +111,10 @@ const Graphics::Surface *VQAPlayer::getSurface() const {
 	return _surface;
 }
 
+const uint16 *VQAPlayer::getZBuffer() const {
+	return _zBuffer;
+}
+
 void VQAPlayer::setLoopSpecial(int loop, bool wait) {
 	_loopSpecial = loop;
 	if (!wait)
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 4d87b59..80ebf19 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -39,6 +39,7 @@ class VQAPlayer {
 	Common::SeekableReadStream  *_s;
 	VQADecoder                   _decoder;
 	const Graphics::Surface     *_surface;
+	const uint16                *_zBuffer;
 	Audio::QueuingAudioStream   *_audioStream;
 
 	int _curFrame;
@@ -80,6 +81,7 @@ public:
 
 	int  update();
 	const Graphics::Surface *getSurface() const;
+	const uint16 *getZBuffer() const;
 	const View &getView() const { return _view; }
 
 	void setLoopSpecial(int loop, bool wait);


Commit: 420d7f9ecc1b2281b36e98c036d090ced3b8b891
    https://github.com/scummvm/scummvm/commit/420d7f9ecc1b2281b36e98c036d090ced3b8b891
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:37+02:00

Commit Message:
BLADERUNNER: Remove commented out code

Changed paths:
    engines/bladerunner/vqa_decoder.cpp



diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 5c08284..a6e7e7c 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -650,7 +650,6 @@ bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-#if 1
 static
 int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 {
@@ -694,13 +693,9 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 	}
 	return dstSize - dstRemain;
 }
-#endif
 
 bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size)
 {
-	// s->skip(roundup(size));
-	// return true;
-#if 1
 	if (size > _maxZBUFChunkSize) {
 		debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
 		s->skip(roundup(size));
@@ -725,12 +720,10 @@ bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 s
 	_zbufChunkComplete = complete;
 	_zbufChunkSize = remain;
 	s->read(_zbufChunk, roundup(remain));
-#endif
 
 	return true;
 }
 
-#if 1
 const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 {
 	if (_maxZBUFChunkSize == 0)
@@ -738,11 +731,6 @@ const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 
 	if (!_zbuffer)
 		_zbuffer = new uint16[_width * _height];
-	// {
-		// if (!complete) {
-		// 	return false;
-		// }
-	// }
 
 	if (_zbufChunkComplete) {
 		size_t zbufOutSize;
@@ -751,13 +739,8 @@ const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 		decodeZBUF_partial(_zbufChunk, _zbuffer, _zbufChunkSize);
 	}
 
-	// if (!_zbuf)
-	// 	return false;
-
-	// memcpy(zbuf, _zbuffer, 2 * _width * _height);
 	return _zbuffer;
 }
-#endif
 
 bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
 {


Commit: abf98fca036025fac269f9b03cdb318b921ce804
    https://github.com/scummvm/scummvm/commit/abf98fca036025fac269f9b03cdb318b921ce804
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:37+02:00

Commit Message:
BLADERUNNER: Read set objects and walkboxes

Changed paths:
  A engines/bladerunner/boundingbox.cpp
  A engines/bladerunner/boundingbox.h
    engines/bladerunner/module.mk
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/set.cpp
    engines/bladerunner/set.h



diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
new file mode 100644
index 0000000..10e529b
--- /dev/null
+++ b/engines/bladerunner/boundingbox.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.
+ *
+ */
+
+#include "bladerunner/boundingbox.h"
+
+namespace BladeRunner {
+
+BoundingBox::BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1) {
+	_vertices[0].x = x0;
+	_vertices[0].y = y0;
+	_vertices[0].z = z0;
+
+	_vertices[1].x = x1;
+	_vertices[1].y = y1;
+	_vertices[1].z = z1;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
new file mode 100644
index 0000000..5dda3f0
--- /dev/null
+++ b/engines/bladerunner/boundingbox.h
@@ -0,0 +1,40 @@
+/* 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 BLADERUNNER_BOUNDING_BOX_H
+#define BLADERUNNER_BOUNDING_BOX_H
+
+#include "vector.h"
+
+namespace BladeRunner {
+
+class BoundingBox {
+	Vector3 _vertices[2];
+
+public:
+	BoundingBox() {}
+	BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 080eda9..52fcf90 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS = \
 	aud_decoder.o \
 	audio_player.o \
 	bladerunner.o \
+	boundingbox.o \
 	chapters.o \
 	decompress_lcw.o \
 	decompress_lzo.o \
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 8a5870d..8ec8b59 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -70,8 +70,8 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		_vm->_script->InitializeScene();
 
 	Common::String setResourceName = Common::String::format("%s-MIN.SET", sceneName.c_str());
-	// if (!_set->open(setResourceName))
-	// 	return false;
+	if (!_set->open(setResourceName))
+		return false;
 
 	// TODO: Set view
 	if (isLoadingGame) {
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 5856e0b..3a71fb3 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -23,6 +23,9 @@
 #ifndef BLADERUNNER_SCENE_H
 #define BLADERUNNER_SCENE_H
 
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/set.h"
 #include "bladerunner/view.h"
 #include "bladerunner/vqa_player.h"
 
@@ -34,6 +37,7 @@ class Scene {
 	BladeRunnerEngine *_vm;
 
 public:
+	Set        *_set;
 	int         _setId;
 	int         _sceneId;
 	VQAPlayer   _vqaPlayer;
@@ -49,6 +53,7 @@ public:
 public:
 	Scene(BladeRunnerEngine *vm)
 		: _vm(vm),
+		  _set(new Set(vm)),
 		  _setId(-1),
 		  _sceneId(-1),
 		  _vqaPlayer(vm),
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index 2751c1d..c37b31a 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -24,6 +24,7 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "common/debug.h"
 #include "common/ptr.h"
 #include "common/str.h"
 #include "common/stream.h"
@@ -32,6 +33,18 @@ namespace BladeRunner {
 
 #define kSet0 0x53657430
 
+Set::Set(BladeRunnerEngine *vm) : _vm(vm) {
+	_objectCount = 0;
+	_walkboxCount = 0;
+	_objects = new Object[85];
+	_walkboxes = new Walkbox[95];
+}
+
+Set::~Set() {
+	delete[] _objects;
+	delete[] _walkboxes;
+}
+
 bool Set::open(const Common::String &name) {
 	Common::ScopedPtr<Common::SeekableReadStream> s(_vm->getResourceStream(name));
 
@@ -39,6 +52,57 @@ bool Set::open(const Common::String &name) {
 	if (sig != kSet0)
 		return false;
 
+	s->skip(4); // TODO: LITE length
+
+	_objectCount = s->readUint32LE();
+	assert(_objectCount <= 85);
+
+	for (uint32 i = 0; i != _objectCount; ++i) {
+		s->read(_objects[i]._name, 20);
+
+		float x0, y0, z0, x1, y1, z1;
+		x0 = s->readFloatLE();
+		y0 = s->readFloatLE();
+		z0 = s->readFloatLE();
+		x1 = s->readFloatLE();
+		y1 = s->readFloatLE();
+		z1 = s->readFloatLE();
+
+		_objects[i]._bbox = BoundingBox(x0, y0, z0, x1, y1, z1);
+
+		_objects[i]._isObstacle = s->readByte();
+		_objects[i]._isClickable = s->readByte();
+		_objects[i]._isHotMouse = 0;
+		_objects[i]._isCombatTarget = 0;
+		s->skip(4);
+
+		// debug("OBJECT: %s", _objects[i]._name);
+	}
+
+	_walkboxCount = s->readUint32LE();
+	assert(_walkboxCount <= 95);
+
+	for (uint32 i = 0; i != _walkboxCount; ++i) {
+		float x, y, z;
+
+		s->read(_walkboxes[i]._name, 20);
+		y = s->readFloatLE();
+		_walkboxes[i]._vertexCount = s->readUint32LE();
+
+		assert(_walkboxes[i]._vertexCount <= 8);
+
+		for (uint32 j = 0; j != _walkboxes[i]._vertexCount; ++j) {
+			x = s->readFloatLE();
+			z = s->readFloatLE();
+
+			_walkboxes[i]._vertices[j] = Vector3(x, y, z);
+		}
+
+		// debug("WALKBOX: %s", _walkboxes[i]._name);
+	}
+
+	// TODO: Read LITE
+
 	return true;
 }
 
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index b298278..e7358fd 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -23,6 +23,9 @@
 #ifndef BLADERUNNER_SET_H
 #define BLADERUNNER_SET_H
 
+#include "bladerunner/boundingbox.h"
+
+#include "common/scummsys.h"
 #include "common/str.h"
 
 namespace BladeRunner {
@@ -31,13 +34,36 @@ class BladeRunnerEngine;
 
 class VQADecoder;
 
+struct Object {
+	char        _name[20];
+	BoundingBox _bbox;
+	uint8       _isObstacle;
+	uint8       _isClickable;
+	uint8       _isHotMouse;
+	uint8       _isCombatTarget;
+};
+
+struct Walkbox {
+	char    _name[20];
+	float   _altitude;
+	uint32  _vertexCount;
+	Vector3 _vertices[8];
+};
+
 class Set {
 	BladeRunnerEngine *_vm;
 
+	uint32   _objectCount;
+	uint32   _walkboxCount;
+	Object  *_objects;
+	Walkbox *_walkboxes;
+	int      _walkboxStepSound[85];
+	int      _footstepSoundOverride;
+	float    _unknown[10];
+
 public:
-	Set(BladeRunnerEngine *vm)
-	{
-	}
+	Set(BladeRunnerEngine *vm);
+	~Set();
 
 	bool open(const Common::String &name);
 };


Commit: b83daefd0840e909ebc34c2e0490a897ac95748d
    https://github.com/scummvm/scummvm/commit/b83daefd0840e909ebc34c2e0490a897ac95748d
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:38+02:00

Commit Message:
BLADERUNNER: Stub out init script

Changed paths:
  A engines/bladerunner/script/init.cpp
  A engines/bladerunner/script/init.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/module.mk
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index c1c6574..f6b0b09 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -31,6 +31,7 @@
 #include "bladerunner/image.h"
 #include "bladerunner/outtake.h"
 #include "bladerunner/scene.h"
+#include "bladerunner/script/init.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/settings.h"
 #include "bladerunner/slice_animations.h"
@@ -163,6 +164,9 @@ bool BladeRunnerEngine::startup() {
 	_zBuffer1 = new uint16[640 * 480];
 	_zBuffer2 = new uint16[640 * 480];
 
+	ScriptInit initScript(this);
+	initScript.SCRIPT_Initialize_Game();
+
 	initChapterAndScene();
 
 	return true;
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 52fcf90..15f2890 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -17,6 +17,7 @@ MODULE_OBJS = \
 	matrix.o \
 	outtake.o \
 	scene.o \
+	script/init.o \
 	script/rc01.o \
 	script/script.o \
 	set.o \
diff --git a/engines/bladerunner/script/init.cpp b/engines/bladerunner/script/init.cpp
new file mode 100644
index 0000000..4fe0da8
--- /dev/null
+++ b/engines/bladerunner/script/init.cpp
@@ -0,0 +1,127 @@
+/* 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 "bladerunner/script/init.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+void ScriptInit::SCRIPT_Initialize_Game() {
+	Assign_Player_Gun_Hit_Sounds(0, 517, 518, 519);
+	Assign_Player_Gun_Hit_Sounds(1, 520, 521, 522);
+	Assign_Player_Gun_Hit_Sounds(2, 523, 524, 525);
+
+	Assign_Player_Gun_Miss_Sounds(0, 526, 527, 528);
+	Assign_Player_Gun_Miss_Sounds(1, 529, 530, 531);
+	Assign_Player_Gun_Miss_Sounds(2, 532, 533, 534);
+
+	Init_Globals();
+	Init_Game_Flags();
+	Init_Clues();
+	Init_Clues2();
+	Init_World_Waypoints();
+	Init_SDB();
+	Init_CDB();
+	Init_Spinner();
+	Init_Actor_Friendliness();
+	Init_Combat_Aggressiveness();
+	Init_Actor_Honesty();
+	Init_Actor_Intelligence();
+	Init_Actor_Stability();
+	Init_Actor_Health();
+	Init_Combat_Cover_Waypoints();
+	Init_Combat_Flee_Waypoints();
+	Init_Shadows();
+}
+
+void ScriptInit::Init_Globals() {
+
+}
+
+void ScriptInit::Init_Game_Flags() {
+
+}
+
+void ScriptInit::Init_Clues() {
+
+}
+
+void ScriptInit::Init_Clues2() {
+
+}
+
+void ScriptInit::Init_World_Waypoints() {
+
+}
+
+void ScriptInit::Init_SDB() {
+
+}
+
+void ScriptInit::Init_CDB() {
+
+}
+
+void ScriptInit::Init_Spinner() {
+
+}
+
+void ScriptInit::Init_Actor_Friendliness() {
+
+}
+
+void ScriptInit::Init_Combat_Aggressiveness() {
+
+}
+
+void ScriptInit::Init_Actor_Honesty() {
+
+}
+
+void ScriptInit::Init_Actor_Intelligence() {
+
+}
+
+void ScriptInit::Init_Actor_Stability() {
+
+}
+
+void ScriptInit::Init_Actor_Health() {
+
+}
+
+void ScriptInit::Init_Combat_Cover_Waypoints() {
+
+}
+
+void ScriptInit::Init_Combat_Flee_Waypoints() {
+
+}
+
+void ScriptInit::Init_Shadows() {
+
+}
+
+
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/init.h b/engines/bladerunner/script/init.h
new file mode 100644
index 0000000..27c6fc0
--- /dev/null
+++ b/engines/bladerunner/script/init.h
@@ -0,0 +1,62 @@
+/* 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 BLADERUNNER_SCRIPT_INIT_H
+#define BLADERUNNER_SCRIPT_INIT_H
+
+#include "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class ScriptInit : ScriptBase {
+public:
+	ScriptInit(BladeRunnerEngine *vm)
+		: ScriptBase(vm)
+	{}
+
+	void SCRIPT_Initialize_Game();
+
+private:
+	void Init_Globals();
+	void Init_Game_Flags();
+	void Init_Clues();
+	void Init_Clues2();
+	void Init_World_Waypoints();
+	void Init_SDB();
+	void Init_CDB();
+	void Init_Spinner();
+	void Init_Actor_Friendliness();
+	void Init_Combat_Aggressiveness();
+	void Init_Actor_Honesty();
+	void Init_Actor_Intelligence();
+	void Init_Actor_Stability();
+	void Init_Actor_Health();
+	void Init_Combat_Cover_Waypoints();
+	void Init_Combat_Flee_Waypoints();
+	void Init_Shadows();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 9aca48f..5b19c0c 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -63,6 +63,107 @@ void Script::SceneFrameAdvanced(int frame) {
 	_inScriptCounter--;
 }
 
+// ScriptBase::Preload
+// ScriptBase::Actor_Put_In_Set
+// ScriptBase::Actor_Set_At_XYZ
+// ScriptBase::Actor_Set_At_Waypoint
+// ScriptBase::Region_Check
+// ScriptBase::Object_Query_Click
+// ScriptBase::Object_Do_Ground_Click
+// ScriptBase::Object_Mark_For_Hot_Mouse
+// ScriptBase::Actor_Face_Actor
+// ScriptBase::Actor_Face_Object
+// ScriptBase::Actor_Face_Item
+// ScriptBase::Actor_Face_Waypoint
+// ScriptBase::Actor_Face_XYZ
+// ScriptBase::Actor_Face_Current_Camera
+// ScriptBase::Actor_Face_Heading
+// ScriptBase::Actor_Query_Friendliness_To_Other
+// ScriptBase::Actor_Modify_Friendliness_To_Other
+// ScriptBase::Actor_Set_Friendliness_To_Other
+// ScriptBase::Actor_Set_Honesty
+// ScriptBase::Actor_Set_Intelligence
+// ScriptBase::Actor_Set_Stability
+// ScriptBase::Actor_Set_Combat_Aggressiveness
+// ScriptBase::Actor_Query_Current_HP
+// ScriptBase::Actor_Query_Max_HP
+// ScriptBase::Actor_Query_Combat_Aggressiveness
+// ScriptBase::Actor_Query_Honesty
+// ScriptBase::Actor_Query_Intelligence
+// ScriptBase::Actor_Query_Stability
+// ScriptBase::Actor_Modify_Current_HP
+// ScriptBase::Actor_Modify_Max_HP
+// ScriptBase::Actor_Modify_Combat_Aggressiveness
+// ScriptBase::Actor_Modify_Honesty
+// ScriptBase::Actor_Modify_Intelligence
+// ScriptBase::Actor_Modify_Stability
+// ScriptBase::Actor_Set_Flag_Damage_Anim_If_Moving
+// ScriptBase::Actor_Query_Flag_Damage_Anim_If_Moving
+// ScriptBase::Actor_Combat_AI_Hit_Attempt
+// ScriptBase::Non_Player_Actor_Combat_Mode_On
+// ScriptBase::Non_Player_Actor_Combat_Mode_Off
+// ScriptBase::Actor_Set_Health
+// ScriptBase::Actor_Set_Targetable
+// ScriptBase::Actor_Says
+// ScriptBase::Actor_Says_With_Pause
+// ScriptBase::Actor_Voice_Over
+// ScriptBase::Actor_Start_Speech_Sample
+// ScriptBase::Actor_Start_Voice_Over_Sample
+// ScriptBase::Actor_Query_Which_Set_In
+// ScriptBase::Actor_Query_Is_In_Current_Set
+// ScriptBase::Actor_Query_In_Set
+// ScriptBase::Actor_Query_Inch_Distance_From_Actor
+// ScriptBase::Actor_Query_Inch_Distance_From_Waypoint
+// ScriptBase::Actor_Query_In_Between_Two_Actors
+// ScriptBase::Actor_Set_Goal_Number
+// ScriptBase::Actor_Query_Goal_Number
+// ScriptBase::Actor_Query_XYZ
+// ScriptBase::Actor_Query_Facing_1024
+// ScriptBase::Actor_Set_Frame_Rate_FPS
+// ScriptBase::Slice_Animation_Query_Number_Of_Frames
+// ScriptBase::Actor_Change_Animation_Mode
+// ScriptBase::Actor_Query_Animation_Mode
+// ScriptBase::Loop_Actor_Walk_To_Actor
+// ScriptBase::Loop_Actor_Walk_To_Item
+// ScriptBase::Loop_Actor_Walk_To_Scene_Object
+// ScriptBase::Loop_Actor_Walk_To_Waypoint
+// ScriptBase::Loop_Actor_Walk_To_XYZ
+// ScriptBase::Async_Actor_Walk_To_Waypoint
+// ScriptBase::Async_Actor_Walk_To_XYZ
+// ScriptBase::Actor_Force_Stop_Walking
+// ScriptBase::Loop_Actor_Travel_Stairs
+// ScriptBase::Loop_Actor_Travel_Ladder
+// ScriptBase::Actor_Clue_Add_To_Database
+// ScriptBase::Actor_Clue_Acquire
+// ScriptBase::Actor_Clue_Lose
+// ScriptBase::Actor_Clue_Query
+// ScriptBase::Actor_Clues_Transfer_New_To_Mainframe
+// ScriptBase::Actor_Clues_Transfer_New_From_Mainframe
+// ScriptBase::Actor_Set_Invisible
+// ScriptBase::Actor_Set_Immunity_To_Obstacles
+// ScriptBase::Item_Add_To_World
+// ScriptBase::Item_Remove_From_World
+// ScriptBase::Item_Spin_In_World
+// ScriptBase::Item_Flag_As_Target
+// ScriptBase::Item_Flag_As_Non_Target
+// ScriptBase::Item_Pickup_Spin_Effect
+// ScriptBase::Animation_Open
+// ScriptBase::Animation_Close
+// ScriptBase::Animation_Start
+// ScriptBase::Animation_Stop
+// ScriptBase::Animation_Skip_To_Frame
+// ScriptBase::Delay
+// ScriptBase::Player_Loses_Control
+// ScriptBase::Player_Gains_Control
+// ScriptBase::Player_Set_Combat_Mode
+// ScriptBase::Player_Query_Combat_Mode
+// ScriptBase::Player_Set_Combat_Mode_Access
+// ScriptBase::Player_Query_Current_Set
+// ScriptBase::Player_Query_Current_Scene
+// ScriptBase::Player_Query_Agenda
+// ScriptBase::Player_Set_Agenda
+// ScriptBase::Query_Difficulty_Level
+
 void ScriptBase::Game_Flag_Set(int flag) {
 	_vm->_gameFlags->set(flag);
 }
@@ -75,6 +176,9 @@ bool ScriptBase::Game_Flag_Query(int flag) {
 	return _vm->_gameFlags->query(flag);
 }
 
+// ScriptBase::Set_Enter
+// ScriptBase::Chapter_Enter
+
 int ScriptBase::Global_Variable_Set(int var, int value) {
 	return _vm->_gameVars[var] = value;
 }
@@ -95,11 +199,29 @@ int ScriptBase::Global_Variable_Decrement(int var, int dec) {
 	return _vm->_gameVars[var] -= dec;
 }
 
+// ScriptBase::Random_Query
+
 void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int priority) {
 	const char *name = _vm->_gameInfo->getSfxTrack(id);
 	_vm->_audioPlayer->playAud(name, volume, panFrom, panTo, priority);
 }
 
+// ScriptBase::Sound_Play_Speech_Line
+// ScriptBase::Sound_Left_Footstep_Walk
+// ScriptBase::Sound_Right_Footstep_Walk
+// ScriptBase::Sound_Left_Footstep_Run
+// ScriptBase::Sound_Right_Footstep_Run
+// ScriptBase::Sound_Walk_Shuffle_Stop
+// ScriptBase::Footstep_Sounds_Set
+// ScriptBase::Footstep_Sound_Override_On
+// ScriptBase::Footstep_Sound_Override_Off
+// ScriptBase::Music_Play
+// ScriptBase::Music_Adjust
+// ScriptBase::Music_Stop
+// ScriptBase::Music_Is_Playing
+// ScriptBase::Overlay_Play
+// ScriptBase::Overlay_Remove
+
 void ScriptBase::Scene_Loop_Set_Default(int a) {
 	debug("Scene_Loop_Set_Default(%d)", a);
 }
@@ -116,6 +238,12 @@ void ScriptBase::Ambient_Sounds_Add_Sound(int id, int time1, int time2, int volu
 	_vm->_ambientSounds->addSound(id, time1, time2, volume1, volume2, pan1begin, pan1end, pan2begin, pan2end, priority, unk);
 }
 
+// ScriptBase::Ambient_Sounds_Remove_Sound
+// ScriptBase::Ambient_Sounds_Add_Speech_Sound
+// ScriptBase::Ambient_Sounds_Remove_Speech_Sound
+// ScriptBase::Ambient_Sounds_Play_Sound
+// ScriptBase::Ambient_Sounds_Play_Speech_Sound
+
 void ScriptBase::Ambient_Sounds_Remove_All_Non_Looping_Sounds(int time) {
 	// _vm->_ambientSounds->removeAllNonLoopingSounds(time);
 }
@@ -124,6 +252,9 @@ void ScriptBase::Ambient_Sounds_Add_Looping_Sound(int id, int volume, int pan, i
 	_vm->_ambientSounds->addLoopingSound(id, volume, pan, fadeInTime);
 }
 
+// ScriptBase::Ambient_Sounds_Adjust_Looping_Sound
+// ScriptBase::Ambient_Sounds_Remove_Looping_Sound
+
 void ScriptBase::Ambient_Sounds_Remove_All_Looping_Sounds(int time) {
 	// _vm->_ambientSounds->removeAllLoopingSounds(time);
 }
@@ -132,14 +263,96 @@ void ScriptBase::Setup_Scene_Information(float actorX, float actorY, float actor
 	_vm->_scene->setActorStart(Vector3(actorX, actorY, actorZ), actorFacing);
 }
 
+// ScriptBase::Dialogue_Menu_Appear
+// ScriptBase::Dialogue_Menu_Disappear
+// ScriptBase::Dialogue_Menu_Clear_List
+// ScriptBase::Dialogue_Menu_Add_To_List
+// ScriptBase::Dialogue_Menu_Add_DONE_To_List
+// ScriptBase::Dialogue_Menu_Add_To_List_Never_Repeat_Once_Selected
+// ScriptBase::DM_Add_To_List
+// ScriptBase::DM_Add_To_List_Never_Repeat_Once_Selected
+// ScriptBase::Dialogue_Menu_Remove_From_List
+// ScriptBase::Dialogue_Menu_Query_Input
+// ScriptBase::Dialogue_Menu_Query_List_Size
+
 void ScriptBase::Scene_Exit_Add_2D_Exit(int a, int b, int c, int d, int e, int f) {
 	debug("Scene_Exit_Add_2D_Exit(%d, %d, %d, %d, %d, %d)", a, b, c, d, e, f);
 }
 
+// ScriptBase::Scene_Exit_Remove
+// ScriptBase::Scene_Exits_Disable
+// ScriptBase::Scene_Exits_Enable
+
 void ScriptBase::Scene_2D_Region_Add(int a, int b, int c, int d, int e) {
 	debug("Scene_2D_Region_Add(%d, %d, %d, %d, %d)", a, b, c, d, e);
 }
 
+// ScriptBase::Scene_2D_Region_Remove
+// ScriptBase::World_Waypoint_Set
+// ScriptBase::World_Waypoint_Reset
+// ScriptBase::World_Waypoint_Query_X
+// ScriptBase::World_Waypoint_Query_Y
+// ScriptBase::World_Waypoint_Query_Z
+// ScriptBase::Combat_Cover_Waypoint_Set_Data
+// ScriptBase::Combat_Flee_Waypoint_Set_Data
+// ScriptBase::Police_Maze_Target_Track_Add
+// ScriptBase::Police_Maze_Query_Score
+// ScriptBase::Police_Maze_Zero_Score
+// ScriptBase::Police_Maze_Increment_Score
+// ScriptBase::Police_Maze_Decrement_Score
+// ScriptBase::Police_Maze_Set_Score
+// ScriptBase::Police_Maze_Set_Pause_State
+// ScriptBase::CDB_Set_Crime
+// ScriptBase::CDB_Set_Clue_Asset_Type
+// ScriptBase::SDB_Set_Actor
+// ScriptBase::SDB_Add_Photo_Clue
+// ScriptBase::SDB_Set_Name
+// ScriptBase::SDB_Set_Sex
+// ScriptBase::SDB_Add_Identity_Clue
+// ScriptBase::SDB_Add_MO_Clue
+// ScriptBase::SDB_Add_Whereabouts_Clue
+// ScriptBase::SDB_Add_Replicant_Clue
+// ScriptBase::SDB_Add_Non_Replicant_Clue
+// ScriptBase::SDB_Add_Other_Clue
+// ScriptBase::Spinner_Set_Selectable_Destination_Flag
+// ScriptBase::Spinner_Query_Selectable_Destination_Flag
+// ScriptBase::Spinner_Interface_Choose_Dest
+// ScriptBase::ESPER_Flag_To_Activate
+// ScriptBase::Voight_Kampff_Activate
+// ScriptBase::Elevator_Activate
+// ScriptBase::View_Score_Board
+// ScriptBase::Query_Score
+// ScriptBase::Set_Score
+// ScriptBase::Give_McCoy_Ammo
+
+void ScriptBase::Assign_Player_Gun_Hit_Sounds(int a0, int a1, int a2, int a3) {
+	debug("STUB: Assign_Player_Gun_Hit_Sounds(%d, %d, %d, %d)", a0, a1, a2, a3);
+}
+
+void ScriptBase::Assign_Player_Gun_Miss_Sounds(int a0, int a1, int a2, int a3) {
+	debug("STUB: Assign_Player_Gun_Miss_Sounds(%d, %d, %d, %d)", a0, a1, a2, a3);
+}
+
+// ScriptBase::Disable_Shadows
+// ScriptBase::Query_System_Currently_Loading_Game
+// ScriptBase::Actor_Retired_Here
+// ScriptBase::Clickable_Object
+// ScriptBase::Unclickable_Object
+// ScriptBase::Obstacle_Object
+// ScriptBase::Unobstacle_Object
+// ScriptBase::Obstacle_Flag_All_Objects
+// ScriptBase::Combat_Target_Object
+// ScriptBase::Un_Combat_Target_Object
+// ScriptBase::Set_Fade_Color
+// ScriptBase::Set_Fade_Density
+// ScriptBase::Set_Fog_Color
+// ScriptBase::Set_Fog_Density
+// ScriptBase::ADQ_Flush
+// ScriptBase::ADQ_Add
+// ScriptBase::ADQ_Add_Pause
+// ScriptBase::Game_Over
+// ScriptBase::Autosave_Game
+
 void ScriptBase::I_Sez(const char *str) {
 	_vm->ISez(str);
 }
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index e8bf1c0..008e034 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -28,61 +28,148 @@
 namespace BladeRunner {
 
 class BladeRunnerEngine;
-class ScriptBase;
-
-class Script {
-public:
-	BladeRunnerEngine *_vm;
-	int                _inScriptCounter;
-	ScriptBase        *_currentScript;
-
-	Script(BladeRunnerEngine *vm)
-		: _vm(vm),
-		  _inScriptCounter(0),
-		  _currentScript(nullptr)
-	{}
-	~Script();
-
-	bool open(const Common::String &name);
-
-	void InitializeScene();
-	void SceneLoaded();
-	void SceneFrameAdvanced(int frame);
-};
 
 class ScriptBase {
 protected:
 	BladeRunnerEngine *_vm;
 
+public:
 	ScriptBase(BladeRunnerEngine *vm)
 		: _vm(vm)
 	{}
-
-public:
 	virtual ~ScriptBase()
 	{}
 
-	virtual void InitializeScene() = 0;
-	virtual void SceneLoaded() = 0;
-	virtual void SceneFrameAdvanced(int frame) = 0;
-
 protected:
-
+	// Preload
+	// Actor_Put_In_Set
+	// Actor_Set_At_XYZ
+	// Actor_Set_At_Waypoint
+	// Region_Check
+	// Object_Query_Click
+	// Object_Do_Ground_Click
+	// Object_Mark_For_Hot_Mouse
+	// Actor_Face_Actor
+	// Actor_Face_Object
+	// Actor_Face_Item
+	// Actor_Face_Waypoint
+	// Actor_Face_XYZ
+	// Actor_Face_Current_Camera
+	// Actor_Face_Heading
+	// Actor_Query_Friendliness_To_Other
+	// Actor_Modify_Friendliness_To_Other
+	// Actor_Set_Friendliness_To_Other
+	// Actor_Set_Honesty
+	// Actor_Set_Intelligence
+	// Actor_Set_Stability
+	// Actor_Set_Combat_Aggressiveness
+	// Actor_Query_Current_HP
+	// Actor_Query_Max_HP
+	// Actor_Query_Combat_Aggressiveness
+	// Actor_Query_Honesty
+	// Actor_Query_Intelligence
+	// Actor_Query_Stability
+	// Actor_Modify_Current_HP
+	// Actor_Modify_Max_HP
+	// Actor_Modify_Combat_Aggressiveness
+	// Actor_Modify_Honesty
+	// Actor_Modify_Intelligence
+	// Actor_Modify_Stability
+	// Actor_Set_Flag_Damage_Anim_If_Moving
+	// Actor_Query_Flag_Damage_Anim_If_Moving
+	// Actor_Combat_AI_Hit_Attempt
+	// Non_Player_Actor_Combat_Mode_On
+	// Non_Player_Actor_Combat_Mode_Off
+	// Actor_Set_Health
+	// Actor_Set_Targetable
+	// Actor_Says
+	// Actor_Says_With_Pause
+	// Actor_Voice_Over
+	// Actor_Start_Speech_Sample
+	// Actor_Start_Voice_Over_Sample
+	// Actor_Query_Which_Set_In
+	// Actor_Query_Is_In_Current_Set
+	// Actor_Query_In_Set
+	// Actor_Query_Inch_Distance_From_Actor
+	// Actor_Query_Inch_Distance_From_Waypoint
+	// Actor_Query_In_Between_Two_Actors
+	// Actor_Set_Goal_Number
+	// Actor_Query_Goal_Number
+	// Actor_Query_XYZ
+	// Actor_Query_Facing_1024
+	// Actor_Set_Frame_Rate_FPS
+	// Slice_Animation_Query_Number_Of_Frames
+	// Actor_Change_Animation_Mode
+	// Actor_Query_Animation_Mode
+	// Loop_Actor_Walk_To_Actor
+	// Loop_Actor_Walk_To_Item
+	// Loop_Actor_Walk_To_Scene_Object
+	// Loop_Actor_Walk_To_Waypoint
+	// Loop_Actor_Walk_To_XYZ
+	// Async_Actor_Walk_To_Waypoint
+	// Async_Actor_Walk_To_XYZ
+	// Actor_Force_Stop_Walking
+	// Loop_Actor_Travel_Stairs
+	// Loop_Actor_Travel_Ladder
+	// Actor_Clue_Add_To_Database
+	// Actor_Clue_Acquire
+	// Actor_Clue_Lose
+	// Actor_Clue_Query
+	// Actor_Clues_Transfer_New_To_Mainframe
+	// Actor_Clues_Transfer_New_From_Mainframe
+	// Actor_Set_Invisible
+	// Actor_Set_Immunity_To_Obstacles
+	// Item_Add_To_World
+	// Item_Remove_From_World
+	// Item_Spin_In_World
+	// Item_Flag_As_Target
+	// Item_Flag_As_Non_Target
+	// Item_Pickup_Spin_Effect
+	// Animation_Open
+	// Animation_Close
+	// Animation_Start
+	// Animation_Stop
+	// Animation_Skip_To_Frame
+	// Delay
+	// Player_Loses_Control
+	// Player_Gains_Control
+	// Player_Set_Combat_Mode
+	// Player_Query_Combat_Mode
+	// Player_Set_Combat_Mode_Access
+	// Player_Query_Current_Set
+	// Player_Query_Current_Scene
+	// Player_Query_Agenda
+	// Player_Set_Agenda
+	// Query_Difficulty_Level
 	void Game_Flag_Set(int flag);
 	void Game_Flag_Reset(int flag);
 	bool Game_Flag_Query(int flag);
-
+	// Set_Enter
+	// Chapter_Enter
 	int Global_Variable_Set(int, int);
 	int Global_Variable_Reset(int);
 	int Global_Variable_Query(int);
 	int Global_Variable_Increment(int, int);
 	int Global_Variable_Decrement(int, int);
-
+	// Random_Query
 	void Sound_Play(int id, int volume, int panFrom, int panTo, int priority);
-
+	// Sound_Play_Speech_Line
+	// Sound_Left_Footstep_Walk
+	// Sound_Right_Footstep_Walk
+	// Sound_Left_Footstep_Run
+	// Sound_Right_Footstep_Run
+	// Sound_Walk_Shuffle_Stop
+	// Footstep_Sounds_Set
+	// Footstep_Sound_Override_On
+	// Footstep_Sound_Override_Off
+	// Music_Play
+	// Music_Adjust
+	// Music_Stop
+	// Music_Is_Playing
+	// Overlay_Play
+	// Overlay_Remove
 	void Scene_Loop_Set_Default(int);
 	void Scene_Loop_Start_Special(int, int, int);
-
 	void Outtake_Play(int id, int noLocalization = false, int container = -1);
 	void Ambient_Sounds_Add_Sound(int id, int time1, int time2, int volume1, int volume2, int pan1begin, int pan1end, int pan2begin, int pan2end, int priority, int unk);
 	// Ambient_Sounds_Remove_Sound
@@ -96,18 +183,119 @@ protected:
 	// Ambient_Sounds_Remove_Looping_Sound
 	void Ambient_Sounds_Remove_All_Looping_Sounds(int time);
 	void Setup_Scene_Information(float actorX, float actorY, float actorZ, int actorFacing);
-
+	// Dialogue_Menu_Appear
+	// Dialogue_Menu_Disappear
+	// Dialogue_Menu_Clear_List
+	// Dialogue_Menu_Add_To_List
+	// Dialogue_Menu_Add_DONE_To_List
+	// Dialogue_Menu_Add_To_List_Never_Repeat_Once_Selected
+	// DM_Add_To_List
+	// DM_Add_To_List_Never_Repeat_Once_Selected
+	// Dialogue_Menu_Remove_From_List
+	// Dialogue_Menu_Query_Input
+	// Dialogue_Menu_Query_List_Size
 	void Scene_Exit_Add_2D_Exit(int, int, int, int, int, int);
+	// Scene_Exit_Remove
+	// Scene_Exits_Disable
+	// Scene_Exits_Enable
 	void Scene_2D_Region_Add(int, int, int, int, int);
-
+	// Scene_2D_Region_Remove
+	// World_Waypoint_Set
+	// World_Waypoint_Reset
+	// World_Waypoint_Query_X
+	// World_Waypoint_Query_Y
+	// World_Waypoint_Query_Z
+	// Combat_Cover_Waypoint_Set_Data
+	// Combat_Flee_Waypoint_Set_Data
+	// Police_Maze_Target_Track_Add
+	// Police_Maze_Query_Score
+	// Police_Maze_Zero_Score
+	// Police_Maze_Increment_Score
+	// Police_Maze_Decrement_Score
+	// Police_Maze_Set_Score
+	// Police_Maze_Set_Pause_State
+	// CDB_Set_Crime
+	// CDB_Set_Clue_Asset_Type
+	// SDB_Set_Actor
+	// SDB_Add_Photo_Clue
+	// SDB_Set_Name
+	// SDB_Set_Sex
+	// SDB_Add_Identity_Clue
+	// SDB_Add_MO_Clue
+	// SDB_Add_Whereabouts_Clue
+	// SDB_Add_Replicant_Clue
+	// SDB_Add_Non_Replicant_Clue
+	// SDB_Add_Other_Clue
+	// Spinner_Set_Selectable_Destination_Flag
+	// Spinner_Query_Selectable_Destination_Flag
+	// Spinner_Interface_Choose_Dest
+	// ESPER_Flag_To_Activate
+	// Voight_Kampff_Activate
+	// Elevator_Activate
+	// View_Score_Board
+	// Query_Score
+	// Set_Score
+	// Give_McCoy_Ammo
+	void Assign_Player_Gun_Hit_Sounds(int a0, int a1, int a2, int a3);
+	void Assign_Player_Gun_Miss_Sounds(int a0, int a1, int a2, int a3);
+	// Disable_Shadows
+	// Query_System_Currently_Loading_Game
+	// Actor_Retired_Here
+	// Clickable_Object
+	// Unclickable_Object
+	// Obstacle_Object
+	// Unobstacle_Object
+	// Obstacle_Flag_All_Objects
+	// Combat_Target_Object
+	// Un_Combat_Target_Object
+	// Set_Fade_Color
+	// Set_Fade_Density
+	// Set_Fog_Color
+	// Set_Fog_Density
+	// ADQ_Flush
+	// ADQ_Add
+	// ADQ_Add_Pause
+	// Game_Over
+	// Autosave_Game
 	void I_Sez(const char *str);
 };
 
+class SceneScriptBase : public ScriptBase {
+public:
+	SceneScriptBase(BladeRunnerEngine *vm)
+		: ScriptBase(vm)
+	{}
+
+	virtual void InitializeScene() = 0;
+	virtual void SceneLoaded() = 0;
+	virtual void SceneFrameAdvanced(int frame) = 0;
+};
+
+class Script {
+public:
+	BladeRunnerEngine *_vm;
+	int                _inScriptCounter;
+	SceneScriptBase   *_currentScript;
+
+	Script(BladeRunnerEngine *vm)
+		: _vm(vm),
+		  _inScriptCounter(0),
+		  _currentScript(nullptr)
+	{}
+	~Script();
+
+	bool open(const Common::String &name);
+
+	void InitializeScene();
+	void SceneLoaded();
+	void SceneFrameAdvanced(int frame);
+};
+
 #define DECLARE_SCRIPT(name) \
-class Script##name : public ScriptBase { \
+class Script##name : public SceneScriptBase { \
 public: \
 	Script##name(BladeRunnerEngine *vm) \
-		: ScriptBase(vm) \
+		: SceneScriptBase(vm) \
 	{} \
 	void InitializeScene(); \
 	void SceneLoaded(); \


Commit: 2d8f421597d3bd31f76695f322c2c324774c567a
    https://github.com/scummvm/scummvm/commit/2d8f421597d3bd31f76695f322c2c324774c567a
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:38+02:00

Commit Message:
BLADERUNNER: Init globals, game flags, and actor clues

Changed paths:
  A engines/bladerunner/clues.cpp
  A engines/bladerunner/clues.h
  A engines/bladerunner/text_resource.cpp
  A engines/bladerunner/text_resource.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/gameinfo.cpp
    engines/bladerunner/gameinfo.h
    engines/bladerunner/module.mk
    engines/bladerunner/script/init.cpp
    engines/bladerunner/script/init.h
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index f6b0b09..48ffb7b 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -26,6 +26,7 @@
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/chapters.h"
+#include "bladerunner/clues.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/image.h"
@@ -36,6 +37,7 @@
 #include "bladerunner/settings.h"
 #include "bladerunner/slice_animations.h"
 #include "bladerunner/slice_renderer.h"
+#include "bladerunner/text_resource.h"
 #include "bladerunner/vqa_decoder.h"
 
 #include "common/error.h"
@@ -58,6 +60,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_ambientSounds = new AmbientSounds(this);
 	_audioPlayer = new AudioPlayer(this);
 	_chapters = nullptr;
+	_clues = nullptr;
 	_gameInfo = nullptr;
 	_gameFlags = new GameFlags();
 	_gameVars = nullptr;
@@ -77,6 +80,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	delete _gameVars;
 	delete _gameFlags;
 	delete _gameInfo;
+	delete _clues;
 	delete _chapters;
 	delete _audioPlayer;
 	delete _ambientSounds;
@@ -164,6 +168,11 @@ bool BladeRunnerEngine::startup() {
 	_zBuffer1 = new uint16[640 * 480];
 	_zBuffer2 = new uint16[640 * 480];
 
+	_actorNames = new TextResource(this);
+	_actorNames->open("ACTORS");
+
+	_clues = new Clues(this, "CLUES", _gameInfo->getClueCount());
+
 	ScriptInit initScript(this);
 	initScript.SCRIPT_Initialize_Game();
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 5ef2310..9d8e4af 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -39,6 +39,7 @@ namespace BladeRunner {
 class AmbientSounds;
 class AudioPlayer;
 class Chapters;
+class Clues;
 class GameInfo;
 class GameFlags;
 class Scene;
@@ -46,6 +47,7 @@ class Script;
 class Settings;
 class SliceAnimations;
 class SliceRenderer;
+class TextResource;
 
 class BladeRunnerEngine : public Engine {
 public:
@@ -55,6 +57,7 @@ public:
 	AmbientSounds   *_ambientSounds;
 	AudioPlayer     *_audioPlayer;
 	Chapters        *_chapters;
+	Clues           *_clues;
 	GameInfo        *_gameInfo;
 	GameFlags       *_gameFlags;
 	Scene           *_scene;
@@ -64,6 +67,8 @@ public:
 	SliceRenderer   *_sliceRenderer;
 	int             *_gameVars;
 
+	TextResource    *_actorNames;
+
 	int in_script_counter;
 
 	Graphics::Surface  _surface1;
diff --git a/engines/bladerunner/clues.cpp b/engines/bladerunner/clues.cpp
new file mode 100644
index 0000000..cc47ae0
--- /dev/null
+++ b/engines/bladerunner/clues.cpp
@@ -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.
+ *
+ */
+
+#include "bladerunner/clues.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/text_resource.h"
+
+namespace BladeRunner {
+
+Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, uint32 clueCount)
+	: _clueCount(clueCount)
+{
+	// reset();
+
+	_crimes     = new int[_clueCount];
+	_assetTypes = new int[_clueCount];
+
+	_cluesText = new TextResource(vm);
+	_cluesText->open(cluesResource);
+
+	for (uint32 i = 0; i != _clueCount; ++i) {
+		_crimes[i] = -1;
+		_assetTypes[i] = -1;
+	}
+}
+
+Clues::~Clues() {
+	delete[] _assetTypes;
+	delete[] _crimes;
+}
+
+const char *Clues::getClueText(int id) {
+	return _cluesText->getText(id);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/clues.h b/engines/bladerunner/clues.h
new file mode 100644
index 0000000..2ffcbd2
--- /dev/null
+++ b/engines/bladerunner/clues.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.
+ *
+ */
+
+#ifndef BLADERUNNER_CLUES_H
+#define BLADERUNNER_CLUES_H
+
+#include "common/scummsys.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class TextResource;
+
+class Clues {
+	uint32        _clueCount;
+	int          *_crimes;
+	int          *_assetTypes;
+	TextResource *_cluesText;
+
+public:
+	Clues(BladeRunnerEngine *vm, const char *cluesResource, uint32 clueCount);
+	~Clues();
+
+	const char *getClueText(int id);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index 15058c8..19037c8 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -55,7 +55,7 @@ bool GameInfo::open(const Common::String &name) {
 	_actor_count          = s->readUint32LE();   /* 00 */
 	_player_id            = s->readUint32LE();   /* 01 */
 	_flag_count           = s->readUint32LE();   /* 02 */
-	unk                   = s->readUint32LE();   /* 03 */
+	_clue_count           = s->readUint32LE();   /* 03 */
 	_global_var_count     = s->readUint32LE();   /* 04 */
 	_set_names_count      = s->readUint32LE();   /* 05 */
 	_initial_scene_id     = s->readUint32LE();   /* 06 */
diff --git a/engines/bladerunner/gameinfo.h b/engines/bladerunner/gameinfo.h
index 8c8202b..f907439 100644
--- a/engines/bladerunner/gameinfo.h
+++ b/engines/bladerunner/gameinfo.h
@@ -37,6 +37,7 @@ class GameInfo {
 	uint32 _actor_count;
 	uint32 _player_id;
 	uint32 _flag_count;
+	uint32 _clue_count;
 	uint32 _global_var_count;
 	uint32 _set_names_count;
 	uint32 _initial_scene_id;
@@ -62,6 +63,7 @@ public:
 	uint32 getActorCount()         { return _actor_count; }
 	uint32 getPlayerId()           { return _player_id; }
 	uint32 getFlagCount()          { return _flag_count; }
+	uint32 getClueCount()          { return _clue_count; }
 	uint32 getGlobalVarCount()     { return _global_var_count; }
 	uint32 getSetNamesCount()      { return _set_names_count; }
 	uint32 getInitialSceneId()     { return _initial_scene_id; }
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 15f2890..8bc3b36 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS = \
 	bladerunner.o \
 	boundingbox.o \
 	chapters.o \
+	clues.o \
 	decompress_lcw.o \
 	decompress_lzo.o \
 	detection.o \
@@ -24,6 +25,7 @@ MODULE_OBJS = \
 	settings.o \
 	slice_animations.o \
 	slice_renderer.o \
+	text_resource.o \
 	view.o \
 	vqa_decoder.o \
 	vqa_player.o
diff --git a/engines/bladerunner/script/init.cpp b/engines/bladerunner/script/init.cpp
index 4fe0da8..6e797fe 100644
--- a/engines/bladerunner/script/init.cpp
+++ b/engines/bladerunner/script/init.cpp
@@ -44,7 +44,7 @@ void ScriptInit::SCRIPT_Initialize_Game() {
 	Init_CDB();
 	Init_Spinner();
 	Init_Actor_Friendliness();
-	Init_Combat_Aggressiveness();
+	Init_Actor_Combat_Aggressiveness();
 	Init_Actor_Honesty();
 	Init_Actor_Intelligence();
 	Init_Actor_Stability();
@@ -55,19 +55,1267 @@ void ScriptInit::SCRIPT_Initialize_Game() {
 }
 
 void ScriptInit::Init_Globals() {
+	for (int i = 0; i != 55; ++i)
+		Global_Variable_Set(i, 0);
 
+	Global_Variable_Set(35, 2);
+	Global_Variable_Set(1, 1);
+	Global_Variable_Set(2, 100);
+
+	Set_Score(0, 0);
+	Set_Score(1, 64);
+	Set_Score(2, 10);
+	Set_Score(3, 47);
+	Set_Score(4, 35);
+	Set_Score(5, 23);
+	Set_Score(6, 28);
 }
 
 void ScriptInit::Init_Game_Flags() {
+	for (int i = 0; i != 730; ++i)
+		Game_Flag_Reset(i);
+
+	if (Random_Query(1, 2) == 1)
+		Game_Flag_Set(44);
+	if (Random_Query(1, 2) == 1)
+		Game_Flag_Set(45);
+	if (Random_Query(1, 2) == 1)
+		Game_Flag_Set(46);
+	if (Random_Query(1, 2) == 1)
+		Game_Flag_Set(47);
+	if (Random_Query(1, 2) == 1)
+		Game_Flag_Set(48);
+	if (Random_Query(1, 2) == 1)
+		Game_Flag_Set(560);
+
+	if (!Game_Flag_Query(45) && !Game_Flag_Query(46) && !Game_Flag_Query(47))
+		Game_Flag_Set(47);
 
+	if (Game_Flag_Query(47)) {
+		Global_Variable_Set(40, 1);
+	} else if (!Game_Flag_Query(45) || Game_Flag_Query(46)) {
+		if (Game_Flag_Query(45) || !Game_Flag_Query(46)) {
+			if (Random_Query(1, 2) == 1)
+				Global_Variable_Set(40, 2);
+			else
+				Global_Variable_Set(40, 3);
+		} else {
+			Global_Variable_Set(40, 3);
+		}
+	} else {
+		Global_Variable_Set(40, 2);
+	}
+
+	Game_Flag_Set(182);
+	Game_Flag_Set(249);
 }
 
 void ScriptInit::Init_Clues() {
-
+	for(int i = 0; i != 288; ++i)
+		Actor_Clue_Add_To_Database(0, i, 0, 0, 0, -1);
 }
 
+struct clue_weigth {
+	int clue;
+	int weight;
+};
+
+static clue_weigth clues_actor_1[44] = {
+	{ 222, 100 }, { 227, 100 }, { 223, 100 }, { 224, 100 }, { 226, 100 }, { 228, 100 }, { 231, 100 }, { 162, 100 },
+	{ 164, 100 }, { 166, 100 }, { 168, 100 }, { 170, 100 }, { 172, 100 }, { 174, 100 }, { 176, 100 }, { 239,  90 },
+	{ 241,  90 }, { 242,  90 }, { 179,  90 }, { 180,  90 }, { 181,  90 }, {   8,  85 }, { 240,  85 }, { 216,  85 },
+	{ 217,  85 }, { 178,  80 }, {   5,  65 }, {   9,  65 }, { 215,  65 }, { 218,  65 }, { 219,  65 }, { 220,  65 },
+	{ 229,  65 }, { 211,  65 }, {  80,  65 }, { 108,  65 }, { 134,  65 }, { 135,  65 }, { 212,  55 }, { 221,  55 },
+	{ 230,  55 }, {   6,  30 }, {   7,  30 }, {  65,  30 }
+};
+
+static clue_weigth clues_actor_2[28] = {
+	{ 227,  70 }, { 240,  65 }, { 241,  70 }, { 242,  95 }, { 212,  70 }, { 213,  70 }, { 214,  70 }, { 215,  70 },
+	{ 216,  95 }, { 217,  70 }, { 218,  70 }, { 219,  70 }, { 220,  70 }, { 221,  65 }, { 222,  70 }, { 223,  70 },
+	{ 224,  70 }, { 226,  70 }, { 228,  70 }, { 229,  70 }, { 230,  70 }, { 231,  70 }, { 232,  70 }, { 116,  65 },
+	{ 117,  65 }, { 145,  70 }, { 207,  55 }, { 211,  65 }
+};
+
+static clue_weigth clues_actor_3[46] = {
+	{ 227,  70 }, { 240,  45 }, { 241,  70 }, { 242,  65 }, { 212,  70 }, { 213,  70 }, { 214,  70 }, { 215,  70 },
+	{ 216,  65 }, { 217,  70 }, { 220,  70 }, { 219,  70 }, { 218,  70 }, { 221,  45 }, { 222,  70 }, { 223,  70 },
+	{ 224,  70 }, { 225,  70 }, { 226,  70 }, { 228,  70 }, { 229,  70 }, { 230,  70 }, { 231,  70 }, {  95,  70 },
+	{ 232,  70 }, { 239,  65 }, {  19,  65 }, {  25,  55 }, {  60,  60 }, {  69,  60 }, {  70,  60 }, {  92,  70 },
+	{ 103,  65 }, { 121,  65 }, { 130,  70 }, { 147,  70 }, { 148,  65 }, { 149,  65 }, { 150,  65 }, { 151,  65 },
+	{ 152,  65 }, { 116,  65 }, { 117,  65 }, { 145,  70 }, { 207,  55 }, { 211,  65 }
+};
+
+static clue_weigth clues_actor_4[23] = {
+	{ 241,  90 }, { 242,  90 }, { 240,  70 }, { 214,  75 }, { 216,  75 }, { 218,  75 }, { 219,  75 }, { 220,  75 },
+	{ 215,  70 }, { 217,  70 }, { 222,  70 }, { 223,  70 }, { 224,  70 }, { 226,  70 }, { 228,  70 }, { 230,  70 },
+	{  73,  65 }, { 211,  65 }, {  80,  65 }, { 108,  65 }, { 134,  65 }, { 135,  65 }, { 212,  55 }
+};
+
+static clue_weigth clues_actor_5[46] = {
+	{ 227,  70 }, { 241,  70 }, { 212,  70 }, { 213,  70 }, { 214,  70 }, { 215,  70 }, { 217,  70 }, { 220,  70 },
+	{ 219,  70 }, { 218,  70 }, { 222,  70 }, { 223,  70 }, { 224,  70 }, { 226,  70 }, { 228,  70 }, { 229,  70 },
+	{ 230,  70 }, { 232,  70 }, { 130,  70 }, { 147,  70 }, { 145,  70 }, { 242,  65 }, { 216,  65 }, { 239,  65 },
+	{  19,  65 }, {  95,  65 }, { 103,  65 }, { 107,  65 }, { 121,  65 }, { 148,  65 }, { 149,  65 }, { 150,  65 },
+	{ 151,  65 }, { 152,  65 }, { 116,  65 }, { 117,  65 }, { 211,  65 }, {  60,  60 }, {  69,  60 }, {  70,  60 },
+	{  92,  60 }, {  25,  55 }, { 133,  55 }, { 207,  55 }, { 240,  45 }, { 221,  45 }
+};
+
+static clue_weigth clues_actor_6[47] = {
+	{ 227,  70 }, { 240,  45 }, { 241,  70 }, { 242,  65 }, { 212,  70 }, { 213,  70 }, { 214,  70 }, { 215,  70 },
+	{ 216,  65 }, { 217,  70 }, { 220,  70 }, { 219,  70 }, { 218,  70 }, { 221,  45 }, { 222,  70 }, { 223,  70 },
+	{ 224,  70 }, { 226,  70 }, { 228,  70 }, { 229,  70 }, { 230,  70 }, { 231,  70 }, { 232,  70 }, { 239,  65 },
+	{  19,  65 }, {  25,  55 }, {  60,  60 }, {  69,  60 }, {  70,  60 }, {  92,  60 }, {  95,  65 }, { 103,  65 },
+	{ 107,  65 }, { 121,  55 }, { 130,  70 }, { 133,  70 }, { 147,  70 }, { 148,  65 }, { 149,  65 }, { 150,  65 },
+	{ 151,  65 }, { 152,  65 }, { 116,  65 }, { 117,  65 }, { 145,  70 }, { 207,  55 }, { 211,  65 }
+};
+
+static clue_weigth clues_actor_7_and_8[47] = {
+	{ 227,  70 }, { 240,  45 }, { 241,  70 }, { 242,  65 }, { 212,  70 }, { 213,  70 }, { 214,  70 }, { 215,  70 },
+	{ 216,  65 }, { 217,  70 }, { 220,  70 }, { 219,  70 }, { 218,  70 }, { 221,  45 }, { 222,  70 }, { 223,  70 },
+	{ 224,  70 }, { 226,  70 }, { 228,  70 }, { 229,  70 }, { 230,  70 }, { 231,  70 }, { 232,  70 }, { 239,  65 },
+	{  19,  45 }, {  25,  45 }, {  60,  45 }, {  69,  45 }, {  70,  45 }, {  92,  45 }, {  95,  45 }, { 103,  45 },
+	{ 107,  45 }, { 121,  45 }, { 130,  45 }, { 133,  45 }, { 147,  70 }, { 148,  70 }, { 149,  70 }, { 150,  70 },
+	{ 151,  70 }, { 152,  70 }, { 116,  65 }, { 117,  65 }, { 145,  70 }, { 207,  55 }, { 211,  65 }
+};
+
+static clue_weigth clues_actor_9[49] = {
+	{ 241,  70 }, { 212,  70 }, { 214,  70 }, { 217,  70 }, { 220,  70 }, { 219,  70 }, { 218,  70 }, { 222,  70 },
+	{ 223,  70 }, { 224,  70 }, { 226,  70 }, { 228,  70 }, { 229,  70 }, { 230,  70 }, { 231,  70 }, { 130,  70 },
+	{ 133,  70 }, { 147,  70 }, { 148,  70 }, { 149,  70 }, { 150,  70 }, { 151,  70 }, { 152,  70 }, { 145,  70 },
+	{ 227,  65 }, { 240,  65 }, { 242,  65 }, { 213,  65 }, { 215,  65 }, { 216,  65 }, { 221,  65 }, { 239,  65 },
+	{  95,  65 }, { 103,  65 }, { 107,  65 }, { 121,  65 }, { 116,  65 }, { 117,  65 }, { 211,  65 }, {  99,  65 },
+	{ 236,  65 }, {  60,  60 }, {  69,  60 }, {  70,  60 }, { 232,  55 }, {  92,  55 }, { 207,  55 }, {  19,  50 },
+	{  25,  40 }
+};
+
+static clue_weigth clues_actor_10[44] = {
+	{ 241,  70 }, { 130,  70 }, { 147,  70 }, { 145,  70 }, { 240,  65 }, { 216,  65 }, { 217,  65 }, { 219,  65 },
+	{ 218,  65 }, { 221,  65 }, { 223,  65 }, { 224,  65 }, { 226,  65 }, { 229,  65 }, { 239,  65 }, {  95,  65 },
+	{ 121,  65 }, { 148,  65 }, { 149,  65 }, { 150,  65 }, { 152,  65 }, { 116,  65 }, { 117,  65 }, { 214,  60 },
+	{ 215,  60 }, {  69,  60 }, {  70,  60 }, { 211,  60 }, { 242,  55 }, { 213,  55 }, { 220,  55 }, { 222,  55 },
+	{  60,  55 }, { 107,  55 }, { 133,  55 }, { 103,  50 }, {  92,  45 }, { 207,  45 }, { 227,  35 }, { 212,  35 },
+	{ 230,  35 }, { 232,  35 }, {  19,  30 }, {  25,  30 }
+};
+
 void ScriptInit::Init_Clues2() {
+	for(int i = 0; i != 288; ++i)
+		Actor_Clue_Add_To_Database(99, i, 100, 0, 0, -1);
+
+#define IMPORT_CLUE_TABLE(a, arr) \
+	for (int i = 0; i != ARRAYSIZE(arr); ++i) \
+		Actor_Clue_Add_To_Database( a, arr[i].clue, arr[i].weight, 0, 0, -1);
+
+	IMPORT_CLUE_TABLE( 1, clues_actor_1);
+	IMPORT_CLUE_TABLE( 2, clues_actor_2);
+	IMPORT_CLUE_TABLE( 3, clues_actor_3);
+	IMPORT_CLUE_TABLE( 4, clues_actor_4);
+	IMPORT_CLUE_TABLE( 5, clues_actor_5);
+	IMPORT_CLUE_TABLE( 6, clues_actor_6);
+	IMPORT_CLUE_TABLE( 7, clues_actor_7_and_8);
+	IMPORT_CLUE_TABLE( 9, clues_actor_9);
+	IMPORT_CLUE_TABLE(10, clues_actor_10);
+
+#undef IMPORT_CLUE_TABLE
 
+	Actor_Clue_Add_To_Database(11, 201,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 213,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 212,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 218,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 219,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 221,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 222,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 225,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 229,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 230,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 232,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 116,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 117,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 207,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(11, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 213,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 219,  75, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 222,  75, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 223,  75, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 228,  75, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 124,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(12, 131, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 227,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 214,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 215,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 216,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 217,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 220,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 221,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 222,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 224,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 226,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 232,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13,  25,  30, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13,  60,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13,  69,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13,  70,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13,  92,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13,  95,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 19,   55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 103,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 107,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 121,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 130,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 133,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 147,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 148,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 149,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 150,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 152,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 116,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 117,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 207,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(13, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14,   5,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 239,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 240,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 241,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 242,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 222,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 212,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 215,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 216,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 230,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14,   0,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14,  73,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 211,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 108,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 134,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 135,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14,  66,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 109,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 110,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 111,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(14, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 221,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 222,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(15, 232,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 240,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 213,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 219,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(16, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 241,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 222,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 218,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 219,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 220,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 221,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 223,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 224,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 226,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 228,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 230,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 231,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17,  73,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(17, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 239,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 240,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 242,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 222, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 227, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 216,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 217,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 223, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 224, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 228, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 231, 100, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 207,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(18, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 218,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 219,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 213,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 229,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 232,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 116,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 117,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 207,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(19, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 240,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 213,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 219,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(20, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 214,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 219,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 223,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21,  25,  30, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 147,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 148,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 150,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 152,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 117,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(21, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 240,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 213,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 219,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(22, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23,  27,  20, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23,  16,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23,  17,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23,  26,  25, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 227,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 218,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 219,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 239,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database( 1,  73 , 65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(23, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 227,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 218,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 219,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 239,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24,  17,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24,  16,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24,  27,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24,  26,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(24, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(25, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(25, 213,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(25, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26,   0,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26,   5,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26,   8,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26,   9,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 239,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 240,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 242,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 222,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 216,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 217,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(26, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 227,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 241,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 215,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 216,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 217,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 220,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 219,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 218,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 221,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 222,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 223,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 224,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 226,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 228,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 230,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 232,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  25,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  60,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  69,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  70,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  92,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  95,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27,  19,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 103,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 107,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 121,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 130,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 133,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 147,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 148,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 149,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 150,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 151,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 152,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 116,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 117,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 145,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 207,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(27, 211,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28,  25,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28,  64,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28,  69,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 111,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 124,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 219,  75, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 241,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 217,  25, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 221,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 223,  75, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 225,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 222,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(28, 232,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 240,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 213,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 219,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(29, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 126,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 195,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 197,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 198,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 202,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 218,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 225,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 222,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 239,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(30, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 240,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 213,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 219,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(31, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 240,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 241,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 212,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 213,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 214,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 219,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 221,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 223,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 229,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 230,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 231,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 232,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 239,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  25,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  60,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  69,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  70,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  92,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32,  19,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 103,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 121,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 207,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(32, 211,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33,   5,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33,   8,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33,   9,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 239,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 240,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 242,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 222,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 216,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 217,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(33, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 126,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 195,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 197,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 198,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 202,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 219,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 218,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 225,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 222,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 239,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34,  80,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(34, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 214,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 219,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 223,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35,  25,  30, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 147,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 148,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 150,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 152,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 117,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(35, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37,   0,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37,   5,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37,   8,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37,   9,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 239,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 240,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 242,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 222,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 216,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 217,  85, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(37, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 241,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 227,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 212,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 219,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 221,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 224,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 228,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 231,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 207,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(42, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 241,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 212,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(44, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 241,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 227,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 216,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 217,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 221,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 224,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 226,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 214,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 229,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 232,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 145,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(51, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 214,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 219,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 223,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52,  25,  30, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 147,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 148,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 150,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 152,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 117,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(52, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 126,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 162,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 164,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 166,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 168,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 170,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 172,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 176,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 195,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 197,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 198,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 202,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 111,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 219,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 241,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 212,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 230,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 215,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 216,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 218,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 220,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 221,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 225,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 222,  90, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 242,  95, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(53, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 241,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 227,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 212,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 219,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 221,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 224,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 228,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 229,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 230,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 231,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55,  80,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 108,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 134,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 135,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 214,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 207,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(55, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 222,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 227,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 240,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 212,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 213,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 216,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 223,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 224,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 229,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 230,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 231,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 232,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 239,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  25,  30, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  60,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  69,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  70,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  92,  25, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  95,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56,  19,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 103,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 107,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 121,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 130,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 133,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 147,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 149,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 150,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 151,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 152,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 116,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 117,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 145,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 207,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(56, 211,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 241,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 227,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 216,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 217,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 221,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 224,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 226,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 228,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 214,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 229,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 232,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 145,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(57, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(58, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(58, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(58, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(58, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(58, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 227,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 240,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 242,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 212,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 213,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 215,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 216,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 217,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 220,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 219,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 218,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 221,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 222,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 224,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 226,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 228,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 230,  35, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59,  95,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 232,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 130,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 147,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 148,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 149,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 150,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 151,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 152,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 116,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 117,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 145,  50, 0, 0, -1);
+	Actor_Clue_Add_To_Database(59, 211,  60, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 239,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 241,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 222,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 227,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 212,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 215,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 216,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 217,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 218,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 219,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 220,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 221,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 223,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 224,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 226,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 228,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 229,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 230,  45, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 231,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 162,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 164,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 166,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 168,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 170,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 172,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 174,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 176,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62,   0,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62,  73,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 211,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62,  80,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 108,  55, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 134,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(62, 135,  40, 0, 0, -1);
+	Actor_Clue_Add_To_Database(66, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(66, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(66, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(66, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(66, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(67, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(67, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(67, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(67, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(67, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(68, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(68, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(68, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(68, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(68, 214,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(69, 240,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(69, 241,  70, 0, 0, -1);
+	Actor_Clue_Add_To_Database(69, 242,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(69, 239,  65, 0, 0, -1);
+	Actor_Clue_Add_To_Database(69, 214,  65, 0, 0, -1);
 }
 
 void ScriptInit::Init_World_Waypoints() {
@@ -90,7 +1338,7 @@ void ScriptInit::Init_Actor_Friendliness() {
 
 }
 
-void ScriptInit::Init_Combat_Aggressiveness() {
+void ScriptInit::Init_Actor_Combat_Aggressiveness() {
 
 }
 
diff --git a/engines/bladerunner/script/init.h b/engines/bladerunner/script/init.h
index 27c6fc0..e7023fb 100644
--- a/engines/bladerunner/script/init.h
+++ b/engines/bladerunner/script/init.h
@@ -47,7 +47,7 @@ private:
 	void Init_CDB();
 	void Init_Spinner();
 	void Init_Actor_Friendliness();
-	void Init_Combat_Aggressiveness();
+	void Init_Actor_Combat_Aggressiveness();
 	void Init_Actor_Honesty();
 	void Init_Actor_Intelligence();
 	void Init_Actor_Stability();
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 5b19c0c..8386fc2 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -26,9 +26,11 @@
 
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
-#include "bladerunner/gameinfo.h"
+#include "bladerunner/clues.h"
 #include "bladerunner/gameflags.h"
+#include "bladerunner/gameinfo.h"
 #include "bladerunner/scene.h"
+#include "bladerunner/text_resource.h"
 #include "bladerunner/vector.h"
 
 namespace BladeRunner {
@@ -133,7 +135,13 @@ void Script::SceneFrameAdvanced(int frame) {
 // ScriptBase::Actor_Force_Stop_Walking
 // ScriptBase::Loop_Actor_Travel_Stairs
 // ScriptBase::Loop_Actor_Travel_Ladder
-// ScriptBase::Actor_Clue_Add_To_Database
+
+void ScriptBase::Actor_Clue_Add_To_Database(int a0, int a1, int a2, int a3, int a4, int a5) {
+	// debug("STUB: Actor_Clue_Add_To_Database(%d, %3d, %3d, %d, %d, %d)", a0, a1, a2, a3, a4, a5);
+	// debug("\tACTOR: %s", _vm->_actorNames->getText(a0));
+	// debug("\tCLUE:  %s\n", _vm->_clues->getClueText(a1));
+}
+
 // ScriptBase::Actor_Clue_Acquire
 // ScriptBase::Actor_Clue_Lose
 // ScriptBase::Actor_Clue_Query
@@ -199,7 +207,9 @@ int ScriptBase::Global_Variable_Decrement(int var, int dec) {
 	return _vm->_gameVars[var] -= dec;
 }
 
-// ScriptBase::Random_Query
+int ScriptBase::Random_Query(int min, int max) {
+	return _vm->_rnd.getRandomNumberRng(min, max);
+}
 
 void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int priority) {
 	const char *name = _vm->_gameInfo->getSfxTrack(id);
@@ -322,7 +332,11 @@ void ScriptBase::Scene_2D_Region_Add(int a, int b, int c, int d, int e) {
 // ScriptBase::Elevator_Activate
 // ScriptBase::View_Score_Board
 // ScriptBase::Query_Score
-// ScriptBase::Set_Score
+
+void ScriptBase::Set_Score(int a0, int a1) {
+	debug("STUB: Set_Score(%d, %d)", a0, a1);
+}
+
 // ScriptBase::Give_McCoy_Ammo
 
 void ScriptBase::Assign_Player_Gun_Hit_Sounds(int a0, int a1, int a2, int a3) {
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 008e034..a6ac20b 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -111,7 +111,7 @@ protected:
 	// Actor_Force_Stop_Walking
 	// Loop_Actor_Travel_Stairs
 	// Loop_Actor_Travel_Ladder
-	// Actor_Clue_Add_To_Database
+	void Actor_Clue_Add_To_Database(int a0, int a1, int a2, int a3, int a4, int a5);
 	// Actor_Clue_Acquire
 	// Actor_Clue_Lose
 	// Actor_Clue_Query
@@ -151,7 +151,7 @@ protected:
 	int Global_Variable_Query(int);
 	int Global_Variable_Increment(int, int);
 	int Global_Variable_Decrement(int, int);
-	// Random_Query
+	int Random_Query(int min, int max);
 	void Sound_Play(int id, int volume, int panFrom, int panTo, int priority);
 	// Sound_Play_Speech_Line
 	// Sound_Left_Footstep_Walk
@@ -234,7 +234,7 @@ protected:
 	// Elevator_Activate
 	// View_Score_Board
 	// Query_Score
-	// Set_Score
+	void Set_Score(int a0, int a1);
 	// Give_McCoy_Ammo
 	void Assign_Player_Gun_Hit_Sounds(int a0, int a1, int a2, int a3);
 	void Assign_Player_Gun_Miss_Sounds(int a0, int a1, int a2, int a3);
diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp
new file mode 100644
index 0000000..9bb71fa
--- /dev/null
+++ b/engines/bladerunner/text_resource.cpp
@@ -0,0 +1,96 @@
+/* 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 "bladerunner/text_resource.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/debug.h"
+#include "common/util.h"
+
+namespace BladeRunner {
+
+TextResource::TextResource(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_count   = 0;
+	_ids     = nullptr;
+	_offsets = nullptr;
+	_strings = nullptr;
+}
+
+TextResource::~TextResource() {
+	delete[] _ids;
+	delete[] _offsets;
+	delete _strings;
+}
+
+bool TextResource::open(const char *name) {
+	assert(strlen(name) <= 8);
+
+	char resName[13];
+	sprintf(resName, "%s.TRE", name);
+	Common::SeekableReadStream *s = _vm->getResourceStream(resName);
+	if (!s)
+		return false;
+
+	_count = s->readUint32LE();
+
+	_ids = new uint32[_count];
+	_offsets = new uint32[_count + 1];
+
+	for (uint32 i = 0; i != _count; ++i) {
+		_ids[i] = s->readUint32LE();
+	}
+
+	for (uint32 i = 0; i != _count + 1; ++i) {
+		_offsets[i] = s->readUint32LE();
+	}
+
+	uint32 stringsStart = s->pos() - 4;
+
+	for (uint32 i = 0; i != _count + 1; ++i) {
+		_offsets[i] -= stringsStart;
+	}
+
+	uint32 remain = s->size() - s->pos();
+	_strings = new char[remain];
+
+	assert(remain >= _offsets[_count]);
+
+	s->read(_strings, remain);
+
+	return true;
+}
+
+const char *TextResource::getText(uint32 id) {
+	for (uint32 i = 0; i != _count; ++i) {
+		if (_ids[i] == id) {
+			return _strings + _offsets[i];
+		}
+	}
+
+	return nullptr;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/text_resource.h b/engines/bladerunner/text_resource.h
new file mode 100644
index 0000000..9554267
--- /dev/null
+++ b/engines/bladerunner/text_resource.h
@@ -0,0 +1,51 @@
+/* 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 BLADERUNNER_TEXT_RESOURCE_H
+#define BLADERUNNER_TEXT_RESOURCE_H
+
+#include "common/scummsys.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class TextResource;
+
+class TextResource {
+	BladeRunnerEngine *_vm;
+
+	uint32  _count;
+	uint32 *_ids;
+	uint32 *_offsets;
+	char   *_strings;
+
+public:
+	TextResource(BladeRunnerEngine *vm);
+	~TextResource();
+
+	bool open(const char *name);
+	const char *getText(uint32 id);
+};
+
+} // End of namespace BladeRunner
+
+#endif


Commit: 35ea84935ff3259aaa09946f0447a75e9b617086
    https://github.com/scummvm/scummvm/commit/35ea84935ff3259aaa09946f0447a75e9b617086
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:38+02:00

Commit Message:
BLADERUNNER: Split aud_decoder into aud_stream and adpcm_decoder

Changed paths:
  A engines/bladerunner/adpcm_decoder.cpp
  A engines/bladerunner/adpcm_decoder.h
  A engines/bladerunner/aud_stream.cpp
  A engines/bladerunner/aud_stream.h
  R engines/bladerunner/aud_decoder.cpp
  R engines/bladerunner/aud_decoder.h
    engines/bladerunner/audio_player.cpp
    engines/bladerunner/audio_player.h
    engines/bladerunner/module.mk
    engines/bladerunner/vqa_decoder.h



diff --git a/engines/bladerunner/adpcm_decoder.cpp b/engines/bladerunner/adpcm_decoder.cpp
new file mode 100644
index 0000000..e262da6
--- /dev/null
+++ b/engines/bladerunner/adpcm_decoder.cpp
@@ -0,0 +1,167 @@
+/* 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 "bladerunner/adpcm_decoder.h"
+
+#include "common/util.h"
+
+namespace BladeRunner {
+
+static const
+int16 imaIndexTable[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
+
+static const
+uint16 imaStepTable[712] =
+{
+ 0x0000,0x0001,0x0003,0x0004,0x0007,0x0008,0x000a,0x000b,
+ 0x0001,0x0003,0x0005,0x0007,0x0009,0x000b,0x000d,0x000f,
+ 0x0001,0x0003,0x0005,0x0007,0x000a,0x000c,0x000e,0x0010,
+ 0x0001,0x0003,0x0006,0x0008,0x000b,0x000d,0x0010,0x0012,
+ 0x0001,0x0003,0x0006,0x0008,0x000c,0x000e,0x0011,0x0013,
+ 0x0001,0x0004,0x0007,0x000a,0x000d,0x0010,0x0013,0x0016,
+ 0x0001,0x0004,0x0007,0x000a,0x000e,0x0011,0x0014,0x0017,
+ 0x0001,0x0004,0x0008,0x000b,0x000f,0x0012,0x0016,0x0019,
+ 0x0002,0x0006,0x000a,0x000e,0x0012,0x0016,0x001a,0x001e,
+ 0x0002,0x0006,0x000a,0x000e,0x0013,0x0017,0x001b,0x001f,
+ 0x0002,0x0006,0x000b,0x000f,0x0015,0x0019,0x001e,0x0022,
+ 0x0002,0x0007,0x000c,0x0011,0x0017,0x001c,0x0021,0x0026,
+ 0x0002,0x0007,0x000d,0x0012,0x0019,0x001e,0x0024,0x0029,
+ 0x0003,0x0009,0x000f,0x0015,0x001c,0x0022,0x0028,0x002e,
+ 0x0003,0x000a,0x0011,0x0018,0x001f,0x0026,0x002d,0x0034,
+ 0x0003,0x000a,0x0012,0x0019,0x0022,0x0029,0x0031,0x0038,
+ 0x0004,0x000c,0x0015,0x001d,0x0026,0x002e,0x0037,0x003f,
+ 0x0004,0x000d,0x0016,0x001f,0x0029,0x0032,0x003b,0x0044,
+ 0x0005,0x000f,0x0019,0x0023,0x002e,0x0038,0x0042,0x004c,
+ 0x0005,0x0010,0x001b,0x0026,0x0032,0x003d,0x0048,0x0053,
+ 0x0006,0x0012,0x001f,0x002b,0x0038,0x0044,0x0051,0x005d,
+ 0x0006,0x0013,0x0021,0x002e,0x003d,0x004a,0x0058,0x0065,
+ 0x0007,0x0016,0x0025,0x0034,0x0043,0x0052,0x0061,0x0070,
+ 0x0008,0x0018,0x0029,0x0039,0x004a,0x005a,0x006b,0x007b,
+ 0x0009,0x001b,0x002d,0x003f,0x0052,0x0064,0x0076,0x0088,
+ 0x000a,0x001e,0x0032,0x0046,0x005a,0x006e,0x0082,0x0096,
+ 0x000b,0x0021,0x0037,0x004d,0x0063,0x0079,0x008f,0x00a5,
+ 0x000c,0x0024,0x003c,0x0054,0x006d,0x0085,0x009d,0x00b5,
+ 0x000d,0x0027,0x0042,0x005c,0x0078,0x0092,0x00ad,0x00c7,
+ 0x000e,0x002b,0x0049,0x0066,0x0084,0x00a1,0x00bf,0x00dc,
+ 0x0010,0x0030,0x0051,0x0071,0x0092,0x00b2,0x00d3,0x00f3,
+ 0x0011,0x0034,0x0058,0x007b,0x00a0,0x00c3,0x00e7,0x010a,
+ 0x0013,0x003a,0x0061,0x0088,0x00b0,0x00d7,0x00fe,0x0125,
+ 0x0015,0x0040,0x006b,0x0096,0x00c2,0x00ed,0x0118,0x0143,
+ 0x0017,0x0046,0x0076,0x00a5,0x00d5,0x0104,0x0134,0x0163,
+ 0x001a,0x004e,0x0082,0x00b6,0x00eb,0x011f,0x0153,0x0187,
+ 0x001c,0x0055,0x008f,0x00c8,0x0102,0x013b,0x0175,0x01ae,
+ 0x001f,0x005e,0x009d,0x00dc,0x011c,0x015b,0x019a,0x01d9,
+ 0x0022,0x0067,0x00ad,0x00f2,0x0139,0x017e,0x01c4,0x0209,
+ 0x0026,0x0072,0x00bf,0x010b,0x0159,0x01a5,0x01f2,0x023e,
+ 0x002a,0x007e,0x00d2,0x0126,0x017b,0x01cf,0x0223,0x0277,
+ 0x002e,0x008a,0x00e7,0x0143,0x01a1,0x01fd,0x025a,0x02b6,
+ 0x0033,0x0099,0x00ff,0x0165,0x01cb,0x0231,0x0297,0x02fd,
+ 0x0038,0x00a8,0x0118,0x0188,0x01f9,0x0269,0x02d9,0x0349,
+ 0x003d,0x00b8,0x0134,0x01af,0x022b,0x02a6,0x0322,0x039d,
+ 0x0044,0x00cc,0x0154,0x01dc,0x0264,0x02ec,0x0374,0x03fc,
+ 0x004a,0x00df,0x0175,0x020a,0x02a0,0x0335,0x03cb,0x0460,
+ 0x0052,0x00f6,0x019b,0x023f,0x02e4,0x0388,0x042d,0x04d1,
+ 0x005a,0x010f,0x01c4,0x0279,0x032e,0x03e3,0x0498,0x054d,
+ 0x0063,0x012a,0x01f1,0x02b8,0x037f,0x0446,0x050d,0x05d4,
+ 0x006d,0x0148,0x0223,0x02fe,0x03d9,0x04b4,0x058f,0x066a,
+ 0x0078,0x0168,0x0259,0x0349,0x043b,0x052b,0x061c,0x070c,
+ 0x0084,0x018d,0x0296,0x039f,0x04a8,0x05b1,0x06ba,0x07c3,
+ 0x0091,0x01b4,0x02d8,0x03fb,0x051f,0x0642,0x0766,0x0889,
+ 0x00a0,0x01e0,0x0321,0x0461,0x05a2,0x06e2,0x0823,0x0963,
+ 0x00b0,0x0210,0x0371,0x04d1,0x0633,0x0793,0x08f4,0x0a54,
+ 0x00c2,0x0246,0x03ca,0x054e,0x06d2,0x0856,0x09da,0x0b5e,
+ 0x00d5,0x027f,0x042a,0x05d4,0x0780,0x092a,0x0ad5,0x0c7f,
+ 0x00ea,0x02bf,0x0495,0x066a,0x0840,0x0a15,0x0beb,0x0dc0,
+ 0x0102,0x0306,0x050b,0x070f,0x0914,0x0b18,0x0d1d,0x0f21,
+ 0x011c,0x0354,0x058c,0x07c4,0x09fc,0x0c34,0x0e6c,0x10a4,
+ 0x0138,0x03a8,0x0619,0x0889,0x0afb,0x0d6b,0x0fdc,0x124c,
+ 0x0157,0x0406,0x06b5,0x0964,0x0c14,0x0ec3,0x1172,0x1421,
+ 0x017a,0x046e,0x0762,0x0a56,0x0d4a,0x103e,0x1332,0x1626,
+ 0x019f,0x04de,0x081e,0x0b5d,0x0e9e,0x11dd,0x151d,0x185c,
+ 0x01c9,0x055c,0x08ef,0x0c82,0x1015,0x13a8,0x173b,0x1ace,
+ 0x01f7,0x05e5,0x09d4,0x0dc2,0x11b1,0x159f,0x198e,0x1d7c,
+ 0x0229,0x067c,0x0acf,0x0f22,0x1375,0x17c8,0x1c1b,0x206e,
+ 0x0260,0x0721,0x0be3,0x10a4,0x1567,0x1a28,0x1eea,0x23ab,
+ 0x029d,0x07d8,0x0d14,0x124f,0x178b,0x1cc6,0x2202,0x273d,
+ 0x02e0,0x08a1,0x0e63,0x1424,0x19e6,0x1fa7,0x2569,0x2b2a,
+ 0x032a,0x097f,0x0fd4,0x1629,0x1c7e,0x22d3,0x2928,0x2f7d,
+ 0x037b,0x0a72,0x1169,0x1860,0x1f57,0x264e,0x2d45,0x343c,
+ 0x03d4,0x0b7d,0x1326,0x1acf,0x2279,0x2a22,0x31cb,0x3974,
+ 0x0436,0x0ca3,0x1511,0x1d7e,0x25ec,0x2e59,0x36c7,0x3f34,
+ 0x04a2,0x0de7,0x172c,0x2071,0x29b7,0x32fc,0x3c41,0x4586,
+ 0x0519,0x0f4b,0x197e,0x23b0,0x2de3,0x3815,0x4248,0x4c7a,
+ 0x059b,0x10d2,0x1c0a,0x2741,0x327a,0x3db1,0x48e9,0x5420,
+ 0x062b,0x1281,0x1ed8,0x2b2e,0x3786,0x43dc,0x5033,0x5c89,
+ 0x06c9,0x145b,0x21ee,0x2f80,0x3d14,0x4aa6,0x5839,0x65cb,
+ 0x0777,0x1665,0x2553,0x3441,0x4330,0x521e,0x610c,0x6ffa,
+ 0x0836,0x18a2,0x290f,0x397b,0x49e8,0x5a54,0x6ac1,0x7b2d,
+ 0x0908,0x1b19,0x2d2a,0x3f3b,0x514c,0x635d,0x756e,0x877f,
+ 0x09ef,0x1dce,0x31ae,0x458d,0x596d,0x6d4c,0x812c,0x950b,
+ 0x0aee,0x20ca,0x36a6,0x4c82,0x625f,0x783b,0x8e17,0xa3f3,
+ 0x0c05,0x2410,0x3c1c,0x5427,0x6c34,0x843f,0x9c4b,0xb456,
+ 0x0d39,0x27ac,0x4220,0x5c93,0x7707,0x917a,0xabee,0xc661,
+ 0x0e8c,0x2ba4,0x48bd,0x65d5,0x82ee,0xa006,0xbd1f,0xda37,
+ 0x0fff,0x2ffe,0x4ffe,0x6ffd,0x8ffe,0xaffd,0xcffd,0xeffc
+};
+
+void ADPCMWestwoodDecoder::decode(uint8 *in, size_t size, int16 *out)
+{
+	uint8 *end = in + size;
+
+	int16 stepIndex = _stepIndex;
+	int32 predictor = _predictor;
+
+	while (in != end)
+	{
+		uint16 bl = *in++;
+
+		for (int n = 0; n != 2; ++n)
+		{
+			uint8 nibble = (bl >> (4 * n)) & 0x0f;
+			uint8 code = nibble & 0x07;
+			uint8 sign = nibble & 0x08;
+
+			int diff = imaStepTable[(stepIndex << 3) | code];
+
+			// Westwood's IMA ADPCM differs from the below standard implementation
+			// in the LSB in a couple of places.
+			//int diff = imaStepTable_std[stepIndex] * code / 4 + imaStepTable_std[stepIndex] / 8;
+
+			if (sign)
+				predictor -= diff;
+			else
+				predictor += diff;
+
+			predictor = CLIP<int32>(predictor, -32768, 32767);
+
+			*out++ = (int16)predictor;
+
+			stepIndex = imaIndexTable[code] + stepIndex;
+			stepIndex = CLIP<int16>(stepIndex, 0, 88);
+		}
+	}
+
+	_stepIndex = stepIndex;
+	_predictor = predictor;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/adpcm_decoder.h b/engines/bladerunner/adpcm_decoder.h
new file mode 100644
index 0000000..fd174ae
--- /dev/null
+++ b/engines/bladerunner/adpcm_decoder.h
@@ -0,0 +1,50 @@
+/* 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 BLADERUNNER_ADPCM_DECODER_H
+#define BLADERUNNER_ADPCM_DECODER_H
+
+#include "common/types.h"
+
+namespace BladeRunner {
+
+class ADPCMWestwoodDecoder {
+	int16 _stepIndex;
+	int32 _predictor;
+
+public:
+	ADPCMWestwoodDecoder()
+		: _stepIndex(0), _predictor(0)
+	{}
+
+	void setParameters(int16 stepIndex, int32 predictor)
+	{
+		_stepIndex = stepIndex;
+		_predictor = predictor;
+	}
+
+	void decode(uint8 *in, size_t size, int16 *out);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/aud_decoder.cpp b/engines/bladerunner/aud_decoder.cpp
deleted file mode 100644
index 3123ddd..0000000
--- a/engines/bladerunner/aud_decoder.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "bladerunner/aud_decoder.h"
-
-#include "common/util.h"
-
-namespace BladeRunner {
-
-static const
-int16 imaIndexTable[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
-
-static const
-uint16 imaStepTable[712] =
-{
- 0x0000,0x0001,0x0003,0x0004,0x0007,0x0008,0x000a,0x000b,
- 0x0001,0x0003,0x0005,0x0007,0x0009,0x000b,0x000d,0x000f,
- 0x0001,0x0003,0x0005,0x0007,0x000a,0x000c,0x000e,0x0010,
- 0x0001,0x0003,0x0006,0x0008,0x000b,0x000d,0x0010,0x0012,
- 0x0001,0x0003,0x0006,0x0008,0x000c,0x000e,0x0011,0x0013,
- 0x0001,0x0004,0x0007,0x000a,0x000d,0x0010,0x0013,0x0016,
- 0x0001,0x0004,0x0007,0x000a,0x000e,0x0011,0x0014,0x0017,
- 0x0001,0x0004,0x0008,0x000b,0x000f,0x0012,0x0016,0x0019,
- 0x0002,0x0006,0x000a,0x000e,0x0012,0x0016,0x001a,0x001e,
- 0x0002,0x0006,0x000a,0x000e,0x0013,0x0017,0x001b,0x001f,
- 0x0002,0x0006,0x000b,0x000f,0x0015,0x0019,0x001e,0x0022,
- 0x0002,0x0007,0x000c,0x0011,0x0017,0x001c,0x0021,0x0026,
- 0x0002,0x0007,0x000d,0x0012,0x0019,0x001e,0x0024,0x0029,
- 0x0003,0x0009,0x000f,0x0015,0x001c,0x0022,0x0028,0x002e,
- 0x0003,0x000a,0x0011,0x0018,0x001f,0x0026,0x002d,0x0034,
- 0x0003,0x000a,0x0012,0x0019,0x0022,0x0029,0x0031,0x0038,
- 0x0004,0x000c,0x0015,0x001d,0x0026,0x002e,0x0037,0x003f,
- 0x0004,0x000d,0x0016,0x001f,0x0029,0x0032,0x003b,0x0044,
- 0x0005,0x000f,0x0019,0x0023,0x002e,0x0038,0x0042,0x004c,
- 0x0005,0x0010,0x001b,0x0026,0x0032,0x003d,0x0048,0x0053,
- 0x0006,0x0012,0x001f,0x002b,0x0038,0x0044,0x0051,0x005d,
- 0x0006,0x0013,0x0021,0x002e,0x003d,0x004a,0x0058,0x0065,
- 0x0007,0x0016,0x0025,0x0034,0x0043,0x0052,0x0061,0x0070,
- 0x0008,0x0018,0x0029,0x0039,0x004a,0x005a,0x006b,0x007b,
- 0x0009,0x001b,0x002d,0x003f,0x0052,0x0064,0x0076,0x0088,
- 0x000a,0x001e,0x0032,0x0046,0x005a,0x006e,0x0082,0x0096,
- 0x000b,0x0021,0x0037,0x004d,0x0063,0x0079,0x008f,0x00a5,
- 0x000c,0x0024,0x003c,0x0054,0x006d,0x0085,0x009d,0x00b5,
- 0x000d,0x0027,0x0042,0x005c,0x0078,0x0092,0x00ad,0x00c7,
- 0x000e,0x002b,0x0049,0x0066,0x0084,0x00a1,0x00bf,0x00dc,
- 0x0010,0x0030,0x0051,0x0071,0x0092,0x00b2,0x00d3,0x00f3,
- 0x0011,0x0034,0x0058,0x007b,0x00a0,0x00c3,0x00e7,0x010a,
- 0x0013,0x003a,0x0061,0x0088,0x00b0,0x00d7,0x00fe,0x0125,
- 0x0015,0x0040,0x006b,0x0096,0x00c2,0x00ed,0x0118,0x0143,
- 0x0017,0x0046,0x0076,0x00a5,0x00d5,0x0104,0x0134,0x0163,
- 0x001a,0x004e,0x0082,0x00b6,0x00eb,0x011f,0x0153,0x0187,
- 0x001c,0x0055,0x008f,0x00c8,0x0102,0x013b,0x0175,0x01ae,
- 0x001f,0x005e,0x009d,0x00dc,0x011c,0x015b,0x019a,0x01d9,
- 0x0022,0x0067,0x00ad,0x00f2,0x0139,0x017e,0x01c4,0x0209,
- 0x0026,0x0072,0x00bf,0x010b,0x0159,0x01a5,0x01f2,0x023e,
- 0x002a,0x007e,0x00d2,0x0126,0x017b,0x01cf,0x0223,0x0277,
- 0x002e,0x008a,0x00e7,0x0143,0x01a1,0x01fd,0x025a,0x02b6,
- 0x0033,0x0099,0x00ff,0x0165,0x01cb,0x0231,0x0297,0x02fd,
- 0x0038,0x00a8,0x0118,0x0188,0x01f9,0x0269,0x02d9,0x0349,
- 0x003d,0x00b8,0x0134,0x01af,0x022b,0x02a6,0x0322,0x039d,
- 0x0044,0x00cc,0x0154,0x01dc,0x0264,0x02ec,0x0374,0x03fc,
- 0x004a,0x00df,0x0175,0x020a,0x02a0,0x0335,0x03cb,0x0460,
- 0x0052,0x00f6,0x019b,0x023f,0x02e4,0x0388,0x042d,0x04d1,
- 0x005a,0x010f,0x01c4,0x0279,0x032e,0x03e3,0x0498,0x054d,
- 0x0063,0x012a,0x01f1,0x02b8,0x037f,0x0446,0x050d,0x05d4,
- 0x006d,0x0148,0x0223,0x02fe,0x03d9,0x04b4,0x058f,0x066a,
- 0x0078,0x0168,0x0259,0x0349,0x043b,0x052b,0x061c,0x070c,
- 0x0084,0x018d,0x0296,0x039f,0x04a8,0x05b1,0x06ba,0x07c3,
- 0x0091,0x01b4,0x02d8,0x03fb,0x051f,0x0642,0x0766,0x0889,
- 0x00a0,0x01e0,0x0321,0x0461,0x05a2,0x06e2,0x0823,0x0963,
- 0x00b0,0x0210,0x0371,0x04d1,0x0633,0x0793,0x08f4,0x0a54,
- 0x00c2,0x0246,0x03ca,0x054e,0x06d2,0x0856,0x09da,0x0b5e,
- 0x00d5,0x027f,0x042a,0x05d4,0x0780,0x092a,0x0ad5,0x0c7f,
- 0x00ea,0x02bf,0x0495,0x066a,0x0840,0x0a15,0x0beb,0x0dc0,
- 0x0102,0x0306,0x050b,0x070f,0x0914,0x0b18,0x0d1d,0x0f21,
- 0x011c,0x0354,0x058c,0x07c4,0x09fc,0x0c34,0x0e6c,0x10a4,
- 0x0138,0x03a8,0x0619,0x0889,0x0afb,0x0d6b,0x0fdc,0x124c,
- 0x0157,0x0406,0x06b5,0x0964,0x0c14,0x0ec3,0x1172,0x1421,
- 0x017a,0x046e,0x0762,0x0a56,0x0d4a,0x103e,0x1332,0x1626,
- 0x019f,0x04de,0x081e,0x0b5d,0x0e9e,0x11dd,0x151d,0x185c,
- 0x01c9,0x055c,0x08ef,0x0c82,0x1015,0x13a8,0x173b,0x1ace,
- 0x01f7,0x05e5,0x09d4,0x0dc2,0x11b1,0x159f,0x198e,0x1d7c,
- 0x0229,0x067c,0x0acf,0x0f22,0x1375,0x17c8,0x1c1b,0x206e,
- 0x0260,0x0721,0x0be3,0x10a4,0x1567,0x1a28,0x1eea,0x23ab,
- 0x029d,0x07d8,0x0d14,0x124f,0x178b,0x1cc6,0x2202,0x273d,
- 0x02e0,0x08a1,0x0e63,0x1424,0x19e6,0x1fa7,0x2569,0x2b2a,
- 0x032a,0x097f,0x0fd4,0x1629,0x1c7e,0x22d3,0x2928,0x2f7d,
- 0x037b,0x0a72,0x1169,0x1860,0x1f57,0x264e,0x2d45,0x343c,
- 0x03d4,0x0b7d,0x1326,0x1acf,0x2279,0x2a22,0x31cb,0x3974,
- 0x0436,0x0ca3,0x1511,0x1d7e,0x25ec,0x2e59,0x36c7,0x3f34,
- 0x04a2,0x0de7,0x172c,0x2071,0x29b7,0x32fc,0x3c41,0x4586,
- 0x0519,0x0f4b,0x197e,0x23b0,0x2de3,0x3815,0x4248,0x4c7a,
- 0x059b,0x10d2,0x1c0a,0x2741,0x327a,0x3db1,0x48e9,0x5420,
- 0x062b,0x1281,0x1ed8,0x2b2e,0x3786,0x43dc,0x5033,0x5c89,
- 0x06c9,0x145b,0x21ee,0x2f80,0x3d14,0x4aa6,0x5839,0x65cb,
- 0x0777,0x1665,0x2553,0x3441,0x4330,0x521e,0x610c,0x6ffa,
- 0x0836,0x18a2,0x290f,0x397b,0x49e8,0x5a54,0x6ac1,0x7b2d,
- 0x0908,0x1b19,0x2d2a,0x3f3b,0x514c,0x635d,0x756e,0x877f,
- 0x09ef,0x1dce,0x31ae,0x458d,0x596d,0x6d4c,0x812c,0x950b,
- 0x0aee,0x20ca,0x36a6,0x4c82,0x625f,0x783b,0x8e17,0xa3f3,
- 0x0c05,0x2410,0x3c1c,0x5427,0x6c34,0x843f,0x9c4b,0xb456,
- 0x0d39,0x27ac,0x4220,0x5c93,0x7707,0x917a,0xabee,0xc661,
- 0x0e8c,0x2ba4,0x48bd,0x65d5,0x82ee,0xa006,0xbd1f,0xda37,
- 0x0fff,0x2ffe,0x4ffe,0x6ffd,0x8ffe,0xaffd,0xcffd,0xeffc
-};
-
-void ADPCMWestwoodDecoder::decode(uint8 *in, size_t size, int16 *out)
-{
-	uint8 *end = in + size;
-
-	int16 stepIndex = _stepIndex;
-	int32 predictor = _predictor;
-
-	while (in != end)
-	{
-		uint16 bl = *in++;
-
-		for (int n = 0; n != 2; ++n)
-		{
-			uint8 nibble = (bl >> (4 * n)) & 0x0f;
-			uint8 code = nibble & 0x07;
-			uint8 sign = nibble & 0x08;
-
-			int diff = imaStepTable[(stepIndex << 3) | code];
-
-			// Westwood's IMA ADPCM differs from the below standard implementation
-			// in the LSB in a couple of places.
-			//int diff = imaStepTable_std[stepIndex] * code / 4 + imaStepTable_std[stepIndex] / 8;
-
-			if (sign)
-				predictor -= diff;
-			else
-				predictor += diff;
-
-			predictor = CLIP<int32>(predictor, -32768, 32767);
-
-			*out++ = (int16)predictor;
-
-			stepIndex = imaIndexTable[code] + stepIndex;
-			stepIndex = CLIP<int16>(stepIndex, 0, 88);
-		}
-	}
-
-	_stepIndex = stepIndex;
-	_predictor = predictor;
-}
-
-} // End of namespace BladeRunner
diff --git a/engines/bladerunner/aud_decoder.h b/engines/bladerunner/aud_decoder.h
deleted file mode 100644
index c09b5fa..0000000
--- a/engines/bladerunner/aud_decoder.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef BLADERUNNER_AUD_DECODER_H
-#define BLADERUNNER_AUD_DECODER_H
-
-#include "common/types.h"
-
-namespace BladeRunner {
-
-class ADPCMWestwoodDecoder {
-	int16 _stepIndex;
-	int32 _predictor;
-
-public:
-	ADPCMWestwoodDecoder()
-		: _stepIndex(0), _predictor(0)
-	{}
-
-	void setParameters(int16 stepIndex, int32 predictor)
-	{
-		_stepIndex = stepIndex;
-		_predictor = predictor;
-	}
-
-	void decode(uint8 *in, size_t size, int16 *out);
-};
-
-}
-
-#endif
diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
new file mode 100644
index 0000000..28f8531
--- /dev/null
+++ b/engines/bladerunner/aud_stream.cpp
@@ -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.
+ *
+ */
+
+#include "bladerunner/aud_stream.h"
+
+#include "bladerunner/audio_player.h"
+
+#include "common/util.h"
+
+namespace BladeRunner {
+
+AudStream::AudStream(byte *data)
+	: _cache(nullptr)
+{
+	init(data);
+}
+
+AudStream::AudStream(AudioCache *cache, int32 hash)
+	: _cache(cache), _hash(hash)
+{
+	_cache->incRef(_hash);
+
+	init(_cache->findByHash(_hash));
+}
+
+void AudStream::init(byte *data)
+{
+	_data = data;
+	_end = _data + READ_LE_UINT32(_data + 2) + 12;
+	assert(_end - _data >= 12);
+
+	_compressionType = *(_data + 11);
+
+	_deafBlockRemain = 0;
+	_p = _data + 12;
+}
+
+AudStream::~AudStream() {
+	if (_cache)
+		_cache->decRef(_hash);
+}
+
+int AudStream::readBuffer(int16 *buffer, const int numSamples) {
+	int samplesRead = 0;
+
+	assert(numSamples % 2 == 0);
+
+	if (_compressionType == 99) {
+		while (samplesRead < numSamples) {
+			if (_deafBlockRemain == 0) {
+				if (_end - _p == 0)
+					break;
+
+				assert(_end - _p >= 6);
+
+				uint16 blockSize     = READ_LE_UINT16(_p);
+				uint16 blockOutSize  = READ_LE_UINT16(_p + 2);
+				uint32 sig           = READ_LE_UINT32(_p + 4);
+				_p += 8;
+
+				assert(sig == 0xdeaf);
+				assert(_end - _p >= blockSize);
+				assert(blockOutSize = 4 * blockSize);
+
+				_deafBlockRemain = blockSize;
+			}
+
+			assert(_end - _p >= _deafBlockRemain);
+
+			int bytesConsumed = MIN<int>(_deafBlockRemain, (numSamples - samplesRead) / 2);
+
+			_decoder.decode(_p, bytesConsumed, buffer + samplesRead);
+			_p += bytesConsumed;
+			_deafBlockRemain -= bytesConsumed;
+
+			samplesRead += 2 * bytesConsumed;
+		}
+	} else {
+		assert(0 && "readBuffer: Unimplemented");
+	}
+
+	return samplesRead;
+}
+
+bool AudStream::rewind() {
+	_p = _data + 12;
+	_decoder.setParameters(0, 0);
+	return true;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/aud_stream.h b/engines/bladerunner/aud_stream.h
new file mode 100644
index 0000000..3279bda
--- /dev/null
+++ b/engines/bladerunner/aud_stream.h
@@ -0,0 +1,63 @@
+/* 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 BLADERUNNER_AUD_STREAM_H
+#define BLADERUNNER_AUD_STREAM_H
+
+#include "bladerunner/adpcm_decoder.h"
+
+#include "audio/audiostream.h"
+#include "common/endian.h"
+#include "common/types.h"
+
+namespace BladeRunner {
+
+class AudioCache;
+
+class AudStream : public Audio::RewindableAudioStream {
+	byte       *_data;
+	byte       *_p;
+	byte       *_end;
+	AudioCache *_cache;
+	int32       _hash;
+	byte        _compressionType;
+	uint16      _deafBlockRemain;
+
+	ADPCMWestwoodDecoder _decoder;
+
+	void init(byte *data);
+
+public:
+	AudStream(byte *data);
+	AudStream(AudioCache *cache, int32 hash);
+	~AudStream();
+
+	int readBuffer(int16 *buffer, const int numSamples);
+	bool isStereo() const { return false; }
+	int getRate() const { return READ_LE_UINT16(_data); };
+	bool endOfData() const { return _p == _end; }
+	bool rewind();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index 293fc56..ecfc95a 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -23,16 +23,14 @@
 #include "audio_player.h"
 
 #include "bladerunner/archive.h"
-#include "bladerunner/aud_decoder.h"
+#include "bladerunner/aud_stream.h"
 
 #include "bladerunner/bladerunner.h"
 
 #include "audio/audiostream.h"
 #include "audio/mixer.h"
 
-#include "common/array.h"
 #include "common/debug.h"
-#include "common/mutex.h"
 #include "common/stream.h"
 
 namespace Common {
@@ -41,41 +39,6 @@ namespace Common {
 
 namespace BladeRunner {
 
-/*
- * This is a poor imitation of Bladerunner's resource cache
- */
-class AudioCache {
-	struct cacheItem {
-		int32   hash;
-		int     refs;
-		uint    lastAccess;
-		byte   *data;
-		uint32  size;
-	};
-
-	Common::Mutex            _mutex;
-	Common::Array<cacheItem> _cacheItems;
-
-	uint32 _totalSize;
-	uint32 _maxSize;
-	uint32 _accessCounter;
-public:
-	AudioCache() :
-		_totalSize(0),
-		_maxSize(2457600),
-		_accessCounter(0)
-	{}
-	~AudioCache();
-
-	bool  canAllocate(uint32 size);
-	bool  dropOldest();
-	byte *findByHash(int32 hash);
-	void  storeByHash(int32 hash, Common::SeekableReadStream *stream);
-
-	void  incRef(int32 hash);
-	void  decRef(int32 hash);
-};
-
 AudioCache::~AudioCache() {
 	for (uint i = 0; i != _cacheItems.size(); ++i) {
 		free(_cacheItems[i].data);
@@ -163,91 +126,6 @@ void AudioCache::decRef(int32 hash) {
 	assert(0 && "AudioCache::decRef: hash not found");
 }
 
-class AudStream : public Audio::RewindableAudioStream {
-	byte       *_data;
-	byte       *_p;
-	byte       *_end;
-	AudioCache *_cache;
-	int32       _hash;
-	byte        _compressionType;
-	uint16      _deafBlockRemain;
-
-	ADPCMWestwoodDecoder _decoder;
-
-public:
-	AudStream(AudioCache *cache, int32 hash)
-		: _cache(cache), _hash(hash)
-	{
-		_data = _cache->findByHash(_hash);
-		_end = _data + READ_LE_UINT32(_data + 2) + 12;
-		_cache->incRef(_hash);
-
-		assert(_end - _data >= 12);
-
-		_compressionType = *(_data + 11);
-
-		_deafBlockRemain = 0;
-		_p = _data + 12;
-	}
-	~AudStream() {
-		_cache->decRef(_hash);
-	}
-
-	int readBuffer(int16 *buffer, const int numSamples);
-	bool isStereo() const { return false; }
-	int getRate() const { return READ_LE_UINT16(_data); };
-	bool endOfData() const { return _p == _end; }
-	bool rewind();
-};
-
-int AudStream::readBuffer(int16 *buffer, const int numSamples) {
-	int samplesRead = 0;
-
-	assert(numSamples % 2 == 0);
-
-	if (_compressionType == 99) {
-		while (samplesRead < numSamples) {
-			if (_deafBlockRemain == 0) {
-				if (_end - _p == 0)
-					break;
-
-				assert(_end - _p >= 6);
-
-				uint16 blockSize     = READ_LE_UINT16(_p);
-				uint16 blockOutSize  = READ_LE_UINT16(_p + 2);
-				uint32 sig           = READ_LE_UINT32(_p + 4);
-				_p += 8;
-
-				assert(sig == 0xdeaf);
-				assert(_end - _p >= blockSize);
-				assert(blockOutSize = 4 * blockSize);
-
-				_deafBlockRemain = blockSize;
-			}
-
-			assert(_end - _p >= _deafBlockRemain);
-
-			int bytesConsumed = MIN<int>(_deafBlockRemain, (numSamples - samplesRead) / 2);
-
-			_decoder.decode(_p, bytesConsumed, buffer + samplesRead);
-			_p += bytesConsumed;
-			_deafBlockRemain -= bytesConsumed;
-
-			samplesRead += 2 * bytesConsumed;
-		}
-	} else {
-		assert(0 && "readBuffer: Unimplemented");
-	}
-
-	return samplesRead;
-}
-
-bool AudStream::rewind() {
-	_p = _data + 12;
-	_decoder.setParameters(0, 0);
-	return true;
-}
-
 AudioPlayer::AudioPlayer(BladeRunnerEngine *vm)
 	: _vm(vm)
 {
diff --git a/engines/bladerunner/audio_player.h b/engines/bladerunner/audio_player.h
index 32c7dbb..eb4c75d 100644
--- a/engines/bladerunner/audio_player.h
+++ b/engines/bladerunner/audio_player.h
@@ -24,6 +24,8 @@
 #define BLADERUNNER_AUDIO_H
 
 #include "audio/mixer.h"
+#include "common/array.h"
+#include "common/mutex.h"
 #include "common/str.h"
 #include "common/types.h"
 
@@ -34,6 +36,41 @@ class AudioCache;
 
 #define TRACKS 6
 
+/*
+ * This is a poor imitation of Bladerunner's resource cache
+ */
+class AudioCache {
+	struct cacheItem {
+		int32   hash;
+		int     refs;
+		uint    lastAccess;
+		byte   *data;
+		uint32  size;
+	};
+
+	Common::Mutex            _mutex;
+	Common::Array<cacheItem> _cacheItems;
+
+	uint32 _totalSize;
+	uint32 _maxSize;
+	uint32 _accessCounter;
+public:
+	AudioCache() :
+		_totalSize(0),
+		_maxSize(2457600),
+		_accessCounter(0)
+	{}
+	~AudioCache();
+
+	bool  canAllocate(uint32 size);
+	bool  dropOldest();
+	byte *findByHash(int32 hash);
+	void  storeByHash(int32 hash, Common::SeekableReadStream *stream);
+
+	void  incRef(int32 hash);
+	void  decRef(int32 hash);
+};
+
 class AudioPlayer {
 	BladeRunnerEngine *_vm;
 	AudioCache *_cache;
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 8bc3b36..64d5ba8 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -1,9 +1,10 @@
 MODULE := engines/bladerunner
 
 MODULE_OBJS = \
+	adpcm_decoder.o \
 	ambient_sounds.o \
 	archive.o \
-	aud_decoder.o \
+	aud_stream.o \
 	audio_player.o \
 	bladerunner.o \
 	boundingbox.o \
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 8b4293d..3f8c968 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -23,7 +23,7 @@
 #ifndef BLADERUNNER_VQA_DECODER_H
 #define BLADERUNNER_VQA_DECODER_H
 
-#include "bladerunner/aud_decoder.h"
+#include "bladerunner/adpcm_decoder.h"
 #include "bladerunner/view.h"
 
 #include "audio/audiostream.h"


Commit: eba8ed5c6642cf3686c4fb7e28ceca9299e3a33a
    https://github.com/scummvm/scummvm/commit/eba8ed5c6642cf3686c4fb7e28ceca9299e3a33a
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:38+02:00

Commit Message:
BLADERUNNER: Add audio_speech and Actor_Voice_Over

Changed paths:
  A engines/bladerunner/audio_speech.cpp
  A engines/bladerunner/audio_speech.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/module.mk
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/audio_speech.cpp b/engines/bladerunner/audio_speech.cpp
new file mode 100644
index 0000000..6fa9c94
--- /dev/null
+++ b/engines/bladerunner/audio_speech.cpp
@@ -0,0 +1,96 @@
+/* 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 "bladerunner/audio_speech.h"
+
+#include "bladerunner/aud_stream.h"
+#include "bladerunner/bladerunner.h"
+
+#include "common/debug.h"
+
+namespace BladeRunner {
+
+#define BUFFER_SIZE 200000
+
+AudioSpeech::AudioSpeech(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_volume = 50;
+	_isMaybeActive = false;
+	_data = new byte[BUFFER_SIZE];
+}
+
+AudioSpeech::~AudioSpeech() {
+	delete[] _data;
+}
+
+bool AudioSpeech::playSpeech(const char *name, int balance) {
+
+	Common::ScopedPtr<Common::SeekableReadStream> r(_vm->getResourceStream(name));
+
+	if (!r) {
+		debug("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name);
+		return false;
+	}
+
+	if (r->size() > BUFFER_SIZE) {
+		debug("AudioSpeech::playSpeech: AUD larger than buffer size (%d > %d)", r->size(), BUFFER_SIZE);
+		return false;
+	}
+
+	if (isPlaying()) {
+		stopSpeech();
+	}
+
+	r->read(_data, r->size());
+	if (r->err()) {
+		debug("AudioSpeech::playSpeech: Error reading resource \"%s\"", name);
+		return false;
+	}
+
+	AudStream *audioStream = new AudStream(_data);
+
+	_vm->_mixer->playStream(
+		Audio::Mixer::kPlainSoundType,
+		&_soundHandle,
+		audioStream,
+		-1,
+		_volume * 255 / 100,
+		balance);
+
+	_isMaybeActive = true;
+
+	return true;
+}
+
+void AudioSpeech::stopSpeech() {
+	_vm->_mixer->stopHandle(_soundHandle);
+}
+
+bool AudioSpeech::isPlaying() {
+	if (!_isMaybeActive)
+		return false;
+
+	return _isMaybeActive = _vm->_mixer->isSoundHandleActive(_soundHandle);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/audio_speech.h b/engines/bladerunner/audio_speech.h
new file mode 100644
index 0000000..e122422
--- /dev/null
+++ b/engines/bladerunner/audio_speech.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.
+ *
+ */
+
+#ifndef BLADERUNNER_AUDIO_SPEECH_H
+#define BLADERUNNER_AUDIO_SPEECH_H
+
+#include "audio/mixer.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class AudioSpeech {
+private:
+	BladeRunnerEngine  *_vm;
+	int                 _volume;
+	bool                _isMaybeActive;
+	Audio::SoundHandle  _soundHandle;
+	byte               *_data;
+
+public:
+	AudioSpeech(BladeRunnerEngine *vm);
+	~AudioSpeech();
+
+	bool playSpeech(const char *name, int balance = 50);
+	void stopSpeech();
+	bool isPlaying();
+	void setVolume(int volume) { _volume = volume; }
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 48ffb7b..d69a77c 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -25,6 +25,7 @@
 
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
+#include "bladerunner/audio_speech.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/clues.h"
 #include "bladerunner/gameinfo.h"
@@ -59,6 +60,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 
 	_ambientSounds = new AmbientSounds(this);
 	_audioPlayer = new AudioPlayer(this);
+	_audioSpeech = new AudioSpeech(this);
 	_chapters = nullptr;
 	_clues = nullptr;
 	_gameInfo = nullptr;
@@ -82,6 +84,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	delete _gameInfo;
 	delete _clues;
 	delete _chapters;
+	delete _audioSpeech;
 	delete _audioPlayer;
 	delete _ambientSounds;
 
@@ -301,6 +304,19 @@ void BladeRunnerEngine::handleEvents() {
 	}
 }
 
+void BladeRunnerEngine::loopActorSpeaking() {
+	if (!_audioSpeech->isPlaying())
+		return;
+
+	// playerLosesControl();
+
+	do {
+		gameTick();
+	} while (_audioSpeech->isPlaying());
+
+	// playerGainsControl();
+}
+
 void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
 	Common::String name = _gameInfo->getOuttake(id);
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 9d8e4af..b0df9bd 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -38,6 +38,7 @@ namespace BladeRunner {
 
 class AmbientSounds;
 class AudioPlayer;
+class AudioSpeech;
 class Chapters;
 class Clues;
 class GameInfo;
@@ -56,6 +57,7 @@ public:
 
 	AmbientSounds   *_ambientSounds;
 	AudioPlayer     *_audioPlayer;
+	AudioSpeech     *_audioSpeech;
 	Chapters        *_chapters;
 	Clues           *_clues;
 	GameInfo        *_gameInfo;
@@ -100,6 +102,7 @@ public:
 	void gameLoop();
 	void gameTick();
 	void handleEvents();
+	void loopActorSpeaking();
 
 	void outtakePlay(int id, bool no_localization, int container = -1);
 
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 64d5ba8..fd23e94 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -6,6 +6,7 @@ MODULE_OBJS = \
 	archive.o \
 	aud_stream.o \
 	audio_player.o \
+	audio_speech.o \
 	bladerunner.o \
 	boundingbox.o \
 	chapters.o \
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 2fa5778..81c4795 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -118,7 +118,17 @@ void ScriptRC01::InitializeScene() {
 }
 
 void ScriptRC01::SceneLoaded() {
-
+	if (!Game_Flag_Query(24)){
+		// ADQ_Flush();
+		Actor_Voice_Over(1830, 99);
+		Actor_Voice_Over(1850, 99);
+		if (!Game_Flag_Query(378)) {
+			Actor_Voice_Over(1860, 99);
+			I_Sez("MG: Is David Leary a self-respecting human or is he powered by rechargeable");
+			I_Sez("batteries?\n");
+		}
+		Game_Flag_Set(24);
+	}
 }
 
 void ScriptRC01::SceneFrameAdvanced(int frame) {
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 8386fc2..62754be 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -26,6 +26,7 @@
 
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
+#include "bladerunner/audio_speech.h"
 #include "bladerunner/clues.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
@@ -108,7 +109,17 @@ void Script::SceneFrameAdvanced(int frame) {
 // ScriptBase::Actor_Set_Targetable
 // ScriptBase::Actor_Says
 // ScriptBase::Actor_Says_With_Pause
-// ScriptBase::Actor_Voice_Over
+
+void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
+	// Wait for any existing speech to end
+	_vm->loopActorSpeaking();
+
+	// TODO: Hack - This needs to go through the actor class
+	char name[13];
+	sprintf(name, "%02d-%04d.AUD", actorId, sentenceId);
+	_vm->_audioSpeech->playSpeech(name);
+}
+
 // ScriptBase::Actor_Start_Speech_Sample
 // ScriptBase::Actor_Start_Voice_Over_Sample
 // ScriptBase::Actor_Query_Which_Set_In
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index a6ac20b..82f7be8 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -84,7 +84,7 @@ protected:
 	// Actor_Set_Targetable
 	// Actor_Says
 	// Actor_Says_With_Pause
-	// Actor_Voice_Over
+	void Actor_Voice_Over(int sentenceId, int actorId);
 	// Actor_Start_Speech_Sample
 	// Actor_Start_Voice_Over_Sample
 	// Actor_Query_Which_Set_In


Commit: da33169b75021d19f35867aca2b9322c1aec0005
    https://github.com/scummvm/scummvm/commit/da33169b75021d19f35867aca2b9322c1aec0005
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:38+02:00

Commit Message:
BLADERUNNER: Fix a couple of memory leaks

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/clues.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/text_resource.cpp
    engines/bladerunner/vqa_decoder.cpp



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index d69a77c..13ccae7 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -71,15 +71,22 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_settings = new Settings(this);
 	_sliceAnimations = new SliceAnimations(this);
 	_sliceRenderer = new SliceRenderer(this);
+
+	_zBuffer1 = nullptr;
+	_zBuffer2 = nullptr;
+
+	_actorNames = nullptr;
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
+	delete _actorNames;
+
 	delete _sliceRenderer;
 	delete _sliceAnimations;
 	delete _settings;
 	delete _script;
 	delete _scene;
-	delete _gameVars;
+	delete[] _gameVars;
 	delete _gameFlags;
 	delete _gameInfo;
 	delete _clues;
@@ -90,6 +97,9 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 
 	_surface1.free();
 	_surface2.free();
+
+	delete[] _zBuffer1;
+	delete[] _zBuffer2;
 }
 
 bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
@@ -102,8 +112,10 @@ Common::Error BladeRunnerEngine::run() {
 
 	_system->showMouse(true);
 
-	if (!startup())
+	if (!startup()) {
+		shutdown();
 		return Common::Error(Common::kUnknownError, "Failed to initialize resources");
+	}
 
 	if (warnUserAboutUnsupportedGame()) {
 		init2();
diff --git a/engines/bladerunner/clues.cpp b/engines/bladerunner/clues.cpp
index cc47ae0..5b1ce97 100644
--- a/engines/bladerunner/clues.cpp
+++ b/engines/bladerunner/clues.cpp
@@ -45,6 +45,7 @@ Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, uint32 clueCount)
 }
 
 Clues::~Clues() {
+	delete _cluesText;
 	delete[] _assetTypes;
 	delete[] _crimes;
 }
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 3a71fb3..f0721b3 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -61,7 +61,10 @@ public:
 		  _nextSetId(-1),
 		  _nextSceneId(-1),
 		  _playerWalkedIn(false)
-	{
+	{}
+
+	~Scene() {
+		delete _set;
 	}
 
 	bool open(int setId, int sceneId, bool isLoadingGame);
diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp
index 9bb71fa..ce9e6f7 100644
--- a/engines/bladerunner/text_resource.cpp
+++ b/engines/bladerunner/text_resource.cpp
@@ -50,7 +50,7 @@ bool TextResource::open(const char *name) {
 
 	char resName[13];
 	sprintf(resName, "%s.TRE", name);
-	Common::SeekableReadStream *s = _vm->getResourceStream(resName);
+	Common::ScopedPtr<Common::SeekableReadStream> s(_vm->getResourceStream(resName));
 	if (!s)
 		return false;
 
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index a6e7e7c..d1e56a9 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -571,6 +571,7 @@ VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
 	if (_surface)
 		_surface->free();
 	delete _surface;
+	delete _zbuffer;
 }
 
 uint16 VQADecoder::VQAVideoTrack::getWidth() const {


Commit: 0fa2191b9532c353ab40a82ee3c29e822dc09840
    https://github.com/scummvm/scummvm/commit/0fa2191b9532c353ab40a82ee3c29e822dc09840
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:38+02:00

Commit Message:
BLADERUNNER: Implement loading and drawing of mouse cursors.

Changed paths:
  A engines/bladerunner/mouse.cpp
  A engines/bladerunner/mouse.h
  A engines/bladerunner/shape.cpp
  A engines/bladerunner/shape.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/module.mk



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 13ccae7..aa2850a 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -28,19 +28,22 @@
 #include "bladerunner/audio_speech.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/clues.h"
-#include "bladerunner/gameinfo.h"
 #include "bladerunner/gameflags.h"
+#include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
+#include "bladerunner/mouse.h"
 #include "bladerunner/outtake.h"
 #include "bladerunner/scene.h"
 #include "bladerunner/script/init.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/settings.h"
+#include "bladerunner/shape.h"
 #include "bladerunner/slice_animations.h"
 #include "bladerunner/slice_renderer.h"
 #include "bladerunner/text_resource.h"
 #include "bladerunner/vqa_decoder.h"
 
+#include "common/array.h"
 #include "common/error.h"
 #include "common/events.h"
 #include "common/system.h"
@@ -66,6 +69,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_gameInfo = nullptr;
 	_gameFlags = new GameFlags();
 	_gameVars = nullptr;
+	_mouse = new Mouse(this);
 	_scene = new Scene(this);
 	_script = new Script(this);
 	_settings = new Settings(this);
@@ -168,6 +172,13 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
+	for (int i = 0; i != 43; ++i) {
+		Shape *shape = new Shape(this);
+		shape->readFromContainer("SHAPES.SHP", i);
+		_shapes.push_back(shape);
+	}
+	_mouse->setCursor(0);
+
 	r = _sliceAnimations->open("INDEX.DAT");
 	if (!r)
 		return false;
@@ -299,6 +310,10 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Draw item pickup (understood, drawing works in Replicant)
 			// TODO: Draw dialogue menu
 			// TODO: Draw mouse (understood)
+
+			Common::Point p = _eventMan->getMousePos();
+			_mouse->draw(_surface2, p.x, p.y);
+
 			// TODO: Process AUD (audio in Replicant)
 			// TODO: Footstep sound
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index b0df9bd..06a1a7a 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -43,9 +43,11 @@ class Chapters;
 class Clues;
 class GameInfo;
 class GameFlags;
+class Mouse;
 class Scene;
 class Script;
 class Settings;
+class Shape;
 class SliceAnimations;
 class SliceRenderer;
 class TextResource;
@@ -60,8 +62,9 @@ public:
 	AudioSpeech     *_audioSpeech;
 	Chapters        *_chapters;
 	Clues           *_clues;
-	GameInfo        *_gameInfo;
 	GameFlags       *_gameFlags;
+	GameInfo        *_gameInfo;
+	Mouse           *_mouse;
 	Scene           *_scene;
 	Script          *_script;
 	Settings        *_settings;
@@ -70,6 +73,7 @@ public:
 	int             *_gameVars;
 
 	TextResource    *_actorNames;
+	Common::Array<Shape*> _shapes;
 
 	int in_script_counter;
 
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index fd23e94..8cd9ba4 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -18,6 +18,7 @@ MODULE_OBJS = \
 	gameinfo.o \
 	image.o \
 	matrix.o \
+	mouse.o \
 	outtake.o \
 	scene.o \
 	script/init.o \
@@ -25,6 +26,7 @@ MODULE_OBJS = \
 	script/script.o \
 	set.o \
 	settings.o \
+	shape.o \
 	slice_animations.o \
 	slice_renderer.o \
 	text_resource.o \
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
new file mode 100644
index 0000000..8a259fd
--- /dev/null
+++ b/engines/bladerunner/mouse.cpp
@@ -0,0 +1,250 @@
+/* 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 "bladerunner/mouse.h"
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/shape.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+Mouse::Mouse(BladeRunnerEngine *vm)
+	: _vm(vm)
+{
+	_cursor = 0;
+	_frame = 3;
+	_hotspotX = 0;
+	_hotspotY = 0;
+	_x = 0;
+	_y = 0;
+	_disabledCounter = 0;
+	_lastFrameTime = 0;
+}
+
+Mouse::~Mouse() {
+}
+
+void Mouse::setCursor(int cursor) {
+	assert(cursor >= 0 && cursor <= 16);
+	if (cursor == _cursor) {
+		return;
+	}
+
+	_cursor = cursor;
+
+	switch (_cursor) {
+	case 0:
+		_frame = 3;
+		_hotspotX = 0;
+		_hotspotY = 0;
+		break;
+	case 1:
+		_frame = 4;
+		_hotspotX = 0;
+		_hotspotY = 0;
+		break;
+	case 2:
+		_frame = 12;
+		_hotspotX = 12;
+		_hotspotY = 0;
+		break;
+	case 3:
+		_frame = 15;
+		_hotspotX = 23;
+		_hotspotY = 12;
+		break;
+	case 4:
+		_frame = 13;
+		_hotspotX = 12;
+		_hotspotY = 23;
+		break;
+	case 5:
+		_frame = 14;
+		_hotspotX = 0;
+		_hotspotY = 12;
+		break;
+	case 6:
+		_frame = 16;
+		_hotspotX = 19;
+		_hotspotY = 19;
+		break;
+	case 7:
+		_frame = 17;
+		_hotspotX = 19;
+		_hotspotY = 19;
+		break;
+	case 8:
+		_frame = 25;
+		_hotspotX = 19;
+		_hotspotY = 19;
+		break;
+	case 9:
+		_frame = 26;
+		_hotspotX = 19;
+		_hotspotY = 19;
+		break;
+	case 10:
+		_frame = 34;
+		_hotspotX = 19;
+		_hotspotY = 19;
+		break;
+	case 11:
+		_frame = 35;
+		_hotspotX = 19;
+		_hotspotY = 19;
+		break;
+	case 12:
+		_frame = 12;
+		_hotspotX = 12;
+		_hotspotY = 0;
+		_animCounter = 0;
+		break;
+	case 13:
+		_frame = 15;
+		_hotspotX = 23;
+		_hotspotY = 12;
+		_animCounter = 0;
+		break;
+	case 14:
+		_frame = 13;
+		_hotspotX = 12;
+		_hotspotY = 23;
+		_animCounter = 0;
+		break;
+	case 15:
+		_frame = 14;
+		_hotspotX = 0;
+		_hotspotY = 12;
+		_animCounter = 0;
+		break;
+	case 16:
+		_frame = 0;
+		_hotspotX = 11;
+		_hotspotY = 11;
+	}
+}
+
+void Mouse::disable() {
+	++_disabledCounter;
+}
+
+void Mouse::enable() {
+	if (--_disabledCounter <= 0) {
+		_disabledCounter = 0;
+	}
+}
+
+bool Mouse::isDisabled() {
+	return _disabledCounter > 0;
+}
+
+void Mouse::draw(Graphics::Surface &surface, int x, int y) {
+	if (_disabledCounter) {
+		return;
+	}
+
+	_x = CLIP(x, 0, surface.w - 1);
+	_y = CLIP(y, 0, surface.h - 1);
+
+
+	if (_cursor < 0 || (uint)_cursor >= _vm->_shapes.size()) {
+		return;
+	}
+
+	Shape *cursorShape = _vm->_shapes[_frame];
+
+	cursorShape->draw(surface, _x - _hotspotX, _y - _hotspotY);
+
+	updateCursorFrame();
+}
+
+void Mouse::updateCursorFrame() {
+	uint32 now = _vm->getTotalPlayTime();
+	const int offset[4] = { 0, 6, 12, 6 };
+
+	if (now - _lastFrameTime < 66) {
+		return;
+	}
+	_lastFrameTime = now;
+
+	switch (_cursor) {
+	case 0:
+		break;
+	case 1:
+		if (++_frame > 11)
+			_frame = 4;
+		break;
+	case 2:
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+		break;
+	case 7:
+		if (++_frame > 24)
+			_frame = 17;
+		break;
+	case 8:
+		break;
+	case 9:
+		if (++_frame > 33)
+			_frame = 26;
+		break;
+	case 10:
+		break;
+	case 11:
+		if (++_frame > 42)
+			_frame = 35;
+		break;
+	case 12:
+		if (++_animCounter >= 4) {
+			_animCounter = 0;
+		}
+		_hotspotY = -offset[_animCounter];
+		break;
+	case 13:
+		if (++_animCounter >= 4) {
+			_animCounter = 0;
+		}
+		_hotspotX = 23 + offset[_animCounter];
+		break;
+	case 14:
+		if (++_animCounter >= 4) {
+			_animCounter = 0;
+		}
+		_hotspotY = 23 + offset[_animCounter];
+		break;
+	case 15:
+		if (++_animCounter >= 4) {
+			_animCounter = 0;
+		}
+		_hotspotX = -offset[_animCounter];
+		break;
+	case 16:
+		if (++_frame > 2)
+			_frame = 0;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/mouse.h b/engines/bladerunner/mouse.h
new file mode 100644
index 0000000..33f2314
--- /dev/null
+++ b/engines/bladerunner/mouse.h
@@ -0,0 +1,63 @@
+/* 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 BLADERUNNER_MOUSE_H
+#define BLADERUNNER_MOUSE_H
+
+namespace Graphics {
+	struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Mouse {
+	BladeRunnerEngine *_vm;
+
+	int _cursor;
+	int _frame;
+	int _hotspotX;
+	int _hotspotY;
+	int _x;
+	int _y;
+	int _disabledCounter;
+	int _lastFrameTime;
+	int _animCounter;
+
+public:
+	Mouse(BladeRunnerEngine *vm);
+	~Mouse();
+
+	void setCursor(int cursor);
+
+	void disable();
+	void enable();
+	bool isDisabled();
+
+	void draw(Graphics::Surface &surface, int x, int y);
+	void updateCursorFrame();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/shape.cpp b/engines/bladerunner/shape.cpp
new file mode 100644
index 0000000..be4db1e
--- /dev/null
+++ b/engines/bladerunner/shape.cpp
@@ -0,0 +1,132 @@
+/* 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 "bladerunner/shape.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/debug.h"
+#include "common/ptr.h"
+#include "common/util.h"
+
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+Shape::Shape(BladeRunnerEngine *vm)
+	: _vm(vm), _data(0)
+{
+}
+
+Shape::~Shape() {
+	delete[] _data;
+}
+
+bool Shape::readFromContainer(const Common::String &container, int index) {
+	Common::ScopedPtr<Common::SeekableReadStream> stream(_vm->getResourceStream(container));
+	if (!stream) {
+		debug("Shape::readFromContainer failed to open '%s'", container.c_str());
+		return false;
+	}
+
+	uint32 count = stream->readUint32LE();
+	if (index < 0 || (uint32)index >= count) {
+		debug("Shape::readFromContainer invalid index %d (count %u)", index, count);
+		return false;
+	}
+
+	uint32 size, width, height;
+	for (int i = 0; i <= index; ++i) {
+		width  = stream->readUint32LE();
+		height = stream->readUint32LE();
+		size   = stream->readUint32LE();
+
+		if (size != width * height * 2) {
+			debug("Shape::readFromContainer size mismatch (w %d, h %d, sz %d)", width, height, size);
+			return false;
+		}
+
+		if (i != index) {
+			stream->skip(size);
+		}
+	}
+
+	// Enfoce a reasonable size limit
+	if (width >= 2048 || height >= 2048) {
+		warning("Shape::readFromContainer shape too big (%d, %d)", width, height);
+	}
+
+	_width  = width;
+	_height = height;
+	_data   = new byte[size];
+
+	if (stream->read(_data, size) != size) {
+		debug("Shape::readFromContainer error reading shape %d (w %d, h %d, sz %d)", index, width, height, size);
+		return false;
+	}
+
+	return true;
+}
+
+void Shape::draw(Graphics::Surface &surface, int x, int y) {
+	// debug("x=%d, y=%d", x, y);
+	// debug("w=%d, h=%d", _width, _height);
+
+	int src_x = CLIP(-x, 0, _width);
+	int src_y = CLIP(-y, 0, _height);
+
+	// debug("src_x=%d, src_y=%d", src_x, src_y);
+
+	int dst_x = CLIP<int>(x, 0, surface.w);
+	int dst_y = CLIP<int>(y, 0, surface.h);
+
+	// debug("dst_x=%d, dst_y=%d", dst_x, dst_y);
+
+	int rect_w = MIN(CLIP(_width + x, 0, _width), surface.w - x);
+	int rect_h = MIN(CLIP(_height + y, 0, _height), surface.h - y);
+
+	// debug("rect_w=%d, rect_h=%d", rect_w, rect_h);
+
+	if (rect_w == 0 || rect_h == 0) {
+		return;
+	}
+
+	byte *src_p = _data + 2 * (src_y * _width + src_x);
+	byte *dst_p = (byte*)surface.getBasePtr(dst_x, dst_y);
+
+	for (int yi = 0; yi != rect_h; ++yi) {
+		for (int xi = 0; xi != rect_w; ++xi) {
+			uint16 color = READ_LE_UINT16(src_p);
+			if ((color & 0x8000) == 0) {
+				*(uint16*)dst_p = color;
+			}
+
+			src_p += 2;
+			dst_p += 2;
+		}
+
+		src_p += 2 * (_width - rect_w);
+		dst_p += surface.pitch - 2*rect_w;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/shape.h b/engines/bladerunner/shape.h
new file mode 100644
index 0000000..782d20f
--- /dev/null
+++ b/engines/bladerunner/shape.h
@@ -0,0 +1,54 @@
+/* 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 BLADERUNNER_SHAPE_H
+#define BLADERUNNER_SHAPE_H
+
+#include "common/substream.h"
+
+namespace Graphics {
+	struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class Shape {
+	BladeRunnerEngine *_vm;
+
+	int   _width;
+	int   _height;
+	byte *_data;
+
+public:
+	Shape(BladeRunnerEngine *vm);
+	~Shape();
+
+	bool readFromContainer(const Common::String &container, int index);
+
+	void draw(Graphics::Surface &surface, int x, int y);
+};
+
+} // End of namespace BladeRunner
+
+#endif


Commit: 28c55ade8985d3721a444bbc253eadcef062b8cf
    https://github.com/scummvm/scummvm/commit/28c55ade8985d3721a444bbc253eadcef062b8cf
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:39+02:00

Commit Message:
BLADERUNNER: Add newline at end of file

Changed paths:
    engines/bladerunner/gameflags.h



diff --git a/engines/bladerunner/gameflags.h b/engines/bladerunner/gameflags.h
index 4df9e5a..ea85819 100644
--- a/engines/bladerunner/gameflags.h
+++ b/engines/bladerunner/gameflags.h
@@ -44,4 +44,4 @@ public:
 
 } // End of namespace BladeRunner
 
-#endif
\ No newline at end of file
+#endif


Commit: 90f879f5a88ed7ab0aff2a46b84f1581f20432e4
    https://github.com/scummvm/scummvm/commit/90f879f5a88ed7ab0aff2a46b84f1581f20432e4
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:39+02:00

Commit Message:
BLADERUNNER: Implement Player_Loses_Control and Player_Gains_Control

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index aa2850a..2279feb 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -60,6 +60,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 {
 	_windowIsActive = true;
 	_gameIsRunning  = true;
+	_playerLosesControlCounter = 0;
 
 	_ambientSounds = new AmbientSounds(this);
 	_audioPlayer = new AudioPlayer(this);
@@ -335,13 +336,13 @@ void BladeRunnerEngine::loopActorSpeaking() {
 	if (!_audioSpeech->isPlaying())
 		return;
 
-	// playerLosesControl();
+	playerLosesControl();
 
 	do {
 		gameTick();
 	} while (_audioSpeech->isPlaying());
 
-	// playerGainsControl();
+	playerGainsControl();
 }
 
 void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
@@ -415,9 +416,34 @@ Common::SeekableReadStream *BladeRunnerEngine::getResourceStream(const Common::S
 	return 0;
 }
 
+bool BladeRunnerEngine::playerHasControl() {
+	return _playerLosesControlCounter == 0;
+}
+
+void BladeRunnerEngine::playerLosesControl() {
+	if (++_playerLosesControlCounter == 1) {
+		_mouse->disable();
+	}
+	debug("Player Lost Control (%d)", _playerLosesControlCounter);
+}
+
+void BladeRunnerEngine::playerGainsControl() {
+	if (_playerLosesControlCounter == 0) {
+		warning("Unbalanced call to BladeRunnerEngine::playerGainsControl");
+	}
+
+	if (_playerLosesControlCounter > 0)
+		--_playerLosesControlCounter;
+
+	debug("Player Gained Control (%d)", _playerLosesControlCounter);
+
+	if (_playerLosesControlCounter == 0) {
+		_mouse->enable();
+	}
+}
+
 void BladeRunnerEngine::ISez(const char *str) {
 	debug("\t%s", str);
 }
 
-
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 06a1a7a..0abd142 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -56,6 +56,7 @@ class BladeRunnerEngine : public Engine {
 public:
 	bool      _gameIsRunning;
 	bool      _windowIsActive;
+	int       _playerLosesControlCounter;
 
 	AmbientSounds   *_ambientSounds;
 	AudioPlayer     *_audioPlayer;
@@ -116,6 +117,10 @@ public:
 
 	Common::SeekableReadStream *getResourceStream(const Common::String &name);
 
+	bool playerHasControl();
+	void playerLosesControl();
+	void playerGainsControl();
+
 	void ISez(const char *str);
 };
 
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 62754be..5788936 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -172,8 +172,15 @@ void ScriptBase::Actor_Clue_Add_To_Database(int a0, int a1, int a2, int a3, int
 // ScriptBase::Animation_Stop
 // ScriptBase::Animation_Skip_To_Frame
 // ScriptBase::Delay
-// ScriptBase::Player_Loses_Control
-// ScriptBase::Player_Gains_Control
+
+void ScriptBase::Player_Loses_Control() {
+		_vm->playerLosesControl();
+}
+
+void ScriptBase::Player_Gains_Control() {
+		_vm->playerGainsControl();
+}
+
 // ScriptBase::Player_Set_Combat_Mode
 // ScriptBase::Player_Query_Combat_Mode
 // ScriptBase::Player_Set_Combat_Mode_Access
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 82f7be8..e399a64 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -131,8 +131,8 @@ protected:
 	// Animation_Stop
 	// Animation_Skip_To_Frame
 	// Delay
-	// Player_Loses_Control
-	// Player_Gains_Control
+	void Player_Loses_Control();
+	void Player_Gains_Control();
 	// Player_Set_Combat_Mode
 	// Player_Query_Combat_Mode
 	// Player_Set_Combat_Mode_Access


Commit: 02473a16c3faf89d03984e85e4852d0c1ce021f1
    https://github.com/scummvm/scummvm/commit/02473a16c3faf89d03984e85e4852d0c1ce021f1
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:39+02:00

Commit Message:
BLADERUNNER: Rearrange startup and shutdown a bit and document TODOs

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 2279feb..d44a0d8 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -62,49 +62,33 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_gameIsRunning  = true;
 	_playerLosesControlCounter = 0;
 
-	_ambientSounds = new AmbientSounds(this);
-	_audioPlayer = new AudioPlayer(this);
-	_audioSpeech = new AudioSpeech(this);
-	_chapters = nullptr;
-	_clues = nullptr;
-	_gameInfo = nullptr;
-	_gameFlags = new GameFlags();
-	_gameVars = nullptr;
-	_mouse = new Mouse(this);
-	_scene = new Scene(this);
 	_script = new Script(this);
 	_settings = new Settings(this);
-	_sliceAnimations = new SliceAnimations(this);
-	_sliceRenderer = new SliceRenderer(this);
-
-	_zBuffer1 = nullptr;
-	_zBuffer2 = nullptr;
-
-	_actorNames = nullptr;
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
-	delete _actorNames;
+	// delete _sliceRenderer;
+	// delete _sliceAnimations;
+	// delete _settings;
+	// delete _script;
+	// delete _scene;
+	// delete[] _gameVars;
+	// delete _gameFlags;
+	// delete _gameInfo;
+	// delete _clues;
+	// delete _chapters;
+	// delete _audioSpeech;
+	// delete _audioPlayer;
+	// delete _ambientSounds;
+
+	// _surface1.free();
+	// _surface2.free();
+
+	// delete[] _zBuffer1;
+	// delete[] _zBuffer2;
 
-	delete _sliceRenderer;
-	delete _sliceAnimations;
 	delete _settings;
 	delete _script;
-	delete _scene;
-	delete[] _gameVars;
-	delete _gameFlags;
-	delete _gameInfo;
-	delete _clues;
-	delete _chapters;
-	delete _audioSpeech;
-	delete _audioPlayer;
-	delete _ambientSounds;
-
-	_surface1.free();
-	_surface2.free();
-
-	delete[] _zBuffer1;
-	delete[] _zBuffer2;
 }
 
 bool BladeRunnerEngine::hasFeature(EngineFeature f) const {
@@ -134,7 +118,7 @@ Common::Error BladeRunnerEngine::run() {
 	return Common::kNoError;
 }
 
-bool BladeRunnerEngine::startup() {
+bool BladeRunnerEngine::startup(bool hasSavegames) {
 	bool r;
 
 	_surface1.create(640, 480, createRGB555());
@@ -143,7 +127,7 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
-	loadSplash();
+	// TODO: Timer
 
 	_gameInfo = new GameInfo(this);
 	if (!_gameInfo)
@@ -153,56 +137,166 @@ bool BladeRunnerEngine::startup() {
 	if (!r)
 		return false;
 
-	_gameFlags->setFlagCount(_gameInfo->getFlagCount());
+	// TODO: Create graphics surfaces 1-4
+
+	// TODO: Allocate audio cache
+
+	if (hasSavegames) {
+		if (!loadSplash()) {
+			return false;
+		}
+	}
+
+	// TODO: World waypoints
+
+	// TODO: Cover waypoints
+
+	// TODO: Flee waypoints
 
 	_gameVars = new int[_gameInfo->getGlobalVarCount()];
 
+	// TODO: Actor AI DLL init
+
+	// Seed rand
+
+	// TODO: Sine and cosine lookup tables for intervals of 1.0, 4.0, and 12.0
+
+	// TODO: View
+
+	// TODO: Screen Index
+
+	_gameFlags = new GameFlags();
+	_gameFlags->setFlagCount(_gameInfo->getFlagCount());
+
+	// TODO: Items
+
+	// Setup sound output
+
+	_audioPlayer = new AudioPlayer(this);
+
+	// TODO: Audio: Music
+
+	_audioSpeech = new AudioSpeech(this);
+
+	_ambientSounds = new AmbientSounds(this);
+
+	// TODO: Read BLADE.INI
+
 	_chapters = new Chapters(this);
 	if (!_chapters)
 		return false;
 
-	r = openArchive("MUSIC.MIX");
-	if (!r)
+	if (!openArchive("MUSIC.MIX"))
 		return false;
 
-	r = openArchive("SFX.MIX");
-	if (!r)
+	if (!openArchive("SFX.MIX"))
 		return false;
 
-	r = openArchive("SPCHSFX.TLK");
-	if (!r)
+	if (!openArchive("SPCHSFX.TLK"))
+		return false;
+
+	// TODO: Video overlays
+
+	// TODO: Proper ZBuf class
+	_zBuffer1 = new uint16[640 * 480];
+	_zBuffer2 = new uint16[640 * 480];
+
+	// TODO: Actors
+
+	// TODO: Player 99 (VO actor)
+
+	// TODO: McCoy setup
+
+	// TODO: Set actor ids (redundant?)
+
+	// TODO: Police Maze
+
+	_textActorNames = new TextResource(this);
+	if (!_textActorNames->open("ACTORS"))
+		return false;
+
+	_textCrimes = new TextResource(this);
+	if (!_textCrimes->open("CRIMES"))
+		return false;
+
+	_textCluetype = new TextResource(this);
+	if (!_textCluetype->open("CLUETYPE"))
 		return false;
 
+	_textKIA = new TextResource(this);
+	if (!_textKIA->open("KIA"))
+		return false;
+
+	_textSpindest = new TextResource(this);
+	if (!_textSpindest->open("SPINDEST"))
+		return false;
+
+	_textVK = new TextResource(this);
+	if (!_textVK->open("VK"))
+		return false;
+
+	_textOptions = new TextResource(this);
+	if (!_textOptions->open("OPTIONS"))
+		return false;
+
+	// TODO: Dialogue Menu (DLGMENU.TRE)
+
+	// TODO: SDB
+
+	// TODO: KIA
+
+	// TODO: Spinner Interface
+
+	// TODO: Elevators
+
+	// TODO: Scores
+
+	// TODO: Font
+
+	// TODO: KIA6PT.FON
+
 	for (int i = 0; i != 43; ++i) {
 		Shape *shape = new Shape(this);
 		shape->readFromContainer("SHAPES.SHP", i);
 		_shapes.push_back(shape);
 	}
+
+	// TODO: Esper
+
+	// TODO: VK
+
+	_mouse = new Mouse(this);
+	// _mouse->setCursorPosition(320, 240);
 	_mouse->setCursor(0);
 
+	_sliceAnimations = new SliceAnimations(this);
 	r = _sliceAnimations->open("INDEX.DAT");
 	if (!r)
 		return false;
 
-	r = _sliceAnimations->openCoreAnim();
-	if (!r)
-		return false;
+	// TODO: Support cdframes
 
 	r = _sliceAnimations->openHDFrames();
 	if (!r)
 		return false;
 
-	_zBuffer1 = new uint16[640 * 480];
-	_zBuffer2 = new uint16[640 * 480];
+	r = _sliceAnimations->openCoreAnim();
+	if (!r)
+		return false;
 
-	_actorNames = new TextResource(this);
-	_actorNames->open("ACTORS");
+	_sliceRenderer = new SliceRenderer(this);
 
 	_clues = new Clues(this, "CLUES", _gameInfo->getClueCount());
 
+	// TODO: Scene
+	_scene = new Scene(this);
+
+	// Load INIT.DLL
 	ScriptInit initScript(this);
 	initScript.SCRIPT_Initialize_Game();
 
+	// TODO: Load AI-ACT1.DLL
+
 	initChapterAndScene();
 
 	return true;
@@ -218,6 +312,23 @@ void BladeRunnerEngine::initChapterAndScene() {
 void BladeRunnerEngine::shutdown() {
 	_mixer->stopAll();
 
+	// TODO: Write BLADE.INI
+
+	// TODO: Shutdown VK
+
+	// TODO: Shutdown Esper
+
+	delete _mouse;
+	_mouse = 0;
+
+	for (uint i = 0; i != _shapes.size(); ++i) {
+		delete _shapes[i];
+	}
+	_shapes.clear();
+
+	// TODO: Shutdown Scene
+	delete _scene;
+
 	if (_chapters) {
 		if (_chapters->hasOpenResources())
 			_chapters->closeResources();
@@ -225,6 +336,50 @@ void BladeRunnerEngine::shutdown() {
 		_chapters = 0;
 	}
 
+	delete _clues;
+	_clues = 0;
+
+	delete _sliceRenderer;
+	_sliceRenderer = 0;
+
+	delete _sliceAnimations;
+	_sliceAnimations = 0;
+
+	delete _textActorNames;
+	_textActorNames = 0;
+
+	delete _textCrimes;
+	_textCrimes = 0;
+
+	delete _textCluetype;
+	_textCluetype = 0;
+
+	delete _textKIA;
+	_textKIA = 0;
+
+	delete _textSpindest;
+	_textSpindest = 0;
+
+	delete _textVK;
+	_textVK = 0;
+
+	delete _textOptions;
+	_textOptions = 0;
+
+	// TODO: Delete dialogue menu
+
+	delete _ambientSounds;
+
+	// TODO: Delete overlays
+
+	delete _audioSpeech;
+
+	// TODO: Delete Audio: Music
+
+	delete _audioPlayer;
+
+	// Shutdown sound output
+
 	if (isArchiveOpen("MUSIC.MIX"))
 		closeArchive("MUSIC.MIX");
 
@@ -234,19 +389,77 @@ void BladeRunnerEngine::shutdown() {
 	if (isArchiveOpen("SPCHSFX.TLK"))
 		closeArchive("SPCHSFX.TLK");
 
+	// TODO: Delete KIA6PT.FON
+
+	// TODO: Delete Items
+
+	delete _gameFlags;
+	_gameFlags = 0;
+
+	// TODO: Delete View
+
+	// TODO: Delete Screen Index
+
+	// TODO: Delete sine and cosine lookup tables
+
+	// TODO: Unload AI dll
+
+	delete[] _gameVars;
+	_gameVars = 0;
+
+	// TODO: Delete World waypoints
+
+	// TODO: Delete Cover waypoints
+
+	// TODO: Delete Flee waypoints
+
+	// TODO: Delete Scores
+
+	// TODO: Delete Elevators
+
+	// TODO: Delete Spinner Interface
+
+	// TODO: Delete KIA
+
+	// TODO: Delete SDB
+
+	// TODO: Delete unknown stuff
+
+	// TODO: Delete actors
+
+	// TODO: Delete proper ZBuf class
+	delete[] _zBuffer1;
+	_zBuffer1 = 0;
+
+	delete[] _zBuffer2;
+	_zBuffer2 = 0;
+
+	delete _gameInfo;
+	_gameInfo = 0;
+
+	// TODO: Delete graphics surfaces here
+	_surface1.free();
+	_surface2.free();
+
 	if (isArchiveOpen("STARTUP.MIX"))
 		closeArchive("STARTUP.MIX");
+
+	// TODO: Delete MIXArchives here
+
+	// TODO: Delete Timer
 }
 
-void BladeRunnerEngine::loadSplash() {
+bool BladeRunnerEngine::loadSplash() {
 	Image img(this);
 	if (!img.open("SPLASH.IMG"))
-		return;
+		return false;
 
 	img.copyToSurface(&_surface1);
 
 	_system->copyRectToScreen(_surface1.getPixels(), _surface1.pitch, 0, 0, _surface1.w, _surface1.h);
 	_system->updateScreen();
+
+	return false;
 }
 
 bool BladeRunnerEngine::init2() {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 0abd142..6343868 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -73,7 +73,14 @@ public:
 	SliceRenderer   *_sliceRenderer;
 	int             *_gameVars;
 
-	TextResource    *_actorNames;
+	TextResource    *_textActorNames;
+	TextResource    *_textCrimes;
+	TextResource    *_textCluetype;
+	TextResource    *_textKIA;
+	TextResource    *_textSpindest;
+	TextResource    *_textVK;
+	TextResource    *_textOptions;
+
 	Common::Array<Shape*> _shapes;
 
 	int in_script_counter;
@@ -97,11 +104,11 @@ public:
 
 	Common::Error run();
 
-	bool startup();
+	bool startup(bool hasSavegames = false);
 	void initChapterAndScene();
 	void shutdown();
 
-	void loadSplash();
+	bool loadSplash();
 	bool init2();
 
 	void gameLoop();


Commit: 6715157fad8960693b5c6749fd5acdb116229079
    https://github.com/scummvm/scummvm/commit/6715157fad8960693b5c6749fd5acdb116229079
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:39+02:00

Commit Message:
BLADERUNNER: Mismatched array new and delete

Changed paths:
    engines/bladerunner/text_resource.cpp



diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp
index ce9e6f7..3c074ee 100644
--- a/engines/bladerunner/text_resource.cpp
+++ b/engines/bladerunner/text_resource.cpp
@@ -42,7 +42,7 @@ TextResource::TextResource(BladeRunnerEngine *vm)
 TextResource::~TextResource() {
 	delete[] _ids;
 	delete[] _offsets;
-	delete _strings;
+	delete[] _strings;
 }
 
 bool TextResource::open(const char *name) {


Commit: a4ba6091316f8f50ea40d4dfd42bd26d419b1206
    https://github.com/scummvm/scummvm/commit/a4ba6091316f8f50ea40d4dfd42bd26d419b1206
Author: Thomas Fach-Pedersen (thomas at fach-pedersen.net)
Date: 2016-09-29T22:33:39+02:00

Commit Message:
BLADERUNNER: Add beginnings of Actor class and move actor drawing to Scene

Changed paths:
  A engines/bladerunner/actor.cpp
  A engines/bladerunner/actor.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/module.mk
    engines/bladerunner/scene.cpp



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
new file mode 100644
index 0000000..f483263
--- /dev/null
+++ b/engines/bladerunner/actor.cpp
@@ -0,0 +1,121 @@
+/* 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 "bladerunner/actor.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/boundingbox.h"
+#include "bladerunner/gameinfo.h"
+#include "bladerunner/slice_renderer.h"
+
+namespace BladeRunner {
+
+Actor::Actor(BladeRunnerEngine *vm, int actorId) {
+	_vm = vm;
+	_id = actorId;
+
+	// TODO: Construct Walkinfo
+
+	_bbox = new BoundingBox();
+
+	// TODO: Construct _clues ((actorId && actor != 99) ? 2 : 4)
+
+	// TODO: Construct _movementTrack
+
+	_friendlinessToOther = new int[_vm->_gameInfo->getActorCount()];
+}
+
+Actor::~Actor() {
+	delete[] _friendlinessToOther;
+	delete   _bbox;
+	// delete   _clues;
+	// delete   _movementTrack;
+}
+
+void Actor::setup(int actorId) {
+	_id  = actorId;
+	_set = -1;
+
+	_position  = Vector3(0.0, 0.0, 0.0);
+	_facing    = 512;
+	_walkboxId = -1;
+
+	_walkboxId = -1;
+	_animationId = 0;
+	_animationFrame = 0;
+	_fps = 15;
+	_frame_ms = 1000 / _fps;
+
+	_isTargetable        = false;
+	_isInvisible         = false;
+	_isImmuneToObstacles = false;
+
+	_width = 0;
+	_height = 0;
+
+	for (int i = 0; i != 7; ++i) {
+		_timersRemain[i] = 0;
+		_timersBegan[i]  = _vm->getTotalPlayTime();
+	}
+
+	_scale = 1.0;
+
+	_honesty              = 50;
+	_intelligence         = 50;
+	_combatAggressiveness = 50;
+	_stability            = 50;
+
+	_currentHP            = 50;
+	_maxHP                = 50;
+	_goalNumber           = -1;
+
+	_timersRemain[4] = 60000;
+	_animationMode = -1;
+	// TODO: screen rect = { -1, -1, -1, -1 };
+
+	int actorCount = (int)_vm->_gameInfo->getActorCount();
+	for (int i = 0; i != actorCount; ++i)
+		_friendlinessToOther[i] = 50;
+
+	// TODO: Setup clues
+
+	// TODO: Flush movement track
+}
+
+void Actor::set_at_xyz(Vector3 pos, int facing) {
+	_position = pos;
+	_facing = facing;
+}
+
+void Actor::draw() {
+	Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0);
+	float   draw_facing = _facing * M_PI / 512.0;
+	// float   draw_scale  = _scale;
+
+	// TODO: Handle SHORTY mode
+
+	_vm->_sliceRenderer->setupFrame(19, 1, draw_position, M_PI - draw_facing);
+	_vm->_sliceRenderer->drawFrame(_vm->_surface2, _vm->_zBuffer2);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
new file mode 100644
index 0000000..b51bc3f
--- /dev/null
+++ b/engines/bladerunner/actor.h
@@ -0,0 +1,94 @@
+/* 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 BLADERUNNER_ACTOR_H
+#define BLADERUNNER_ACTOR_H
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/vector.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class BoundingBox;
+
+class Actor {
+	BladeRunnerEngine *_vm;
+
+private:
+	BoundingBox   *_bbox;
+	// MovementTrack *_movementTrack;
+
+	int  _honesty;
+	int  _intelligence;
+	int  _stability;
+	int  _combatAggressiveness;
+	int  _goalNumber;
+	int *_friendlinessToOther;
+
+	int _currentHP;
+	int _maxHP;
+
+	// Clues _clues;
+
+	int     _id;
+	int     _set;
+	Vector3 _position;
+	int     _facing; // [0, 1024)
+	int     _walkboxId;
+
+	// Flags
+	bool _isTargetable;
+	bool _isInvisible;
+	bool _isImmuneToObstacles;
+
+	// Animation
+	int _width;
+	int _height;
+	int _animationMode;
+	int _fps;
+	int _frame_ms;
+	int _animationId;
+	int _animationFrame;
+
+	// WalkInfo _walkInfo;
+
+	int _timersRemain[7];
+	int _timersBegan[7];
+
+	float _scale;
+
+public:
+	Actor(BladeRunnerEngine *_vm, int actorId);
+	~Actor();
+
+	void setup(int actorId);
+
+	void set_at_xyz(Vector3 pos, int facing);
+
+	void draw();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index d44a0d8..ca83ac9 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -23,6 +23,7 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/actor.h"
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/audio_speech.h"
@@ -201,11 +202,15 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 	_zBuffer1 = new uint16[640 * 480];
 	_zBuffer2 = new uint16[640 * 480];
 
-	// TODO: Actors
-
-	// TODO: Player 99 (VO actor)
+	int actorCount = (int)_gameInfo->getActorCount();
+	assert(actorCount < 99);
+	for (int i = 0; i != actorCount; ++i) {
+		_actors[i] = new Actor(this, i);
+	}
+	_voiceoverActor = new Actor(this, 99);
+	_playerActor = _actors[_gameInfo->getPlayerId()];
 
-	// TODO: McCoy setup
+	// TODO: set _playerActor countdown timer 6
 
 	// TODO: Set actor ids (redundant?)
 
@@ -511,19 +516,13 @@ void BladeRunnerEngine::gameTick() {
 
 			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
 
-			// Hardcode McCoy in place to test the slice renderer
-			Vector3 pos = _scene->_actorStartPosition;
-			Vector3 draw_pos(pos.x, -pos.z, pos.y + 2);
-			float facing = -1.570796f;
-
+			// HACK to draw McCoy
 			_sliceRenderer->setView(_scene->_view);
-			_sliceRenderer->setupFrame(19, 1, draw_pos, facing);
-			_sliceRenderer->drawFrame(_surface2, _zBuffer2);
+			_playerActor->draw();
 
 			// TODO: Draw items (drawing works in Replicant)
 			// TODO: Draw item pickup (understood, drawing works in Replicant)
 			// TODO: Draw dialogue menu
-			// TODO: Draw mouse (understood)
 
 			Common::Point p = _eventMan->getMousePos();
 			_mouse->draw(_surface2, p.x, p.y);
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 6343868..d0ded00 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -36,6 +36,7 @@
 
 namespace BladeRunner {
 
+class Actor;
 class AmbientSounds;
 class AudioPlayer;
 class AudioSpeech;
@@ -83,6 +84,10 @@ public:
 
 	Common::Array<Shape*> _shapes;
 
+	Actor *_actors[99];
+	Actor *_voiceoverActor;
+	Actor *_playerActor;
+
 	int in_script_counter;
 
 	Graphics::Surface  _surface1;
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 8cd9ba4..7ec48f6 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -1,6 +1,7 @@
 MODULE := engines/bladerunner
 
 MODULE_OBJS = \
+	actor.o \
 	adpcm_decoder.o \
 	ambient_sounds.o \
 	archive.o \
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 8ec8b59..925c86a 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -23,6 +23,8 @@
 #include "bladerunner/scene.h"
 
 #include "bladerunner/bladerunner.h"
+
+#include "bladerunner/actor.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/script/script.h"
@@ -81,9 +83,12 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	}
 
 	// TODO: set VQADecoder parameters
+
 	// TODO: Set actor position from scene info
+	_vm->_playerActor->set_at_xyz(_actorStartPosition, _actorStartFacing);
+
 	// TODO: Set actor set
-	// TODO: call SCRIPT_Scene_Loaded
+
 	_vm->_script->SceneLoaded();
 
 #if 0


Commit: 6672e443a870963354ee43298c75164d382a5636
    https://github.com/scummvm/scummvm/commit/6672e443a870963354ee43298c75164d382a5636
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:40+02:00

Commit Message:
BLADERUNNER: just basic objects description scene stuff - lightning and effects movement track actor clues db actor walking info moved view from vqa decoder, because its needed elsewhere

does not compile, because new files are not in makefile...

Changed paths:
  A engines/bladerunner/actor_clues.cpp
  A engines/bladerunner/actor_clues.h
  A engines/bladerunner/actor_walk.cpp
  A engines/bladerunner/actor_walk.h
  A engines/bladerunner/color.h
  A engines/bladerunner/fog.cpp
  A engines/bladerunner/fog.h
  A engines/bladerunner/light.cpp
  A engines/bladerunner/light.h
  A engines/bladerunner/lights.cpp
  A engines/bladerunner/lights.h
  A engines/bladerunner/movement_track.cpp
  A engines/bladerunner/movement_track.h
  A engines/bladerunner/scene_objects.cpp
  A engines/bladerunner/scene_objects.h
  A engines/bladerunner/set_effects.cpp
  A engines/bladerunner/set_effects.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/audio_player.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/boundingbox.cpp
    engines/bladerunner/boundingbox.h
    engines/bladerunner/outtake.cpp
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/set.cpp
    engines/bladerunner/set.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/view.cpp
    engines/bladerunner/view.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index f483263..af9cef7 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -38,7 +38,7 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
 
 	_bbox = new BoundingBox();
 
-	// TODO: Construct _clues ((actorId && actor != 99) ? 2 : 4)
+	_clues = new ActorClues(vm, ((actorId && actorId != 99) ? 2 : 4));
 
 	// TODO: Construct _movementTrack
 
@@ -69,6 +69,8 @@ void Actor::setup(int actorId) {
 	_isTargetable        = false;
 	_isInvisible         = false;
 	_isImmuneToObstacles = false;
+	
+	_isRetired           = false;
 
 	_width = 0;
 	_height = 0;
@@ -105,11 +107,35 @@ void Actor::setup(int actorId) {
 void Actor::set_at_xyz(Vector3 pos, int facing) {
 	_position = pos;
 	_facing = facing;
+
+
+//	this->x = x;
+//	this->y = y;
+//	this->z = z;
+//	actor::set_angle(this, angle, addOrSet);
+//	if (scene::get_sceneId(Scene) == this->sceneId)
+//		this->walkboxId = set::findWalkbox(Scene->set, x, z);
+//	else
+//		this->walkboxId = -1;
+//	actor::setBoundingBox(this, x, y, z, retired);
+//	sceneObjects::removeScreneObject(SceneObjects, this->id);
+//	scene = this->sceneId;
+//	if (scene == scene::get_sceneId(Scene))
+//		sceneObjects::addActor(
+//			SceneObjects,
+//			this->id,
+//			this->boundingBox,
+//			&this->screenRect,
+//			1,
+//			a7,
+//			this->targetable,
+//			retired);
 }
 
 void Actor::draw() {
 	Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0);
 	float   draw_facing = _facing * M_PI / 512.0;
+	// just for viewing animations _facing = (_facing + 10) % 1024;
 	// float   draw_scale  = _scale;
 
 	// TODO: Handle SHORTY mode
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index b51bc3f..d621d53 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -26,6 +26,11 @@
 #include "bladerunner/bladerunner.h"
 
 #include "bladerunner/vector.h"
+#include "bladerunner/movement_track.h"
+#include "bladerunner/actor_clues.h"
+#include "bladerunner/actor_walk.h"
+
+#include "common/rect.h"
 
 namespace BladeRunner {
 
@@ -37,7 +42,8 @@ class Actor {
 
 private:
 	BoundingBox   *_bbox;
-	// MovementTrack *_movementTrack;
+	Common::Rect _screenRectangle;
+	MovementTrack *_movementTrack;
 
 	int  _honesty;
 	int  _intelligence;
@@ -49,7 +55,7 @@ private:
 	int _currentHP;
 	int _maxHP;
 
-	// Clues _clues;
+	ActorClues* _clues;
 
 	int     _id;
 	int     _set;
@@ -62,6 +68,8 @@ private:
 	bool _isInvisible;
 	bool _isImmuneToObstacles;
 
+	bool _isRetired;
+
 	// Animation
 	int _width;
 	int _height;
@@ -71,7 +79,7 @@ private:
 	int _animationId;
 	int _animationFrame;
 
-	// WalkInfo _walkInfo;
+	ActorWalk* _walkInfo;
 
 	int _timersRemain[7];
 	int _timersBegan[7];
@@ -87,6 +95,12 @@ public:
 	void set_at_xyz(Vector3 pos, int facing);
 
 	void draw();
+
+	int getSet() { return _set; }
+	BoundingBox* getBoundingBox() { return _bbox; }
+	Common::Rect* getScreenRectangle() { return &_screenRectangle; }
+	bool isRetired() { return _isRetired; }
+	bool isTargetable() { return _isTargetable; }
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
new file mode 100644
index 0000000..f99b6b1
--- /dev/null
+++ b/engines/bladerunner/actor_clues.cpp
@@ -0,0 +1,181 @@
+#include "bladerunner/actor_clues.h"
+
+namespace BladeRunner
+{
+
+	ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType)
+	{
+		_vm = vm;
+		_count = 0;
+		_maxCount = 0;
+		_clues = 0;
+		switch (cluesType)
+		{
+		case 4:
+			_maxCount = _vm->_gameInfo->getClueCount();
+			break;
+		case 3:
+			_maxCount = 100;
+			break;
+		case 2:
+			_maxCount = 50;
+			break;
+		case 1:
+			_maxCount = 25;
+			break;
+		case 0:
+			_maxCount = 0;
+			break;
+		default:
+			return;
+		}
+
+		if (_maxCount > 0)
+			_clues = new ActorClue[_maxCount];
+		else
+			_clues = NULL;
+
+		if (_clues)
+			removeAll();
+		else
+			_maxCount = NULL;
+	}
+
+	ActorClues::~ActorClues()
+	{
+		if (_clues)
+			delete[] _clues;
+
+		_maxCount = 0;
+		_count = 0;
+	}
+
+	void ActorClues::acquire(int clueId, char flag2, int fromActorId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		_clues[clueIndex]._flags |= 0x01;
+		_clues[_count]._flags = _clues[_count]._flags & 0xFD | ((flag2 << 1) & 0x02);
+		_clues[clueIndex]._fromActorId = fromActorId;
+	}
+
+	void ActorClues::lose(int clueId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		_clues[clueIndex]._flags = 0;
+	}
+
+	int ActorClues::isAcquired(int clueId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		if (clueIndex == -1)
+			return 0;
+
+		return _clues[clueIndex]._flags & 0x01;
+	}
+
+	int ActorClues::getFromActorId(int clueId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		if (clueIndex == -1)
+			return  -1;
+
+		return _clues[clueIndex]._fromActorId;
+	}
+
+	int ActorClues::isFlag2(int clueId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		if (clueIndex == -1)
+			return 0;
+
+		return (_clues[clueIndex]._flags & 0x02) >> 1;
+	}
+
+	int ActorClues::isFlag3(int clueId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		if (clueIndex == -1)
+			return 0;
+
+		return (_clues[clueIndex]._flags & 0x04) >> 2;
+	}
+
+	int ActorClues::isFlag4(int clueId)
+	{
+		int clueIndex = findClueIndex(clueId);
+		if (clueIndex == -1)
+			return 0;
+
+		return (_clues[clueIndex]._flags & 0x08) >> 3;
+	}
+
+	int ActorClues::getField1(int clueId)
+	{
+		if (!_count)
+			return 0;
+
+		int clueIndex = findClueIndex(clueId);
+		if (clueIndex == -1)
+			return 0;
+
+		return _clues[clueIndex]._field1;
+	}
+
+	int ActorClues::getCount()
+	{
+		return _count;
+	}
+
+	void ActorClues::removeAll()
+	{
+		_count = 0;
+		for (int i = 0; i < _maxCount; ++i) {
+			remove(i);
+		}
+	}
+
+	int ActorClues::findClueIndex(int clueId)
+	{
+		for (int i = 0; i < _count; i++) {
+			if (clueId == _clues[i]._clueId) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	void ActorClues::add(int actorId, int clueId, int field1, char acquired, char flag2, int fromActorId)
+	{
+		_clues[_count]._clueId = clueId;
+		_clues[_count]._field1 = field1;
+
+		_clues[_count]._flags = 0;
+		_clues[_count]._flags = _clues[_count]._flags & 0xFE | (acquired & 0x01);
+		_clues[_count]._flags = _clues[_count]._flags & 0xFD | ((flag2 << 1) & 0x02);
+
+		_clues[_count]._fromActorId = fromActorId;
+		++_count;
+	}
+
+	void ActorClues::remove(int index)
+	{
+		_clues[index]._clueId = -1;
+		_clues[index]._field1 = 0;
+		_clues[index]._flags = 0;
+		_clues[index]._fromActorId = -1;
+
+		_clues[index]._field3 = -1;
+		_clues[index]._field4 = 0;
+		_clues[index]._field5 = -1;
+		_clues[index]._field6 = 0;
+		_clues[index]._field7 = -1;
+		_clues[index]._field8 = 0;
+	}
+
+	int ActorClues::exists(int clueId)
+	{
+		return findClueIndex(clueId) != -1;
+	}
+
+
+}
\ No newline at end of file
diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h
new file mode 100644
index 0000000..02d6bbb
--- /dev/null
+++ b/engines/bladerunner/actor_clues.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 BLADERUNNER_ACTOR_CLUES_H
+#define BLADERUNNER_ACTOR_CLUES_H
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/gameinfo.h"
+
+namespace BladeRunner {
+
+	struct ActorClue
+	{
+		int _clueId;
+		int _field1;
+		int _fromActorId;
+		int _field3;
+		int _field4;
+		int _field5;
+		int _field6;
+		int _field7;
+		int _field8;
+		unsigned char _flags;
+	};
+
+	class ActorClues
+	{
+		BladeRunnerEngine *_vm;
+
+	private:
+		int _count;
+		int _maxCount;
+		ActorClue *_clues;
+
+	public:
+		ActorClues(BladeRunnerEngine *_vm, int cluesType);
+		~ActorClues();
+
+		void acquire(int clueId, char flag2, int fromActorId);
+		void lose(int clueId);
+		int isAcquired(int clueId);
+		int getFromActorId(int clueId);
+		int isFlag2(int clueId);
+		int isFlag3(int clueId);
+		int isFlag4(int clueId);
+		int getField1(int clueId);
+
+		int getCount();
+
+		void removeAll();
+
+		//savegame
+		//loadgame
+	private:
+		int findClueIndex(int clueId);
+		void add(int actorId, int clueId, int field1, char acquired, char flag2, int fromActorId);
+		void remove(int clueIndex);
+		int exists(int clueId);
+	};
+}
+
+#endif
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
new file mode 100644
index 0000000..a4cfad7
--- /dev/null
+++ b/engines/bladerunner/actor_walk.cpp
@@ -0,0 +1,8 @@
+#include "bladerunner/actor_walk.h"
+
+namespace BladeRunner
+{
+
+
+
+}
\ No newline at end of file
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
new file mode 100644
index 0000000..c44c15b
--- /dev/null
+++ b/engines/bladerunner/actor_walk.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.
+*
+*/
+
+#ifndef BLADERUNNER_ACTOR_WALK_H
+#define BLADERUNNER_ACTOR_WALK_H
+
+#include "bladerunner/vector.h"
+
+namespace BladeRunner
+{
+	struct ActorWalkEntry
+	{
+		int _actorId;
+		int _present;
+	};
+
+	class ActorWalk
+	{
+		int _walking;
+		int _running;
+		Vector3 _wanted;
+		Vector3 _unknown;
+		Vector3 _start;
+		Vector3 _end;
+		int facing;
+		ActorWalkEntry _actors[20];
+		int _actorsCount;
+		int _field15;
+		int _status;
+	};
+}
+
+#endif
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index ecfc95a..b8df01c 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -165,7 +165,7 @@ void AudioPlayer::fadeAndStopTrack(Track *track, int time)
 
 int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, int panTo, int priority, byte flags) {
 	/* Find first available track or, alternatively, the lowest priority playing track */
-	int    trackId;
+	int    trackId = -1;
 	Track *track = NULL;
 	int    lowestPriority = 100;
 	Track *lowestPriorityTrack = NULL;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index ca83ac9..22199e6 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -35,6 +35,7 @@
 #include "bladerunner/mouse.h"
 #include "bladerunner/outtake.h"
 #include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
 #include "bladerunner/script/init.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/settings.h"
@@ -65,6 +66,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 
 	_script = new Script(this);
 	_settings = new Settings(this);
+	_lights = new Lights(this);
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
@@ -87,7 +89,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
-
+	delete _lights;
 	delete _settings;
 	delete _script;
 }
@@ -162,9 +164,9 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	// TODO: Sine and cosine lookup tables for intervals of 1.0, 4.0, and 12.0
 
-	// TODO: View
+	_view = new View(this);
 
-	// TODO: Screen Index
+	_sceneObjects = new SceneObjects(this, _view);
 
 	_gameFlags = new GameFlags();
 	_gameFlags->setFlagCount(_gameInfo->getFlagCount());
@@ -401,9 +403,11 @@ void BladeRunnerEngine::shutdown() {
 	delete _gameFlags;
 	_gameFlags = 0;
 
-	// TODO: Delete View
+	delete _view;
+	_view = 0;
 
-	// TODO: Delete Screen Index
+	delete _sceneObjects;
+	_sceneObjects = 0;
 
 	// TODO: Delete sine and cosine lookup tables
 
@@ -517,7 +521,7 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
 
 			// HACK to draw McCoy
-			_sliceRenderer->setView(_scene->_view);
+			//_sliceRenderer->setView(&_scene->_view);
 			_playerActor->draw();
 
 			// TODO: Draw items (drawing works in Replicant)
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index d0ded00..814041d 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -46,12 +46,16 @@ class GameInfo;
 class GameFlags;
 class Mouse;
 class Scene;
+class SceneObjects;
 class Script;
 class Settings;
 class Shape;
 class SliceAnimations;
 class SliceRenderer;
 class TextResource;
+class Lights;
+class View;
+
 
 class BladeRunnerEngine : public Engine {
 public:
@@ -67,13 +71,17 @@ public:
 	GameFlags       *_gameFlags;
 	GameInfo        *_gameInfo;
 	Mouse           *_mouse;
+	View            *_view;
 	Scene           *_scene;
+	SceneObjects    *_sceneObjects;
 	Script          *_script;
 	Settings        *_settings;
 	SliceAnimations *_sliceAnimations;
 	SliceRenderer   *_sliceRenderer;
 	int             *_gameVars;
 
+	Lights          *_lights;
+
 	TextResource    *_textActorNames;
 	TextResource    *_textCrimes;
 	TextResource    *_textCluetype;
diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
index 10e529b..fb2ae94 100644
--- a/engines/bladerunner/boundingbox.cpp
+++ b/engines/bladerunner/boundingbox.cpp
@@ -34,4 +34,23 @@ BoundingBox::BoundingBox(float x0, float y0, float z0, float x1, float y1, float
 	_vertices[1].z = z1;
 }
 
+void BoundingBox::expand(float x0, float y0, float z0, float x1, float y1, float z1)
+{
+	_vertices[0].x += x0;
+	_vertices[0].y += y0;
+	_vertices[0].z += z0;
+
+	_vertices[1].x += x1;
+	_vertices[1].y += y1;
+	_vertices[1].z += z1;
+}
+
+
+bool BoundingBox::isXYZInside(float x, float y, float z)
+{
+	return
+		x >= _vertices[0].x && x <= _vertices[1].x
+		&& y >= _vertices[0].y && y <= _vertices[1].y
+		&& z >= _vertices[0].z && z <= _vertices[1].z;
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
index 5dda3f0..1766973 100644
--- a/engines/bladerunner/boundingbox.h
+++ b/engines/bladerunner/boundingbox.h
@@ -28,11 +28,15 @@
 namespace BladeRunner {
 
 class BoundingBox {
+public:
 	Vector3 _vertices[2];
 
 public:
 	BoundingBox() {}
 	BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1);
+
+	void expand(float x0, float y0, float z0, float x1, float y1, float z1);
+	bool isXYZInside(float x, float y, float z);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/color.h b/engines/bladerunner/color.h
new file mode 100644
index 0000000..54983b4
--- /dev/null
+++ b/engines/bladerunner/color.h
@@ -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.
+*
+*/
+
+#ifndef BLADERUNNER_COLOR_H
+#define BLADERUNNER_COLOR_H
+
+namespace BladeRunner {
+
+	struct Color
+	{
+		float r;
+		float g;
+		float b;
+	};
+}
+
+
+#endif
diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
new file mode 100644
index 0000000..5951ba8
--- /dev/null
+++ b/engines/bladerunner/fog.cpp
@@ -0,0 +1,94 @@
+#include "bladerunner/fog.h"
+
+namespace BladeRunner
+{
+	Fog::Fog()
+	{
+	}
+
+	Fog::~Fog()
+	{
+	}
+
+	int Fog::readCommon(Common::ReadStream* stream)
+	{
+		int offset = stream->readUint32LE();
+		stream->read(_name, 20);
+		_fogColor.r = stream->readFloatLE();
+		_fogColor.g = stream->readFloatLE();
+		_fogColor.b = stream->readFloatLE();
+		_fogDensity = stream->readFloatLE();
+		return offset;
+	}
+
+
+	void Fog::readAnimationData(Common::ReadStream* stream, int size)
+	{
+		_animatedParameters = stream->readUint32LE();
+		_animationData = new float[size / sizeof(float)];
+		stream->read(_animationData, size);
+		
+		_m11ptr = _animationData;
+		_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? _framesCount : 1);
+		_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? _framesCount : 1);
+		_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? _framesCount : 1);
+		_m21ptr = _m14ptr + (_animatedParameters & 0x08 ? _framesCount : 1);
+		_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? _framesCount : 1);
+		_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? _framesCount : 1);
+		_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? _framesCount : 1);
+		_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? _framesCount : 1);
+		_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? _framesCount : 1);
+		_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? _framesCount : 1);
+		_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? _framesCount : 1);
+
+		setupFrame(0);
+	}
+
+	void Fog::reset()
+	{
+	}
+
+	void Fog::setupFrame(int frame)
+	{
+		int offset = frame % _framesCount;
+		_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
+		_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
+		_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
+		_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
+		_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
+		_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
+		_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
+		_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
+		_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
+		_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
+		_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
+		_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
+		_inverted = invertMatrix(_matrix);
+	}
+
+	void FogCone::read(Common::ReadStream* stream, int framesCount)
+	{
+		_framesCount = framesCount;
+		int size = readCommon(stream);
+		_parameter1 = stream->readFloatLE();
+		readAnimationData(stream, size - 52);
+	}
+
+	void FogSphere::read(Common::ReadStream* stream, int framesCount)
+	{
+		_framesCount = framesCount;
+		int size = readCommon(stream);
+		_parameter1 = stream->readFloatLE();
+		readAnimationData(stream, size - 52);
+	}
+
+	void FogBox::read(Common::ReadStream* stream, int framesCount)
+	{
+		_framesCount = framesCount;
+		int size = readCommon(stream);
+		_parameter1 = stream->readFloatLE();
+		_parameter2 = stream->readFloatLE();
+		_parameter3 = stream->readFloatLE();
+		readAnimationData(stream, size - 60);
+	}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h
new file mode 100644
index 0000000..627e8f1
--- /dev/null
+++ b/engines/bladerunner/fog.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.
+*
+*/
+
+#ifndef BLADERUNNER_FOG_H
+#define BLADERUNNER_FOG_H
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/color.h"
+#include "bladerunner/matrix.h"
+
+#include "common/stream.h"
+
+
+namespace BladeRunner {
+
+	class SetEffects;
+
+	class Fog
+	{
+		friend class SetEffects;
+
+	protected:
+		char _name[20];
+		int _framesCount;
+		int _animatedParameters;
+		Matrix4x3 _matrix;
+		Matrix4x3 _inverted;
+		Color _fogColor;
+		float _fogDensity;
+		float *_animationData;
+		float *_m11ptr;
+		float *_m12ptr;
+		float *_m13ptr;
+		float *_m14ptr;
+		float *_m21ptr;
+		float *_m22ptr;
+		float *_m23ptr;
+		float *_m24ptr;
+		float *_m31ptr;
+		float *_m32ptr;
+		float *_m33ptr;
+		float *_m34ptr;
+		
+		float _parameter1;
+		float _parameter2;
+		float _parameter3;
+
+		Fog *_next;
+
+	public:
+		Fog();
+		~Fog();
+
+		virtual void read(Common::ReadStream *stream, int framesCount) = 0;
+
+		void reset();
+
+		void setupFrame(int frame);
+
+	private:
+	protected:
+		int readCommon(Common::ReadStream *stream);
+		void readAnimationData(Common::ReadStream *stream, int count);
+
+	};
+
+	class FogCone : public Fog
+	{
+		void read(Common::ReadStream *stream, int framesCount);
+	};
+
+	class FogSphere : public Fog
+	{
+		void read(Common::ReadStream *stream, int framesCount);
+	};
+
+	class FogBox : public Fog
+	{
+		void read(Common::ReadStream *stream, int framesCount);
+	};
+
+
+
+}
+#endif
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
new file mode 100644
index 0000000..6bc97f8
--- /dev/null
+++ b/engines/bladerunner/light.cpp
@@ -0,0 +1,84 @@
+#include "bladerunner/light.h"
+
+namespace BladeRunner
+{
+	Light::Light()
+	{
+	}
+
+	Light::~Light()
+	{
+	}
+
+	void Light::read(Common::ReadStream* stream, int framesCount, int frame, int animated)
+	{
+		_framesCount = framesCount;
+		_animated = animated;
+
+		int size = stream->readUint32LE();
+		size = size - 32;
+
+		stream->read(_name, 20);
+
+		_animatedParameters = stream->readUint32LE();
+
+		_animationData = new float[size / sizeof(float)];
+		stream->read(_animationData, size);
+
+		_m11ptr = _animationData;
+		_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? framesCount : 1);
+		_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? framesCount : 1);
+		_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? framesCount : 1);
+		_m21ptr = _m14ptr + (_animatedParameters & 0x8 ? framesCount : 1);
+		_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? framesCount : 1);
+		_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? framesCount : 1);
+		_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? framesCount : 1);
+		_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? framesCount : 1);
+		_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? framesCount : 1);
+		_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? framesCount : 1);
+		_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? framesCount : 1);
+		_colorRPtr = _m34ptr + (_animatedParameters & 0x800 ? framesCount : 1);
+		_colorGPtr = _colorRPtr + (_animatedParameters & 0x1000 ? framesCount : 1);
+		_colorBPtr = _colorGPtr + (_animatedParameters & 0x2000 ? framesCount : 1);
+		_field16ptr = _colorGPtr + (_animatedParameters & 0x4000 ? framesCount : 1);
+		_field17ptr = _field16ptr + (_animatedParameters & 0x8000 ? framesCount : 1);
+		_field18ptr = _field17ptr + (_animatedParameters & 0x10000 ? framesCount : 1);
+		_field19ptr = _field18ptr + (_animatedParameters & 0x20000 ? framesCount : 1);
+
+		setupFrame(frame);
+	}
+
+	void Light::readVqa(Common::ReadStream* stream)
+	{
+	}
+
+	void Light::setupFrame(int frame)
+	{
+		int offset = frame % _framesCount;
+		_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
+		_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
+		_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
+		_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
+		_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
+		_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
+		_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
+		_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
+		_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
+		_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
+		_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
+		_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
+		_color.r = (_animatedParameters & 0x1000 ? _colorRPtr[offset] : *_colorRPtr);
+		_color.g = (_animatedParameters & 0x2000 ? _colorGPtr[offset] : *_colorGPtr);
+		_color.b = (_animatedParameters & 0x4000 ? _colorBPtr[offset] : *_colorBPtr);
+		_field16 = (_animatedParameters & 0x8000 ? _field16ptr[offset] : *_field16ptr);
+		_field17 = (_animatedParameters & 0x10000 ? _field17ptr[offset] : *_field17ptr);
+		_field18 = (_animatedParameters & 0x20000 ? _field18ptr[offset] : *_field18ptr);
+		_field19 = (_animatedParameters & 0x40000 ? _field19ptr[offset] : *_field19ptr);
+
+	}
+
+	float Light::attenuation(float min, float max, float distance)
+	{
+		return 0.0;
+	}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
new file mode 100644
index 0000000..f4c142e
--- /dev/null
+++ b/engines/bladerunner/light.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.
+*
+*/
+
+#ifndef BLADERUNNER_LIGHT_H
+#define BLADERUNNER_LIGHT_H
+
+#include "bladerunner/matrix.h"
+#include "bladerunner/color.h"
+
+#include "common/stream.h"
+
+namespace Common{
+	class ReadStream;
+}
+
+namespace BladeRunner {
+	class Lights;
+
+	class Light
+	{
+		friend class Lights;
+	private:
+		char _name[20];
+		int _framesCount;
+		int _animated;
+		int _animatedParameters;
+		Matrix4x3 _matrix;
+		Color _color;
+		float _field16;
+		float _field17;
+		float _field18;
+		float _field19;
+		float *_animationData;
+		float *_m11ptr;
+		float *_m12ptr;
+		float *_m13ptr;
+		float *_m14ptr;
+		float *_m21ptr;
+		float *_m22ptr;
+		float *_m23ptr;
+		float *_m24ptr;
+		float *_m31ptr;
+		float *_m32ptr;
+		float *_m33ptr;
+		float *_m34ptr;
+		float *_colorRPtr;
+		float *_colorGPtr;
+		float *_colorBPtr;
+		float *_field16ptr;
+		float *_field17ptr;
+		float *_field18ptr;
+		float *_field19ptr;
+		Light *_next;
+	public:
+		Light();
+		~Light();
+		void read(Common::ReadStream *stream, int framesCount, int frame, int animated);
+		void readVqa(Common::ReadStream *stream);
+
+		void setupFrame(int frame);
+	private:
+		static float attenuation(float min, float max, float distance);
+	};
+
+	class Light1 : public Light {
+
+	};
+
+	class Light2 : public Light {
+
+	};
+
+	class Light3 : public Light {
+
+	};
+
+	class Light4 : public Light {
+
+	};
+
+	class Light5 : public Light {
+
+	};
+}
+#endif
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
new file mode 100644
index 0000000..33ee3d1
--- /dev/null
+++ b/engines/bladerunner/lights.cpp
@@ -0,0 +1,100 @@
+#include "bladerunner/lights.h"
+
+namespace BladeRunner {
+	Lights::Lights(BladeRunnerEngine *vm)
+	{
+		_vm = vm;
+
+		_ambientLightColor.r = 1.0;
+		_ambientLightColor.g = 0.0;
+		_ambientLightColor.b = 0.0;
+
+		_lights = NULL;
+		_frame = 0;
+	}
+
+	Lights::~Lights()
+	{
+		reset();
+	}
+
+	void Lights::read(Common::ReadStream* stream, int framesCount)
+	{
+		_ambientLightColor.r = stream->readFloatLE();
+		_ambientLightColor.g = stream->readFloatLE();
+		_ambientLightColor.b = stream->readFloatLE();
+
+		_lightsCount = stream->readUint32LE();
+		int i;
+		for (i = 0; i < _lightsCount; i++)
+		{
+			Light *light;
+			int type = stream->readUint32LE();
+			switch (type)
+			{
+			case 1:
+				light = new Light1();
+				break;
+			case 2:
+				light = new Light2();
+				break;
+			case 3:
+				light = new Light3();
+				break;
+			case 4:
+				light = new Light4();
+				break;
+			case 5:
+				light = new Light5();
+				break;
+			default:
+				light = new Light();
+			}
+			
+			light->read(stream, framesCount, _frame, 0);
+			light->_next = _lights;
+			_lights = light;
+		}
+	}
+
+	void Lights::readVqa(Common::ReadStream* stream)
+	{
+		reset();
+		//int framesCount = stream->readUint32LE();
+		//int count = stream->readUint32LE();
+
+	}
+
+	void Lights::setupFrame(int frame)
+	{
+		Light *light;
+
+		if (frame == _frame)
+			return;
+
+		if (!_lights)
+			return;
+
+		for (light = _lights; light; light = light->_next)
+		{
+			light->setupFrame(frame);
+		}
+	}
+
+	void Lights::reset()
+	{
+		Light *light;
+		Light *nextLight;
+
+		if (!_lights)
+			return;
+
+		do
+		{
+			light = _lights;
+			nextLight = light->_next;
+			delete light;
+			_lights = nextLight;
+		} while (nextLight);
+	}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
new file mode 100644
index 0000000..d6ff7f5
--- /dev/null
+++ b/engines/bladerunner/lights.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.
+*
+*/
+
+#ifndef BLADERUNNER_LIGHTS_H
+#define BLADERUNNER_LIGHTS_H
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/color.h"
+#include "bladerunner/light.h"
+
+#include "common/stream.h"
+
+
+namespace BladeRunner {
+
+	class Lights
+	{
+		BladeRunnerEngine *_vm;
+
+	private:
+		Color _ambientLightColor;
+
+		int _lightsCount;
+		Light *_lights;
+		
+		int _frame;
+		//char gap[28];
+
+	public:
+		Lights(BladeRunnerEngine *vm);
+		~Lights();
+
+		void read(Common::ReadStream *stream, int framesCount);
+		void readVqa(Common::ReadStream *stream);
+
+		void reset();
+
+		void setupFrame(int frame);
+
+	private:
+
+	};
+
+}
+#endif
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
new file mode 100644
index 0000000..fff4508
--- /dev/null
+++ b/engines/bladerunner/movement_track.cpp
@@ -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.
+*
+*/
+
+#include "bladerunner/movement_track.h"
+
+namespace BladeRunner {
+	MovementTrack::MovementTrack()
+	{
+		reset();
+	}
+
+	MovementTrack::~MovementTrack()
+	{
+		reset();
+	}
+
+	void MovementTrack::reset()
+	{
+		_currentIndex = -1;
+		_lastIndex = -1;
+		_hasNext = 0;
+		_paused = 0;
+		for (int i = 0; i < sizeof(this->_entries); i++)
+		{
+			_entries[i].waypointId = -1;
+			_entries[i].delay = -1;
+			_entries[i].angle = -1;
+			_entries[i].running = 0;
+		}
+	}
+
+	int MovementTrack::append(int waypointId, int delay, int running)
+	{
+		return append(waypointId, delay, -1, running);
+	}
+
+	int MovementTrack::append(int waypointId, int delay, int angle, int running)
+	{
+		if (_lastIndex > sizeof(_entries))
+			return 0;
+		_entries[_lastIndex].waypointId = waypointId;
+		_entries[_lastIndex].delay = delay;
+		_entries[_lastIndex].angle = angle;
+		_entries[_lastIndex].running = running;
+
+		_lastIndex++;
+		_hasNext = 1;
+		_currentIndex = 0;
+		return 1;
+	}
+
+	void MovementTrack::flush()
+	{
+		reset();
+	}
+
+	void MovementTrack::repeat()
+	{
+		_currentIndex = 0;
+		_hasNext = 1;
+	}
+
+	int MovementTrack::pause()
+	{
+		_paused = 1;
+		return 1;
+	}
+
+	int MovementTrack::unpause()
+	{
+		_paused = 0;
+		return 1;
+	}
+
+	int MovementTrack::isPaused()
+	{
+		return _paused;
+	}
+
+	int MovementTrack::hasNext()
+	{
+		return _hasNext;
+	}
+
+	int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running)
+	{
+		if (_currentIndex < _lastIndex && this->_hasNext)
+		{
+			*waypointId = _entries[_currentIndex].waypointId;
+			*delay = _entries[_currentIndex].delay;
+			*angle = _entries[_currentIndex].angle;
+			*running = _entries[_currentIndex++].running;
+			return 1;
+		}
+		else
+		{
+			*waypointId = -1;
+			*delay = -1;
+			*angle = -1;
+			*running = 0;
+			_hasNext = 0;
+			return 0;
+		}
+	}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
new file mode 100644
index 0000000..491de80
--- /dev/null
+++ b/engines/bladerunner/movement_track.h
@@ -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.
+*
+*/
+
+#ifndef BLADERUNNER_MOVEMENT_TRACK_H
+#define BLADERUNNER_MOVEMENT_TRACK_H
+
+#include "bladerunner/bladerunner.h"
+
+
+namespace BladeRunner {
+
+	class BladeRunnerEngine;
+	class BoundingBox;
+
+	struct MovementTrackEntry
+	{
+		int waypointId;
+		int delay;
+		int angle;
+		int running;
+	};
+
+	class MovementTrack {
+		BladeRunnerEngine *_vm;
+
+	private:
+		int _currentIndex;
+		int _lastIndex;
+		int _hasNext;
+		int _paused;
+		MovementTrackEntry _entries[100];
+		void reset();
+
+	public:
+		MovementTrack();
+		~MovementTrack();
+		int append(int waypointId, int delay, int running);
+		int append(int waypointId, int delay, int angle, int running);
+		void flush();
+		void repeat();
+		int pause();
+		int unpause();
+		int isPaused();
+		int hasNext();
+		int next(int *waypointId, int *delay, int *angle, int *running);
+
+		//int saveGame();
+	};
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index b81b212..3ffc964 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -43,7 +43,7 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
 	else
 		resName = name + "_E.VQA";
 
-	VQAPlayer vqa_player(_vm);
+	VQAPlayer vqa_player(_vm, _vm->_view);
 
 	vqa_player.open(resName);
 
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 925c86a..fc0aa8c 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -28,6 +28,8 @@
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/script/script.h"
+#include "bladerunner/slice_renderer.h"
+#include "bladerunner/scene_objects.h"
 
 #include "common/str.h"
 #include "common/stream.h"
@@ -38,7 +40,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (!isLoadingGame) {
 		// flush ADQ
 	}
-
+	// reset mouse button status
 	_setId = setId;
 	_sceneId = sceneId;
 
@@ -48,9 +50,11 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		// TODO: Set up overlays
 	} else {
 		// TODO: Clear regions
+		// reset aesc
 		// TODO: Destroy all overlays
 		_defaultLoop = 0;
 		_frame = -1;
+		//_loopStartSpecial = -1;
 	}
 
 	Common::String vqaName;
@@ -75,34 +79,50 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (!_set->open(setResourceName))
 		return false;
 
-	// TODO: Set view
+	_vm->_sliceRenderer->setView(_vm->_view);
+
 	if (isLoadingGame) {
-		if (sceneId >= 73 && sceneId <= 76)
-			_vm->_script->InitializeScene();
-		return true;
+		// resume()
+		if (sceneId >= 73 && sceneId <= 76) {
+			_vm->_script->SceneLoaded();
+			return true;
+		}
 	}
 
 	// TODO: set VQADecoder parameters
 
 	// TODO: Set actor position from scene info
+	//advance frame 0
 	_vm->_playerActor->set_at_xyz(_actorStartPosition, _actorStartFacing);
-
 	// TODO: Set actor set
-
 	_vm->_script->SceneLoaded();
 
-#if 0
+	_vm->_sceneObjects->reset();
+	
 	// Init click map
 	int actorCount = _vm->_gameInfo->getActorCount();
 	for (int i = 0; i != actorCount; ++i) {
 		Actor *actor = _vm->_actors[i];
 		if (actor->getSet() == setId) {
-
+			_vm->_sceneObjects->addActor(
+				i,
+				actor->getBoundingBox(),
+				actor->getScreenRectangle(),
+				1,
+				0,
+				actor->isTargetable(),
+				actor->isRetired());
 		}
 	}
-	// TODO: Update click map for set, items
-#endif
-
+	
+	_set->addAllObjectsToScene(_vm->_sceneObjects);
+	//add all items to scene
+	//calculate walking obstacles??
+
+	 if (_playerWalkedIn) {
+		//_vm->_script->PlayerWalkedIn();
+	 }
+	
 	return true;
 }
 
@@ -111,7 +131,6 @@ int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer.getSurface());
 		memcpy(zBuffer, _vqaPlayer.getZBuffer(), 640*480*2);
-		_view = _vqaPlayer.getView();
 	}
 	return frame;
 }
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index f0721b3..ee286ca 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -26,7 +26,7 @@
 #include "bladerunner/bladerunner.h"
 
 #include "bladerunner/set.h"
-#include "bladerunner/view.h"
+//#include "bladerunner/view.h"
 #include "bladerunner/vqa_player.h"
 
 namespace BladeRunner {
@@ -48,7 +48,6 @@ public:
 	Vector3     _actorStartPosition;
 	int         _actorStartFacing;
 	bool        _playerWalkedIn;
-	View        _view;
 
 public:
 	Scene(BladeRunnerEngine *vm)
@@ -56,7 +55,7 @@ public:
 		  _set(new Set(vm)),
 		  _setId(-1),
 		  _sceneId(-1),
-		  _vqaPlayer(vm),
+		  _vqaPlayer(vm, vm->_view),
 		  _defaultLoop(0),
 		  _nextSetId(-1),
 		  _nextSceneId(-1),
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
new file mode 100644
index 0000000..f54a9b7
--- /dev/null
+++ b/engines/bladerunner/scene_objects.cpp
@@ -0,0 +1,188 @@
+#include "bladerunner/scene_objects.h"
+
+namespace BladeRunner {
+
+	SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
+		_vm = vm;
+		_view = view;
+
+		_count = 0;
+		_sceneObjects = new SceneObject[SCENE_OBJECTS_COUNT];
+		_sceneObjectsSortedByDistance = new int[SCENE_OBJECTS_COUNT];
+
+		int i;
+		for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+			_sceneObjectsSortedByDistance[i] = -1;
+		}
+	}
+
+	SceneObjects::~SceneObjects() {
+		_vm = nullptr;
+		_view = nullptr;
+		_count = 0;
+
+		delete[] _sceneObjectsSortedByDistance;
+		delete[] _sceneObjects;
+	}
+
+
+	void SceneObjects::reset() {
+		int i;
+		for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+			_sceneObjects[i]._present = 0;
+		}
+	}
+
+	bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 unknown1, uint8 isCombatTarget, uint8 isRetired) {
+		return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isCombatTarget, unknown1, isRetired);
+	}
+
+	bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget) {
+		Common::Rect rect(-1, -1, -1, -1);
+		return addSceneObject(sceneObjectId, SceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isCombatTarget, 0, 0);
+	}
+
+	bool SceneObjects::addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle) {
+		return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isCombatTarget, 0, 0);
+	}
+
+
+	bool SceneObjects::remove(int sceneObjectId)
+	{
+		int i = findById(sceneObjectId);
+		if (i == -1 || !_sceneObjects[i]._present) {
+			return false;
+		}
+		int j;
+		for (j = 0; j < _count; j++) {
+			if (_sceneObjectsSortedByDistance[j] == i) {
+				break;
+			}
+		}
+		int k;
+		for (k = j; k < _count - 1; k++) {
+			_sceneObjectsSortedByDistance[k] = _sceneObjectsSortedByDistance[k + 1];
+		}
+
+		--_count;
+		return true;
+	}
+
+	int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int firstClickable, int firstObstacle, int firstCombatTarget) {
+		BoundingBox boundingBox;
+		*isClickable = 0;
+		*isObstacle = 0;
+		*isCombatTarget = 0;
+
+		if (!_count)
+			return -1;
+
+		int i;
+		for (i = 0; i < _count; i++) {
+			//assert(_sceneObjectsSortedByDistance[i] < _count);
+			SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
+			if ((firstClickable && sceneObject->_isClickable)
+				|| (firstObstacle && sceneObject->_isObstacle)
+				|| (firstCombatTarget && sceneObject->_isCombatTarget)) {
+				break;
+			}
+
+			boundingBox = sceneObject->_boundingBox;
+
+			if (sceneObject->_sceneObjectType == SceneObjectTypeObject || sceneObject->_sceneObjectType == SceneObjectTypeItem) {
+				boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
+			}
+
+			if (boundingBox.isXYZInside(x, y, z)) {
+				*isClickable = sceneObject->_isClickable;
+				*isObstacle = sceneObject->_isObstacle;
+				*isCombatTarget = sceneObject->_isCombatTarget;
+				return sceneObject->_sceneObjectId;
+			}
+		}
+
+		return -1;
+	}
+
+	int SceneObjects::findById(int sceneObjectId)
+	{
+		int i;
+		for (i = 0; i < _count; i++) {
+			if (_sceneObjects[i]._present && _sceneObjects[i]._sceneObjectId == sceneObjectId) {
+				return i;
+			}
+		}
+		return -1;
+	}
+
+	bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint unknown2, uint isRetired) {
+		int index = findEmpty();
+		if (_count >= SCENE_OBJECTS_COUNT || index == -1) {
+			return false;
+		}
+
+		_sceneObjects[index]._sceneObjectId = sceneObjectId;
+		_sceneObjects[index]._sceneObjectType = sceneObjectType;
+		_sceneObjects[index]._present = 1;
+		_sceneObjects[index]._boundingBox = *boundingBox;
+		_sceneObjects[index]._screenRectangle = *screenRectangle;
+		_sceneObjects[index]._isClickable = isClickable;
+		_sceneObjects[index]._isObstacle = isObstacle;
+		_sceneObjects[index]._unknown1 = unknown1;
+		_sceneObjects[index]._isCombatTarget = isCombatTarget;
+		_sceneObjects[index]._unknown2 = unknown2;
+		_sceneObjects[index]._isRetired = isRetired;
+
+		float centerZ = (_sceneObjects[index]._boundingBox._vertices[0].z + _sceneObjects[index]._boundingBox._vertices[1].z) / 2.0;
+
+		float distanceToCamera = fabs(_view->_cameraPosition.z - centerZ);
+		_sceneObjects[index]._distanceToCamera = distanceToCamera;
+
+		// insert according to distance from camera
+		int i, j;
+		for (i = 0; i < _count; i++) {
+			if (distanceToCamera < _sceneObjects[_sceneObjectsSortedByDistance[i]]._distanceToCamera) {
+				break;
+			}
+		}
+
+		for (j = _count - 1; j >= i; j--) {
+			_sceneObjectsSortedByDistance[j + 1] = _sceneObjectsSortedByDistance[j];
+		}
+
+		_sceneObjectsSortedByDistance[i] = index;
+		++_count;
+		return true;
+	}
+
+	int SceneObjects::findEmpty()
+	{
+		int i;
+		for (i = 0; i < SCENE_OBJECTS_COUNT; i++)
+		{
+			if (!_sceneObjects[i]._present)
+				return i;
+		}
+		return -1;
+	}
+
+
+
+	SceneObject::SceneObject()
+	{
+		_sceneObjectId = -1;
+		_sceneObjectType = SceneObjectTypeUnknown;
+		_distanceToCamera = 0;
+		_present = 0;
+		_isClickable = 0;
+		_isObstacle = 0;
+		_unknown1 = 0;
+		_isCombatTarget = 0;
+		_unknown2 = 0;
+		_isRetired = 0;
+	}
+
+	SceneObject::~SceneObject()
+	{
+	}
+}
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
new file mode 100644
index 0000000..999d821
--- /dev/null
+++ b/engines/bladerunner/scene_objects.h
@@ -0,0 +1,96 @@
+/* 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 BLADERUNNER_SCENE_OBJECTS_H
+#define BLADERUNNER_SCENE_OBJECTS_H
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/boundingbox.h"
+#include "bladerunner/view.h"
+
+#include "common/rect.h"
+
+namespace BladeRunner {
+	class BladeRunnerEngine;
+	class SceneObject;
+
+	enum SceneObjectType
+	{
+		SceneObjectTypeUnknown = -1,
+		SceneObjectTypeActor = 0,
+		SceneObjectTypeObject = 1,
+		SceneObjectTypeItem = 2,
+	};
+
+#define SCENE_OBJECTS_COUNT 115
+#define SCENE_OBJECTS_ACTORS_OFFSET 0
+#define SCENE_OBJECTS_ITEMS_OFFSET 74
+#define SCENE_OBJECTS_OBJECTS_OFFSET 198
+
+
+
+	class SceneObjects {
+		BladeRunnerEngine *_vm;
+	private:
+		View *_view;
+		int _count;
+		SceneObject *_sceneObjects;
+		int *_sceneObjectsSortedByDistance;
+
+	public:
+		SceneObjects(BladeRunnerEngine *vm, View *view);
+		~SceneObjects();
+		void reset();
+		bool addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 unknown1, uint8 isCombatTarget, uint8 isRetired);
+		bool addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget);
+		bool addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle);
+		bool remove(int sceneObjectId);
+		int findByXYZ(int* clickable, int* obstacle, int* targetable, float x, float y, float z, int firstClickable, int firstObstacle, int firstTargetable);		
+	private:
+		int findById(int sceneObjectId);
+		bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint unknown2, uint isRetired);
+		int findEmpty();
+	};
+
+	class SceneObject
+	{
+		friend class SceneObjects;
+	private:
+		int _sceneObjectId;
+		SceneObjectType _sceneObjectType;
+		BoundingBox _boundingBox;
+		Common::Rect _screenRectangle;
+		float _distanceToCamera;
+		int _present;
+		int _isClickable;
+		int _isObstacle;
+		int _unknown1;
+		int _isCombatTarget;
+		int _unknown2;
+		int _isRetired;
+	public:
+		SceneObject();
+		~SceneObject();
+	};
+}
+#endif
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index c37b31a..a2e5410 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -23,12 +23,14 @@
 #include "bladerunner/set.h"
 
 #include "bladerunner/bladerunner.h"
+#include "bladerunner/slice_renderer.h"
 
 #include "common/debug.h"
 #include "common/ptr.h"
 #include "common/str.h"
 #include "common/stream.h"
 
+
 namespace BladeRunner {
 
 #define kSet0 0x53657430
@@ -38,9 +40,12 @@ Set::Set(BladeRunnerEngine *vm) : _vm(vm) {
 	_walkboxCount = 0;
 	_objects = new Object[85];
 	_walkboxes = new Walkbox[95];
+	_footstepSoundOverride = -1;
+	_effects = new SetEffects(vm);
 }
 
 Set::~Set() {
+	delete _effects;
 	delete[] _objects;
 	delete[] _walkboxes;
 }
@@ -52,7 +57,7 @@ bool Set::open(const Common::String &name) {
 	if (sig != kSet0)
 		return false;
 
-	s->skip(4); // TODO: LITE length
+	int framesCount = s->readUint32LE();
 
 	_objectCount = s->readUint32LE();
 	assert(_objectCount <= 85);
@@ -101,9 +106,24 @@ bool Set::open(const Common::String &name) {
 		// debug("WALKBOX: %s", _walkboxes[i]._name);
 	}
 
-	// TODO: Read LITE
+	_vm->_lights->reset();
+	_vm->_lights->read(s.get(), framesCount);
+	_vm->_sliceRenderer->setLights(_vm->_lights);
+	_effects->reset();
+	_effects->read(s.get(), framesCount);
+	_vm->_sliceRenderer->setSetEffects(_effects);
 
 	return true;
 }
 
+
+void Set::addAllObjectsToScene(SceneObjects* sceneObjects)
+{
+	uint32 i;
+	for (i = 0; i < _objectCount; i++)
+	{
+		sceneObjects->addObject(i + SCENE_OBJECTS_OBJECTS_OFFSET, &_objects[i]._bbox, _objects[i]._isClickable, _objects[i]._isObstacle, _objects[i]._unknown1, _objects[i]._isCombatTarget);
+	}
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index e7358fd..fba2d2a 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -24,6 +24,10 @@
 #define BLADERUNNER_SET_H
 
 #include "bladerunner/boundingbox.h"
+#include "bladerunner/set_effects.h"
+#include "bladerunner/lights.h"
+#include "bladerunner/scene_objects.h"
+
 
 #include "common/scummsys.h"
 #include "common/str.h"
@@ -41,6 +45,7 @@ struct Object {
 	uint8       _isClickable;
 	uint8       _isHotMouse;
 	uint8       _isCombatTarget;
+	uint8       _unknown1;
 };
 
 struct Walkbox {
@@ -53,19 +58,24 @@ struct Walkbox {
 class Set {
 	BladeRunnerEngine *_vm;
 
-	uint32   _objectCount;
-	uint32   _walkboxCount;
-	Object  *_objects;
-	Walkbox *_walkboxes;
-	int      _walkboxStepSound[85];
-	int      _footstepSoundOverride;
-	float    _unknown[10];
+	uint32      _objectCount;
+	uint32      _walkboxCount;
+	Object     *_objects;
+	Walkbox    *_walkboxes;
+	int         _walkboxStepSound[85];
+	int         _footstepSoundOverride;
+	SetEffects *_effects;
+public:
+	
 
 public:
 	Set(BladeRunnerEngine *vm);
 	~Set();
 
 	bool open(const Common::String &name);
+	void addAllObjectsToScene(SceneObjects *sceneObjects);
+
+	
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
new file mode 100644
index 0000000..f524820
--- /dev/null
+++ b/engines/bladerunner/set_effects.cpp
@@ -0,0 +1,83 @@
+#include "bladerunner/set_effects.h"
+
+namespace BladeRunner
+{
+	SetEffects::SetEffects(BladeRunnerEngine* vm)
+	{
+		_vm = vm;
+
+		_distanceColor.r = 1.0f;
+		_distanceColor.g = 1.0f;
+		_distanceColor.b = 1.0f;
+		_distanceCoeficient = 0.1f;
+
+		_fadeColor.r = 0.0f;
+		_fadeColor.g = 0.0f;
+		_fadeColor.b = 0.0f;
+		_fadeDensity = 0.0f;
+
+		_fogsCount = 0;
+		_fogs = NULL;
+	}
+
+	SetEffects::~SetEffects()
+	{
+		reset();
+	}
+
+	void SetEffects::read(Common::ReadStream* stream, int framesCount)
+	{
+		_distanceCoeficient = stream->readFloatLE();
+		_distanceColor.r = stream->readFloatLE();
+		_distanceColor.g = stream->readFloatLE();
+		_distanceColor.b = stream->readFloatLE();
+
+		_fogsCount = stream->readUint32LE();
+		int i;
+		for (i = 0; i < _fogsCount; i++)
+		{
+			int type = stream->readUint32LE();
+			Fog* fog = NULL;
+			switch(type)
+			{
+			case 0: 
+				fog = new FogCone();
+				break;
+			case 1:
+				fog = new FogSphere();
+				break;
+			case 2:
+				fog = new FogBox();
+				break;
+			}
+			if(!fog)
+			{
+				//TODO exception, unknown fog type
+			}
+			fog->read(stream, framesCount);
+			fog->_next = _fogs;
+			_fogs = fog;
+		}
+	}
+
+	void SetEffects::reset()
+	{
+		Fog* fog, *nextFog;
+		
+		if (!_fogs)
+			return;
+
+		do
+		{
+			fog = _fogs;
+			nextFog = fog->_next;
+			delete fog;
+			fog = nextFog;
+		} while (nextFog);
+
+	}
+
+	void SetEffects::setupFrame(int frame)
+	{
+	}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
new file mode 100644
index 0000000..5165cfb
--- /dev/null
+++ b/engines/bladerunner/set_effects.h
@@ -0,0 +1,62 @@
+/* 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 BLADERUNNER_SET_EFFECTS_H
+#define BLADERUNNER_SET_EFFECTS_H
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/color.h"
+#include "bladerunner/fog.h"
+
+#include "common/stream.h"
+
+
+namespace BladeRunner {
+
+	class SetEffects
+	{
+		BladeRunnerEngine *_vm;
+
+	private:
+		Color _distanceColor;
+		float _distanceCoeficient;
+		Color _fadeColor;
+		float _fadeDensity;
+		int _fogsCount;
+		Fog *_fogs;
+
+	public:
+		SetEffects(BladeRunnerEngine *vm);
+		~SetEffects();
+
+		void read(Common::ReadStream *stream, int framesCount);
+
+		void reset();
+
+		void setupFrame(int frame);
+
+	private:
+
+	};
+
+}
+#endif
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 4e2300e..a1e8497 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -24,6 +24,9 @@
 
 #include "bladerunner/bladerunner.h"
 #include "bladerunner/slice_animations.h"
+#include "bladerunner/lights.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/set.h"
 
 #include "common/debug.h"
 #include "common/memstream.h"
@@ -54,7 +57,7 @@ void dump(const char *str, Matrix4x3 m) {
 SliceRenderer::~SliceRenderer() {
 }
 
-void SliceRenderer::setView(const View &view) {
+void SliceRenderer::setView(View *view) {
 	_view = view;
 }
 
@@ -84,7 +87,7 @@ void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float
 Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
 	assert(_sliceFramePtr);
 
-	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
+	Matrix4x3 viewMatrix = _view->_sliceViewMatrix;
 	Vector3 viewPos = viewMatrix * _position;
 	float dir = atan2f(viewPos.x, viewPos.z) + _facing;
 	float s = sinf(dir);
@@ -107,7 +110,7 @@ void SliceRenderer::calculateBoundingRect() {
 	_minY = 0.0f;
 	_maxY = 0.0f;
 
-	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
+	Matrix4x3 viewMatrix = _view->_sliceViewMatrix;
 
 	Vector3 frameBottom = Vector3(0.0f, 0.0f, _frameBottomZ);
 	Vector3 frameTop    = Vector3(0.0f, 0.0f, _frameBottomZ + _frameSliceCount * _frameSliceHeight);
@@ -122,7 +125,7 @@ void SliceRenderer::calculateBoundingRect() {
 
 	Matrix3x2 facingRotation = calculateFacingRotationMatrix();
 
-	Matrix3x2 m4(_view._viewportDistance / bottom.z,  0.0f, 0.0f,
+	Matrix3x2 m4(_view->_viewportDistance / bottom.z,  0.0f, 0.0f,
 	                                           0.0f, 25.5f, 0.0f);
 
 	Matrix3x2 m2(_frameFront.x,          0.0f, _framePos.x,
@@ -130,13 +133,13 @@ void SliceRenderer::calculateBoundingRect() {
 
 	_field_109E = m4 * (facingRotation * m2);
 
-	Vector4 B6(_view._viewportHalfWidth   + top.x / top.z * _view._viewportDistance,
-	           _view._viewportHalfHeight  + top.y / top.z * _view._viewportDistance,
+	Vector4 B6(_view->_viewportHalfWidth   + top.x / top.z * _view->_viewportDistance,
+	           _view->_viewportHalfHeight  + top.y / top.z * _view->_viewportDistance,
 	           1.0f / top.z,
 	           _frameSliceCount * (1.0f / top.z));
 
-	Vector4 C2(_view._viewportHalfWidth   + bottom.x / bottom.z * _view._viewportDistance,
-	           _view._viewportHalfHeight  + bottom.y / bottom.z * _view._viewportDistance,
+	Vector4 C2(_view->_viewportHalfWidth   + bottom.x / bottom.z * _view->_viewportDistance,
+	           _view->_viewportHalfHeight  + bottom.y / bottom.z * _view->_viewportDistance,
 	           1.0f / bottom.z,
 	           0.0f);
 
@@ -324,6 +327,9 @@ void setupLookupTable(int t[256], int inc) {
 
 void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) {
 	assert(_sliceFramePtr);
+	assert(_lights);
+	assert(_setEffects);
+	assert(_view);
 
 	SliceLineIterator sliceLineIterator;
 	sliceLineIterator.setup(
@@ -333,6 +339,9 @@ void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) {
 		_field_109E              // 3x2 matrix
 		);
 
+	_lights->setupFrame(_view->_frame);
+	_setEffects->setupFrame(_view->_frame);
+	
 	setupLookupTable(_t1, sliceLineIterator._field_00[0][0]);
 	setupLookupTable(_t2, sliceLineIterator._field_00[0][1]);
 	setupLookupTable(_t4, sliceLineIterator._field_00[1][0]);
@@ -407,4 +416,13 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 	}
 }
 
+void SliceRenderer::setLights(Lights* lights)
+{
+	_lights = lights;
+}
+
+void SliceRenderer::setSetEffects(SetEffects* setEffects)
+{
+	_setEffects = setEffects;
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index 79ebdd8..c04560a 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -26,6 +26,8 @@
 #include "bladerunner/vector.h"
 #include "bladerunner/view.h"
 #include "bladerunner/matrix.h"
+#include "bladerunner/lights.h"
+#include "bladerunner/set_effects.h"
 
 #include "graphics/surface.h"
 
@@ -34,8 +36,9 @@ namespace Common {
 }
 
 namespace BladeRunner {
+	class SetEffects;
 
-class BladeRunnerEngine;
+	class BladeRunnerEngine;
 
 class SliceRenderer {
 	BladeRunnerEngine *_vm;
@@ -46,7 +49,9 @@ class SliceRenderer {
 	float     _facing;
 	float     _scale;
 
-	View      _view;
+	View       *_view;
+	Lights     *_lights;
+	SetEffects *_setEffects;
 
 	void                     *_sliceFramePtr;
 
@@ -75,6 +80,8 @@ class SliceRenderer {
 	int _t5[256];
 	int _c6;
 
+
+
 	Matrix3x2 calculateFacingRotationMatrix();
 	void drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr);
 
@@ -84,11 +91,16 @@ public:
 	{}
 	~SliceRenderer();
 
-	void setView(const View &view);
+	void setView(View *view);
+	void setLights(Lights *lights);
+	void setSetEffects(SetEffects *setEffects);
+
 	void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f);
 	void calculateBoundingRect();
 
 	void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
+
+
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index b3b6ad8..029f829 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -27,6 +27,11 @@
 
 namespace BladeRunner {
 
+View::View(BladeRunnerEngine* vm)
+{
+	_vm = vm;
+}
+
 bool View::read(Common::ReadStream *stream) {
 	uint32 frame;
 	frame = stream->readUint32LE();
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
index 511ea66..3e3a0e8 100644
--- a/engines/bladerunner/view.h
+++ b/engines/bladerunner/view.h
@@ -23,6 +23,8 @@
 #ifndef BLADERUNNER_VIEW_H
 #define BLADERUNNER_VIEW_H
 
+#include "bladerunner/bladerunner.h"
+
 #include "matrix.h"
 
 namespace Common {
@@ -32,6 +34,7 @@ namespace Common {
 namespace BladeRunner {
 
 class View {
+	BladeRunnerEngine *_vm;
 public:
 	float     _fovX;
 	Matrix4x3 _frameViewMatrix;
@@ -44,8 +47,12 @@ public:
 	float     _viewportHalfHeight;
 	float     _viewportDistance;
 
+	View(BladeRunnerEngine *vm);
+
 	bool read(Common::ReadStream *stream);
 
+
+
 private:
 	void setFovX(float fovX);
 	void calculateSliceViewMatrix();
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index d1e56a9..63378dc 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -30,6 +30,7 @@
 
 #include "common/array.h"
 #include "common/util.h"
+#include "common/memstream.h"
 
 namespace BladeRunner {
 
@@ -524,7 +525,12 @@ bool VQADecoder::readMFCI(Common::SeekableReadStream *s, uint32 size) {
 	return true;
 }
 
-VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
+void VQADecoder::decodeView(View* view)
+{
+	_videoTrack->decodeView(view);
+}
+
+	VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
 	VQADecoder::Header *header = &vqaDecoder->_header;
 
 	_surface = nullptr;
@@ -560,6 +566,8 @@ VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
 
 	_surface = new Graphics::Surface();
 	_surface->create(_width, _height, createRGB555());
+
+	_viewData = new uint8[56];
 }
 
 VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
@@ -567,6 +575,7 @@ VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
 	delete[] _cbfz;
 	delete[] _zbufChunk;
 	delete[] _vpointer;
+	delete[] _viewData;
 
 	if (_surface)
 		_surface->free();
@@ -743,18 +752,29 @@ const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 	return _zbuffer;
 }
 
-bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
+
+void VQADecoder::VQAVideoTrack::decodeView(View* view)
+{
+	assert(_viewData);
+	assert(view);
+	
+	Common::MemoryReadStream s(_viewData, 56);
+	view->read(&s);
+}
+
+	bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 56)
 		return false;
 
-	_view.read(s);
+	s->read(_viewData, 56);
 
 	return true;
 }
 
 bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size)
 {
+	// some screen (2d not 3d) effects for transparency
 	s->skip(roundup(size));
 	return true;
 }
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index 3f8c968..c573720 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -52,8 +52,8 @@ public:
 	const Graphics::Surface    *decodeVideoFrame();
 	const uint16               *decodeZBuffer();
 	Audio::SeekableAudioStream *decodeAudioFrame();
-
-	const View &getView() { return _videoTrack->getView(); }
+	void                        decodeView(View *view);
+	//const View &getView() { return _videoTrack->getView(); }
 
 	uint16 numFrames() const { return _header.numFrames; }
 	uint8  frameRate() const { return _header.frameRate; }
@@ -163,7 +163,7 @@ private:
 		int getFrameCount() const;
 		const Graphics::Surface *decodeVideoFrame();
 		const uint16 *decodeZBuffer();
-		const View &getView() { return _view; }
+		void decodeView(View *view);
 
 		bool readVQFR(Common::SeekableReadStream *s, uint32 size);
 		bool readVPTR(Common::SeekableReadStream *s, uint32 size);
@@ -207,7 +207,7 @@ private:
 
 		int      _curFrame;
 
-		View     _view;
+		uint8   *_viewData;
 
 		void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false);
 		bool decodeFrame(uint16 *frame);
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 8146c1a..0a04d1b 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -65,7 +65,7 @@ int VQAPlayer::update() {
 				queueAudioFrame(_decoder.decodeAudioFrame());
 			_surface = _decoder.decodeVideoFrame();
 			_zBuffer = _decoder.decodeZBuffer();
-			_view = _decoder.getView();
+			_decoder.decodeView(_view);
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
@@ -89,7 +89,7 @@ int VQAPlayer::update() {
 		if (_curFrame >= 0) {
 			_surface = _decoder.decodeVideoFrame();
 			_zBuffer = _decoder.decodeZBuffer();
-			_view = _decoder.getView();
+			_decoder.decodeView(_view);
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 80ebf19..98f1fcf 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -42,14 +42,14 @@ class VQAPlayer {
 	const uint16                *_zBuffer;
 	Audio::QueuingAudioStream   *_audioStream;
 
+	View                        *_view;
+
 	int _curFrame;
 	int _decodedFrame;
 	int _curLoop;
 	int _loopSpecial;
 	int _loopDefault;
 
-	View _view;
-
 	uint32 _nextFrameTime;
 	bool   _hasAudio;
 	bool   _audioStarted;
@@ -57,7 +57,7 @@ class VQAPlayer {
 
 public:
 
-	VQAPlayer(BladeRunnerEngine *vm)
+	VQAPlayer(BladeRunnerEngine *vm, View *view)
 		: _vm(vm),
 		  _s(nullptr),
 		  _surface(nullptr),
@@ -69,7 +69,8 @@ public:
 		  _loopDefault(-1),
 		  _nextFrameTime(0),
 		  _hasAudio(false),
-		  _audioStarted(false)
+		  _audioStarted(false),
+		  _view(view)
 	{}
 
 	~VQAPlayer() {
@@ -82,7 +83,6 @@ public:
 	int  update();
 	const Graphics::Surface *getSurface() const;
 	const uint16 *getZBuffer() const;
-	const View &getView() const { return _view; }
 
 	void setLoopSpecial(int loop, bool wait);
 	void setLoopDefault(int loop);


Commit: 479d2f5b6293af2ae84fbdc718348a6e1126efb0
    https://github.com/scummvm/scummvm/commit/479d2f5b6293af2ae84fbdc718348a6e1126efb0
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:40+02:00

Commit Message:
BLADERUNNER: still adding structures... and implementing some of script methods...

Changed paths:
  A engines/bladerunner/actor_combat.cpp
  A engines/bladerunner/actor_combat.h
  A engines/bladerunner/item.cpp
  A engines/bladerunner/item.h
  A engines/bladerunner/items.cpp
  A engines/bladerunner/items.h
  A engines/bladerunner/regions.cpp
  A engines/bladerunner/regions.h
  A engines/bladerunner/waypoints.cpp
  A engines/bladerunner/waypoints.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/actor_walk.cpp
    engines/bladerunner/actor_walk.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/boundingbox.cpp
    engines/bladerunner/boundingbox.h
    engines/bladerunner/matrix.cpp
    engines/bladerunner/matrix.h
    engines/bladerunner/mouse.cpp
    engines/bladerunner/mouse.h
    engines/bladerunner/movement_track.cpp
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/set.cpp
    engines/bladerunner/set.h
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index af9cef7..d95c652 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -27,6 +27,9 @@
 #include "bladerunner/boundingbox.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/slice_renderer.h"
+#include "bladerunner/waypoints.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/items.h"
 
 namespace BladeRunner {
 
@@ -34,33 +37,35 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
 	_vm = vm;
 	_id = actorId;
 
-	// TODO: Construct Walkinfo
-
-	_bbox = new BoundingBox();
-
-	_clues = new ActorClues(vm, ((actorId && actorId != 99) ? 2 : 4));
-
-	// TODO: Construct _movementTrack
+	_walkInfo      = new ActorWalk(vm);
+	_movementTrack = new MovementTrack();
+	_clues         = new ActorClues(vm, (actorId && actorId != 99) ? 2 : 4);
+	_bbox          = new BoundingBox();
+	_combatInfo    = new ActorCombat(vm);
 
 	_friendlinessToOther = new int[_vm->_gameInfo->getActorCount()];
 }
 
 Actor::~Actor() {
+	
 	delete[] _friendlinessToOther;
+	delete   _combatInfo;
 	delete   _bbox;
-	// delete   _clues;
-	// delete   _movementTrack;
+	delete   _clues;
+	delete   _movementTrack;
+	delete   _walkInfo;
+	
 }
 
 void Actor::setup(int actorId) {
 	_id  = actorId;
-	_set = -1;
+	_setId = -1;
 
-	_position  = Vector3(0.0, 0.0, 0.0);
-	_facing    = 512;
-	_walkboxId = -1;
+	_position     = Vector3(0.0, 0.0, 0.0);
+	_facing       = 512;
+	_targetFacing = -1;
+	_walkboxId    = -1;
 
-	_walkboxId = -1;
 	_animationId = 0;
 	_animationFrame = 0;
 	_fps = 15;
@@ -72,8 +77,10 @@ void Actor::setup(int actorId) {
 	
 	_isRetired           = false;
 
-	_width = 0;
-	_height = 0;
+	_width         = 0;
+	_height        = 0;
+	_retiredWidth  = 0;
+	_retiredHeight = 0;
 
 	for (int i = 0; i != 7; ++i) {
 		_timersRemain[i] = 0;
@@ -104,32 +111,30 @@ void Actor::setup(int actorId) {
 	// TODO: Flush movement track
 }
 
-void Actor::set_at_xyz(Vector3 pos, int facing) {
-	_position = pos;
-	_facing = facing;
-
-
-//	this->x = x;
-//	this->y = y;
-//	this->z = z;
-//	actor::set_angle(this, angle, addOrSet);
-//	if (scene::get_sceneId(Scene) == this->sceneId)
-//		this->walkboxId = set::findWalkbox(Scene->set, x, z);
-//	else
-//		this->walkboxId = -1;
-//	actor::setBoundingBox(this, x, y, z, retired);
-//	sceneObjects::removeScreneObject(SceneObjects, this->id);
-//	scene = this->sceneId;
-//	if (scene == scene::get_sceneId(Scene))
-//		sceneObjects::addActor(
-//			SceneObjects,
-//			this->id,
-//			this->boundingBox,
-//			&this->screenRect,
-//			1,
-//			a7,
-//			this->targetable,
-//			retired);
+void Actor::set_at_xyz(Vector3 position, int facing, bool halfOrSet, int moving, bool retired) {
+	_position = position;
+	setFacing(facing, halfOrSet);
+	
+	if(_vm->_scene->_setId == _setId) {
+		_walkboxId = _vm->_scene->_set->findWalkbox(position.x, position.y);
+	}else {
+		_walkboxId = -1;
+	}
+
+	setBoundingBox(position, retired);
+
+	_vm->_sceneObjects->remove(_id);
+
+	if(_vm->_scene->getSetId() == _setId) {
+		_vm->_sceneObjects->addActor(_id, _bbox, &_screenRectangle, 1, moving, _isTargetable, retired);
+	}
+}
+
+
+void Actor::set_at_waypoint(int waypointId, int angle, int unknown, bool retired) {
+	Vector3 waypointPosition;
+	_vm->_waypoints->getXyz(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
+	set_at_xyz(waypointPosition, angle, true, unknown, retired);
 }
 
 void Actor::draw() {
@@ -144,4 +149,278 @@ void Actor::draw() {
 	_vm->_sliceRenderer->drawFrame(_vm->_surface2, _vm->_zBuffer2);
 }
 
+
+int Actor::getSetId() {
+	return _setId;
+}
+
+void Actor::setSetId(int setId) {
+	if (_setId == setId) {
+		return;
+	}
+
+	int i;
+
+	if(_setId > 0) {
+		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
+				//actorScript->OtherAgentExitedThisScene( i, _id);
+			}
+		}
+	}
+	_setId = setId;
+	//actorScript->EnteredScene(_id, set);
+	if (_setId > 0) {
+		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
+				//actorScript->OtherAgentEnteredThisScene(i, _id);
+			}
+		}
+	}
+}
+
+
+void Actor::setFacing(int facing, bool halfOrSet) {
+	if (facing < 0 || facing >= 1024) {
+		return;
+	}
+
+	if (halfOrSet) {
+		_facing = facing;
+		return;
+	}
+
+	int cw;
+	int ccw;
+	int offset;
+
+	if (facing > _facing) {
+		cw = facing - _facing;
+		ccw = _facing + 1024 - facing;
+	} else {
+		ccw = _facing - facing;
+		cw = facing + 1024 - _facing;
+	}
+	if (cw < ccw) {
+		if (cw <= 32) {
+			offset = cw;
+		} else {
+			offset = cw / 2;
+		}
+	} else {
+		if (ccw <= 32) {
+			offset = -ccw;
+		} else {
+			offset = -ccw / 2;
+		}
+	}
+	_facing = (_facing + offset) % 1024;
+}
+
+void Actor::setBoundingBox(Vector3 position, bool retired) {
+	if(retired) {
+		
+	}else {
+		_bbox->setXyz(position.x - 12.0f, position.y + 6.0f, position.z - 12.0f, position.x + 12.0f, position.y + 72.0f, position.z + 12.0f);
+	}
+}
+
+
+void Actor::changeAnimationMode(int animationMode, int force) {
+	if (force == 1) {
+		_animationMode = -1;
+	}
+	if(animationMode != _animationMode) {
+		//TODO: _vm->actorScript->ChangeAnimationMode(_id, animationMode);
+		_animationMode = animationMode;
+	}
+
+}
+
+bool Actor::isWalking() {
+	return _walkInfo->isWalking();
+}
+
+void Actor::stopWalking(int value) {
+	if (value == 1 && _id == 0) {
+		_vm->_playerActorIdle = true;
+	}
+
+	if(isWalking()) {
+		_walkInfo->stop(_id, 1, _combatAnimationMode, 0);
+	} else if(inCombat()) {
+		changeAnimationMode(_combatAnimationMode, 0);
+	} else {
+		changeAnimationMode(0, 0);
+	}
+}
+
+void Actor::faceActor(int otherActorId, bool animate) {
+	if (_setId != _vm->_scene->_setId) {
+		return;
+	}
+	
+	Actor *otherActor = _vm->_actors[otherActorId];
+
+	if (_setId != otherActor->_setId) {
+		return;
+	}
+
+	faceXYZ(otherActor->_position.x, otherActor->_position.y, otherActor->_position.z, animate);
+}
+
+void Actor::faceObject(char *objectName, bool animate) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1) {
+		return;
+	}
+
+	BoundingBox boundingBox;
+	_vm->_scene->objectGetBoundingBox(objectId, &boundingBox);
+
+	float x0, y0, z0, x1, y1, z1;
+	boundingBox.getXyz(&x0, &y0, &z0, &x1, &y1, &z1);
+
+	float x = (x1 + x0) / 2.0f;
+	float z = (z1 + z0) / 2.0f;
+	faceXYZ(x, y0, z, animate);
+}
+
+void Actor::faceItem(int itemId, bool animate) {
+	float x, y, z;
+	_vm->_items->getXyz(itemId, &x, &y, &z);
+	faceXYZ(x, y, z, animate);
+}
+
+void Actor::faceWaypoint(int waypointId, bool animate) {
+	float x, y, z;
+	_vm->_waypoints->getXyz(waypointId, &x, &y, &z);
+	faceXYZ(x, y, z, animate);
+}
+
+void Actor::faceXYZ(float x, float y, float z, bool animate) {
+	if (isWalking()) {
+		stopWalking(0);
+	}
+	if (x == _position.x && z == _position.z) {
+		return;
+	}
+
+	int heading = int(512.0f * atan2f(_position.x - x, _position.z - z) / M_PI) % 1024;
+	faceHeading(heading, animate);
+}
+
+void Actor::faceCurrentCamera(bool animate) {
+	faceXYZ(_vm->_view->_cameraPosition.x, _vm->_view->_cameraPosition.y, -_vm->_view->_cameraPosition.z, animate);
+}
+
+void Actor::faceHeading(int heading, bool animate) {
+	if (heading != _facing) {
+		if (animate) {
+			_targetFacing = heading;
+		}
+		else {
+			setFacing(heading, true);
+		}
+	}
+}
+
+int Actor::getFriendlinessToOther(int otherActorId) {
+	return _friendlinessToOther[otherActorId];
+}
+
+void Actor::modifyFriendlinessToOther(int otherActorId, signed int change) {
+	_friendlinessToOther[otherActorId] = MIN(MAX(_friendlinessToOther[otherActorId] + change, 0), 100);
+}
+
+void Actor::setFriendlinessToOther(int otherActorId, int friendliness) {
+	_friendlinessToOther[otherActorId] = friendliness;
+}
+
+void Actor::setHonesty(int honesty) {
+	_honesty = honesty;
+}
+
+void Actor::setIntelligence(int intelligence) {
+	_intelligence = intelligence;
+}
+
+void Actor::setStability(int stability) {
+	_stability = stability;
+}
+
+void Actor::setCombatAggressiveness(int combatAggressiveness) {
+	_combatAggressiveness = combatAggressiveness;
+}
+
+int Actor::getCurrentHP() {
+	return _currentHP;
+}
+
+int Actor::getMaxHP() {
+	return _maxHP;
+}
+
+int Actor::getCombatAggressiveness() {
+	return _combatAggressiveness;
+}
+
+int Actor::getHonesty() {
+	return _honesty;
+}
+
+int Actor::getIntelligence() {
+	return _intelligence;
+}
+
+int Actor::getStability() {
+	return _stability;
+}
+
+void Actor::modifyCurrentHP(signed int change) {
+	_currentHP = MIN(MAX(_currentHP + change, 0), 100);
+	if (_currentHP > 0)
+		retire(0, 0, 0, -1);
+}
+
+void Actor::modifyMaxHP(signed int change) {
+	_maxHP = MIN(MAX(_maxHP + change, 0), 100);
+}
+
+void Actor::modifyCombatAggressiveness(signed int change) {
+	_combatAggressiveness = MIN(MAX(_combatAggressiveness + change, 0), 100);
+}
+
+void Actor::modifyHonesty(signed int change) {
+	_honesty = MIN(MAX(_honesty + change, 0), 100);
+}
+
+void Actor::modifyIntelligence(signed int change) {
+	_intelligence = MIN(MAX(_intelligence + change, 0), 100);
+}
+
+void Actor::modifyStability(signed int change) {
+	_stability = MIN(MAX(_stability + change, 0), 100);
+}
+
+void Actor::setFlagDamageAnimIfMoving(bool value) {
+	_damageAnimIfMoving = value;
+}
+
+bool Actor::getFlagDamageAnimIfMoving() {
+	return _damageAnimIfMoving;
+}
+
+void Actor::retire(bool isRetired, int width, int height, int retiredByActorId) {
+	_isRetired = isRetired;
+	_retiredWidth = MAX(width, 0);
+	_retiredHeight = MAX(height, 0);
+	if(_id == 0 && isRetired) {
+		_vm->playerLosesControl();
+		_vm->_playerDead = true;
+	}
+	if(isRetired) {
+		//TODO: _vm->actorScript->Retired(_id, retiredByActorId);
+	}
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index d621d53..4da73d4 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -29,6 +29,7 @@
 #include "bladerunner/movement_track.h"
 #include "bladerunner/actor_clues.h"
 #include "bladerunner/actor_walk.h"
+#include "bladerunner/actor_combat.h"
 
 #include "common/rect.h"
 
@@ -42,8 +43,10 @@ class Actor {
 
 private:
 	BoundingBox   *_bbox;
-	Common::Rect _screenRectangle;
+	Common::Rect   _screenRectangle;
 	MovementTrack *_movementTrack;
+	ActorWalk     *_walkInfo;
+	ActorCombat   *_combatInfo;
 
 	int  _honesty;
 	int  _intelligence;
@@ -58,28 +61,35 @@ private:
 	ActorClues* _clues;
 
 	int     _id;
-	int     _set;
+	int     _setId;
 	Vector3 _position;
 	int     _facing; // [0, 1024)
+	int     _targetFacing;
 	int     _walkboxId;
 
 	// Flags
 	bool _isTargetable;
 	bool _isInvisible;
 	bool _isImmuneToObstacles;
-
 	bool _isRetired;
+	bool _inCombat;
+	bool _isMoving;
+	bool _damageAnimIfMoving;
+
 
 	// Animation
-	int _width;
+	int _width;	
 	int _height;
 	int _animationMode;
+	int _combatAnimationMode;
 	int _fps;
 	int _frame_ms;
 	int _animationId;
 	int _animationFrame;
 
-	ActorWalk* _walkInfo;
+	int _retiredWidth;
+	int _retiredHeight;
+
 
 	int _timersRemain[7];
 	int _timersBegan[7];
@@ -92,15 +102,64 @@ public:
 
 	void setup(int actorId);
 
-	void set_at_xyz(Vector3 pos, int facing);
+	void set_at_xyz(Vector3 pos, int facing, bool halfOrSet, int unknown, bool retired);
+	void set_at_waypoint(int waypointId, int angle, int unknown, bool retired);
 
 	void draw();
 
-	int getSet() { return _set; }
+	int getSetId();
+	void setSetId(int setId);
 	BoundingBox* getBoundingBox() { return _bbox; }
 	Common::Rect* getScreenRectangle() { return &_screenRectangle; }
 	bool isRetired() { return _isRetired; }
 	bool isTargetable() { return _isTargetable; }
+	bool inCombat() { return _inCombat; }
+	bool isMoving() { return _isMoving; }
+	void setMoving(bool value) { _isMoving = value; }
+	bool isWalking();
+	void stopWalking(int value);
+
+	void changeAnimationMode(int animationMode, int force);
+
+	void faceActor(int otherActorId, bool animate);
+	void faceObject(char *objectName, bool animate);
+	void faceItem(int itemId, bool animate);
+	void faceWaypoint(int waypointId, bool animate);
+	void faceXYZ(float x, float y, float z, bool animate);
+	void faceCurrentCamera(bool animate);
+	void faceHeading(int heading, bool animate);
+	int getFriendlinessToOther(int otherActorId);
+	void modifyFriendlinessToOther(int otherActorId, signed int change);
+	void setFriendlinessToOther(int otherActorId, int friendliness);
+	void setHonesty(int honesty);
+	void setIntelligence(int intelligence);
+	void setStability(int stability);
+	void setCombatAggressiveness(int combatAggressiveness);
+	int getCurrentHP();
+	int getMaxHP();
+	int getCombatAggressiveness();
+	int getHonesty();
+	int getIntelligence();
+	int getStability();
+	void modifyCurrentHP(signed int change);
+	void modifyMaxHP(signed int change);
+	void modifyCombatAggressiveness(signed int change);
+	void modifyHonesty(signed int change);
+	void modifyIntelligence(signed int change);
+	void modifyStability(signed int change);
+	void setFlagDamageAnimIfMoving(bool value);
+	bool getFlagDamageAnimIfMoving();
+
+
+	void retire(bool isRetired, int unknown1, int unknown2, int retiredByActorId);
+
+
+
+
+private:
+	void setFacing(int facing, bool halfOrSet);
+	void setBoundingBox(Vector3 position, bool retired);
+
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp
new file mode 100644
index 0000000..286ec1d
--- /dev/null
+++ b/engines/bladerunner/actor_combat.cpp
@@ -0,0 +1,11 @@
+#include "bladerunner/actor_combat.h"
+
+namespace BladeRunner {
+
+ActorCombat::ActorCombat(BladeRunnerEngine* vm) {
+	_vm = vm;
+}
+
+ActorCombat::~ActorCombat() {
+}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h
new file mode 100644
index 0000000..a4ab4c9
--- /dev/null
+++ b/engines/bladerunner/actor_combat.h
@@ -0,0 +1,65 @@
+/* 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 BLADERUNNER_ACTOR_COMBAT_H
+#define BLADERUNNER_ACTOR_COMBAT_H
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/vector.h"
+
+namespace BladeRunner {
+	
+	class ActorCombat
+	{
+		BladeRunnerEngine *_vm;
+	private:
+		int _actorId;
+		int _combatOn;
+		int _field2;
+		int _field3;
+		int _otherActorId;
+		int _field5;
+		int _field6;
+		int _field7;
+		int _field8;
+		int _field9;
+		int _field10;
+		int _field11;
+		int _field12;
+		int _actorHp;
+		int _field14;
+		int _field15;
+		Vector3 actorPosition;
+		Vector3 otherActorPosition;
+		int _availableCoversCount;
+		int _availableFleeWaypointsCount;
+		int _field24;
+
+	public:
+		ActorCombat(BladeRunnerEngine *vm);
+		~ActorCombat();
+
+	};
+}
+
+#endif
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index a4cfad7..e814180 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -1,8 +1,40 @@
 #include "bladerunner/actor_walk.h"
+#include "bladerunner/actor.h"
+#include "bladerunner/scene_objects.h"
 
 namespace BladeRunner
 {
 
+	ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
+	_vm = vm;
+}
 
+ActorWalk::~ActorWalk() {
+}
+
+bool ActorWalk::isWalking() {
+	return _walking;
+}
+
+void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused) {
+	_vm->_sceneObjects->setMoving(actorId, 0); 
+	_vm->_actors[actorId]->setMoving(0);
+
+	if(_vm->_actors[actorId]->inCombat()) {
+		_vm->_actors[actorId]->changeAnimationMode(animationMode, 0);
+	} else {
+		_vm->_actors[actorId]->changeAnimationMode(notused, 0);
+	}
+	
+	if(unknown) {
+		_walking = 0;
+		_running = 0;
+		_status = 0;
+	}else {
+		_walking = 1;
+		_running = 0;
+		_status = 5;
+	}
+}
 
 }
\ No newline at end of file
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index c44c15b..c382189 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -23,6 +23,7 @@
 #ifndef BLADERUNNER_ACTOR_WALK_H
 #define BLADERUNNER_ACTOR_WALK_H
 
+#include "bladerunner/bladerunner.h"
 #include "bladerunner/vector.h"
 
 namespace BladeRunner
@@ -35,6 +36,8 @@ namespace BladeRunner
 
 	class ActorWalk
 	{
+		BladeRunnerEngine *_vm;
+	private:
 		int _walking;
 		int _running;
 		Vector3 _wanted;
@@ -46,6 +49,13 @@ namespace BladeRunner
 		int _actorsCount;
 		int _field15;
 		int _status;
+	public:
+		ActorWalk(BladeRunnerEngine *vm);
+		~ActorWalk();
+
+		bool isWalking();
+		void stop(int actorId, bool unknown, int animationMode, int notused);
+
 	};
 }
 
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 22199e6..62d6a81 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -44,6 +44,8 @@
 #include "bladerunner/slice_renderer.h"
 #include "bladerunner/text_resource.h"
 #include "bladerunner/vqa_decoder.h"
+#include "bladerunner/waypoints.h"
+#include "bladerunner/items.h"
 
 #include "common/array.h"
 #include "common/error.h"
@@ -89,6 +91,8 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
+	delete _items;
+	delete _waypoints;
 	delete _lights;
 	delete _settings;
 	delete _script;
@@ -150,7 +154,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 		}
 	}
 
-	// TODO: World waypoints
+	_waypoints = new Waypoints(this, _gameInfo->getWaypointCount());
 
 	// TODO: Cover waypoints
 
@@ -171,7 +175,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 	_gameFlags = new GameFlags();
 	_gameFlags->setFlagCount(_gameInfo->getFlagCount());
 
-	// TODO: Items
+	_items = new Items(this);
 
 	// Setup sound output
 
@@ -529,6 +533,7 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Draw dialogue menu
 
 			Common::Point p = _eventMan->getMousePos();
+			_mouse->tick(p.x, p.y);
 			_mouse->draw(_surface2, p.x, p.y);
 
 			// TODO: Process AUD (audio in Replicant)
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 814041d..87391d7 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -55,6 +55,8 @@ class SliceRenderer;
 class TextResource;
 class Lights;
 class View;
+class Waypoints;
+class Items;
 
 
 class BladeRunnerEngine : public Engine {
@@ -81,6 +83,8 @@ public:
 	int             *_gameVars;
 
 	Lights          *_lights;
+	Waypoints       *_waypoints;
+	Items           *_items;
 
 	TextResource    *_textActorNames;
 	TextResource    *_textCrimes;
@@ -105,6 +109,9 @@ public:
 
 	Common::RandomSource _rnd;
 
+	bool _playerActorIdle;
+	bool _playerDead;
+
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
index fb2ae94..9b36eab 100644
--- a/engines/bladerunner/boundingbox.cpp
+++ b/engines/bladerunner/boundingbox.cpp
@@ -34,8 +34,7 @@ BoundingBox::BoundingBox(float x0, float y0, float z0, float x1, float y1, float
 	_vertices[1].z = z1;
 }
 
-void BoundingBox::expand(float x0, float y0, float z0, float x1, float y1, float z1)
-{
+void BoundingBox::expand(float x0, float y0, float z0, float x1, float y1, float z1) {
 	_vertices[0].x += x0;
 	_vertices[0].y += y0;
 	_vertices[0].z += z0;
@@ -46,11 +45,40 @@ void BoundingBox::expand(float x0, float y0, float z0, float x1, float y1, float
 }
 
 
-bool BoundingBox::isXYZInside(float x, float y, float z)
-{
+bool BoundingBox::inside(float x, float y, float z) {
 	return
 		x >= _vertices[0].x && x <= _vertices[1].x
 		&& y >= _vertices[0].y && y <= _vertices[1].y
 		&& z >= _vertices[0].z && z <= _vertices[1].z;
 }
+
+
+void BoundingBox::setXyz(float x0, float y0, float z0, float x1, float y1, float z1) {
+	_vertices[0].x = x0;
+	_vertices[0].y = y0;
+	_vertices[0].z = z0;
+
+	_vertices[1].x = x1;
+	_vertices[1].y = y1;
+	_vertices[1].z = z1;
+}
+
+void BoundingBox::getXyz(float *x0, float *y0, float *z0, float *x1, float *y1, float *z1) {
+	*x0 = _vertices[0].x;
+	*y0 = _vertices[0].y;
+	*z0 = _vertices[0].z;
+
+	*x1 = _vertices[1].x;
+	*y1 = _vertices[1].y;
+	*z1 = _vertices[1].z;
+}
+
+
+float BoundingBox::getZ0() {
+	return _vertices[0].z;
+}
+
+float BoundingBox::getZ1() {
+	return _vertices[1].z;
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
index 1766973..d9f7df6 100644
--- a/engines/bladerunner/boundingbox.h
+++ b/engines/bladerunner/boundingbox.h
@@ -28,7 +28,7 @@
 namespace BladeRunner {
 
 class BoundingBox {
-public:
+private:
 	Vector3 _vertices[2];
 
 public:
@@ -36,7 +36,11 @@ public:
 	BoundingBox(float x0, float y0, float z0, float x1, float y1, float z1);
 
 	void expand(float x0, float y0, float z0, float x1, float y1, float z1);
-	bool isXYZInside(float x, float y, float z);
+	bool inside(float x, float y, float z);
+	void setXyz(float x0, float y0, float z0, float x1, float y1, float z1);
+	void getXyz(float* x0, float* y0, float* z0, float* x1, float* y1, float* z1);
+	float getZ0();
+	float getZ1();
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
new file mode 100644
index 0000000..7a3ec92
--- /dev/null
+++ b/engines/bladerunner/item.cpp
@@ -0,0 +1,20 @@
+#include "bladerunner/item.h"
+
+namespace BladeRunner {
+
+Item::Item() {
+	_animationId = -1;
+	_itemId = -1;
+	_setId = -1;
+}
+
+Item::~Item() {
+}
+
+
+void Item::getXyz(float* x, float* y, float* z) {
+	*x = _position.x;
+	*y = _position.y;
+	*z = _position.z;
+}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
new file mode 100644
index 0000000..a4a9282
--- /dev/null
+++ b/engines/bladerunner/item.h
@@ -0,0 +1,67 @@
+/* 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 BLADERUNNER_ITEM_H
+#define BLADERUNNER_ITEM_H
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/boundingbox.h"
+
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace BladeRunner {
+	class Items;
+
+	class Item {
+		friend class Items;
+	private:
+		int          _itemId;
+		int          _setId;
+
+		BoundingBox  _boundingBox;
+		Common::Rect _screenRectangle;
+		int          _animationId;
+		Vector3      _position;
+		int          _facing;
+		float        _angle;
+		int          _width;
+		int          _height;
+		//int field_1C8;
+		int          _target;
+		//float field_1D0;
+		int          _targetable;
+		int          _spinning;
+		int          _angleChange;
+		float        _cameraAngle;
+		int          _obstacle;
+		//int field_1E8;
+	public:
+		Item();
+		~Item();
+
+		void getXyz(float *x, float *y, float *z);
+	};
+
+}
+
+#endif
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
new file mode 100644
index 0000000..7d717ff
--- /dev/null
+++ b/engines/bladerunner/items.cpp
@@ -0,0 +1,28 @@
+#include "bladerunner/items.h"
+
+namespace BladeRunner {
+
+Items::Items(BladeRunnerEngine *vm) {
+	_vm = vm;
+}
+
+Items::~Items() {
+}
+
+
+void Items::getXyz(int itemId, float* x, float* y, float* z) {
+	int itemIndex = findItem(itemId);
+	assert(itemIndex != -1);
+
+	_items[itemIndex].getXyz(x, y, z);
+}
+
+int Items::findItem(int itemId) {
+	int i;
+	for (i = 0; i < _items.size();i++) {
+		if (_items[i]._itemId == itemId)
+			return i;
+	}
+	return -1;
+}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
new file mode 100644
index 0000000..39f574c
--- /dev/null
+++ b/engines/bladerunner/items.h
@@ -0,0 +1,50 @@
+/* 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 BLADERUNNER_ITEMS_H
+#define BLADERUNNER_ITEMS_H
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/item.h"
+
+#include "common/array.h"
+#include "common/rect.h"
+
+namespace BladeRunner {	
+
+	class Items {
+		BladeRunnerEngine *_vm;
+	private:
+		Common::Array<Item> _items;
+
+	public:
+		Items(BladeRunnerEngine *vm);
+		~Items();
+		
+		void getXyz(int itemId, float *x, float *y, float *z);
+
+	private:
+		int findItem(int itemId);
+	};
+}
+
+#endif
diff --git a/engines/bladerunner/matrix.cpp b/engines/bladerunner/matrix.cpp
index a55271e..fae8e43 100644
--- a/engines/bladerunner/matrix.cpp
+++ b/engines/bladerunner/matrix.cpp
@@ -166,4 +166,16 @@ Matrix4x3 invertMatrix(const Matrix4x3 &m)
 	return result;
 }
 
+
+void Matrix4x3::unknown()
+{
+	float m14 = _m[0][3];
+	float m24 = _m[1][3];
+	float m34 = _m[2][3];
+
+	_m[0][3] = -(m34 * _m[0][2]) - m24 * _m[0][1] - m14 * _m[0][0];
+	_m[1][3] = -(m34 * _m[1][2]) - m24 * _m[1][1] - m14 * _m[1][0];
+	_m[2][3] = -(m34 * _m[2][2]) - m24 * _m[2][1] - m14 * _m[2][0];
+
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/matrix.h b/engines/bladerunner/matrix.h
index 64c3070..cb7bc2f 100644
--- a/engines/bladerunner/matrix.h
+++ b/engines/bladerunner/matrix.h
@@ -93,7 +93,7 @@ public:
 
 	      float &operator()(int r, int c)       { assert(r >= 0 && r < 3); assert(c >= 0 && c < 4); return _m[r][c]; }
 	const float &operator()(int r, int c) const { assert(r >= 0 && r < 3); assert(c >= 0 && c < 4); return _m[r][c]; }
-
+	void unknown();
 };
 
 Matrix4x3 invertMatrix(const Matrix4x3 &m);
@@ -128,6 +128,8 @@ Vector3 operator*(const Matrix4x3 &m, const Vector3 &v)
 	return r;
 }
 
+
+
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 8a259fd..2eede84 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -24,8 +24,10 @@
 
 #include "bladerunner/bladerunner.h"
 #include "bladerunner/shape.h"
+#include "bladerunner/scene.h"
 
 #include "graphics/surface.h"
+#include "common/rect.h""
 
 namespace BladeRunner {
 
@@ -247,4 +249,48 @@ void Mouse::updateCursorFrame() {
 	}
 }
 
+void Mouse::tick(int x, int y)
+{
+	if (!_vm->playerHasControl() || isDisabled())
+		return;
+
+	Vector3 mousePosition;
+
+	getXYZ(x, y, &mousePosition);
+	int isClickable = 0;
+	int isObstacle = 0;
+	int isCombatTarget = 0;
+	int sceneObjectId = _vm->_sceneObjects->findByXYZ(&isClickable, &isObstacle, &isCombatTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
+	//debug("mouse tick: objectid = %d", sceneObjectId);
+}
+
+void Mouse::getXYZ(int x, int y, Vector3* mousePosition)
+{
+	if (_vm->_scene->_setId == -1)
+		return;
+
+	int screenRight = 640 - x;
+	int screenDown = 480 - y;
+	
+	float zcoef = 1.0f / tan(_vm->_view->_fovX / 2.0f);
+
+	float x3d = (2.0f / 640.0f * screenRight - 1)  * zcoef / (1*zcoef);
+	float y3d = (2.0f / 480.0f * screenDown- 1) / (4/3 * zcoef) * zcoef;
+
+	uint16 zbufval = _vm->_zBuffer1[x + y * 480];
+
+	Vector3 vector;
+	vector.z = zbufval / 25.5f;
+	vector.x = vector.z / zcoef * x3d;
+	vector.y = vector.z / zcoef * y3d;
+
+	Matrix4x3 matrix = _vm->_view->_frameViewMatrix;
+	matrix.unknown();
+	vector = matrix * vector;
+
+	mousePosition->x = vector.x;
+	mousePosition->y = vector.y;
+	mousePosition->z = vector.z;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/mouse.h b/engines/bladerunner/mouse.h
index 33f2314..d708960 100644
--- a/engines/bladerunner/mouse.h
+++ b/engines/bladerunner/mouse.h
@@ -28,8 +28,9 @@ namespace Graphics {
 }
 
 namespace BladeRunner {
+	class Vector3;
 
-class BladeRunnerEngine;
+	class BladeRunnerEngine;
 
 class Mouse {
 	BladeRunnerEngine *_vm;
@@ -56,6 +57,10 @@ public:
 
 	void draw(Graphics::Surface &surface, int x, int y);
 	void updateCursorFrame();
+
+	void tick(int x, int y);
+private:
+	void Mouse::getXYZ(int x, int y, Vector3* mousePosition);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
index fff4508..01dff24 100644
--- a/engines/bladerunner/movement_track.cpp
+++ b/engines/bladerunner/movement_track.cpp
@@ -39,7 +39,7 @@ namespace BladeRunner {
 		_lastIndex = -1;
 		_hasNext = 0;
 		_paused = 0;
-		for (int i = 0; i < sizeof(this->_entries); i++)
+		for (int i = 0; i < 100; i++)
 		{
 			_entries[i].waypointId = -1;
 			_entries[i].delay = -1;
diff --git a/engines/bladerunner/regions.cpp b/engines/bladerunner/regions.cpp
new file mode 100644
index 0000000..fe817e0
--- /dev/null
+++ b/engines/bladerunner/regions.cpp
@@ -0,0 +1,47 @@
+#include "bladerunner/regions.h"
+
+namespace BladeRunner {
+	Regions::Regions() {
+		_enabled = true;
+		_regions = new Region[10];
+	}
+
+	Regions::~Regions() {
+		delete[] _regions;
+	}
+
+	bool Regions::add(int index, Common::Rect rect, int type) {
+		if (index <= 0 || index >= 10)
+			return false;
+
+		if (_regions[index]._present)
+			return false;
+
+		_regions[index]._rectangle = rect;
+		_regions[index]._type = type;
+		_regions[index]._present = 1;
+
+		return true;
+	}
+
+	bool Regions::remove(int index) {
+		if (index <= 0 || index >= 10)
+			return false;
+
+		_regions[index]._rectangle = Common::Rect(-1, -1, -1, -1);
+		_regions[index]._type = -1;
+		_regions[index]._present = 0;
+
+		return true;
+	}
+
+	void BladeRunner::Regions::clear() {
+		int i;
+		for (i = 0; i < 10; i++)
+			remove(i);
+	}
+
+	void Regions::setEnabled(bool enabled) {
+		_enabled = enabled;
+	}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
new file mode 100644
index 0000000..e92e812
--- /dev/null
+++ b/engines/bladerunner/regions.h
@@ -0,0 +1,55 @@
+/* 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 BLADERUNNER_REGIONS_H
+#define BLADERUNNER_REGIONS_H
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/rect.h"
+
+
+namespace BladeRunner {
+	struct Region
+	{
+		Common::Rect _rectangle;
+		int _type;
+		int _present;
+	};
+
+	class Regions
+	{
+	private:
+		Region* _regions;
+		bool _enabled;
+	public:
+		Regions();
+		~Regions();
+
+		bool add(int index, Common::Rect rect, int type);
+		bool remove(int index);
+		void clear();
+
+		void setEnabled(bool enabled);
+	};
+}
+#endif
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index fc0aa8c..c734a1a 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -49,7 +49,8 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (isLoadingGame) {
 		// TODO: Set up overlays
 	} else {
-		// TODO: Clear regions
+		_regions->clear();
+		_exits->clear();
 		// reset aesc
 		// TODO: Destroy all overlays
 		_defaultLoop = 0;
@@ -93,17 +94,17 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 
 	// TODO: Set actor position from scene info
 	//advance frame 0
-	_vm->_playerActor->set_at_xyz(_actorStartPosition, _actorStartFacing);
+	_vm->_playerActor->set_at_xyz(_actorStartPosition, _actorStartFacing, false, 0, 0);
 	// TODO: Set actor set
 	_vm->_script->SceneLoaded();
 
-	_vm->_sceneObjects->reset();
+	_vm->_sceneObjects->clear();
 	
 	// Init click map
 	int actorCount = _vm->_gameInfo->getActorCount();
 	for (int i = 0; i != actorCount; ++i) {
 		Actor *actor = _vm->_actors[i];
-		if (actor->getSet() == setId) {
+		if (actor->getSetId() == setId) {
 			_vm->_sceneObjects->addActor(
 				i,
 				actor->getBoundingBox(),
@@ -115,7 +116,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		}
 	}
 	
-	_set->addAllObjectsToScene(_vm->_sceneObjects);
+	_set->addObjectsToScene(_vm->_sceneObjects);
 	//add all items to scene
 	//calculate walking obstacles??
 
@@ -131,6 +132,8 @@ int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer.getSurface());
 		memcpy(zBuffer, _vqaPlayer.getZBuffer(), 640*480*2);
+
+		memcpy(surface.getPixels(), _vqaPlayer.getZBuffer(), 640 * 480 * 2);
 	}
 	return frame;
 }
@@ -140,4 +143,21 @@ void Scene::setActorStart(Vector3 position, int facing) {
 	_actorStartFacing = facing;
 }
 
+
+int Scene::getSetId() {
+	return _setId;
+}
+
+int Scene::findObject(char* objectName) {
+	return _set->findObject(objectName);
+}
+
+bool Scene::objectSetHotMouse(int objectId) {
+	return _set->objectSetHotMouse(objectId);
+}
+
+bool Scene::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
+	return _set->objectGetBoundingBox(objectId, boundingBox);
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index ee286ca..97a9b34 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -28,6 +28,7 @@
 #include "bladerunner/set.h"
 //#include "bladerunner/view.h"
 #include "bladerunner/vqa_player.h"
+#include "bladerunner/regions.h"
 
 namespace BladeRunner {
 
@@ -48,6 +49,8 @@ public:
 	Vector3     _actorStartPosition;
 	int         _actorStartFacing;
 	bool        _playerWalkedIn;
+	Regions*    _regions;
+	Regions*    _exits;
 
 public:
 	Scene(BladeRunnerEngine *vm)
@@ -59,16 +62,24 @@ public:
 		  _defaultLoop(0),
 		  _nextSetId(-1),
 		  _nextSceneId(-1),
-		  _playerWalkedIn(false)
+		  _playerWalkedIn(false),
+		  _regions(new Regions()),
+		  _exits(new Regions())
 	{}
 
 	~Scene() {
 		delete _set;
+		delete _regions;
+		delete _exits;
 	}
 
 	bool open(int setId, int sceneId, bool isLoadingGame);
 	int  advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer);
 	void setActorStart(Vector3 position, int facing);
+	int getSetId();
+	int findObject(char *objectName);
+	bool objectSetHotMouse(int objectId);
+	bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index f54a9b7..6ac00dc 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -26,15 +26,24 @@ namespace BladeRunner {
 	}
 
 
-	void SceneObjects::reset() {
+	void SceneObjects::clear() {
 		int i;
 		for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+			_sceneObjects[i]._sceneObjectId = -1;
+			_sceneObjects[i]._sceneObjectType = SceneObjectTypeUnknown;
+			_sceneObjects[i]._distanceToCamera = 0;
 			_sceneObjects[i]._present = 0;
+			_sceneObjects[i]._isClickable = 0;
+			_sceneObjects[i]._isObstacle = 0;
+			_sceneObjects[i]._unknown1 = 0;
+			_sceneObjects[i]._isCombatTarget = 0;
+			_sceneObjects[i]._isMoving = 0;
+			_sceneObjects[i]._isRetired = 0;
 		}
 	}
 
-	bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 unknown1, uint8 isCombatTarget, uint8 isRetired) {
-		return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isCombatTarget, unknown1, isRetired);
+	bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isCombatTarget, uint8 isRetired) {
+		return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isCombatTarget, isMoving, isRetired);
 	}
 
 	bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget) {
@@ -46,7 +55,6 @@ namespace BladeRunner {
 		return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isCombatTarget, 0, 0);
 	}
 
-
 	bool SceneObjects::remove(int sceneObjectId)
 	{
 		int i = findById(sceneObjectId);
@@ -68,7 +76,7 @@ namespace BladeRunner {
 		return true;
 	}
 
-	int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int firstClickable, int firstObstacle, int firstCombatTarget) {
+	int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget) {
 		BoundingBox boundingBox;
 		*isClickable = 0;
 		*isObstacle = 0;
@@ -81,10 +89,10 @@ namespace BladeRunner {
 		for (i = 0; i < _count; i++) {
 			//assert(_sceneObjectsSortedByDistance[i] < _count);
 			SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
-			if ((firstClickable && sceneObject->_isClickable)
-				|| (firstObstacle && sceneObject->_isObstacle)
-				|| (firstCombatTarget && sceneObject->_isCombatTarget)) {
-				break;
+			if ((mustBeClickable && !sceneObject->_isClickable)
+				|| (mustBeObstacle && !sceneObject->_isObstacle)
+				|| (mustBeCombatTarget && !sceneObject->_isCombatTarget)) {
+				continue;
 			}
 
 			boundingBox = sceneObject->_boundingBox;
@@ -93,7 +101,7 @@ namespace BladeRunner {
 				boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
 			}
 
-			if (boundingBox.isXYZInside(x, y, z)) {
+			if (boundingBox.inside(x, y, z)) {
 				*isClickable = sceneObject->_isClickable;
 				*isObstacle = sceneObject->_isObstacle;
 				*isCombatTarget = sceneObject->_isCombatTarget;
@@ -115,7 +123,7 @@ namespace BladeRunner {
 		return -1;
 	}
 
-	bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint unknown2, uint isRetired) {
+	bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint isMoving, uint isRetired) {
 		int index = findEmpty();
 		if (_count >= SCENE_OBJECTS_COUNT || index == -1) {
 			return false;
@@ -130,10 +138,10 @@ namespace BladeRunner {
 		_sceneObjects[index]._isObstacle = isObstacle;
 		_sceneObjects[index]._unknown1 = unknown1;
 		_sceneObjects[index]._isCombatTarget = isCombatTarget;
-		_sceneObjects[index]._unknown2 = unknown2;
+		_sceneObjects[index]._isMoving = isMoving;
 		_sceneObjects[index]._isRetired = isRetired;
 
-		float centerZ = (_sceneObjects[index]._boundingBox._vertices[0].z + _sceneObjects[index]._boundingBox._vertices[1].z) / 2.0;
+		float centerZ = (_sceneObjects[index]._boundingBox.getZ0() + _sceneObjects[index]._boundingBox.getZ1()) / 2.0;
 
 		float distanceToCamera = fabs(_view->_cameraPosition.z - centerZ);
 		_sceneObjects[index]._distanceToCamera = distanceToCamera;
@@ -155,8 +163,7 @@ namespace BladeRunner {
 		return true;
 	}
 
-	int SceneObjects::findEmpty()
-	{
+	int SceneObjects::findEmpty() {
 		int i;
 		for (i = 0; i < SCENE_OBJECTS_COUNT; i++)
 		{
@@ -166,23 +173,12 @@ namespace BladeRunner {
 		return -1;
 	}
 
-
-
-	SceneObject::SceneObject()
-	{
-		_sceneObjectId = -1;
-		_sceneObjectType = SceneObjectTypeUnknown;
-		_distanceToCamera = 0;
-		_present = 0;
-		_isClickable = 0;
-		_isObstacle = 0;
-		_unknown1 = 0;
-		_isCombatTarget = 0;
-		_unknown2 = 0;
-		_isRetired = 0;
+	void SceneObjects::setMoving(int sceneObjectId, bool isMoving) {
+		int i = findById(sceneObjectId);
+		if (i == -1 || !_sceneObjects[i]._present) {
+			return;
+		}
+		_sceneObjects[i]._isMoving = isMoving;
 	}
 
-	SceneObject::~SceneObject()
-	{
-	}
 }
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 999d821..16188d9 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -32,7 +32,6 @@
 
 namespace BladeRunner {
 	class BladeRunnerEngine;
-	class SceneObject;
 
 	enum SceneObjectType
 	{
@@ -47,6 +46,21 @@ namespace BladeRunner {
 #define SCENE_OBJECTS_ITEMS_OFFSET 74
 #define SCENE_OBJECTS_OBJECTS_OFFSET 198
 
+	struct SceneObject
+	{
+		int _sceneObjectId;
+		SceneObjectType _sceneObjectType;
+		BoundingBox _boundingBox;
+		Common::Rect _screenRectangle;
+		float _distanceToCamera;
+		int _present;
+		int _isClickable;
+		int _isObstacle;
+		int _unknown1;
+		int _isCombatTarget;
+		int _isMoving;
+		int _isRetired;
+	};
 
 
 	class SceneObjects {
@@ -60,37 +74,19 @@ namespace BladeRunner {
 	public:
 		SceneObjects(BladeRunnerEngine *vm, View *view);
 		~SceneObjects();
-		void reset();
 		bool addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 unknown1, uint8 isCombatTarget, uint8 isRetired);
 		bool addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget);
 		bool addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle);
 		bool remove(int sceneObjectId);
-		int findByXYZ(int* clickable, int* obstacle, int* targetable, float x, float y, float z, int firstClickable, int firstObstacle, int firstTargetable);		
+		void clear();
+		int findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget);
+		void setMoving(int sceneObjectId, bool isMoving);
 	private:
 		int findById(int sceneObjectId);
 		bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint unknown2, uint isRetired);
 		int findEmpty();
 	};
 
-	class SceneObject
-	{
-		friend class SceneObjects;
-	private:
-		int _sceneObjectId;
-		SceneObjectType _sceneObjectType;
-		BoundingBox _boundingBox;
-		Common::Rect _screenRectangle;
-		float _distanceToCamera;
-		int _present;
-		int _isClickable;
-		int _isObstacle;
-		int _unknown1;
-		int _isCombatTarget;
-		int _unknown2;
-		int _isRetired;
-	public:
-		SceneObject();
-		~SceneObject();
-	};
+
 }
 #endif
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index a2e5410..7c1f25d 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -117,13 +117,84 @@ bool Set::open(const Common::String &name) {
 }
 
 
-void Set::addAllObjectsToScene(SceneObjects* sceneObjects)
+void Set::addObjectsToScene(SceneObjects* sceneObjects)
 {
 	uint32 i;
-	for (i = 0; i < _objectCount; i++)
-	{
+	for (i = 0; i < _objectCount; i++) {
 		sceneObjects->addObject(i + SCENE_OBJECTS_OBJECTS_OFFSET, &_objects[i]._bbox, _objects[i]._isClickable, _objects[i]._isObstacle, _objects[i]._unknown1, _objects[i]._isCombatTarget);
 	}
 }
 
+
+int Set::findWalkbox(float x, float z) {
+	int i;
+	float altitude = 0.0f;
+	int foundWalkboxId = -1;
+	for (i = 0; i < _walkboxCount; i++) {
+		if (isXzInWalkbox(x, z, &_walkboxes[i])) {
+			if (foundWalkboxId == -1 || altitude < _walkboxes[i]._altitude) {
+				altitude = _walkboxes[i]._altitude;
+				foundWalkboxId = i;
+			}
+		}
+	}
+	return foundWalkboxId;
+}
+
+bool Set::isXzInWalkbox(float x, float z, Walkbox* walkbox) {
+	int found = 0;
+	int i;
+
+	float lastX = walkbox->_vertices[walkbox->_vertexCount - 1].x;
+	float lastZ = walkbox->_vertices[walkbox->_vertexCount - 1].z;
+	for (i = 0; i < walkbox->_vertexCount; i++) {
+
+		float currentX = walkbox->_vertices[i].x;
+		float currentZ = walkbox->_vertices[i].z;
+
+		if ((currentZ > z && z >= lastZ) || (currentZ <= z && z < lastZ)) {
+			float lineX = (lastX - currentX) / (lastZ - currentZ) * (z - currentZ) + currentX;
+			if (x < lineX)
+				found++;
+		}
+
+	}
+	return found & 1;
+}
+
+
+int Set::findObject(char* objectName) {
+	int i;	
+	for (i = 0; i < _objectCount; i++) {
+		if (scumm_stricmp(objectName, _objects[i]._name) == 0) {
+			return i;
+		}
+	}
+	return -1;
+}
+
+bool Set::objectSetHotMouse(int objectId) {
+	if(!_objects || objectId < 0 || objectId >= _objectCount) {
+		return false;
+	}
+	
+	_objects[objectId]._isHotMouse = true;
+	return true;
+}
+
+bool Set::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
+	assert(boundingBox);
+
+	if (!_objects || objectId < 0 || objectId >= _objectCount) {
+		boundingBox->setXyz(0, 0, 0, 0, 0, 0);
+		return false;
+	}
+	float x0, y0, z0, x1, y1, z1;
+
+	_objects[objectId]._bbox.getXyz(&x0, &y0, &z0, &x1, &y1, &z1);
+	boundingBox->setXyz(x0, y0, z0, x1, y1, z1);
+
+	return true;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index fba2d2a..395ec6c 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -35,8 +35,8 @@
 namespace BladeRunner {
 
 class BladeRunnerEngine;
-
 class VQADecoder;
+class Scene;
 
 struct Object {
 	char        _name[20];
@@ -56,6 +56,8 @@ struct Walkbox {
 };
 
 class Set {
+	friend class Scene;
+
 	BladeRunnerEngine *_vm;
 
 	uint32      _objectCount;
@@ -73,9 +75,17 @@ public:
 	~Set();
 
 	bool open(const Common::String &name);
-	void addAllObjectsToScene(SceneObjects *sceneObjects);
+	void addObjectsToScene(SceneObjects *sceneObjects);
+
+	int findWalkbox(float x, float z);
+	int findObject(char* objectName);
+
+	bool objectSetHotMouse(int objectId);
+	bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
+
+private:
+	bool isXzInWalkbox(float x, float z, Walkbox* walkbox);
 
-	
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index 6d0347c..efcd4b3 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -170,4 +170,10 @@ void *SliceAnimations::getFramePtr(uint32 animation, uint32 frame) {
 	return (byte*)_pages[page]._data + pageOffset;
 }
 
+
+int SliceAnimations::getNumberOfFrames(int animationId) {
+	if (animationId > _animations.size())
+		return 0;
+	return _animations[animationId].frameCount;
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index cc07b57..b0c53b1 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -104,6 +104,8 @@ public:
 
 	SlicePalette &getPalette(int i) { return _palettes[i]; };
 	void *getFramePtr(uint32 animation, uint32 frame);
+
+	int getNumberOfFrames(int animationId);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index a1e8497..a52a123 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -416,13 +416,17 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 	}
 }
 
-void SliceRenderer::setLights(Lights* lights)
-{
+void SliceRenderer::setLights(Lights* lights){
 	_lights = lights;
 }
 
-void SliceRenderer::setSetEffects(SetEffects* setEffects)
-{
+void SliceRenderer::setSetEffects(SetEffects* setEffects){
 	_setEffects = setEffects;
 }
+
+void SliceRenderer::preload(int animationId) {
+	int i;
+	for (i = 0; i < _vm->_sliceAnimations->getNumberOfFrames(animationId); i++)
+		_vm->_sliceAnimations->getFramePtr(animationId, i);
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index c04560a..6e21d4f 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -53,7 +53,7 @@ class SliceRenderer {
 	Lights     *_lights;
 	SetEffects *_setEffects;
 
-	void                     *_sliceFramePtr;
+	void       *_sliceFramePtr;
 
 	// Animation frame data
 	Vector2 _frameFront;
@@ -101,6 +101,8 @@ public:
 	void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
 
 
+	void preload(int animationId);
+
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
new file mode 100644
index 0000000..d174e26
--- /dev/null
+++ b/engines/bladerunner/waypoints.cpp
@@ -0,0 +1,55 @@
+#include "bladerunner/waypoints.h"
+namespace BladeRunner {
+
+Waypoints::Waypoints(BladeRunnerEngine* vm, int count) {
+	_count = count;
+	_waypoints = new Waypoint[count];
+}
+
+Waypoints::~Waypoints() {
+}
+
+void Waypoints::getXyz(int waypointId, float *x, float *y, float *z) {
+	*x = 0;
+	*y = 0;
+	*z = 0;
+
+	if (waypointId < 0 || waypointId >= _count || !_waypoints[waypointId]._present)
+		return;
+
+	*x = _waypoints[waypointId]._position.x;
+	*y = _waypoints[waypointId]._position.y;
+	*z = _waypoints[waypointId]._position.z;
+}
+
+int Waypoints::getSetId(int waypointId) {
+	if (waypointId < 0 || waypointId >= _count || !_waypoints[waypointId]._present)
+		return -1;
+	return _waypoints[waypointId]._setId;
+}
+
+bool Waypoints::set(int waypointId, int setId, Vector3 position) {
+	if (waypointId < 0 || waypointId >= _count)
+		return false;
+
+	_waypoints[waypointId]._setId = setId;
+	_waypoints[waypointId]._position = position;
+	_waypoints[waypointId]._present = true;
+
+	return true;
+}
+
+bool Waypoints::reset(int waypointId) {
+	if (waypointId < 0 || waypointId >= _count)
+		return false;
+
+	_waypoints[waypointId]._setId = -1;
+	_waypoints[waypointId]._position.x = 0;
+	_waypoints[waypointId]._position.y = 0;
+	_waypoints[waypointId]._position.z = 0;
+	_waypoints[waypointId]._present = false;
+
+	return true;
+
+}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
new file mode 100644
index 0000000..c74e405
--- /dev/null
+++ b/engines/bladerunner/waypoints.h
@@ -0,0 +1,57 @@
+/* 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 BLADERUNNER_WAYPOINTS_H
+#define BLADERUNNER_WAYPOINTS_H
+
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/vector.h"
+
+#include "common/array.h"
+
+
+namespace BladeRunner {
+
+	struct Waypoint {
+		int _setId;
+		Vector3 _position;
+		bool _present;
+	};
+
+	class Waypoints {
+		BladeRunnerEngine *_vm;
+	private:
+		int       _count;
+		Waypoint *_waypoints;
+	public:
+		Waypoints(BladeRunnerEngine *vm, int count);
+		~Waypoints();
+
+		void getXyz(int waypointId, float *x, float *y, float *z);
+		int getSetId(int waypointId);
+
+		bool set(int waypointId, int setId, Vector3 position);
+		bool reset(int waypointId);
+	};
+}
+
+#endif


Commit: de7f961f484bc29c33240a29376bbd24dc4d6139
    https://github.com/scummvm/scummvm/commit/de7f961f484bc29c33240a29376bbd24dc4d6139
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:40+02:00

Commit Message:
BLADERUNNER: added implementation of more script methods added combat structure (maybe it combat mode??)

Changed paths:
  A engines/bladerunner/combat.cpp
  A engines/bladerunner/combat.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/actor_clues.cpp
    engines/bladerunner/actor_clues.h
    engines/bladerunner/actor_combat.cpp
    engines/bladerunner/actor_combat.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/items.cpp
    engines/bladerunner/mouse.cpp
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/set.cpp
    engines/bladerunner/set.h
    engines/bladerunner/set_effects.cpp
    engines/bladerunner/set_effects.h
    engines/bladerunner/settings.cpp
    engines/bladerunner/settings.h
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/vector.h
    engines/bladerunner/waypoints.cpp
    engines/bladerunner/waypoints.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index d95c652..d16ee84 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -30,6 +30,9 @@
 #include "bladerunner/waypoints.h"
 #include "bladerunner/scene.h"
 #include "bladerunner/items.h"
+#include "bladerunner/script/script.h"
+#include "bladerunner/slice_animations.h"
+#include "bladerunner/audio_speech.h"
 
 namespace BladeRunner {
 
@@ -100,15 +103,20 @@ void Actor::setup(int actorId) {
 
 	_timersRemain[4] = 60000;
 	_animationMode = -1;
-	// TODO: screen rect = { -1, -1, -1, -1 };
+	_screenRectangle = Common::Rect(-1, -1, -1, -1);
+	_combatAnimationMode = 4;
+	_unknown1 = 7;
+	_unknown2 = 8;
 
 	int actorCount = (int)_vm->_gameInfo->getActorCount();
 	for (int i = 0; i != actorCount; ++i)
 		_friendlinessToOther[i] = 50;
 
-	// TODO: Setup clues
+	_combatInfo->setup();
+	_clues->removeAll();
+	_movementTrack->flush();
 
-	// TODO: Flush movement track
+	_actorSpeed = Vector3();
 }
 
 void Actor::set_at_xyz(Vector3 position, int facing, bool halfOrSet, int moving, bool retired) {
@@ -179,7 +187,6 @@ void Actor::setSetId(int setId) {
 	}
 }
 
-
 void Actor::setFacing(int facing, bool halfOrSet) {
 	if (facing < 0 || facing >= 1024) {
 		return;
@@ -218,15 +225,15 @@ void Actor::setFacing(int facing, bool halfOrSet) {
 }
 
 void Actor::setBoundingBox(Vector3 position, bool retired) {
-	if(retired) {
-		
-	}else {
+	if (retired) {
+		_bbox->setXyz(position.x - (_retiredWidth / 2.0f), position.y, position.z - (_retiredWidth / 2.0f), position.x + (_retiredWidth / 2.0f), position.y + _retiredHeight, position.z + (_retiredWidth / 2.0f));
+	} else {
 		_bbox->setXyz(position.x - 12.0f, position.y + 6.0f, position.z - 12.0f, position.x + 12.0f, position.y + 72.0f, position.z + 12.0f);
 	}
 }
 
 
-void Actor::changeAnimationMode(int animationMode, int force) {
+void Actor::changeAnimationMode(int animationMode, bool force) {
 	if (force == 1) {
 		_animationMode = -1;
 	}
@@ -234,15 +241,30 @@ void Actor::changeAnimationMode(int animationMode, int force) {
 		//TODO: _vm->actorScript->ChangeAnimationMode(_id, animationMode);
 		_animationMode = animationMode;
 	}
+}
 
+void Actor::setFps(int fps) {
+	_fps = fps;
+	if (fps == 0) {
+		_frame_ms = 0;
+	} else {
+		if(_fps == -1) {
+			_frame_ms = -1000;
+		} else if (_fps == -2) {
+			_fps = _vm->_sliceAnimations->getFps(_animationId);
+			_frame_ms = 1000 / _fps;
+		} else {
+			_frame_ms = 1000 / _fps;
+		}
+	}
 }
 
 bool Actor::isWalking() {
 	return _walkInfo->isWalking();
 }
 
-void Actor::stopWalking(int value) {
-	if (value == 1 && _id == 0) {
+void Actor::stopWalking(bool value) {
+	if (value && _id == 0) {
 		_vm->_playerActorIdle = true;
 	}
 
@@ -325,10 +347,6 @@ void Actor::faceHeading(int heading, bool animate) {
 	}
 }
 
-int Actor::getFriendlinessToOther(int otherActorId) {
-	return _friendlinessToOther[otherActorId];
-}
-
 void Actor::modifyFriendlinessToOther(int otherActorId, signed int change) {
 	_friendlinessToOther[otherActorId] = MIN(MAX(_friendlinessToOther[otherActorId] + change, 0), 100);
 }
@@ -353,28 +371,12 @@ void Actor::setCombatAggressiveness(int combatAggressiveness) {
 	_combatAggressiveness = combatAggressiveness;
 }
 
-int Actor::getCurrentHP() {
-	return _currentHP;
+void Actor::setInvisible(bool isInvisible) {
+	_isInvisible = isInvisible;
 }
 
-int Actor::getMaxHP() {
-	return _maxHP;
-}
-
-int Actor::getCombatAggressiveness() {
-	return _combatAggressiveness;
-}
-
-int Actor::getHonesty() {
-	return _honesty;
-}
-
-int Actor::getIntelligence() {
-	return _intelligence;
-}
-
-int Actor::getStability() {
-	return _stability;
+void Actor::setImmunityToObstacles(bool isImmune) {
+	_isImmuneToObstacles = isImmune;
 }
 
 void Actor::modifyCurrentHP(signed int change) {
@@ -415,12 +417,156 @@ void Actor::retire(bool isRetired, int width, int height, int retiredByActorId)
 	_isRetired = isRetired;
 	_retiredWidth = MAX(width, 0);
 	_retiredHeight = MAX(height, 0);
-	if(_id == 0 && isRetired) {
+	if (_id == 0 && isRetired) {
 		_vm->playerLosesControl();
 		_vm->_playerDead = true;
 	}
-	if(isRetired) {
+	if (isRetired) {
 		//TODO: _vm->actorScript->Retired(_id, retiredByActorId);
 	}
 }
+
+void Actor::setTargetable(bool targetable) {
+	_isTargetable = targetable;
+}
+
+void Actor::setHealth(int hp, int maxHp) {
+	_currentHP = hp;
+	_maxHP = maxHp;
+	if(hp > 0) {
+		retire(0, 0, 0, -1);
+	}
+}
+
+void Actor::combatModeOn(int a2, int a3, int otherActorId, int a5, int combatAnimationMode, int a7, int a8, int a9, int a10, int a11, int ammoDamage, int a13, int a14) {
+	_combatAnimationMode = combatAnimationMode;
+	_unknown1 = a7;
+	_unknown2 = a8;
+	_inCombat = true;
+	if (_id > 0)
+		_combatInfo->combatOn(_id, a2, a3, otherActorId, a5, a9, a10, a11, ammoDamage, a13, a14);
+	stopWalking(0);
+	changeAnimationMode(_combatAnimationMode, 0);
+	int i;
+	for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+		Actor *otherActor = _vm->_actors[i];
+		if (i != _id && otherActor->_setId == _setId && !otherActor->_isRetired) {
+			//TODO: _vm->actorScript->OtherAgentEnteredCombatMode(i, _id, 1);
+		}
+	}
+}
+
+void Actor::combatModeOff() {
+	if (_id > 0)
+		_combatInfo->combatOff();
+	_inCombat = false;
+	stopWalking(0);
+	changeAnimationMode(0, 0);
+	int i;
+	for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
+		Actor *otherActor = _vm->_actors[i];
+		if (i != _id && otherActor->_setId == _setId && !otherActor->_isRetired) {
+			//TODO: _vm->actorScript->OtherAgentEnteredCombatMode(i, _id, 0);
+		}
+	}
+}
+
+float Actor::distanceFromActor(int otherActorId) {
+	return (_position - _vm->_actors[otherActorId]->_position).length();
+}
+
+float Actor::getX() {
+	return _position.x;
+}
+
+float Actor::getY() {
+	return _position.y;
+}
+
+float Actor::getZ() {
+	return _position.z;
+}
+
+void Actor::getXYZ(float* x, float* y, float* z) {
+	*x = _position.x;
+	*y = _position.y;
+	*z = _position.z;
+}
+
+int Actor::getFacing() {
+	return _facing;
+}
+
+int Actor::getAnimationMode() {
+	return _animationMode;
+}
+
+void Actor::setGoal(int goalNumber) {
+	if (goalNumber == _goalNumber)
+		return;
+
+	//TODO: _vm->actorScript->GoalChanged(_id, _goalNumber, goalNumber);
+
+	_vm->_script->SceneActorChangedGoal(_id, goalNumber, _goalNumber, _vm->_scene->getSetId() == _setId);
+}
+
+int Actor::getGoal() {
+	return _goalNumber;
+}
+
+void Actor::speechPlay(int sentenceId, bool voiceOver) {
+	char name[13];
+	sprintf(name, "%02d-%04d.AUD", _id, sentenceId); //TODO somewhere here should be also language code
+	int balance;
+
+	if(voiceOver || _id == 99) {
+		balance = 0;
+	}else {
+		Vector3 pos = _vm->_view->_frameViewMatrix * _position;
+		int screenX = 0, screenY = 0;
+		//TODO: transform to screen space using fov;
+		balance = 127 * (2 * screenX - 640) / 640;
+		balance = MIN(127, MAX(-127, balance));
+	}
+
+	_vm->_audioSpeech->playSpeech(name, balance);
+}
+
+void Actor::speechStop() {
+	_vm->_audioSpeech->stopSpeech();
+}
+
+bool Actor::isSpeeching() {
+	return _vm->_audioSpeech->isPlaying();
+}
+
+void Actor::addClueToDatabase(int clueId, int unknown, bool clueAcquired, bool unknownFlag, int fromActorId) {
+	_clues->add(_id, clueId, unknown, clueAcquired, unknownFlag, fromActorId);
+}
+
+void Actor::acquireClue(int clueId, byte unknownFlag, int fromActorId) {
+	_clues->acquire(clueId, unknownFlag, fromActorId);
+}
+
+void Actor::loseClue(int clueId) {
+	_clues->lose(clueId);
+}
+
+bool Actor::hasClue(int clueId) {
+	return _clues->isAcquired(clueId);
+}
+
+void Actor::copyClues(int actorId) {
+	Actor *otherActor = _vm->_actors[actorId];
+	int i;
+	for (i = 0; i < (int)_vm->_gameInfo->getClueCount(); i++) {
+		if(hasClue(i) && !_clues->isFlag4(i) && !otherActor->hasClue(i)) {
+			int fromActorId = _id;
+			if (_id == 99)
+				fromActorId = _clues->getFromActorId(i);
+			otherActor->acquireClue(i, 0, fromActorId);
+		}
+	}
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 4da73d4..4d383f0 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -40,7 +40,7 @@ class BoundingBox;
 
 class Actor {
 	BladeRunnerEngine *_vm;
-
+	friend class ScriptBase;
 private:
 	BoundingBox   *_bbox;
 	Common::Rect   _screenRectangle;
@@ -76,7 +76,6 @@ private:
 	bool _isMoving;
 	bool _damageAnimIfMoving;
 
-
 	// Animation
 	int _width;	
 	int _height;
@@ -96,6 +95,12 @@ private:
 
 	float _scale;
 
+	int _unknown1;
+	int _unknown2;
+	int _unknown3;
+
+	Vector3 _actorSpeed;
+
 public:
 	Actor(BladeRunnerEngine *_vm, int actorId);
 	~Actor();
@@ -105,6 +110,13 @@ public:
 	void set_at_xyz(Vector3 pos, int facing, bool halfOrSet, int unknown, bool retired);
 	void set_at_waypoint(int waypointId, int angle, int unknown, bool retired);
 
+	float getX();
+	float getY();
+	float getZ();
+	void getXYZ(float* x, float* y, float* z);
+	int getFacing();
+	int getAnimationMode();
+
 	void draw();
 
 	int getSetId();
@@ -113,13 +125,15 @@ public:
 	Common::Rect* getScreenRectangle() { return &_screenRectangle; }
 	bool isRetired() { return _isRetired; }
 	bool isTargetable() { return _isTargetable; }
+	void setTargetable(bool targetable);
 	bool inCombat() { return _inCombat; }
 	bool isMoving() { return _isMoving; }
 	void setMoving(bool value) { _isMoving = value; }
 	bool isWalking();
-	void stopWalking(int value);
-
-	void changeAnimationMode(int animationMode, int force);
+	void stopWalking(bool value);
+	
+	void changeAnimationMode(int animationMode, bool force);
+	void setFps(int fps);
 
 	void faceActor(int otherActorId, bool animate);
 	void faceObject(char *objectName, bool animate);
@@ -128,19 +142,14 @@ public:
 	void faceXYZ(float x, float y, float z, bool animate);
 	void faceCurrentCamera(bool animate);
 	void faceHeading(int heading, bool animate);
-	int getFriendlinessToOther(int otherActorId);
 	void modifyFriendlinessToOther(int otherActorId, signed int change);
 	void setFriendlinessToOther(int otherActorId, int friendliness);
 	void setHonesty(int honesty);
 	void setIntelligence(int intelligence);
 	void setStability(int stability);
 	void setCombatAggressiveness(int combatAggressiveness);
-	int getCurrentHP();
-	int getMaxHP();
-	int getCombatAggressiveness();
-	int getHonesty();
-	int getIntelligence();
-	int getStability();
+	void setInvisible(bool isInvisible);
+	void setImmunityToObstacles(bool isImmune);
 	void modifyCurrentHP(signed int change);
 	void modifyMaxHP(signed int change);
 	void modifyCombatAggressiveness(signed int change);
@@ -149,13 +158,27 @@ public:
 	void modifyStability(signed int change);
 	void setFlagDamageAnimIfMoving(bool value);
 	bool getFlagDamageAnimIfMoving();
+	void setHealth(int hp, int maxHp);
 
+	void retire(bool isRetired, int width, int height, int retiredByActorId);
 
-	void retire(bool isRetired, int unknown1, int unknown2, int retiredByActorId);
+	void combatModeOn(int a2, int a3, int a4, int a5, int combatAnimationMode, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14);
+	void combatModeOff();
 
+	void setGoal(int goalNumber);
+	int getGoal();
 
+	float distanceFromActor(int otherActorId);
 
+	void speechPlay(int sentenceId, bool voiceOver);
+	void speechStop();
+	bool isSpeeching();
 
+	void addClueToDatabase(int clueId, int unknown, bool clueAcquired, bool unknownFlag, int fromActorId);
+	void acquireClue(int clueId, byte unknownFlag, int fromActorId);
+	void loseClue(int clueId);
+	bool hasClue(int clueId);
+	void copyClues(int actorId);
 private:
 	void setFacing(int facing, bool halfOrSet);
 	void setBoundingBox(Vector3 position, bool retired);
diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
index f99b6b1..c8bc04c 100644
--- a/engines/bladerunner/actor_clues.cpp
+++ b/engines/bladerunner/actor_clues.cpp
@@ -64,7 +64,7 @@ namespace BladeRunner
 		_clues[clueIndex]._flags = 0;
 	}
 
-	int ActorClues::isAcquired(int clueId)
+	bool ActorClues::isAcquired(int clueId)
 	{
 		int clueIndex = findClueIndex(clueId);
 		if (clueIndex == -1)
@@ -82,7 +82,7 @@ namespace BladeRunner
 		return _clues[clueIndex]._fromActorId;
 	}
 
-	int ActorClues::isFlag2(int clueId)
+	bool ActorClues::isFlag2(int clueId)
 	{
 		int clueIndex = findClueIndex(clueId);
 		if (clueIndex == -1)
@@ -91,7 +91,7 @@ namespace BladeRunner
 		return (_clues[clueIndex]._flags & 0x02) >> 1;
 	}
 
-	int ActorClues::isFlag3(int clueId)
+	bool ActorClues::isFlag3(int clueId)
 	{
 		int clueIndex = findClueIndex(clueId);
 		if (clueIndex == -1)
@@ -100,7 +100,7 @@ namespace BladeRunner
 		return (_clues[clueIndex]._flags & 0x04) >> 2;
 	}
 
-	int ActorClues::isFlag4(int clueId)
+	bool ActorClues::isFlag4(int clueId)
 	{
 		int clueIndex = findClueIndex(clueId);
 		if (clueIndex == -1)
@@ -144,14 +144,14 @@ namespace BladeRunner
 		return -1;
 	}
 
-	void ActorClues::add(int actorId, int clueId, int field1, char acquired, char flag2, int fromActorId)
+	void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId)
 	{
 		_clues[_count]._clueId = clueId;
-		_clues[_count]._field1 = field1;
+		_clues[_count]._field1 = unknown;
 
 		_clues[_count]._flags = 0;
 		_clues[_count]._flags = _clues[_count]._flags & 0xFE | (acquired & 0x01);
-		_clues[_count]._flags = _clues[_count]._flags & 0xFD | ((flag2 << 1) & 0x02);
+		_clues[_count]._flags = _clues[_count]._flags & 0xFD | ((unknownFlag << 1) & 0x02);
 
 		_clues[_count]._fromActorId = fromActorId;
 		++_count;
@@ -172,7 +172,7 @@ namespace BladeRunner
 		_clues[index]._field8 = 0;
 	}
 
-	int ActorClues::exists(int clueId)
+	bool ActorClues::exists(int clueId)
 	{
 		return findClueIndex(clueId) != -1;
 	}
diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h
index 02d6bbb..0f08254 100644
--- a/engines/bladerunner/actor_clues.h
+++ b/engines/bladerunner/actor_clues.h
@@ -56,13 +56,14 @@ namespace BladeRunner {
 		ActorClues(BladeRunnerEngine *_vm, int cluesType);
 		~ActorClues();
 
+		void add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId);
 		void acquire(int clueId, char flag2, int fromActorId);
 		void lose(int clueId);
-		int isAcquired(int clueId);
+		bool isAcquired(int clueId);
 		int getFromActorId(int clueId);
-		int isFlag2(int clueId);
-		int isFlag3(int clueId);
-		int isFlag4(int clueId);
+		bool isFlag2(int clueId);
+		bool isFlag3(int clueId);
+		bool isFlag4(int clueId);
 		int getField1(int clueId);
 
 		int getCount();
@@ -72,10 +73,10 @@ namespace BladeRunner {
 		//savegame
 		//loadgame
 	private:
+		bool exists(int clueId);
 		int findClueIndex(int clueId);
-		void add(int actorId, int clueId, int field1, char acquired, char flag2, int fromActorId);
 		void remove(int clueIndex);
-		int exists(int clueId);
+		
 	};
 }
 
diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp
index 286ec1d..f595b01 100644
--- a/engines/bladerunner/actor_combat.cpp
+++ b/engines/bladerunner/actor_combat.cpp
@@ -8,4 +8,19 @@ ActorCombat::ActorCombat(BladeRunnerEngine* vm) {
 
 ActorCombat::~ActorCombat() {
 }
+
+
+void ActorCombat::hitAttempt() {
+}
+
+
+void ActorCombat::combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int ammoDamage, int a11, int a12) {
+}
+
+void ActorCombat::combatOff() {
+}
+
+
+void ActorCombat::setup() {
+}
 }
\ No newline at end of file
diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h
index a4ab4c9..0f6ccc9 100644
--- a/engines/bladerunner/actor_combat.h
+++ b/engines/bladerunner/actor_combat.h
@@ -58,6 +58,13 @@ namespace BladeRunner {
 	public:
 		ActorCombat(BladeRunnerEngine *vm);
 		~ActorCombat();
+		
+		void setup();
+
+		void hitAttempt();
+		
+		void combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int a10, int a11, int a12);
+		void combatOff();
 
 	};
 }
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 62d6a81..0f5f320 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -46,6 +46,7 @@
 #include "bladerunner/vqa_decoder.h"
 #include "bladerunner/waypoints.h"
 #include "bladerunner/items.h"
+#include "bladerunner/combat.h"
 
 #include "common/array.h"
 #include "common/error.h"
@@ -69,6 +70,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_script = new Script(this);
 	_settings = new Settings(this);
 	_lights = new Lights(this);
+	_combat = new Combat(this);
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
@@ -91,7 +93,8 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
-	delete _items;
+
+	delete _combat;
 	delete _waypoints;
 	delete _lights;
 	delete _settings;
@@ -402,7 +405,8 @@ void BladeRunnerEngine::shutdown() {
 
 	// TODO: Delete KIA6PT.FON
 
-	// TODO: Delete Items
+	delete _items;
+	_items = 0;
 
 	delete _gameFlags;
 	_gameFlags = 0;
@@ -553,6 +557,12 @@ void BladeRunnerEngine::handleEvents() {
 	}
 }
 
+void BladeRunnerEngine::gameWaitForActive() {
+	while(!_windowIsActive) {
+		handleEvents();
+	}
+}
+
 void BladeRunnerEngine::loopActorSpeaking() {
 	if (!_audioSpeech->isPlaying())
 		return;
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 87391d7..e90889a 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -57,6 +57,7 @@ class Lights;
 class View;
 class Waypoints;
 class Items;
+class Combat;
 
 
 class BladeRunnerEngine : public Engine {
@@ -85,6 +86,7 @@ public:
 	Lights          *_lights;
 	Waypoints       *_waypoints;
 	Items           *_items;
+	Combat          *_combat;
 
 	TextResource    *_textActorNames;
 	TextResource    *_textCrimes;
@@ -111,7 +113,12 @@ public:
 
 	bool _playerActorIdle;
 	bool _playerDead;
-
+	bool _speechSkipped;
+	bool _gameOver;
+	int  _gameAutoSave;
+	bool _gameIsLoading;
+	bool _sceneIsLoading;
+	
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
@@ -130,10 +137,11 @@ public:
 
 	bool loadSplash();
 	bool init2();
-
+	
 	void gameLoop();
 	void gameTick();
 	void handleEvents();
+	void gameWaitForActive();
 	void loopActorSpeaking();
 
 	void outtakePlay(int id, bool no_localization, int container = -1);
diff --git a/engines/bladerunner/combat.cpp b/engines/bladerunner/combat.cpp
new file mode 100644
index 0000000..5fe2e3f
--- /dev/null
+++ b/engines/bladerunner/combat.cpp
@@ -0,0 +1,59 @@
+#include "bladerunner/combat.h"
+#include "bladerunner/bladerunner.h"
+#include "bladerunner/actor.h"
+#include "bladerunner/settings.h"
+
+namespace BladeRunner {
+
+
+Combat::Combat(BladeRunnerEngine* vm) {
+	_vm = vm;
+
+	_active = false;
+	_enabled = true;
+
+	int i;
+	for (i = 0; i < 9; i++) {
+		_hitSoundId[i] = -1;
+		_missSoundId[i] = -1;
+	}
+}
+
+Combat::~Combat() {
+}
+
+void Combat::activate() {
+	if(_enabled) {
+		_vm->_playerActor->combatModeOn(-1, -1, -1, -1, 4, 7, 8, -1, -1, -1, _vm->_combat->_ammoDamage[_vm->_settings->getAmmoType()], 0, 0);
+		_active = true;
+	}
+}
+
+void Combat::deactivate() {
+	if (_enabled) {
+		_vm->_playerActor->combatModeOff();
+		_active = false;
+	}
+}
+
+bool Combat::isActive() {
+	return _active;
+}
+
+void Combat::enable() {
+	_enabled = true;
+}
+
+void Combat::disable() {
+	_enabled = false;
+}
+
+
+void Combat::setHitSoundId(int row, int column, int soundId) {
+	_hitSoundId[row * 3 + column] = soundId;
+}
+
+void Combat::setMissSoundId(int row, int column, int soundId) {
+	_missSoundId[row * 3 + column] = soundId;
+}
+}
\ No newline at end of file
diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h
new file mode 100644
index 0000000..5860fd7
--- /dev/null
+++ b/engines/bladerunner/combat.h
@@ -0,0 +1,61 @@
+/* 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 BLADERUNNER_COMBAT_H
+#define BLADERUNNER_COMBAT_H
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+class Combat {
+	BladeRunnerEngine *_vm;
+
+	bool _active;
+	bool _enabled;
+	int _hitSoundId[9];
+	int _missSoundId[9];
+	int _random1;
+	int _random2;
+
+public:
+	int _ammoDamage[3] = { 10, 20, 30 };
+
+public:
+	Combat(BladeRunnerEngine *vm);
+	~Combat();
+
+	void activate();
+	void deactivate();
+	bool isActive();
+
+	void enable();
+	void disable();
+
+	void setHitSoundId(int row, int column, int soundId);
+	void setMissSoundId(int row, int column, int soundId);
+
+};
+
+}
+
+#endif
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 7d717ff..be03b9b 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -19,7 +19,7 @@ void Items::getXyz(int itemId, float* x, float* y, float* z) {
 
 int Items::findItem(int itemId) {
 	int i;
-	for (i = 0; i < _items.size();i++) {
+	for (i = 0; i < (int)_items.size(); i++) {
 		if (_items[i]._itemId == itemId)
 			return i;
 	}
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 2eede84..64c64b2 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -27,7 +27,7 @@
 #include "bladerunner/scene.h"
 
 #include "graphics/surface.h"
-#include "common/rect.h""
+#include "common/rect.h"
 
 namespace BladeRunner {
 
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index c734a1a..3c04ee8 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -148,6 +148,11 @@ int Scene::getSetId() {
 	return _setId;
 }
 
+
+int Scene::getSceneId() {
+	return _sceneId;
+}
+
 int Scene::findObject(char* objectName) {
 	return _set->findObject(objectName);
 }
@@ -160,4 +165,38 @@ bool Scene::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
 	return _set->objectGetBoundingBox(objectId, boundingBox);
 }
 
+void Scene::objectSetIsClickable(int objectId, bool isClickable, bool sceneLoaded) {
+	_set->objectSetIsClickable(objectId, isClickable);
+	if (sceneLoaded) {
+		_vm->_sceneObjects->setIsClickable(objectId + 198, isClickable);
+	}
+}
+
+void Scene::objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, bool updateWalkpath) {
+	_set->objectSetIsObstacle(objectId, isObstacle);
+	if (sceneLoaded) {
+		_vm->_sceneObjects->setIsObstacle(objectId + 198, isObstacle);
+		if(updateWalkpath) {
+			_vm->_sceneObjects->updateWalkpath();
+		}
+	}
+}
+
+void Scene::objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded) {
+	int i;
+	for (i = 0; i < (int)_set->_objectCount; i++) {
+		_set->objectSetIsObstacle(i, isObstacle);
+		if (sceneLoaded) {
+			_vm->_sceneObjects->setIsObstacle(i + 198, isObstacle);
+		}
+	}
+}
+
+void Scene::objectSetIsCombatTarget(int objectId, bool isCombatTarget, bool sceneLoaded) {
+	_set->objectSetIsCombatTarget(objectId, isCombatTarget);
+	if (sceneLoaded) {
+		_vm->_sceneObjects->setIsCombatTarget(objectId + 198, isCombatTarget);
+	}
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 97a9b34..cabd912 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -77,9 +77,14 @@ public:
 	int  advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer);
 	void setActorStart(Vector3 position, int facing);
 	int getSetId();
+	int getSceneId();
 	int findObject(char *objectName);
 	bool objectSetHotMouse(int objectId);
 	bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
+	void objectSetIsClickable(int objectId, bool isClickable, bool sceneLoaded);
+	void objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, bool updateWalkpath);
+	void objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded);
+	void objectSetIsCombatTarget(int objectId, bool isCombatTarget, bool sceneLoaded);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 6ac00dc..ec9e247 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -2,183 +2,239 @@
 
 namespace BladeRunner {
 
-	SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
-		_vm = vm;
-		_view = view;
+SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
+	_vm = vm;
+	_view = view;
 
-		_count = 0;
-		_sceneObjects = new SceneObject[SCENE_OBJECTS_COUNT];
-		_sceneObjectsSortedByDistance = new int[SCENE_OBJECTS_COUNT];
+	_count = 0;
+	_sceneObjects = new SceneObject[SCENE_OBJECTS_COUNT];
+	_sceneObjectsSortedByDistance = new int[SCENE_OBJECTS_COUNT];
 
-		int i;
-		for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
-			_sceneObjectsSortedByDistance[i] = -1;
-		}
+	int i;
+	for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+		_sceneObjectsSortedByDistance[i] = -1;
 	}
+}
+
+SceneObjects::~SceneObjects() {
+	_vm = nullptr;
+	_view = nullptr;
+	_count = 0;
+
+	delete[] _sceneObjectsSortedByDistance;
+	delete[] _sceneObjects;
+}
 
-	SceneObjects::~SceneObjects() {
-		_vm = nullptr;
-		_view = nullptr;
-		_count = 0;
 
-		delete[] _sceneObjectsSortedByDistance;
-		delete[] _sceneObjects;
+void SceneObjects::clear() {
+	int i;
+	for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+		_sceneObjects[i]._sceneObjectId = -1;
+		_sceneObjects[i]._sceneObjectType = SceneObjectTypeUnknown;
+		_sceneObjects[i]._distanceToCamera = 0;
+		_sceneObjects[i]._present = 0;
+		_sceneObjects[i]._isClickable = 0;
+		_sceneObjects[i]._isObstacle = 0;
+		_sceneObjects[i]._unknown1 = 0;
+		_sceneObjects[i]._isCombatTarget = 0;
+		_sceneObjects[i]._isMoving = 0;
+		_sceneObjects[i]._isRetired = 0;
 	}
+}
 
+bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isCombatTarget, uint8 isRetired) {
+	return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isCombatTarget, isMoving, isRetired);
+}
 
-	void SceneObjects::clear() {
-		int i;
-		for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
-			_sceneObjects[i]._sceneObjectId = -1;
-			_sceneObjects[i]._sceneObjectType = SceneObjectTypeUnknown;
-			_sceneObjects[i]._distanceToCamera = 0;
-			_sceneObjects[i]._present = 0;
-			_sceneObjects[i]._isClickable = 0;
-			_sceneObjects[i]._isObstacle = 0;
-			_sceneObjects[i]._unknown1 = 0;
-			_sceneObjects[i]._isCombatTarget = 0;
-			_sceneObjects[i]._isMoving = 0;
-			_sceneObjects[i]._isRetired = 0;
+bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget) {
+	Common::Rect rect(-1, -1, -1, -1);
+	return addSceneObject(sceneObjectId, SceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isCombatTarget, 0, 0);
+}
+
+bool SceneObjects::addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle) {
+	return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isCombatTarget, 0, 0);
+}
+
+bool SceneObjects::remove(int sceneObjectId)
+{
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return false;
+	}
+	int j;
+	for (j = 0; j < _count; j++) {
+		if (_sceneObjectsSortedByDistance[j] == i) {
+			break;
 		}
 	}
-
-	bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isCombatTarget, uint8 isRetired) {
-		return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isCombatTarget, isMoving, isRetired);
+	int k;
+	for (k = j; k < _count - 1; k++) {
+		_sceneObjectsSortedByDistance[k] = _sceneObjectsSortedByDistance[k + 1];
 	}
 
-	bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget) {
-		Common::Rect rect(-1, -1, -1, -1);
-		return addSceneObject(sceneObjectId, SceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isCombatTarget, 0, 0);
-	}
+	--_count;
+	return true;
+}
 
-	bool SceneObjects::addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle) {
-		return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isCombatTarget, 0, 0);
-	}
+int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget) {
+	BoundingBox boundingBox;
+	*isClickable = 0;
+	*isObstacle = 0;
+	*isCombatTarget = 0;
 
-	bool SceneObjects::remove(int sceneObjectId)
-	{
-		int i = findById(sceneObjectId);
-		if (i == -1 || !_sceneObjects[i]._present) {
-			return false;
+	if (!_count)
+		return -1;
+
+	int i;
+	for (i = 0; i < _count; i++) {
+		//assert(_sceneObjectsSortedByDistance[i] < _count);
+		SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
+		if ((mustBeClickable && !sceneObject->_isClickable)
+			|| (mustBeObstacle && !sceneObject->_isObstacle)
+			|| (mustBeCombatTarget && !sceneObject->_isCombatTarget)) {
+			continue;
 		}
-		int j;
-		for (j = 0; j < _count; j++) {
-			if (_sceneObjectsSortedByDistance[j] == i) {
-				break;
-			}
+
+		boundingBox = sceneObject->_boundingBox;
+
+		if (sceneObject->_sceneObjectType == SceneObjectTypeObject || sceneObject->_sceneObjectType == SceneObjectTypeItem) {
+			boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
 		}
-		int k;
-		for (k = j; k < _count - 1; k++) {
-			_sceneObjectsSortedByDistance[k] = _sceneObjectsSortedByDistance[k + 1];
+
+		if (boundingBox.inside(x, y, z)) {
+			*isClickable = sceneObject->_isClickable;
+			*isObstacle = sceneObject->_isObstacle;
+			*isCombatTarget = sceneObject->_isCombatTarget;
+			return sceneObject->_sceneObjectId;
 		}
+	}
 
-		--_count;
-		return true;
-	}
-
-	int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget) {
-		BoundingBox boundingBox;
-		*isClickable = 0;
-		*isObstacle = 0;
-		*isCombatTarget = 0;
-
-		if (!_count)
-			return -1;
-
-		int i;
-		for (i = 0; i < _count; i++) {
-			//assert(_sceneObjectsSortedByDistance[i] < _count);
-			SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
-			if ((mustBeClickable && !sceneObject->_isClickable)
-				|| (mustBeObstacle && !sceneObject->_isObstacle)
-				|| (mustBeCombatTarget && !sceneObject->_isCombatTarget)) {
-				continue;
-			}
-
-			boundingBox = sceneObject->_boundingBox;
-
-			if (sceneObject->_sceneObjectType == SceneObjectTypeObject || sceneObject->_sceneObjectType == SceneObjectTypeItem) {
-				boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
-			}
-
-			if (boundingBox.inside(x, y, z)) {
-				*isClickable = sceneObject->_isClickable;
-				*isObstacle = sceneObject->_isObstacle;
-				*isCombatTarget = sceneObject->_isCombatTarget;
-				return sceneObject->_sceneObjectId;
-			}
+	return -1;
+}
+
+int SceneObjects::findById(int sceneObjectId)
+{
+	int i;
+	for (i = 0; i < _count; i++) {
+		if (_sceneObjects[i]._present && _sceneObjects[i]._sceneObjectId == sceneObjectId) {
+			return i;
 		}
+	}
+	return -1;
+}
 
-		return -1;
+bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint isMoving, uint isRetired) {
+	int index = findEmpty();
+	if (_count >= SCENE_OBJECTS_COUNT || index == -1) {
+		return false;
 	}
 
-	int SceneObjects::findById(int sceneObjectId)
-	{
-		int i;
-		for (i = 0; i < _count; i++) {
-			if (_sceneObjects[i]._present && _sceneObjects[i]._sceneObjectId == sceneObjectId) {
-				return i;
-			}
+	_sceneObjects[index]._sceneObjectId = sceneObjectId;
+	_sceneObjects[index]._sceneObjectType = sceneObjectType;
+	_sceneObjects[index]._present = 1;
+	_sceneObjects[index]._boundingBox = *boundingBox;
+	_sceneObjects[index]._screenRectangle = *screenRectangle;
+	_sceneObjects[index]._isClickable = isClickable;
+	_sceneObjects[index]._isObstacle = isObstacle;
+	_sceneObjects[index]._unknown1 = unknown1;
+	_sceneObjects[index]._isCombatTarget = isCombatTarget;
+	_sceneObjects[index]._isMoving = isMoving;
+	_sceneObjects[index]._isRetired = isRetired;
+
+	float centerZ = (_sceneObjects[index]._boundingBox.getZ0() + _sceneObjects[index]._boundingBox.getZ1()) / 2.0;
+
+	float distanceToCamera = fabs(_view->_cameraPosition.z - centerZ);
+	_sceneObjects[index]._distanceToCamera = distanceToCamera;
+
+	// insert according to distance from camera
+	int i, j;
+	for (i = 0; i < _count; i++) {
+		if (distanceToCamera < _sceneObjects[_sceneObjectsSortedByDistance[i]]._distanceToCamera) {
+			break;
 		}
-		return -1;
 	}
 
-	bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint isMoving, uint isRetired) {
-		int index = findEmpty();
-		if (_count >= SCENE_OBJECTS_COUNT || index == -1) {
-			return false;
-		}
+	for (j = _count - 1; j >= i; j--) {
+		_sceneObjectsSortedByDistance[j + 1] = _sceneObjectsSortedByDistance[j];
+	}
 
-		_sceneObjects[index]._sceneObjectId = sceneObjectId;
-		_sceneObjects[index]._sceneObjectType = sceneObjectType;
-		_sceneObjects[index]._present = 1;
-		_sceneObjects[index]._boundingBox = *boundingBox;
-		_sceneObjects[index]._screenRectangle = *screenRectangle;
-		_sceneObjects[index]._isClickable = isClickable;
-		_sceneObjects[index]._isObstacle = isObstacle;
-		_sceneObjects[index]._unknown1 = unknown1;
-		_sceneObjects[index]._isCombatTarget = isCombatTarget;
-		_sceneObjects[index]._isMoving = isMoving;
-		_sceneObjects[index]._isRetired = isRetired;
-
-		float centerZ = (_sceneObjects[index]._boundingBox.getZ0() + _sceneObjects[index]._boundingBox.getZ1()) / 2.0;
-
-		float distanceToCamera = fabs(_view->_cameraPosition.z - centerZ);
-		_sceneObjects[index]._distanceToCamera = distanceToCamera;
-
-		// insert according to distance from camera
-		int i, j;
-		for (i = 0; i < _count; i++) {
-			if (distanceToCamera < _sceneObjects[_sceneObjectsSortedByDistance[i]]._distanceToCamera) {
-				break;
-			}
-		}
+	_sceneObjectsSortedByDistance[i] = index;
+	++_count;
+	return true;
+}
 
-		for (j = _count - 1; j >= i; j--) {
-			_sceneObjectsSortedByDistance[j + 1] = _sceneObjectsSortedByDistance[j];
-		}
+int SceneObjects::findEmpty() {
+	int i;
+	for (i = 0; i < SCENE_OBJECTS_COUNT; i++)
+	{
+		if (!_sceneObjects[i]._present)
+			return i;
+	}
+	return -1;
+}
 
-		_sceneObjectsSortedByDistance[i] = index;
-		++_count;
-		return true;
+void SceneObjects::setMoving(int sceneObjectId, bool isMoving) {
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return;
 	}
+	_sceneObjects[i]._isMoving = isMoving;
+}
 
-	int SceneObjects::findEmpty() {
-		int i;
-		for (i = 0; i < SCENE_OBJECTS_COUNT; i++)
-		{
-			if (!_sceneObjects[i]._present)
-				return i;
-		}
-		return -1;
+void SceneObjects::setRetired(int sceneObjectId, bool isRetired) {
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return;
 	}
+	_sceneObjects[i]._isRetired = isRetired;
+}
 
-	void SceneObjects::setMoving(int sceneObjectId, bool isMoving) {
-		int i = findById(sceneObjectId);
-		if (i == -1 || !_sceneObjects[i]._present) {
-			return;
-		}
-		_sceneObjects[i]._isMoving = isMoving;
+bool SceneObjects::isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2) {
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return false;
 	}
 
+	float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2;
+	_sceneObjects[i]._boundingBox.getXyz(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
+
+	//TODO
+//		if (!lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ1, objectX2, objectZ1, &intersectionX, &intersectionY, &v18)
+//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ1, objectX2, objectZ2, &intersectionX, &intersectionY, &v18)
+//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ2, objectX1, objectZ2, &intersectionX, &intersectionY, &v18)
+//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ2, objectX1, objectZ1, &intersectionX, &intersectionY, &v18))
+//			return false;
+	return true;
+}
+
+
+void SceneObjects::setIsClickable(int sceneObjectId, bool isClickable) {
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return;
+	}
+	_sceneObjects[i]._isClickable = isClickable;
+}
+
+void SceneObjects::setIsObstacle(int sceneObjectId, bool isObstacle) {
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return;
+	}
+	_sceneObjects[i]._isObstacle = isObstacle;
+}
+
+void SceneObjects::setIsCombatTarget(int sceneObjectId, bool isCombatTarget) {
+	int i = findById(sceneObjectId);
+	if (i == -1 || !_sceneObjects[i]._present) {
+		return;
+	}
+	_sceneObjects[i]._isCombatTarget = isCombatTarget;
+}
+
+
+void SceneObjects::updateWalkpath() {
+	//TODO: implement
+}
+
 }
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 16188d9..bccb2ea 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -81,6 +81,12 @@ namespace BladeRunner {
 		void clear();
 		int findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget);
 		void setMoving(int sceneObjectId, bool isMoving);
+		void setRetired(int sceneObjectId, bool isRetired);
+		bool isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2);
+		void setIsClickable(int sceneObjectId, bool isClickable);
+		void setIsObstacle(int sceneObjectId, bool isObstacle);
+		void setIsCombatTarget(int sceneObjectId, bool isCombatTarget);
+		void updateWalkpath();
 	private:
 		int findById(int sceneObjectId);
 		bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint unknown2, uint isRetired);
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index 7c1f25d..070fd64 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -130,7 +130,7 @@ int Set::findWalkbox(float x, float z) {
 	int i;
 	float altitude = 0.0f;
 	int foundWalkboxId = -1;
-	for (i = 0; i < _walkboxCount; i++) {
+	for (i = 0; i < (int)_walkboxCount; i++) {
 		if (isXzInWalkbox(x, z, &_walkboxes[i])) {
 			if (foundWalkboxId == -1 || altitude < _walkboxes[i]._altitude) {
 				altitude = _walkboxes[i]._altitude;
@@ -147,7 +147,7 @@ bool Set::isXzInWalkbox(float x, float z, Walkbox* walkbox) {
 
 	float lastX = walkbox->_vertices[walkbox->_vertexCount - 1].x;
 	float lastZ = walkbox->_vertices[walkbox->_vertexCount - 1].z;
-	for (i = 0; i < walkbox->_vertexCount; i++) {
+	for (i = 0; i < (int)walkbox->_vertexCount; i++) {
 
 		float currentX = walkbox->_vertices[i].x;
 		float currentZ = walkbox->_vertices[i].z;
@@ -165,7 +165,7 @@ bool Set::isXzInWalkbox(float x, float z, Walkbox* walkbox) {
 
 int Set::findObject(char* objectName) {
 	int i;	
-	for (i = 0; i < _objectCount; i++) {
+	for (i = 0; i < (int)_objectCount; i++) {
 		if (scumm_stricmp(objectName, _objects[i]._name) == 0) {
 			return i;
 		}
@@ -174,7 +174,7 @@ int Set::findObject(char* objectName) {
 }
 
 bool Set::objectSetHotMouse(int objectId) {
-	if(!_objects || objectId < 0 || objectId >= _objectCount) {
+	if(!_objects || objectId < 0 || objectId >= (int)_objectCount) {
 		return false;
 	}
 	
@@ -185,7 +185,7 @@ bool Set::objectSetHotMouse(int objectId) {
 bool Set::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
 	assert(boundingBox);
 
-	if (!_objects || objectId < 0 || objectId >= _objectCount) {
+	if (!_objects || objectId < 0 || objectId >= (int)_objectCount) {
 		boundingBox->setXyz(0, 0, 0, 0, 0, 0);
 		return false;
 	}
@@ -197,4 +197,16 @@ bool Set::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
 	return true;
 }
 
+void Set::objectSetIsClickable(int objectId, bool isClickable) {
+	_objects[objectId]._isClickable = isClickable;
+}
+
+void Set::objectSetIsObstacle(int objectId, bool isObstacle) {
+	_objects[objectId]._isObstacle = isObstacle;
+}
+
+void Set::objectSetIsCombatTarget(int objectId, bool isCombatTarget) {
+	_objects[objectId]._isCombatTarget = isCombatTarget;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index 395ec6c..2db9c82 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -66,9 +66,8 @@ class Set {
 	Walkbox    *_walkboxes;
 	int         _walkboxStepSound[85];
 	int         _footstepSoundOverride;
-	SetEffects *_effects;
 public:
-	
+	SetEffects *_effects;
 
 public:
 	Set(BladeRunnerEngine *vm);
@@ -82,6 +81,9 @@ public:
 
 	bool objectSetHotMouse(int objectId);
 	bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
+	void objectSetIsClickable(int objectId, bool isClickable);
+	void objectSetIsObstacle(int objectId, bool isObstacle);
+	void objectSetIsCombatTarget(int objectId, bool isCombatTarget);
 
 private:
 	bool isXzInWalkbox(float x, float z, Walkbox* walkbox);
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
index f524820..6db81ce 100644
--- a/engines/bladerunner/set_effects.cpp
+++ b/engines/bladerunner/set_effects.cpp
@@ -2,82 +2,121 @@
 
 namespace BladeRunner
 {
-	SetEffects::SetEffects(BladeRunnerEngine* vm)
-	{
-		_vm = vm;
-
-		_distanceColor.r = 1.0f;
-		_distanceColor.g = 1.0f;
-		_distanceColor.b = 1.0f;
-		_distanceCoeficient = 0.1f;
-
-		_fadeColor.r = 0.0f;
-		_fadeColor.g = 0.0f;
-		_fadeColor.b = 0.0f;
-		_fadeDensity = 0.0f;
-
-		_fogsCount = 0;
-		_fogs = NULL;
-	}
 
-	SetEffects::~SetEffects()
-	{
-		reset();
-	}
+SetEffects::SetEffects(BladeRunnerEngine* vm) {
+	_vm = vm;
+
+	_distanceColor.r = 1.0f;
+	_distanceColor.g = 1.0f;
+	_distanceColor.b = 1.0f;
+	_distanceCoeficient = 0.1f;
+
+	_fadeColor.r = 0.0f;
+	_fadeColor.g = 0.0f;
+	_fadeColor.b = 0.0f;
+	_fadeDensity = 0.0f;
+
+	_fogsCount = 0;
+	_fogs = NULL;
+}
+
+SetEffects::~SetEffects() {
+	reset();
+}
 
-	void SetEffects::read(Common::ReadStream* stream, int framesCount)
-	{
-		_distanceCoeficient = stream->readFloatLE();
-		_distanceColor.r = stream->readFloatLE();
-		_distanceColor.g = stream->readFloatLE();
-		_distanceColor.b = stream->readFloatLE();
+void SetEffects::read(Common::ReadStream* stream, int framesCount) {
+	_distanceCoeficient = stream->readFloatLE();
+	_distanceColor.r = stream->readFloatLE();
+	_distanceColor.g = stream->readFloatLE();
+	_distanceColor.b = stream->readFloatLE();
 
-		_fogsCount = stream->readUint32LE();
-		int i;
-		for (i = 0; i < _fogsCount; i++)
+	_fogsCount = stream->readUint32LE();
+	int i;
+	for (i = 0; i < _fogsCount; i++) {
+		int type = stream->readUint32LE();
+		Fog* fog = NULL;
+		switch (type)
 		{
-			int type = stream->readUint32LE();
-			Fog* fog = NULL;
-			switch(type)
-			{
-			case 0: 
-				fog = new FogCone();
-				break;
-			case 1:
-				fog = new FogSphere();
-				break;
-			case 2:
-				fog = new FogBox();
-				break;
-			}
-			if(!fog)
-			{
-				//TODO exception, unknown fog type
-			}
-			fog->read(stream, framesCount);
-			fog->_next = _fogs;
-			_fogs = fog;
+		case 0:
+			fog = new FogCone();
+			break;
+		case 1:
+			fog = new FogSphere();
+			break;
+		case 2:
+			fog = new FogBox();
+			break;
 		}
+		if (!fog)
+		{
+			//TODO exception, unknown fog type
+		}
+		fog->read(stream, framesCount);
+		fog->_next = _fogs;
+		_fogs = fog;
 	}
+}
 
-	void SetEffects::reset()
-	{
-		Fog* fog, *nextFog;
-		
-		if (!_fogs)
-			return;
+void SetEffects::reset() {
+	Fog* fog, *nextFog;
 
-		do
-		{
-			fog = _fogs;
-			nextFog = fog->_next;
-			delete fog;
-			fog = nextFog;
-		} while (nextFog);
+	if (!_fogs)
+		return;
 
-	}
+	do {
+		fog = _fogs;
+		nextFog = fog->_next;
+		delete fog;
+		fog = nextFog;
+	} while (nextFog);
+
+}
+
+void SetEffects::setupFrame(int frame) {
+}
 
-	void SetEffects::setupFrame(int frame)
-	{
+void SetEffects::setFadeColor(float r, float g, float b) {
+	_fadeColor.r = r;
+	_fadeColor.r = g;
+	_fadeColor.b = b;
+}
+
+void SetEffects::setFadeDensity(float density) {
+	_fadeDensity = density;
+}
+
+void SetEffects::setFogColor(char* fogName, float r, float g, float b) {
+	Fog* fog = findFog(fogName);
+	if (fog == nullptr)
+		return;
+
+	fog->_fogColor.r = r;
+	fog->_fogColor.g = g;
+	fog->_fogColor.b = b;
+}
+
+void SetEffects::setFogDensity(char* fogName, float density) {
+	Fog* fog = findFog(fogName);
+	if (fog == nullptr)
+		return;
+
+	fog->_fogDensity = density;
+}
+
+Fog* SetEffects::findFog(char* fogName) {
+	if (!_fogs)
+		return nullptr;
+
+	Fog* fog = _fogs;
+
+	while (fog != nullptr) {
+		if (strcmp(fogName, fog->_name) == 0) {
+			break;
+		}
+		fog = fog->_next;
 	}
+
+	return fog;
+}
+
 }
\ No newline at end of file
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
index 5165cfb..8f62807 100644
--- a/engines/bladerunner/set_effects.h
+++ b/engines/bladerunner/set_effects.h
@@ -29,34 +29,39 @@
 
 #include "common/stream.h"
 
-
 namespace BladeRunner {
 
-	class SetEffects
-	{
-		BladeRunnerEngine *_vm;
+class SetEffects
+{
+	BladeRunnerEngine *_vm;
+
+private:
+	Color _distanceColor;
+	float _distanceCoeficient;
+	Color _fadeColor;
+	float _fadeDensity;
+	int   _fogsCount;
+	Fog  *_fogs;
 
-	private:
-		Color _distanceColor;
-		float _distanceCoeficient;
-		Color _fadeColor;
-		float _fadeDensity;
-		int _fogsCount;
-		Fog *_fogs;
+public:
+	SetEffects(BladeRunnerEngine *vm);
+	~SetEffects();
 
-	public:
-		SetEffects(BladeRunnerEngine *vm);
-		~SetEffects();
+	void read(Common::ReadStream *stream, int framesCount);
 
-		void read(Common::ReadStream *stream, int framesCount);
+	void reset();
 
-		void reset();
+	void setupFrame(int frame);
 
-		void setupFrame(int frame);
+	void setFadeColor(float r, float g, float b);
+	void setFadeDensity(float density);
+	void setFogColor(char* fogName, float r, float g, float b);
+	void setFogDensity(char* fogName, float density);
+private:
 
-	private:
+	Fog* findFog(char* fogName);
 
-	};
+};
 
 }
 #endif
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index 0759762..100f492 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -95,4 +95,33 @@ bool Settings::openNewScene() {
 	return true;
 }
 
+
+int Settings::getAmmoType() {
+	return _ammoType;
+}
+
+int Settings::getAmmoAmount(int ammoType) {
+	return _ammoAmounts[ammoType];
+}
+
+void Settings::addAmmo(int ammoType, int ammo) {
+	if (ammoType > _ammoType || _ammoAmounts[_ammoType] == 0)
+		_ammoType = ammoType;
+	_ammoAmounts[ammoType] += ammo;
+}
+
+int Settings::getDifficulty() {
+	return _difficulty;
+}
+
+int Settings::getPlayerAgenda() {
+	return _playerAgenda;
+}
+
+void Settings::setPlayerAgenda(int agenda) {
+	_playerAgenda = agenda;
+}
+
+
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h
index 61ac420..e45eb32 100644
--- a/engines/bladerunner/settings.h
+++ b/engines/bladerunner/settings.h
@@ -44,6 +44,12 @@ class Settings {
 	int   _fullHDFrames;
 	int   _mst3k;
 
+	int   _difficulty;
+	int   _playerAgenda;
+	
+	int   _ammoType;
+	int   _ammoAmounts[3];
+
 public:
 	Settings(BladeRunnerEngine *vm);
 
@@ -87,6 +93,14 @@ public:
 	}
 
 	bool openNewScene();
+
+	int getAmmoType();
+	int getAmmoAmount(int ammoType);
+
+	int getDifficulty();
+	int getPlayerAgenda();
+	void setPlayerAgenda(int agenda);
+	void addAmmo(int ammoType, int ammo);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index efcd4b3..b813c13 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -63,14 +63,14 @@ bool SliceAnimations::open(const Common::String &name) {
 	_animations.resize(animationCount);
 
 	for (uint32 i = 0; i != animationCount; ++i) {
-		_animations[i].frameCount = file.readUint32LE();
-		_animations[i].frameSize  = file.readUint32LE();
-		_animations[i].fps        = file.readFloatLE();
-		_animations[i].unk0       = file.readFloatLE();
-		_animations[i].unk1       = file.readFloatLE();
-		_animations[i].unk2       = file.readFloatLE();
-		_animations[i].unk3       = file.readFloatLE();
-		_animations[i].offset     = file.readUint32LE();
+		_animations[i].frameCount       = file.readUint32LE();
+		_animations[i].frameSize        = file.readUint32LE();
+		_animations[i].fps              = file.readFloatLE();
+		_animations[i].positionChange.x = file.readFloatLE();
+		_animations[i].positionChange.y = file.readFloatLE();
+		_animations[i].positionChange.z = file.readFloatLE();
+		_animations[i].facingChange     = file.readFloatLE();
+		_animations[i].offset           = file.readUint32LE();
 
 #if 0
 		debug("%4d  %6d %6x  %7.2g %7.2g %7.2g %7.2g %7.2g %8x",
@@ -172,8 +172,16 @@ void *SliceAnimations::getFramePtr(uint32 animation, uint32 frame) {
 
 
 int SliceAnimations::getNumberOfFrames(int animationId) {
-	if (animationId > _animations.size())
+	if (animationId > (int)_animations.size())
 		return 0;
 	return _animations[animationId].frameCount;
 }
+
+
+float SliceAnimations::getFps(int animationId) {
+	if (animationId > (int)_animations.size())
+		return 15.0f;
+	return _animations[animationId].fps;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index b0c53b1..9af12e4 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -23,6 +23,8 @@
 #ifndef BLADERUNNER_SLICE_ANIMATIONS_H
 #define BLADERUNNER_SLICE_ANIMATIONS_H
 
+#include "bladerunner/vector.h"
+
 #include "common/array.h"
 #include "common/file.h"
 #include "common/str.h"
@@ -46,10 +48,8 @@ class SliceAnimations {
 		uint32 frameCount;
 		uint32 frameSize;
 		float  fps;
-		float  unk0;
-		float  unk1;
-		float  unk2;
-		float  unk3;
+		Vector3 positionChange;
+		float facingChange;
 		uint32 offset;
 	};
 
@@ -102,10 +102,10 @@ public:
 	bool openCoreAnim();
 	bool openHDFrames();
 
-	SlicePalette &getPalette(int i) { return _palettes[i]; };
+	SlicePalette &getPalette(int i) { return _palettes[i]; }
 	void *getFramePtr(uint32 animation, uint32 frame);
-
 	int getNumberOfFrames(int animationId);
+	float getFps(int animationId);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index a52a123..389d818 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -54,6 +54,16 @@ void dump(const char *str, Matrix4x3 m) {
 }
 #endif
 
+
+SliceRenderer::SliceRenderer(BladeRunnerEngine* vm) {
+	_vm = vm;
+	int i; 
+
+	for (i = 0; i < 942; i++) { // yes, its going just to 942 and not 997
+		_animationsShadowEnabled[i] = true;
+	}
+}
+
 SliceRenderer::~SliceRenderer() {
 }
 
@@ -429,4 +439,12 @@ void SliceRenderer::preload(int animationId) {
 	for (i = 0; i < _vm->_sliceAnimations->getNumberOfFrames(animationId); i++)
 		_vm->_sliceAnimations->getFramePtr(animationId, i);
 }
+
+void SliceRenderer::disableShadows(int* animationsIdsList, int listSize) {
+	int i;
+	for (i = 0; i < listSize; i++) {
+		_animationsShadowEnabled[animationsIdsList[i]] = false;
+	}
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index 6e21d4f..c702616 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -80,15 +80,13 @@ class SliceRenderer {
 	int _t5[256];
 	int _c6;
 
-
+	bool _animationsShadowEnabled[997];
 
 	Matrix3x2 calculateFacingRotationMatrix();
 	void drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr);
 
 public:
-	SliceRenderer(BladeRunnerEngine *vm)
-		: _vm(vm)
-	{}
+	SliceRenderer(BladeRunnerEngine *vm);
 	~SliceRenderer();
 
 	void setView(View *view);
@@ -100,9 +98,9 @@ public:
 
 	void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
 
-
 	void preload(int animationId);
 
+	void disableShadows(int* animationsIdsList, int listSize);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index 3b85da4..4f4bfed 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -56,6 +56,8 @@ public:
 	Vector3(float ax, float ay, float az)
 		: x(ax), y(ay), z(az)
 	{}
+
+	float length() { return sqrtf(x * x + y * y + z * z); }
 };
 
 inline
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
index d174e26..60d3422 100644
--- a/engines/bladerunner/waypoints.cpp
+++ b/engines/bladerunner/waypoints.cpp
@@ -50,6 +50,18 @@ bool Waypoints::reset(int waypointId) {
 	_waypoints[waypointId]._present = false;
 
 	return true;
+}
+
+float Waypoints::getX(int waypointId) {
+	return _waypoints[waypointId]._position.x;
+}
 
+float Waypoints::getY(int waypointId) {
+	return _waypoints[waypointId]._position.y;
 }
+
+float Waypoints::getZ(int waypointId) {
+	return _waypoints[waypointId]._position.z;
+}
+
 }
\ No newline at end of file
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
index c74e405..5ee4696 100644
--- a/engines/bladerunner/waypoints.h
+++ b/engines/bladerunner/waypoints.h
@@ -47,6 +47,9 @@ namespace BladeRunner {
 		~Waypoints();
 
 		void getXyz(int waypointId, float *x, float *y, float *z);
+		float getX(int waypointId);
+		float getY(int waypointId);
+		float getZ(int waypointId);
 		int getSetId(int waypointId);
 
 		bool set(int waypointId, int setId, Vector3 position);


Commit: 2888d0b3460cdca2dd52f8d6aa94b429d46345ad
    https://github.com/scummvm/scummvm/commit/2888d0b3460cdca2dd52f8d6aa94b429d46345ad
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:40+02:00

Commit Message:
BLADERUNNER: forgotten script files....

Changed paths:
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 81c4795..73a5f89 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -154,4 +154,11 @@ void ScriptRC01::SceneFrameAdvanced(int frame) {
 		Sound_Play(118, 40, 80, 80, 50);  // CARDOWN3.AUD
 }
 
+
+void ScriptRC01::SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+
+}
+
+
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 5788936..c71326d 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -33,6 +33,12 @@
 #include "bladerunner/scene.h"
 #include "bladerunner/text_resource.h"
 #include "bladerunner/vector.h"
+#include "bladerunner/slice_renderer.h"
+#include "bladerunner/actor.h"
+#include "bladerunner/waypoints.h"
+#include "bladerunner/slice_animations.h"
+#include "bladerunner/combat.h"
+#include "bladerunner/settings.h"
 
 namespace BladeRunner {
 
@@ -41,6 +47,8 @@ bool Script::open(const Common::String &name) {
 
 	if (name == "RC01") { _currentScript = new ScriptRC01(_vm); return true; }
 
+	_currentScript = new ScriptRC01(_vm); return true;
+
 	return false;
 }
 
@@ -66,76 +74,344 @@ void Script::SceneFrameAdvanced(int frame) {
 	_inScriptCounter--;
 }
 
-// ScriptBase::Preload
-// ScriptBase::Actor_Put_In_Set
-// ScriptBase::Actor_Set_At_XYZ
-// ScriptBase::Actor_Set_At_Waypoint
-// ScriptBase::Region_Check
+void Script::SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+	_inScriptCounter++;
+	_currentScript->SceneActorChangedGoal(actorId, newGoal, oldGoal, currentSet);
+	_inScriptCounter--;
+}
+
+void ScriptBase::Preload(int animationId) {
+	_vm->_sliceRenderer->preload(animationId);
+}
+
+void ScriptBase::Actor_Put_In_Set(int actorId, int setId) {
+	_vm->_actors[actorId]->setSetId(setId);
+}
+
+void ScriptBase::Actor_Set_At_XYZ(int actorId, float x, float y, float z, int angle) {
+	_vm->_actors[actorId]->set_at_xyz(Vector3(x, y, z), angle, true, 0, 0);
+}
+
+void ScriptBase::Actor_Set_At_Waypoint(int actorId, int waypointId, int angle) {
+	_vm->_actors[actorId]->set_at_waypoint(waypointId, angle, 0, 0);
+}
+
+bool ScriptBase::Region_Check(int left, int top, int right, int down) {
+	//TODO: return _vm->_mouse.x >= left && _vm->_mouse.y >= top && _vm->_mouse.x <= right && _vm->_mouse.y <= down;
+	return false;
+}
+
 // ScriptBase::Object_Query_Click
 // ScriptBase::Object_Do_Ground_Click
-// ScriptBase::Object_Mark_For_Hot_Mouse
-// ScriptBase::Actor_Face_Actor
-// ScriptBase::Actor_Face_Object
-// ScriptBase::Actor_Face_Item
-// ScriptBase::Actor_Face_Waypoint
-// ScriptBase::Actor_Face_XYZ
-// ScriptBase::Actor_Face_Current_Camera
-// ScriptBase::Actor_Face_Heading
-// ScriptBase::Actor_Query_Friendliness_To_Other
-// ScriptBase::Actor_Modify_Friendliness_To_Other
-// ScriptBase::Actor_Set_Friendliness_To_Other
-// ScriptBase::Actor_Set_Honesty
-// ScriptBase::Actor_Set_Intelligence
-// ScriptBase::Actor_Set_Stability
-// ScriptBase::Actor_Set_Combat_Aggressiveness
-// ScriptBase::Actor_Query_Current_HP
-// ScriptBase::Actor_Query_Max_HP
-// ScriptBase::Actor_Query_Combat_Aggressiveness
-// ScriptBase::Actor_Query_Honesty
-// ScriptBase::Actor_Query_Intelligence
-// ScriptBase::Actor_Query_Stability
-// ScriptBase::Actor_Modify_Current_HP
-// ScriptBase::Actor_Modify_Max_HP
-// ScriptBase::Actor_Modify_Combat_Aggressiveness
-// ScriptBase::Actor_Modify_Honesty
-// ScriptBase::Actor_Modify_Intelligence
-// ScriptBase::Actor_Modify_Stability
-// ScriptBase::Actor_Set_Flag_Damage_Anim_If_Moving
-// ScriptBase::Actor_Query_Flag_Damage_Anim_If_Moving
-// ScriptBase::Actor_Combat_AI_Hit_Attempt
-// ScriptBase::Non_Player_Actor_Combat_Mode_On
-// ScriptBase::Non_Player_Actor_Combat_Mode_Off
-// ScriptBase::Actor_Set_Health
-// ScriptBase::Actor_Set_Targetable
-// ScriptBase::Actor_Says
-// ScriptBase::Actor_Says_With_Pause
+
+bool ScriptBase::Object_Mark_For_Hot_Mouse(char *objectName) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return false;
+	return _vm->_scene->objectSetHotMouse(objectId);
+}
+
+void ScriptBase::Actor_Face_Actor(int actorId, int otherActorId, bool animate) {
+	_vm->_actors[actorId]->faceActor(otherActorId, animate);
+}
+
+void ScriptBase::Actor_Face_Object(int actorId, char *objectName, bool animate) {
+	_vm->_actors[actorId]->faceObject(objectName, animate);
+}
+
+void ScriptBase::Actor_Face_Item(int actorId, int itemId, bool animate) {
+	_vm->_actors[actorId]->faceItem(itemId, animate);
+}
+
+void ScriptBase::Actor_Face_Waypoint(int actorId, int waypointId, bool animate) {
+	_vm->_actors[actorId]->faceWaypoint(waypointId, animate);
+}
+
+void ScriptBase::Actor_Face_XYZ(int actorId, float x, float y, float z, bool animate) {
+	_vm->_actors[actorId]->faceXYZ(x, y, z, animate);
+}
+
+void ScriptBase::Actor_Face_Current_Camera(int actorId, bool animate) {
+	_vm->_actors[actorId]->faceCurrentCamera(animate);
+}
+
+void ScriptBase::Actor_Face_Heading(int actorId, int heading) {
+	_vm->_actors[actorId]->faceHeading(heading, true);
+}
+
+int ScriptBase::Actor_Query_Friendliness_To_Other(int actorId, int otherActorId) {
+	return _vm->_actors[actorId]->_friendlinessToOther[otherActorId];
+}
+
+void ScriptBase::Actor_Modify_Friendliness_To_Other(int actorId, int otherActorId, signed int change) {
+	_vm->_actors[actorId]->modifyFriendlinessToOther(otherActorId, change);
+}
+
+void ScriptBase::Actor_Set_Friendliness_To_Other(int actorId, int otherActorId, int friendliness) {
+	_vm->_actors[actorId]->setFriendlinessToOther(otherActorId, friendliness);
+}
+
+void ScriptBase::Actor_Set_Honesty(int actorId, int honesty) {
+	_vm->_actors[actorId]->setHonesty(honesty);
+}
+
+void ScriptBase::Actor_Set_Intelligence(int actorId, int intelligence) {
+	_vm->_actors[actorId]->setIntelligence(intelligence);
+}
+
+void ScriptBase::Actor_Set_Stability(int actorId, int stability) {
+	_vm->_actors[actorId]->setStability(stability);
+}
+
+void ScriptBase::Actor_Set_Combat_Aggressiveness(int actorId, int combatAggressiveness) {
+	_vm->_actors[actorId]->setCombatAggressiveness(combatAggressiveness);
+}
+
+int ScriptBase::Actor_Query_Current_HP(int actorId) {
+	return _vm->_actors[actorId]->_currentHP;
+}
+
+int ScriptBase::Actor_Query_Max_HP(int actorId) {
+	return _vm->_actors[actorId]->_maxHP;
+}
+
+int ScriptBase::Actor_Query_Combat_Aggressiveness(int actorId) {
+	return _vm->_actors[actorId]->_combatAggressiveness;
+}
+
+int ScriptBase::Actor_Query_Honesty(int actorId) {
+	return _vm->_actors[actorId]->_honesty;
+}
+
+int ScriptBase::Actor_Query_Intelligence(int actorId) {
+	return _vm->_actors[actorId]->_intelligence;
+}
+
+int ScriptBase::Actor_Query_Stability(int actorId) {
+	return _vm->_actors[actorId]->_stability;
+}
+
+void ScriptBase::Actor_Modify_Current_HP(int actorId, signed int change) {
+	_vm->_actors[actorId]->modifyCurrentHP(change);
+}
+
+void ScriptBase::Actor_Modify_Max_HP(int actorId, signed int change) {
+	_vm->_actors[actorId]->modifyMaxHP(change);
+}
+
+void ScriptBase::Actor_Modify_Combat_Aggressiveness(int actorId, signed int change) {
+	_vm->_actors[actorId]->modifyCombatAggressiveness(change);
+}
+
+void ScriptBase::Actor_Modify_Honesty(int actorId, signed int change) {
+	_vm->_actors[actorId]->modifyHonesty(change);
+}
+
+void ScriptBase::Actor_Modify_Intelligence(int actorId, signed int change) {
+	_vm->_actors[actorId]->modifyIntelligence(change);
+}
+
+void ScriptBase::Actor_Modify_Stability(int actorId, signed int change) {
+	_vm->_actors[actorId]->modifyStability(change);
+}
+
+void ScriptBase::Actor_Set_Flag_Damage_Anim_If_Moving(int actorId, bool value) {
+	_vm->_actors[actorId]->setFlagDamageAnimIfMoving(value);
+}
+
+bool ScriptBase::Actor_Query_Flag_Damage_Anim_If_Moving(int actorId) {
+	return _vm->_actors[actorId]->getFlagDamageAnimIfMoving();
+}
+
+void ScriptBase::Actor_Combat_AI_Hit_Attempt(int actorId) {
+	if (_vm->_actors[actorId]->inCombat())
+		_vm->_actors[actorId]->_combatInfo->hitAttempt();
+}
+
+void ScriptBase::Non_Player_Actor_Combat_Mode_On(int actorId, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14) {
+	_vm->_actors[actorId]->combatModeOn(a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14);
+}
+
+void ScriptBase::Non_Player_Actor_Combat_Mode_Off(int actorId) {
+	_vm->_actors[actorId]->combatModeOff();
+}
+
+void ScriptBase::Actor_Set_Health(int actorId, int hp, int maxHp) {
+	_vm->_actors[actorId]->setHealth(hp, maxHp);
+}
+
+void ScriptBase::Actor_Set_Targetable(int actorId, bool targetable) {
+	_vm->_actors[actorId]->setTargetable(targetable);
+	
+}
+
+void ScriptBase::Actor_Says(int actorId, int sentenceId, int animationMode){
+	_vm->loopActorSpeaking();
+	//_vm->ADQ->flush(1,1)
+	Actor_Says_With_Pause(actorId, sentenceId, 0.5f, animationMode);
+}
+
+void ScriptBase::Actor_Says_With_Pause(int actorId, int sentenceId, float pause, int animationMode) {
+	_vm->gameWaitForActive();
+	_vm->loopActorSpeaking();
+	//_vm->ADQ->flush(1,1)
+
+	Actor *actor = _vm->_actors[actorId];
+
+	if(animationMode != -1) {
+		actor->stopWalking(false);
+	}
+
+	actor->speechPlay(sentenceId, false);
+	bool animationModeChanged = false;
+	if(animationMode >= 0) {
+		if (actorId != 0) {
+			actor->changeAnimationMode(animationMode, false);
+			animationModeChanged = true;
+		} else if(_vm->_combat->isActive()) {
+			actor->changeAnimationMode(animationMode, false);
+			animationModeChanged = true;
+		}
+	}
+	Player_Loses_Control();
+	while (_vm->_gameIsRunning) {
+		_vm->_speechSkipped = false;
+		_vm->gameTick();
+		if (_vm->_speechSkipped || !actor->isSpeeching()) {
+			actor->speechStop();
+			break;
+		}
+	}
+	if (animationModeChanged) {
+		actor->changeAnimationMode(0, false);
+	}
+
+	//TODO: sitcom
+	//if (_vm->isSitcom)
+	//{
+	//	int rnd = _vm->random(1, 100);
+	//	if (rnd <= actor::get_unknown3(actor))
+	//	{
+	//		int soundId = _vm->random(319, 327);
+	//		_vm->_audioPlayer->play(soundId, 40, 0, 0, 50);
+	//	}
+	//}
+	if(pause > 0.0f && !_vm->_speechSkipped) {
+		Delay(pause * 1000);
+	}
+	Player_Gains_Control();
+}
 
 void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
-	// Wait for any existing speech to end
+	_vm->gameWaitForActive();
+	_vm->loopActorSpeaking();
+	//_vm->ADQ->flush(1,1)
+
+	Actor *actor = _vm->_actors[actorId];
+
+	actor->speechPlay(sentenceId, true);
+	Player_Loses_Control();
+	while(_vm->_gameIsRunning) {
+		_vm->_speechSkipped = false;
+		_vm->gameTick();
+		if(_vm->_speechSkipped || !actor->isSpeeching()) {
+			actor->speechStop();
+			break;
+		}
+	}
+	Player_Gains_Control();
+}
+
+void ScriptBase::Actor_Start_Speech_Sample(int actorId, int sentenceId) {
 	_vm->loopActorSpeaking();
+	_vm->_actors[actorId]->speechPlay(sentenceId, false);
+}
+
+void ScriptBase::Actor_Start_Voice_Over_Sample(int sentenceId) {
+	_vm->loopActorSpeaking();	
+	_vm->_voiceoverActor->speechPlay(sentenceId, true);
+}
+
+int ScriptBase::Actor_Query_Which_Set_In(int actorId) {
+	return _vm->_actors[actorId]->getSetId();
+}
+
+bool ScriptBase::Actor_Query_Is_In_Current_Set(int actorId) {
+	int actorSetId = _vm->_actors[actorId]->getSetId();
+	return actorSetId >= 0 && _vm->_scene->getSetId();
+}
+
+bool ScriptBase::Actor_Query_In_Set(int actorId, int setId) {
+	return _vm->_actors[actorId]->getSetId() == setId;
+}
+
+int ScriptBase::Actor_Query_Inch_Distance_From_Actor(int actorId, int otherActorId) {
+	if (_vm->_actors[actorId]->getSetId() != _vm->_actors[otherActorId]->getSetId())
+		return 0.0f;
+	return _vm->_actors[actorId]->distanceFromActor(otherActorId);
+}
+
+int ScriptBase::Actor_Query_Inch_Distance_From_Waypoint(int actorId, int waypointId) {
+	if (_vm->_actors[actorId]->getSetId() != _vm->_waypoints->getSetId(waypointId))
+		return 0;
+
+	float actorX = _vm->_actors[actorId]->getX();
+	float actorZ = _vm->_actors[actorId]->getZ();
+	float waypointX = _vm->_waypoints->getX(waypointId);
+	float waypointZ = _vm->_waypoints->getZ(waypointId);
+
+	float distX = actorX - waypointX;
+	float distZ = actorZ - waypointZ;
+
+	return sqrtf(distX * distX + distZ * distZ);
+}
+
+bool ScriptBase::Actor_Query_In_Between_Two_Actors(int actorId, int otherActor1Id, int otherActor2Id) {
+	float x1 = _vm->_actors[otherActor1Id]->getX();
+	float z1 = _vm->_actors[otherActor1Id]->getZ();
+	float x2 = _vm->_actors[otherActor2Id]->getX();
+	float z2 = _vm->_actors[otherActor2Id]->getZ();
+	return _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1, z1, x2, z1)
+		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 - 12.0f, z1 - 12.0f, x2 - 12.0f, z2 - 12.0f)
+		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 + 12.0f, z1 - 12.0f, x2 + 12.0f, z2 - 12.0f)
+		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 + 12.0f, z1 + 12.0f, x2 + 12.0f, z2 + 12.0f)
+		|| _vm->_sceneObjects->isBetweenTwoXZ(actorId, x1 - 12.0f, z1 + 12.0f, x2 - 12.0f, z2 + 12.0f);
+}
+
+void ScriptBase::Actor_Set_Goal_Number(int actorId, int goalNumber) {
+	_vm->_actors[actorId]->setGoal(goalNumber);
+}
+
+int ScriptBase::Actor_Query_Goal_Number(int actorId) {
+	return _vm->_actors[actorId]->getGoal();
+}
+
+void ScriptBase::Actor_Query_XYZ(int actorId, float *x, float *y, float *z) {
+	*x = _vm->_actors[actorId]->getX();
+	*y = _vm->_actors[actorId]->getY();
+	*z = _vm->_actors[actorId]->getZ();
+}
+
+int ScriptBase::Actor_Query_Facing_1024(int actorId) {
+	return _vm->_actors[actorId]->getFacing();
+}
+
+void ScriptBase::Actor_Set_Frame_Rate_FPS(int actorId, int fps) {
+	_vm->_actors[actorId]->setFps(fps);
+}
+
+int ScriptBase::Slice_Animation_Query_Number_Of_Frames(int animationId) {
+	return _vm->_sliceAnimations->getNumberOfFrames(animationId);
+}
+
+void ScriptBase::Actor_Change_Animation_Mode(int actorId, int animationMode) {
+	_vm->_actors[actorId]->changeAnimationMode(animationMode, 0);
+}
+
+int ScriptBase::Actor_Query_Animation_Mode(int actorId) {
+	return _vm->_actors[actorId]->getAnimationMode();
+}
 
-	// TODO: Hack - This needs to go through the actor class
-	char name[13];
-	sprintf(name, "%02d-%04d.AUD", actorId, sentenceId);
-	_vm->_audioSpeech->playSpeech(name);
-}
-
-// ScriptBase::Actor_Start_Speech_Sample
-// ScriptBase::Actor_Start_Voice_Over_Sample
-// ScriptBase::Actor_Query_Which_Set_In
-// ScriptBase::Actor_Query_Is_In_Current_Set
-// ScriptBase::Actor_Query_In_Set
-// ScriptBase::Actor_Query_Inch_Distance_From_Actor
-// ScriptBase::Actor_Query_Inch_Distance_From_Waypoint
-// ScriptBase::Actor_Query_In_Between_Two_Actors
-// ScriptBase::Actor_Set_Goal_Number
-// ScriptBase::Actor_Query_Goal_Number
-// ScriptBase::Actor_Query_XYZ
-// ScriptBase::Actor_Query_Facing_1024
-// ScriptBase::Actor_Set_Frame_Rate_FPS
-// ScriptBase::Slice_Animation_Query_Number_Of_Frames
-// ScriptBase::Actor_Change_Animation_Mode
-// ScriptBase::Actor_Query_Animation_Mode
 // ScriptBase::Loop_Actor_Walk_To_Actor
 // ScriptBase::Loop_Actor_Walk_To_Item
 // ScriptBase::Loop_Actor_Walk_To_Scene_Object
@@ -147,48 +423,129 @@ void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
 // ScriptBase::Loop_Actor_Travel_Stairs
 // ScriptBase::Loop_Actor_Travel_Ladder
 
-void ScriptBase::Actor_Clue_Add_To_Database(int a0, int a1, int a2, int a3, int a4, int a5) {
-	// debug("STUB: Actor_Clue_Add_To_Database(%d, %3d, %3d, %d, %d, %d)", a0, a1, a2, a3, a4, a5);
-	// debug("\tACTOR: %s", _vm->_actorNames->getText(a0));
-	// debug("\tCLUE:  %s\n", _vm->_clues->getClueText(a1));
+void ScriptBase::Actor_Clue_Add_To_Database(int actorId, int clueId, int unknown, bool clueAcquired, bool unknownFlag, int fromActorId) {
+	_vm->_actors[actorId]->addClueToDatabase(clueId, unknown, clueAcquired, unknownFlag, fromActorId);
+}
+
+void ScriptBase::Actor_Clue_Acquire(int actorId, int clueId, byte unknownFlag, int fromActorId) {
+	_vm->_actors[actorId]->acquireClue(clueId, unknownFlag, fromActorId);
+}
+
+void ScriptBase::Actor_Clue_Lose(int actorId, int clueId) {
+	_vm->_actors[actorId]->loseClue(clueId);
+}
+
+bool ScriptBase::Actor_Clue_Query(int actorId, int clueId) {
+	return _vm->_actors[actorId]->hasClue(clueId);
+}
+
+void ScriptBase::Actor_Clues_Transfer_New_To_Mainframe(int actorId) {
+	_vm->_actors[actorId]->copyClues(99);
+}
+
+void ScriptBase::Actor_Clues_Transfer_New_From_Mainframe(int actorId) {
+	_vm->_voiceoverActor->copyClues(actorId);
+}
+
+void ScriptBase::Actor_Set_Invisible(int actorId, bool isInvisible) {
+	_vm->_actors[actorId]->setInvisible(isInvisible);
+}
+
+void ScriptBase::Actor_Set_Immunity_To_Obstacles(int actorId, bool isImmune) {
+	_vm->_actors[actorId]->setImmunityToObstacles(isImmune);
 }
 
-// ScriptBase::Actor_Clue_Acquire
-// ScriptBase::Actor_Clue_Lose
-// ScriptBase::Actor_Clue_Query
-// ScriptBase::Actor_Clues_Transfer_New_To_Mainframe
-// ScriptBase::Actor_Clues_Transfer_New_From_Mainframe
-// ScriptBase::Actor_Set_Invisible
-// ScriptBase::Actor_Set_Immunity_To_Obstacles
 // ScriptBase::Item_Add_To_World
 // ScriptBase::Item_Remove_From_World
 // ScriptBase::Item_Spin_In_World
 // ScriptBase::Item_Flag_As_Target
 // ScriptBase::Item_Flag_As_Non_Target
 // ScriptBase::Item_Pickup_Spin_Effect
-// ScriptBase::Animation_Open
-// ScriptBase::Animation_Close
-// ScriptBase::Animation_Start
-// ScriptBase::Animation_Stop
-// ScriptBase::Animation_Skip_To_Frame
-// ScriptBase::Delay
+
+int ScriptBase::Animation_Open() {
+	//This is not implemented in game
+	return -1;
+}
+
+int ScriptBase::Animation_Close() {
+	//This is not implemented in game
+	return 0;
+}
+
+int ScriptBase::Animation_Start() {
+	//This is not implemented in game
+	return 0;
+}
+
+int ScriptBase::Animation_Stop() {
+	//This is not implemented in game
+	return 0;
+}
+
+int ScriptBase::Animation_Skip_To_Frame() {
+	//This is not implemented in game
+	return 0;
+}
+
+
+void ScriptBase::Delay(int miliseconds) {
+	Player_Loses_Control();
+	int endTime = _vm->getTotalPlayTime() + miliseconds;
+	while ((int)_vm->getTotalPlayTime() < endTime)
+		_vm->gameTick();
+	Player_Gains_Control();
+	
+}
 
 void ScriptBase::Player_Loses_Control() {
-		_vm->playerLosesControl();
+	_vm->playerLosesControl();
 }
 
 void ScriptBase::Player_Gains_Control() {
-		_vm->playerGainsControl();
+	_vm->playerGainsControl();
+}
+
+void ScriptBase::Player_Set_Combat_Mode(bool activate) {
+	if(!_vm->_combat->isActive() || activate) {
+		if(_vm->_combat->isActive() && activate) {
+			_vm->_combat->activate();
+		}
+	}else {
+		_vm->_combat->deactivate();
+	}
+}
+
+bool ScriptBase::Player_Query_Combat_Mode() {
+	return _vm->_combat->isActive();
 }
 
-// ScriptBase::Player_Set_Combat_Mode
-// ScriptBase::Player_Query_Combat_Mode
-// ScriptBase::Player_Set_Combat_Mode_Access
-// ScriptBase::Player_Query_Current_Set
-// ScriptBase::Player_Query_Current_Scene
-// ScriptBase::Player_Query_Agenda
-// ScriptBase::Player_Set_Agenda
-// ScriptBase::Query_Difficulty_Level
+void ScriptBase::Player_Set_Combat_Mode_Access(bool enable) {
+	if(enable) {
+		_vm->_combat->enable();
+	}else {
+		_vm->_combat->disable();
+	}
+}
+
+int ScriptBase::Player_Query_Current_Set() {
+	return _vm->_scene->getSetId();
+}
+
+int ScriptBase::Player_Query_Current_Scene() {
+	return _vm->_scene->getSceneId();
+}
+
+int ScriptBase::Player_Query_Agenda() {
+	return _vm->_settings->getPlayerAgenda();
+}
+
+void ScriptBase::Player_Set_Agenda(int agenda) {
+	_vm->_settings->setPlayerAgenda(agenda);
+}
+
+int ScriptBase::Query_Difficulty_Level() {
+	return _vm->_settings->getDifficulty();
+}
 
 void ScriptBase::Game_Flag_Set(int flag) {
 	_vm->_gameFlags->set(flag);
@@ -202,8 +559,14 @@ bool ScriptBase::Game_Flag_Query(int flag) {
 	return _vm->_gameFlags->query(flag);
 }
 
-// ScriptBase::Set_Enter
-// ScriptBase::Chapter_Enter
+void ScriptBase::Set_Enter(int setId, int sceneId) {
+	_vm->_settings->setNewSetAndScene(setId, sceneId);
+}
+
+void ScriptBase::Chapter_Enter(int chapter, int setId, int sceneId) {
+	_vm->_settings->setChapter(chapter);
+	Set_Enter(setId, sceneId);
+}
 
 int ScriptBase::Global_Variable_Set(int var, int value) {
 	return _vm->_gameVars[var] = value;
@@ -303,19 +666,29 @@ void ScriptBase::Setup_Scene_Information(float actorX, float actorY, float actor
 // ScriptBase::Dialogue_Menu_Query_Input
 // ScriptBase::Dialogue_Menu_Query_List_Size
 
-void ScriptBase::Scene_Exit_Add_2D_Exit(int a, int b, int c, int d, int e, int f) {
-	debug("Scene_Exit_Add_2D_Exit(%d, %d, %d, %d, %d, %d)", a, b, c, d, e, f);
+void ScriptBase::Scene_Exit_Add_2D_Exit(int index, int left, int top, int right, int down, int type) {
+	_vm->_scene->_exits->add(index, Common::Rect(left, top, right, down), type);
 }
 
-// ScriptBase::Scene_Exit_Remove
-// ScriptBase::Scene_Exits_Disable
-// ScriptBase::Scene_Exits_Enable
+void ScriptBase::Scene_Exit_Remove(int index) {
+	_vm->_scene->_exits->remove(index);
+}
+
+void ScriptBase::Scene_Exits_Disable() {
+	_vm->_scene->_exits->setEnabled(false);
+}
+void ScriptBase::Scene_Exits_Enable() {
+	_vm->_scene->_exits->setEnabled(true);
+}
 
-void ScriptBase::Scene_2D_Region_Add(int a, int b, int c, int d, int e) {
-	debug("Scene_2D_Region_Add(%d, %d, %d, %d, %d)", a, b, c, d, e);
+void ScriptBase::Scene_2D_Region_Add(int index, int left, int top, int right, int down) {
+	_vm->_scene->_regions->add(index, Common::Rect(left, top, right, down), 0);
+}
+
+void ScriptBase::Scene_2D_Region_Remove(int index) {
+	_vm->_scene->_regions->remove(index);
 }
 
-// ScriptBase::Scene_2D_Region_Remove
 // ScriptBase::World_Waypoint_Set
 // ScriptBase::World_Waypoint_Reset
 // ScriptBase::World_Waypoint_Query_X
@@ -355,35 +728,114 @@ void ScriptBase::Set_Score(int a0, int a1) {
 	debug("STUB: Set_Score(%d, %d)", a0, a1);
 }
 
-// ScriptBase::Give_McCoy_Ammo
+void ScriptBase::Give_McCoy_Ammo(int ammoType, int ammo) {
+	_vm->_settings->addAmmo(ammoType, ammo);
+}
+
+void ScriptBase::Assign_Player_Gun_Hit_Sounds(int row, int soundId1, int soundId2, int soundId3) {
+	_vm->_combat->setHitSoundId(row, 0, soundId1);
+	_vm->_combat->setHitSoundId(row, 1, soundId2);
+	_vm->_combat->setHitSoundId(row, 2, soundId3);
+}
+
+void ScriptBase::Assign_Player_Gun_Miss_Sounds(int row, int soundId1, int soundId2, int soundId3) {
+	_vm->_combat->setMissSoundId(row, 0, soundId1);
+	_vm->_combat->setMissSoundId(row, 1, soundId2);
+	_vm->_combat->setMissSoundId(row, 2, soundId3);
+}
+
+void ScriptBase::Disable_Shadows(int *animationsIdsList, int listSize) {
+	_vm->_sliceRenderer->disableShadows(animationsIdsList, listSize);
+}
 
-void ScriptBase::Assign_Player_Gun_Hit_Sounds(int a0, int a1, int a2, int a3) {
-	debug("STUB: Assign_Player_Gun_Hit_Sounds(%d, %d, %d, %d)", a0, a1, a2, a3);
+bool ScriptBase::Query_System_Currently_Loading_Game() {
+	return _vm->_gameIsLoading;
 }
 
-void ScriptBase::Assign_Player_Gun_Miss_Sounds(int a0, int a1, int a2, int a3) {
-	debug("STUB: Assign_Player_Gun_Miss_Sounds(%d, %d, %d, %d)", a0, a1, a2, a3);
+void ScriptBase::Actor_Retired_Here(int actorId, int width, int height, int retired, int retiredByActorId) {
+	Actor *actor = _vm->_actors[actorId];
+	Vector3 actorPosition;
+	actor->getXYZ(&actorPosition.x, &actorPosition.y, &actorPosition.z);
+	actor->retire(retired, width, height, retiredByActorId);
+	actor->set_at_xyz(actorPosition, actor->getFacing(), true, 0, true);
+	_vm->_sceneObjects->setRetired(actorId, true);
+}
+
+void ScriptBase::Clickable_Object(char *objectName) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return;
+	_vm->_scene->objectSetIsClickable(objectId, true, !_vm->_sceneIsLoading);
+}
+
+void ScriptBase::Unclickable_Object(char *objectName) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return;
+	_vm->_scene->objectSetIsClickable(objectId, false, !_vm->_sceneIsLoading);
+}
+
+void ScriptBase::Obstacle_Object(char *objectName, bool updateWalkpath) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return;
+	_vm->_scene->objectSetIsObstacle(objectId, true, !_vm->_sceneIsLoading, !_vm->_sceneIsLoading && updateWalkpath);
+}
+
+void ScriptBase::Unobstacle_Object(char *objectName, bool updateWalkpath) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return;
+	_vm->_scene->objectSetIsObstacle(objectId, false, !_vm->_sceneIsLoading, !_vm->_sceneIsLoading && updateWalkpath);
+}
+
+void ScriptBase::Obstacle_Flag_All_Objects(bool isObstacle) {
+	_vm->_scene->objectSetIsObstacleAll(isObstacle, !_vm->_sceneIsLoading);
+}
+
+void ScriptBase::Combat_Target_Object(char *objectName) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return;
+	_vm->_scene->objectSetIsCombatTarget(objectId, true, !_vm->_sceneIsLoading);
+}
+
+void ScriptBase::Un_Combat_Target_Object(char *objectName) {
+	int objectId = _vm->_scene->findObject(objectName);
+	if (objectId == -1)
+		return;
+	_vm->_scene->objectSetIsCombatTarget(objectId, true, !_vm->_sceneIsLoading);
+}
+
+void ScriptBase::Set_Fade_Color(float r, float g, float b) {
+	_vm->_scene->_set->_effects->setFadeColor(r, g, b);
+}
+
+void ScriptBase::Set_Fade_Density(float density) {
+	_vm->_scene->_set->_effects->setFadeDensity(density);
+}
+
+void ScriptBase::Set_Fog_Color(char* fogName, float r, float g, float b) {
+	_vm->_scene->_set->_effects->setFogColor(fogName, r, g, b);
+}
+
+void ScriptBase::Set_Fog_Density(char* fogName, float density) {
+	_vm->_scene->_set->_effects->setFogDensity(fogName, density);
 }
 
-// ScriptBase::Disable_Shadows
-// ScriptBase::Query_System_Currently_Loading_Game
-// ScriptBase::Actor_Retired_Here
-// ScriptBase::Clickable_Object
-// ScriptBase::Unclickable_Object
-// ScriptBase::Obstacle_Object
-// ScriptBase::Unobstacle_Object
-// ScriptBase::Obstacle_Flag_All_Objects
-// ScriptBase::Combat_Target_Object
-// ScriptBase::Un_Combat_Target_Object
-// ScriptBase::Set_Fade_Color
-// ScriptBase::Set_Fade_Density
-// ScriptBase::Set_Fog_Color
-// ScriptBase::Set_Fog_Density
 // ScriptBase::ADQ_Flush
 // ScriptBase::ADQ_Add
 // ScriptBase::ADQ_Add_Pause
-// ScriptBase::Game_Over
-// ScriptBase::Autosave_Game
+
+bool ScriptBase::Game_Over() {
+	_vm->_gameIsRunning = false;
+	_vm->_gameOver = true;
+	return true;
+}
+
+void ScriptBase::Autosave_Game(int textId) {
+	_vm->_gameAutoSave = textId;
+}
 
 void ScriptBase::I_Sez(const char *str) {
 	_vm->ISez(str);
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index e399a64..97db6eb 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -41,66 +41,66 @@ public:
 	{}
 
 protected:
-	// Preload
-	// Actor_Put_In_Set
-	// Actor_Set_At_XYZ
-	// Actor_Set_At_Waypoint
-	// Region_Check
+	void Preload(int animationId);
+	void Actor_Put_In_Set(int actorId, int setId);
+	void Actor_Set_At_XYZ(int actorId, float x, float y, float z, int angle);
+	void Actor_Set_At_Waypoint(int actorId, int waypointId, int angle);
+	bool Region_Check(int left, int top, int right, int down);
 	// Object_Query_Click
 	// Object_Do_Ground_Click
-	// Object_Mark_For_Hot_Mouse
-	// Actor_Face_Actor
-	// Actor_Face_Object
-	// Actor_Face_Item
-	// Actor_Face_Waypoint
-	// Actor_Face_XYZ
-	// Actor_Face_Current_Camera
-	// Actor_Face_Heading
-	// Actor_Query_Friendliness_To_Other
-	// Actor_Modify_Friendliness_To_Other
-	// Actor_Set_Friendliness_To_Other
-	// Actor_Set_Honesty
-	// Actor_Set_Intelligence
-	// Actor_Set_Stability
-	// Actor_Set_Combat_Aggressiveness
-	// Actor_Query_Current_HP
-	// Actor_Query_Max_HP
-	// Actor_Query_Combat_Aggressiveness
-	// Actor_Query_Honesty
-	// Actor_Query_Intelligence
-	// Actor_Query_Stability
-	// Actor_Modify_Current_HP
-	// Actor_Modify_Max_HP
-	// Actor_Modify_Combat_Aggressiveness
-	// Actor_Modify_Honesty
-	// Actor_Modify_Intelligence
-	// Actor_Modify_Stability
-	// Actor_Set_Flag_Damage_Anim_If_Moving
-	// Actor_Query_Flag_Damage_Anim_If_Moving
-	// Actor_Combat_AI_Hit_Attempt
-	// Non_Player_Actor_Combat_Mode_On
-	// Non_Player_Actor_Combat_Mode_Off
-	// Actor_Set_Health
-	// Actor_Set_Targetable
-	// Actor_Says
-	// Actor_Says_With_Pause
+	bool Object_Mark_For_Hot_Mouse(char *objectName);
+	void Actor_Face_Actor(int actorId, int otherActorId, bool animate);
+	void Actor_Face_Object(int actorId, char *objectName, bool animate);
+	void Actor_Face_Item(int actorId, int itemId, bool animate);
+	void Actor_Face_Waypoint(int actorId, int waypointId, bool animate);
+	void Actor_Face_XYZ(int actorId, float x, float y, float z, bool animate);
+	void Actor_Face_Current_Camera(int actorId, bool animate);
+	void Actor_Face_Heading(int actorId, int heading);
+	int Actor_Query_Friendliness_To_Other(int actorId, int otherActorId);
+	void Actor_Modify_Friendliness_To_Other(int actorId, int otherActorId, signed int change);
+	void Actor_Set_Friendliness_To_Other(int actorId, int otherActorId, int friendliness);
+	void Actor_Set_Honesty(int actorId, int honesty);
+	void Actor_Set_Intelligence(int actorId, int intelligence);
+	void Actor_Set_Stability(int actorId, int stability);
+	void Actor_Set_Combat_Aggressiveness(int actorId, int combatAggressiveness);
+	int Actor_Query_Current_HP(int actorId);
+	int Actor_Query_Max_HP(int actorId);
+	int Actor_Query_Combat_Aggressiveness(int actorId);
+	int Actor_Query_Honesty(int actorId);
+	int Actor_Query_Intelligence(int actorId);
+	int Actor_Query_Stability(int actorId);
+	void Actor_Modify_Current_HP(int actorId, signed int change);
+	void Actor_Modify_Max_HP(int actorId, signed int change);
+	void Actor_Modify_Combat_Aggressiveness(int actorId, signed int change);
+	void Actor_Modify_Honesty(int actorId, signed int change);
+	void Actor_Modify_Intelligence(int actorId, signed int change);
+	void Actor_Modify_Stability(int actorId, signed int change);
+	void Actor_Set_Flag_Damage_Anim_If_Moving(int actorId, bool value);
+	bool Actor_Query_Flag_Damage_Anim_If_Moving(int actorId);
+	void Actor_Combat_AI_Hit_Attempt(int actorId);
+	void Non_Player_Actor_Combat_Mode_On(int actorId, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12, int a13, int a14);
+	void Non_Player_Actor_Combat_Mode_Off(int actorId);
+	void Actor_Set_Health(int actor, int hp, int maxHp);
+	void Actor_Set_Targetable(int actor, bool targetable);
+	void Actor_Says(int actorId, int sentenceId, int animationMode);
+	void Actor_Says_With_Pause(int actorId, int sentenceId, float pause, int animationMode);
 	void Actor_Voice_Over(int sentenceId, int actorId);
-	// Actor_Start_Speech_Sample
-	// Actor_Start_Voice_Over_Sample
-	// Actor_Query_Which_Set_In
-	// Actor_Query_Is_In_Current_Set
-	// Actor_Query_In_Set
-	// Actor_Query_Inch_Distance_From_Actor
-	// Actor_Query_Inch_Distance_From_Waypoint
-	// Actor_Query_In_Between_Two_Actors
-	// Actor_Set_Goal_Number
-	// Actor_Query_Goal_Number
-	// Actor_Query_XYZ
-	// Actor_Query_Facing_1024
-	// Actor_Set_Frame_Rate_FPS
-	// Slice_Animation_Query_Number_Of_Frames
-	// Actor_Change_Animation_Mode
-	// Actor_Query_Animation_Mode
+	void Actor_Start_Speech_Sample(int actorId, int sentenceId);
+	void Actor_Start_Voice_Over_Sample(int sentenceId);
+	int Actor_Query_Which_Set_In(int actorId);
+	bool Actor_Query_Is_In_Current_Set(int actorId);
+	bool Actor_Query_In_Set(int actorId, int setId);
+	int Actor_Query_Inch_Distance_From_Actor(int actorId, int otherActorId);
+	int Actor_Query_Inch_Distance_From_Waypoint(int actorId, int waypointId);
+	bool Actor_Query_In_Between_Two_Actors(int actorId, int otherActor1Id, int otherActor2Id);
+	void Actor_Set_Goal_Number(int actorId, int goalNumber);
+	int Actor_Query_Goal_Number(int actorId);
+	void Actor_Query_XYZ(int actorId, float *x, float *y, float *z);
+	int Actor_Query_Facing_1024(int actorId);
+	void Actor_Set_Frame_Rate_FPS(int actorId, int fps);
+	int Slice_Animation_Query_Number_Of_Frames(int animationId);
+	void Actor_Change_Animation_Mode(int actorId, int animationMode);
+	int Actor_Query_Animation_Mode(int actorId);
 	// Loop_Actor_Walk_To_Actor
 	// Loop_Actor_Walk_To_Item
 	// Loop_Actor_Walk_To_Scene_Object
@@ -111,41 +111,41 @@ protected:
 	// Actor_Force_Stop_Walking
 	// Loop_Actor_Travel_Stairs
 	// Loop_Actor_Travel_Ladder
-	void Actor_Clue_Add_To_Database(int a0, int a1, int a2, int a3, int a4, int a5);
-	// Actor_Clue_Acquire
-	// Actor_Clue_Lose
-	// Actor_Clue_Query
-	// Actor_Clues_Transfer_New_To_Mainframe
-	// Actor_Clues_Transfer_New_From_Mainframe
-	// Actor_Set_Invisible
-	// Actor_Set_Immunity_To_Obstacles
+	void Actor_Clue_Add_To_Database(int actorId, int clueId, int unknown, bool clueAcquired, bool unknownFlag, int fromActorId);
+	void Actor_Clue_Acquire(int actorId, int clueId, byte unknownFlag, int fromActorId);
+	void Actor_Clue_Lose(int actorId, int clueId);
+	bool Actor_Clue_Query(int actorId, int clueId);
+	void Actor_Clues_Transfer_New_To_Mainframe(int actorId);
+	void Actor_Clues_Transfer_New_From_Mainframe(int actorId);
+	void Actor_Set_Invisible(int actorId, bool isInvisible);
+	void Actor_Set_Immunity_To_Obstacles(int actorId, bool isImmune);
 	// Item_Add_To_World
 	// Item_Remove_From_World
 	// Item_Spin_In_World
 	// Item_Flag_As_Target
 	// Item_Flag_As_Non_Target
 	// Item_Pickup_Spin_Effect
-	// Animation_Open
-	// Animation_Close
-	// Animation_Start
-	// Animation_Stop
-	// Animation_Skip_To_Frame
-	// Delay
+	int Animation_Open();
+	int Animation_Close();
+	int Animation_Start();
+	int Animation_Stop();
+	int Animation_Skip_To_Frame();
+	void Delay(int miliseconds);
 	void Player_Loses_Control();
 	void Player_Gains_Control();
-	// Player_Set_Combat_Mode
-	// Player_Query_Combat_Mode
-	// Player_Set_Combat_Mode_Access
-	// Player_Query_Current_Set
-	// Player_Query_Current_Scene
-	// Player_Query_Agenda
-	// Player_Set_Agenda
-	// Query_Difficulty_Level
+	void Player_Set_Combat_Mode(bool activate);
+	bool Player_Query_Combat_Mode();
+	void Player_Set_Combat_Mode_Access(bool enable);
+	int Player_Query_Current_Set();
+	int Player_Query_Current_Scene();
+	int Player_Query_Agenda();
+	void Player_Set_Agenda(int agenda);
+	int Query_Difficulty_Level();
 	void Game_Flag_Set(int flag);
 	void Game_Flag_Reset(int flag);
 	bool Game_Flag_Query(int flag);
-	// Set_Enter
-	// Chapter_Enter
+	void Set_Enter(int setId, int sceneId);
+	void Chapter_Enter(int chapter, int setId, int sceneId);
 	int Global_Variable_Set(int, int);
 	int Global_Variable_Reset(int);
 	int Global_Variable_Query(int);
@@ -194,12 +194,12 @@ protected:
 	// Dialogue_Menu_Remove_From_List
 	// Dialogue_Menu_Query_Input
 	// Dialogue_Menu_Query_List_Size
-	void Scene_Exit_Add_2D_Exit(int, int, int, int, int, int);
-	// Scene_Exit_Remove
-	// Scene_Exits_Disable
-	// Scene_Exits_Enable
-	void Scene_2D_Region_Add(int, int, int, int, int);
-	// Scene_2D_Region_Remove
+	void Scene_Exit_Add_2D_Exit(int index, int left, int top, int right, int down, int type);
+	void Scene_Exit_Remove(int index);
+	void Scene_Exits_Disable();
+	void Scene_Exits_Enable();
+	void Scene_2D_Region_Add(int index, int left, int top, int right, int down);
+	void Scene_2D_Region_Remove(int index);
 	// World_Waypoint_Set
 	// World_Waypoint_Reset
 	// World_Waypoint_Query_X
@@ -235,28 +235,28 @@ protected:
 	// View_Score_Board
 	// Query_Score
 	void Set_Score(int a0, int a1);
-	// Give_McCoy_Ammo
-	void Assign_Player_Gun_Hit_Sounds(int a0, int a1, int a2, int a3);
-	void Assign_Player_Gun_Miss_Sounds(int a0, int a1, int a2, int a3);
-	// Disable_Shadows
-	// Query_System_Currently_Loading_Game
-	// Actor_Retired_Here
-	// Clickable_Object
-	// Unclickable_Object
-	// Obstacle_Object
-	// Unobstacle_Object
-	// Obstacle_Flag_All_Objects
-	// Combat_Target_Object
-	// Un_Combat_Target_Object
-	// Set_Fade_Color
-	// Set_Fade_Density
-	// Set_Fog_Color
-	// Set_Fog_Density
+	void Give_McCoy_Ammo(int ammoType, int ammo);
+	void Assign_Player_Gun_Hit_Sounds(int row, int soundId1, int soundId2, int soundId3);
+	void Assign_Player_Gun_Miss_Sounds(int row, int soundId1, int soundId2, int soundId3);
+	void Disable_Shadows(int *animationsIdsList, int listSize);
+	bool Query_System_Currently_Loading_Game();
+	void Actor_Retired_Here(int actorId, int width, int height, int retired, int retiredByActorId);
+	void Clickable_Object(char *objectName);
+	void Unclickable_Object(char *objectName);
+	void Obstacle_Object(char *objectName, bool updateWalkpath);
+	void Unobstacle_Object(char *objectName, bool updateWalkpath);
+	void Obstacle_Flag_All_Objects(bool isObstacle);
+	void Combat_Target_Object(char *objectName);
+	void Un_Combat_Target_Object(char *objectName);
+	void Set_Fade_Color(float r, float g, float b);
+	void Set_Fade_Density(float density);
+	void Set_Fog_Color(char* fogName, float r, float g, float b);
+	void Set_Fog_Density(char* fogName, float density);
 	// ADQ_Flush
 	// ADQ_Add
 	// ADQ_Add_Pause
-	// Game_Over
-	// Autosave_Game
+	bool Game_Over();
+	void Autosave_Game(int textId);
 	void I_Sez(const char *str);
 };
 
@@ -269,6 +269,7 @@ public:
 	virtual void InitializeScene() = 0;
 	virtual void SceneLoaded() = 0;
 	virtual void SceneFrameAdvanced(int frame) = 0;
+	virtual void SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) = 0;
 };
 
 class Script {
@@ -289,6 +290,7 @@ public:
 	void InitializeScene();
 	void SceneLoaded();
 	void SceneFrameAdvanced(int frame);
+	void SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet);
 };
 
 #define DECLARE_SCRIPT(name) \
@@ -300,6 +302,7 @@ public: \
 	void InitializeScene(); \
 	void SceneLoaded(); \
 	void SceneFrameAdvanced(int frame); \
+	void SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet); \
 };
 
 DECLARE_SCRIPT(RC01)


Commit: b67bca20b5db7f3d6473341efd7fabfa6532f465
    https://github.com/scummvm/scummvm/commit/b67bca20b5db7f3d6473341efd7fabfa6532f465
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:40+02:00

Commit Message:
BLADERUNNER: Pull in changes from madmoose

Changed paths:
  A engines/bladerunner/script/ai_00_mccoy.cpp
  A engines/bladerunner/script/ai_00_mccoy.h
  A engines/bladerunner/script/aiscript_officer_leroy.cpp
  A engines/bladerunner/script/aiscript_officer_leroy.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/actor_clues.cpp
    engines/bladerunner/actor_clues.h
    engines/bladerunner/actor_combat.cpp
    engines/bladerunner/actor_combat.h
    engines/bladerunner/actor_walk.cpp
    engines/bladerunner/actor_walk.h
    engines/bladerunner/archive.cpp
    engines/bladerunner/audio_player.cpp
    engines/bladerunner/audio_speech.cpp
    engines/bladerunner/audio_speech.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/boundingbox.cpp
    engines/bladerunner/boundingbox.h
    engines/bladerunner/clues.cpp
    engines/bladerunner/clues.h
    engines/bladerunner/color.h
    engines/bladerunner/combat.cpp
    engines/bladerunner/combat.h
    engines/bladerunner/detection_tables.h
    engines/bladerunner/fog.cpp
    engines/bladerunner/fog.h
    engines/bladerunner/gameflags.cpp
    engines/bladerunner/image.cpp
    engines/bladerunner/image.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/items.cpp
    engines/bladerunner/items.h
    engines/bladerunner/light.cpp
    engines/bladerunner/light.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/matrix.cpp
    engines/bladerunner/matrix.h
    engines/bladerunner/module.mk
    engines/bladerunner/mouse.cpp
    engines/bladerunner/mouse.h
    engines/bladerunner/movement_track.cpp
    engines/bladerunner/movement_track.h
    engines/bladerunner/outtake.cpp
    engines/bladerunner/regions.cpp
    engines/bladerunner/regions.h
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/set.cpp
    engines/bladerunner/set.h
    engines/bladerunner/set_effects.cpp
    engines/bladerunner/set_effects.h
    engines/bladerunner/settings.cpp
    engines/bladerunner/settings.h
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/text_resource.cpp
    engines/bladerunner/view.cpp
    engines/bladerunner/view.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h
    engines/bladerunner/waypoints.cpp
    engines/bladerunner/waypoints.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index d16ee84..b4bdd68 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -24,15 +24,22 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/actor_clues.h"
+#include "bladerunner/actor_combat.h"
+#include "bladerunner/actor_walk.h"
+#include "bladerunner/audio_speech.h"
 #include "bladerunner/boundingbox.h"
 #include "bladerunner/gameinfo.h"
-#include "bladerunner/slice_renderer.h"
-#include "bladerunner/waypoints.h"
-#include "bladerunner/scene.h"
 #include "bladerunner/items.h"
+#include "bladerunner/movement_track.h"
+#include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/slice_animations.h"
-#include "bladerunner/audio_speech.h"
+#include "bladerunner/slice_renderer.h"
+#include "bladerunner/waypoints.h"
+
+#include "common/system.h"
 
 namespace BladeRunner {
 
@@ -50,24 +57,22 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
 }
 
 Actor::~Actor() {
-	
 	delete[] _friendlinessToOther;
 	delete   _combatInfo;
 	delete   _bbox;
 	delete   _clues;
 	delete   _movementTrack;
 	delete   _walkInfo;
-	
 }
 
 void Actor::setup(int actorId) {
 	_id  = actorId;
 	_setId = -1;
 
-	_position     = Vector3(0.0, 0.0, 0.0);
-	_facing       = 512;
+	_position  = Vector3(0.0, 0.0, 0.0);
+	_facing    = 512;
 	_targetFacing = -1;
-	_walkboxId    = -1;
+	_walkboxId = -1;
 
 	_animationId = 0;
 	_animationFrame = 0;
@@ -77,7 +82,7 @@ void Actor::setup(int actorId) {
 	_isTargetable        = false;
 	_isInvisible         = false;
 	_isImmuneToObstacles = false;
-	
+
 	_isRetired           = false;
 
 	_width         = 0;
@@ -87,7 +92,7 @@ void Actor::setup(int actorId) {
 
 	for (int i = 0; i != 7; ++i) {
 		_timersRemain[i] = 0;
-		_timersBegan[i]  = _vm->getTotalPlayTime();
+		_timersStart[i]  = _vm->getTotalPlayTime();
 	}
 
 	_scale = 1.0;
@@ -104,6 +109,7 @@ void Actor::setup(int actorId) {
 	_timersRemain[4] = 60000;
 	_animationMode = -1;
 	_screenRectangle = Common::Rect(-1, -1, -1, -1);
+
 	_combatAnimationMode = 4;
 	_unknown1 = 7;
 	_unknown2 = 8;
@@ -119,17 +125,52 @@ void Actor::setup(int actorId) {
 	_actorSpeed = Vector3();
 }
 
-void Actor::set_at_xyz(Vector3 position, int facing, bool halfOrSet, int moving, bool retired) {
-	_position = position;
-	setFacing(facing, halfOrSet);
-	
-	if(_vm->_scene->_setId == _setId) {
-		_walkboxId = _vm->_scene->_set->findWalkbox(position.x, position.y);
-	}else {
+void Actor::changeAnimationMode(int animationMode, bool force)
+{
+	if (force)
+		_animationMode = -1;
+
+	if (animationMode != _animationMode) {
+		_vm->_aiScripts->ChangeAnimationMode(_id, animationMode);
+		_animationMode = animationMode;
+	}
+}
+
+void Actor::setFPS(int fps)
+{
+	_fps = fps;
+
+	if (fps == 0)
+	{
+		_frame_ms = 0;
+	}
+	else if (fps == -1)
+	{
+		_frame_ms = -1000;
+	}
+	else if (fps == -2)
+	{
+		_fps = _vm->_sliceAnimations->getFPS(_animationId);
+		_frame_ms = 1000 / _fps;
+	}
+	else
+	{
+		_frame_ms = 1000 / fps;
+	}
+}
+
+void Actor::setAtXYZ(Vector3 pos, int facing, bool snapFacing, bool moving, bool retired)
+{
+	_position = pos;
+	setFacing(facing, snapFacing);
+
+	if (_vm->_scene->_setId == _setId) {
+		_walkboxId = _vm->_scene->_set->findWalkbox(_position.x, _position.y);
+	} else {
 		_walkboxId = -1;
 	}
 
-	setBoundingBox(position, retired);
+	setBoundingBox(_position, retired);
 
 	_vm->_sceneObjects->remove(_id);
 
@@ -138,26 +179,152 @@ void Actor::set_at_xyz(Vector3 position, int facing, bool halfOrSet, int moving,
 	}
 }
 
-
-void Actor::set_at_waypoint(int waypointId, int angle, int unknown, bool retired) {
+void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired)
+{
 	Vector3 waypointPosition;
-	_vm->_waypoints->getXyz(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
-	set_at_xyz(waypointPosition, angle, true, unknown, retired);
+	_vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
+	setAtXYZ(waypointPosition, angle, true, moving, retired);
+}
+
+void Actor::loopWalkToXYZ(Vector3 destination)
+{
+	int unk1;
+	_walkInfo->setup(_id, false, _position, destination, 0, &unk1);
+
+	for (;;)
+	{
+		_vm->gameTick();
+		if (!_walkInfo->isWalking() && !_walkInfo->isRunning())
+			break;
+		if (!_vm->_gameIsRunning)
+			break;
+	}
+}
+
+float distance(float, float, float, float);
+float distance(Vector3 &v1, Vector3 &v2);
+
+void Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset)
+{
+	int sceneObject = _vm->_scene->_set->findObject(objectName);
+	if (sceneObject < 0)
+		return;
+
+	BoundingBox bbox;
+	if (!_vm->_scene->_set->objectGetBoundingBox(sceneObject, &bbox))
+		return;
+
+	float x0, y0, z0, x1, y1, z1;
+	bbox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
+
+	// debug("[%f %f] -> [%f %f %f, %f %f %f]", _position.x, _position.z, x0, y0, z0, x1, y1, z1);
+
+	float closest_distance = distance(_position.x, _position.z, x0, z0);
+	float closest_x = x0;
+	float closest_z = z0;
+
+	float d = distance(_position.x, _position.z, x1, z0);
+	// debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0);
+	if (d < closest_distance) {
+		closest_x = x1;
+		closest_z = z0;
+		closest_distance = d;
+	}
+
+	d = distance(_position.x, _position.z, x1, z1);
+	// debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0);
+	if (d < closest_distance) {
+		closest_x = x1;
+		closest_z = z1;
+		closest_distance = d;
+	}
+
+	d = distance(_position.x, _position.z, x0, z1);
+	// debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0);
+	if (d < closest_distance) {
+		closest_x = x0;
+		closest_z = z1;
+		closest_distance = d;
+	}
+
+	// debug("%f = %f %f %f %f", closest_distance, _position.x, _position.z, closest_x, closest_z);
+
+	Vector3 destination(closest_x, _position.y, closest_z);
+
+	// Vector3 properDestination(-124.2592, -0.3046913, 204.0923);
+	// debug("delta: %f\n", distance(destination, properDestination));
+
+	loopWalkToXYZ(destination);
+}
+
+bool Actor::tick(bool forceDraw)
+{
+	int remain = 0;
+	bool needsUpdate = false;
+	if (_fps > 0)
+	{
+		countdownTimerUpdate(5);
+		remain = countdownTimerGetRemainingTime(5);
+		needsUpdate = remain <= 0;
+	}
+	else if (forceDraw)
+	{
+		needsUpdate = true;
+		remain = 0;
+	}
+
+	if (needsUpdate)
+	{
+		int newAnimation = 0, newFrame = 0;
+		_vm->_aiScripts->UpdateAnimation(_id, &newAnimation, &newFrame);
+
+		if (_animationId != newAnimation) {
+			_animationId = newAnimation;
+			setFPS(-2);
+		}
+		_animationFrame = newFrame;
+
+		if (isWalking())
+		{
+			float stepDistance = 3.0;
+			if (stepDistance <= 0.0) {
+				stepDistance = 4.0;
+			}
+			if (_walkInfo->tick(_id, stepDistance, false)) {
+				_vm->_actors[_id]->changeAnimationMode(0);
+			}
+
+			Vector3 pos; int facing;
+			_walkInfo->getCurrentPosition(_id, &pos, &facing);
+
+			setAtXYZ(pos, facing);
+		}
+	}
+
+	draw();
+
+	if (needsUpdate)
+	{
+		int nextFrameTime = remain + _frame_ms;
+		if (nextFrameTime <= 0)
+			nextFrameTime = 1;
+		countdownTimerStart(5, nextFrameTime);
+	}
+
+	return false;
 }
 
 void Actor::draw() {
 	Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0);
-	float   draw_facing = _facing * M_PI / 512.0;
-	// just for viewing animations _facing = (_facing + 10) % 1024;
+	float   draw_facing = M_PI - _facing * M_PI / 512.0;
 	// float   draw_scale  = _scale;
 
 	// TODO: Handle SHORTY mode
 
-	_vm->_sliceRenderer->setupFrame(19, 1, draw_position, M_PI - draw_facing);
+	_vm->_sliceRenderer->setupFrame(_animationId, _animationFrame, draw_position, draw_facing);
 	_vm->_sliceRenderer->drawFrame(_vm->_surface2, _vm->_zBuffer2);
 }
 
-
 int Actor::getSetId() {
 	return _setId;
 }
@@ -172,16 +339,16 @@ void Actor::setSetId(int setId) {
 	if(_setId > 0) {
 		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
-				//actorScript->OtherAgentExitedThisScene( i, _id);
+				// TODO: actorScript->OtherAgentExitedThisScene( i, _id);
 			}
 		}
 	}
 	_setId = setId;
-	//actorScript->EnteredScene(_id, set);
+	// TODO: actorScript->EnteredScene(_id, set);
 	if (_setId > 0) {
 		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
-				//actorScript->OtherAgentEnteredThisScene(i, _id);
+				// TODO: actorScript->OtherAgentEnteredThisScene(i, _id);
 			}
 		}
 	}
@@ -221,41 +388,27 @@ void Actor::setFacing(int facing, bool halfOrSet) {
 			offset = -ccw / 2;
 		}
 	}
+
 	_facing = (_facing + offset) % 1024;
 }
 
 void Actor::setBoundingBox(Vector3 position, bool retired) {
 	if (retired) {
-		_bbox->setXyz(position.x - (_retiredWidth / 2.0f), position.y, position.z - (_retiredWidth / 2.0f), position.x + (_retiredWidth / 2.0f), position.y + _retiredHeight, position.z + (_retiredWidth / 2.0f));
-	} else {
-		_bbox->setXyz(position.x - 12.0f, position.y + 6.0f, position.z - 12.0f, position.x + 12.0f, position.y + 72.0f, position.z + 12.0f);
-	}
-}
-
-
-void Actor::changeAnimationMode(int animationMode, bool force) {
-	if (force == 1) {
-		_animationMode = -1;
-	}
-	if(animationMode != _animationMode) {
-		//TODO: _vm->actorScript->ChangeAnimationMode(_id, animationMode);
-		_animationMode = animationMode;
-	}
-}
+		_bbox->setXYZ(position.x - (_retiredWidth / 2.0f),
+		              position.y,
+		              position.z - (_retiredWidth / 2.0f),
 
-void Actor::setFps(int fps) {
-	_fps = fps;
-	if (fps == 0) {
-		_frame_ms = 0;
+		              position.x + (_retiredWidth / 2.0f),
+		              position.y + _retiredHeight,
+		              position.z + (_retiredWidth / 2.0f));
 	} else {
-		if(_fps == -1) {
-			_frame_ms = -1000;
-		} else if (_fps == -2) {
-			_fps = _vm->_sliceAnimations->getFps(_animationId);
-			_frame_ms = 1000 / _fps;
-		} else {
-			_frame_ms = 1000 / _fps;
-		}
+		_bbox->setXYZ(position.x - 12.0f,
+		              position.y + 6.0f,
+		              position.z - 12.0f,
+
+		              position.x + 12.0f,
+		              position.y + 72.0f,
+		              position.z + 12.0f);
 	}
 }
 
@@ -268,9 +421,9 @@ void Actor::stopWalking(bool value) {
 		_vm->_playerActorIdle = true;
 	}
 
-	if(isWalking()) {
+	if (isWalking()) {
 		_walkInfo->stop(_id, 1, _combatAnimationMode, 0);
-	} else if(inCombat()) {
+	} else if (inCombat()) {
 		changeAnimationMode(_combatAnimationMode, 0);
 	} else {
 		changeAnimationMode(0, 0);
@@ -281,7 +434,7 @@ void Actor::faceActor(int otherActorId, bool animate) {
 	if (_setId != _vm->_scene->_setId) {
 		return;
 	}
-	
+
 	Actor *otherActor = _vm->_actors[otherActorId];
 
 	if (_setId != otherActor->_setId) {
@@ -291,7 +444,7 @@ void Actor::faceActor(int otherActorId, bool animate) {
 	faceXYZ(otherActor->_position.x, otherActor->_position.y, otherActor->_position.z, animate);
 }
 
-void Actor::faceObject(char *objectName, bool animate) {
+void Actor::faceObject(const char *objectName, bool animate) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1) {
 		return;
@@ -301,7 +454,7 @@ void Actor::faceObject(char *objectName, bool animate) {
 	_vm->_scene->objectGetBoundingBox(objectId, &boundingBox);
 
 	float x0, y0, z0, x1, y1, z1;
-	boundingBox.getXyz(&x0, &y0, &z0, &x1, &y1, &z1);
+	boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
 
 	float x = (x1 + x0) / 2.0f;
 	float z = (z1 + z0) / 2.0f;
@@ -310,13 +463,13 @@ void Actor::faceObject(char *objectName, bool animate) {
 
 void Actor::faceItem(int itemId, bool animate) {
 	float x, y, z;
-	_vm->_items->getXyz(itemId, &x, &y, &z);
+	_vm->_items->getXYZ(itemId, &x, &y, &z);
 	faceXYZ(x, y, z, animate);
 }
 
 void Actor::faceWaypoint(int waypointId, bool animate) {
 	float x, y, z;
-	_vm->_waypoints->getXyz(waypointId, &x, &y, &z);
+	_vm->_waypoints->getXYZ(waypointId, &x, &y, &z);
 	faceXYZ(x, y, z, animate);
 }
 
@@ -413,15 +566,15 @@ bool Actor::getFlagDamageAnimIfMoving() {
 	return _damageAnimIfMoving;
 }
 
-void Actor::retire(bool isRetired, int width, int height, int retiredByActorId) {
-	_isRetired = isRetired;
+void Actor::retire(bool retired, int width, int height, int retiredByActorId) {
+	_isRetired = retired;
 	_retiredWidth = MAX(width, 0);
 	_retiredHeight = MAX(height, 0);
-	if (_id == 0 && isRetired) {
+	if (_id == 0 && _isRetired) {
 		_vm->playerLosesControl();
 		_vm->_playerDead = true;
 	}
-	if (isRetired) {
+	if (_isRetired) {
 		//TODO: _vm->actorScript->Retired(_id, retiredByActorId);
 	}
 }
@@ -433,7 +586,7 @@ void Actor::setTargetable(bool targetable) {
 void Actor::setHealth(int hp, int maxHp) {
 	_currentHP = hp;
 	_maxHP = maxHp;
-	if(hp > 0) {
+	if (hp > 0) {
 		retire(0, 0, 0, -1);
 	}
 }
@@ -519,11 +672,11 @@ void Actor::speechPlay(int sentenceId, bool voiceOver) {
 	sprintf(name, "%02d-%04d.AUD", _id, sentenceId); //TODO somewhere here should be also language code
 	int balance;
 
-	if(voiceOver || _id == 99) {
+	if (voiceOver || _id == 99) {
 		balance = 0;
-	}else {
-		Vector3 pos = _vm->_view->_frameViewMatrix * _position;
-		int screenX = 0, screenY = 0;
+	} else {
+		// Vector3 pos = _vm->_view->_frameViewMatrix * _position;
+		int screenX = 320; //, screenY = 0;
 		//TODO: transform to screen space using fov;
 		balance = 127 * (2 * screenX - 640) / 640;
 		balance = MIN(127, MAX(-127, balance));
@@ -560,7 +713,7 @@ void Actor::copyClues(int actorId) {
 	Actor *otherActor = _vm->_actors[actorId];
 	int i;
 	for (i = 0; i < (int)_vm->_gameInfo->getClueCount(); i++) {
-		if(hasClue(i) && !_clues->isFlag4(i) && !otherActor->hasClue(i)) {
+		if (hasClue(i) && !_clues->isFlag4(i) && !otherActor->hasClue(i)) {
 			int fromActorId = _id;
 			if (_id == 99)
 				fromActorId = _clues->getFromActorId(i);
@@ -569,4 +722,58 @@ void Actor::copyClues(int actorId) {
 	}
 }
 
+void Actor::countdownTimerStart(int timerId, int interval)
+{
+	assert(timerId >= 0 && timerId < 7);
+	_timersRemain[timerId] = interval;
+	_timersStart[timerId] = _vm->getTotalPlayTime();
+}
+
+void Actor::countdownTimerReset(int timerId)
+{
+	assert(timerId >= 0 && timerId < 7);
+	_timersRemain[timerId] = 0;
+}
+
+int Actor::countdownTimerGetRemainingTime(int timerId)
+{
+	assert(timerId >= 0 && timerId < 7);
+	return _timersRemain[timerId];
+}
+
+void Actor::countdownTimerUpdate(int timerId)
+{
+	if (_timersRemain[timerId] == 0)
+		return;
+
+	uint32 now = _vm->getTotalPlayTime();
+	int tickInterval = now - _timersStart[timerId];
+	_timersStart[timerId] = now;
+
+	// warning("tickInterval: %d", tickInterval);
+	_timersRemain[timerId] -= tickInterval;
+
+	if (_timersRemain[timerId] <= 0) {
+		switch (timerId) {
+		case 0:
+		case 1:
+		case 2:
+			// AI timers, call AI dll
+			break;
+		case 3:
+			// Movement track timer
+			break;
+		case 4:
+			// Something timer
+			break;
+		case 5:
+			// Actor animation frame timer
+			break;
+		case 6:
+			// Slow down actor run timer?
+			break;
+		}
+	}
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 4d383f0..34d8a5a 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -23,24 +23,24 @@
 #ifndef BLADERUNNER_ACTOR_H
 #define BLADERUNNER_ACTOR_H
 
-#include "bladerunner/bladerunner.h"
-
 #include "bladerunner/vector.h"
-#include "bladerunner/movement_track.h"
-#include "bladerunner/actor_clues.h"
-#include "bladerunner/actor_walk.h"
-#include "bladerunner/actor_combat.h"
 
 #include "common/rect.h"
 
 namespace BladeRunner {
 
+class ActorClues;
+class ActorCombat;
+class ActorWalk;
 class BladeRunnerEngine;
 class BoundingBox;
+class MovementTrack;
 
 class Actor {
-	BladeRunnerEngine *_vm;
 	friend class ScriptBase;
+
+	BladeRunnerEngine *_vm;
+
 private:
 	BoundingBox   *_bbox;
 	Common::Rect   _screenRectangle;
@@ -58,7 +58,7 @@ private:
 	int _currentHP;
 	int _maxHP;
 
-	ActorClues* _clues;
+	ActorClues *_clues;
 
 	int     _id;
 	int     _setId;
@@ -77,7 +77,7 @@ private:
 	bool _damageAnimIfMoving;
 
 	// Animation
-	int _width;	
+	int _width;
 	int _height;
 	int _animationMode;
 	int _combatAnimationMode;
@@ -89,15 +89,13 @@ private:
 	int _retiredWidth;
 	int _retiredHeight;
 
-
 	int _timersRemain[7];
-	int _timersBegan[7];
+	int _timersStart[7];
 
 	float _scale;
 
 	int _unknown1;
 	int _unknown2;
-	int _unknown3;
 
 	Vector3 _actorSpeed;
 
@@ -107,8 +105,8 @@ public:
 
 	void setup(int actorId);
 
-	void set_at_xyz(Vector3 pos, int facing, bool halfOrSet, int unknown, bool retired);
-	void set_at_waypoint(int waypointId, int angle, int unknown, bool retired);
+	void setAtXYZ(Vector3 pos, int facing, bool setFacing = true, bool moving = false, bool retired = false);
+	void setAtWaypoint(int waypointId, int angle, int unknown, bool retired);
 
 	float getX();
 	float getY();
@@ -117,8 +115,22 @@ public:
 	int getFacing();
 	int getAnimationMode();
 
+	Vector3 getPosition() { return _position; }
+
+	void changeAnimationMode(int animationMode, bool force = false);
+	void setFPS(int fps);
+
+	void loopWalkToXYZ(Vector3 destination);
+	void loopWalkToSceneObject(const char *objectName, int destinationOffset = 0);
+
+	bool tick(bool forceUpdate);
 	void draw();
 
+	void countdownTimerStart(int timerId, int interval);
+	void countdownTimerReset(int timerId);
+	int  countdownTimerGetRemainingTime(int timerId);
+	void countdownTimerUpdate(int timerId);
+
 	int getSetId();
 	void setSetId(int setId);
 	BoundingBox* getBoundingBox() { return _bbox; }
@@ -131,12 +143,9 @@ public:
 	void setMoving(bool value) { _isMoving = value; }
 	bool isWalking();
 	void stopWalking(bool value);
-	
-	void changeAnimationMode(int animationMode, bool force);
-	void setFps(int fps);
 
 	void faceActor(int otherActorId, bool animate);
-	void faceObject(char *objectName, bool animate);
+	void faceObject(const char *objectName, bool animate);
 	void faceItem(int itemId, bool animate);
 	void faceWaypoint(int waypointId, bool animate);
 	void faceXYZ(float x, float y, float z, bool animate);
@@ -180,9 +189,8 @@ public:
 	bool hasClue(int clueId);
 	void copyClues(int actorId);
 private:
-	void setFacing(int facing, bool halfOrSet);
+	void setFacing(int facing, bool halfOrSet = true);
 	void setBoundingBox(Vector3 position, bool retired);
-
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
index c8bc04c..2f02ddf 100644
--- a/engines/bladerunner/actor_clues.cpp
+++ b/engines/bladerunner/actor_clues.cpp
@@ -1,181 +1,192 @@
 #include "bladerunner/actor_clues.h"
 
-namespace BladeRunner
-{
+#include "bladerunner/clues.h"
 
-	ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType)
-	{
-		_vm = vm;
-		_count = 0;
-		_maxCount = 0;
-		_clues = 0;
-		switch (cluesType)
-		{
-		case 4:
-			_maxCount = _vm->_gameInfo->getClueCount();
-			break;
-		case 3:
-			_maxCount = 100;
-			break;
-		case 2:
-			_maxCount = 50;
-			break;
-		case 1:
-			_maxCount = 25;
-			break;
-		case 0:
-			_maxCount = 0;
-			break;
-		default:
-			return;
-		}
+#include "common/debug.h"
 
-		if (_maxCount > 0)
-			_clues = new ActorClue[_maxCount];
-		else
-			_clues = NULL;
+namespace BladeRunner {
 
-		if (_clues)
-			removeAll();
-		else
-			_maxCount = NULL;
+ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType)
+{
+	_vm = vm;
+	_count = 0;
+	_maxCount = 0;
+	_clues = 0;
+	switch (cluesType)
+	{
+	case 4:
+		_maxCount = _vm->_gameInfo->getClueCount();
+		break;
+	case 3:
+		_maxCount = 100;
+		break;
+	case 2:
+		_maxCount = 50;
+		break;
+	case 1:
+		_maxCount = 25;
+		break;
+	case 0:
+		_maxCount = 0;
+		break;
+	default:
+		return;
 	}
 
-	ActorClues::~ActorClues()
-	{
-		if (_clues)
-			delete[] _clues;
+	if (_maxCount > 0)
+		_clues = new ActorClue[_maxCount];
+	else
+		_clues = NULL;
 
+	if (_clues)
+		removeAll();
+	else
 		_maxCount = 0;
-		_count = 0;
-	}
+}
 
-	void ActorClues::acquire(int clueId, char flag2, int fromActorId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		_clues[clueIndex]._flags |= 0x01;
-		_clues[_count]._flags = _clues[_count]._flags & 0xFD | ((flag2 << 1) & 0x02);
-		_clues[clueIndex]._fromActorId = fromActorId;
-	}
+ActorClues::~ActorClues()
+{
+	if (_clues)
+		delete[] _clues;
 
-	void ActorClues::lose(int clueId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		_clues[clueIndex]._flags = 0;
-	}
+	_maxCount = 0;
+	_count = 0;
+}
 
-	bool ActorClues::isAcquired(int clueId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		if (clueIndex == -1)
-			return 0;
+void ActorClues::acquire(int clueId, char flag2, int fromActorId)
+{
+	int clueIndex = findClueIndex(clueId);
+	_clues[clueIndex]._flags |= 0x01;
+	_clues[_count]._flags = (_clues[_count]._flags & ~0x02) | ((flag2 << 1) & 0x02);
+	_clues[clueIndex]._fromActorId = fromActorId;
 
-		return _clues[clueIndex]._flags & 0x01;
-	}
+	debug("Actor acquired clue: \"%s\" from %d", _vm->_clues->getClueText(clueId), fromActorId);
+}
 
-	int ActorClues::getFromActorId(int clueId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		if (clueIndex == -1)
-			return  -1;
+void ActorClues::lose(int clueId)
+{
+	int clueIndex = findClueIndex(clueId);
+	_clues[clueIndex]._flags = 0;
+}
 
-		return _clues[clueIndex]._fromActorId;
-	}
+bool ActorClues::isAcquired(int clueId)
+{
+	int clueIndex = findClueIndex(clueId);
+	if (clueIndex == -1)
+		return 0;
 
-	bool ActorClues::isFlag2(int clueId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		if (clueIndex == -1)
-			return 0;
+	return _clues[clueIndex]._flags & 0x01;
+}
 
-		return (_clues[clueIndex]._flags & 0x02) >> 1;
-	}
+int ActorClues::getFromActorId(int clueId)
+{
+	int clueIndex = findClueIndex(clueId);
+	if (clueIndex == -1)
+		return  -1;
 
-	bool ActorClues::isFlag3(int clueId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		if (clueIndex == -1)
-			return 0;
+	return _clues[clueIndex]._fromActorId;
+}
 
-		return (_clues[clueIndex]._flags & 0x04) >> 2;
-	}
+bool ActorClues::isFlag2(int clueId)
+{
+	int clueIndex = findClueIndex(clueId);
+	if (clueIndex == -1)
+		return 0;
 
-	bool ActorClues::isFlag4(int clueId)
-	{
-		int clueIndex = findClueIndex(clueId);
-		if (clueIndex == -1)
-			return 0;
+	return (_clues[clueIndex]._flags & 0x02) >> 1;
+}
 
-		return (_clues[clueIndex]._flags & 0x08) >> 3;
-	}
+bool ActorClues::isFlag3(int clueId)
+{
+	int clueIndex = findClueIndex(clueId);
+	if (clueIndex == -1)
+		return 0;
 
-	int ActorClues::getField1(int clueId)
-	{
-		if (!_count)
-			return 0;
+	return (_clues[clueIndex]._flags & 0x04) >> 2;
+}
 
-		int clueIndex = findClueIndex(clueId);
-		if (clueIndex == -1)
-			return 0;
+bool ActorClues::isFlag4(int clueId)
+{
+	int clueIndex = findClueIndex(clueId);
+	if (clueIndex == -1)
+		return 0;
 
-		return _clues[clueIndex]._field1;
-	}
+	return (_clues[clueIndex]._flags & 0x08) >> 3;
+}
 
-	int ActorClues::getCount()
-	{
-		return _count;
-	}
+int ActorClues::getField1(int clueId)
+{
+	if (!_count)
+		return 0;
 
-	void ActorClues::removeAll()
-	{
-		_count = 0;
-		for (int i = 0; i < _maxCount; ++i) {
-			remove(i);
-		}
+	int clueIndex = findClueIndex(clueId);
+	if (clueIndex == -1)
+		return 0;
+
+	return _clues[clueIndex]._field1;
+}
+
+int ActorClues::getCount()
+{
+	return _count;
+}
+
+void ActorClues::removeAll()
+{
+	_count = 0;
+	for (int i = 0; i < _maxCount; ++i) {
+		remove(i);
 	}
+}
 
-	int ActorClues::findClueIndex(int clueId)
-	{
-		for (int i = 0; i < _count; i++) {
-			if (clueId == _clues[i]._clueId) {
-				return i;
-			}
+int ActorClues::findClueIndex(int clueId)
+{
+	for (int i = 0; i < _count; i++) {
+		if (clueId == _clues[i]._clueId) {
+			return i;
 		}
-		return -1;
 	}
+	return -1;
+}
 
-	void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId)
-	{
-		_clues[_count]._clueId = clueId;
-		_clues[_count]._field1 = unknown;
+void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId)
+{
+	assert(_count < _maxCount);
 
-		_clues[_count]._flags = 0;
-		_clues[_count]._flags = _clues[_count]._flags & 0xFE | (acquired & 0x01);
-		_clues[_count]._flags = _clues[_count]._flags & 0xFD | ((unknownFlag << 1) & 0x02);
+	debug("Actor %d added clue: \"%s\" from %d", actorId, _vm->_clues->getClueText(clueId), fromActorId);
 
-		_clues[_count]._fromActorId = fromActorId;
-		++_count;
-	}
+	_clues[_count]._clueId = clueId;
+	_clues[_count]._field1 = unknown;
 
-	void ActorClues::remove(int index)
-	{
-		_clues[index]._clueId = -1;
-		_clues[index]._field1 = 0;
-		_clues[index]._flags = 0;
-		_clues[index]._fromActorId = -1;
-
-		_clues[index]._field3 = -1;
-		_clues[index]._field4 = 0;
-		_clues[index]._field5 = -1;
-		_clues[index]._field6 = 0;
-		_clues[index]._field7 = -1;
-		_clues[index]._field8 = 0;
-	}
+	_clues[_count]._flags = 0;
+	_clues[_count]._flags = (_clues[_count]._flags & ~0x01) | (acquired & 0x01);
+	_clues[_count]._flags = (_clues[_count]._flags & ~0x02) | ((unknownFlag << 1) & 0x02);
 
-	bool ActorClues::exists(int clueId)
-	{
-		return findClueIndex(clueId) != -1;
-	}
+	_clues[_count]._fromActorId = fromActorId;
+	++_count;
+}
 
+void ActorClues::remove(int index)
+{
+	if (_vm->_clues)
+		debug("Actor removed clue: \"%s\"", _vm->_clues->getClueText(_clues[index]._clueId));
+
+	_clues[index]._clueId = -1;
+	_clues[index]._field1 = 0;
+	_clues[index]._flags = 0;
+	_clues[index]._fromActorId = -1;
+
+	_clues[index]._field3 = -1;
+	_clues[index]._field4 = 0;
+	_clues[index]._field5 = -1;
+	_clues[index]._field6 = 0;
+	_clues[index]._field7 = -1;
+	_clues[index]._field8 = 0;
+}
+
+bool ActorClues::exists(int clueId)
+{
+	return findClueIndex(clueId) != -1;
+}
 
-}
\ No newline at end of file
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h
index 0f08254..06ac815 100644
--- a/engines/bladerunner/actor_clues.h
+++ b/engines/bladerunner/actor_clues.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_ACTOR_CLUES_H
 #define BLADERUNNER_ACTOR_CLUES_H
@@ -29,55 +29,56 @@
 
 namespace BladeRunner {
 
-	struct ActorClue
-	{
-		int _clueId;
-		int _field1;
-		int _fromActorId;
-		int _field3;
-		int _field4;
-		int _field5;
-		int _field6;
-		int _field7;
-		int _field8;
-		unsigned char _flags;
-	};
+struct ActorClue
+{
+	int _clueId;
+	int _field1;
+	int _fromActorId;
+	int _field3;
+	int _field4;
+	int _field5;
+	int _field6;
+	int _field7;
+	int _field8;
+	unsigned char _flags;
+};
 
-	class ActorClues
-	{
-		BladeRunnerEngine *_vm;
+class ActorClues
+{
+	BladeRunnerEngine *_vm;
 
-	private:
-		int _count;
-		int _maxCount;
-		ActorClue *_clues;
+private:
+	int _count;
+	int _maxCount;
+	ActorClue *_clues;
 
-	public:
-		ActorClues(BladeRunnerEngine *_vm, int cluesType);
-		~ActorClues();
+public:
+	ActorClues(BladeRunnerEngine *_vm, int cluesType);
+	~ActorClues();
 
-		void add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId);
-		void acquire(int clueId, char flag2, int fromActorId);
-		void lose(int clueId);
-		bool isAcquired(int clueId);
-		int getFromActorId(int clueId);
-		bool isFlag2(int clueId);
-		bool isFlag3(int clueId);
-		bool isFlag4(int clueId);
-		int getField1(int clueId);
+	void add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId);
+	void acquire(int clueId, char flag2, int fromActorId);
+	void lose(int clueId);
+	bool isAcquired(int clueId);
+	int getFromActorId(int clueId);
+	bool isFlag2(int clueId);
+	bool isFlag3(int clueId);
+	bool isFlag4(int clueId);
+	int getField1(int clueId);
 
-		int getCount();
+	int getCount();
 
-		void removeAll();
+	void removeAll();
 
-		//savegame
-		//loadgame
-	private:
-		bool exists(int clueId);
-		int findClueIndex(int clueId);
-		void remove(int clueIndex);
-		
-	};
-}
+	//savegame
+	//loadgame
+
+private:
+	bool exists(int clueId);
+	int findClueIndex(int clueId);
+	void remove(int clueIndex);
+};
+
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp
index f595b01..aac9086 100644
--- a/engines/bladerunner/actor_combat.cpp
+++ b/engines/bladerunner/actor_combat.cpp
@@ -9,18 +9,16 @@ ActorCombat::ActorCombat(BladeRunnerEngine* vm) {
 ActorCombat::~ActorCombat() {
 }
 
-
 void ActorCombat::hitAttempt() {
 }
 
-
 void ActorCombat::combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int ammoDamage, int a11, int a12) {
 }
 
 void ActorCombat::combatOff() {
 }
 
-
 void ActorCombat::setup() {
 }
-}
\ No newline at end of file
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h
index 0f6ccc9..37fc577 100644
--- a/engines/bladerunner/actor_combat.h
+++ b/engines/bladerunner/actor_combat.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_ACTOR_COMBAT_H
 #define BLADERUNNER_ACTOR_COMBAT_H
@@ -28,45 +28,46 @@
 #include "bladerunner/vector.h"
 
 namespace BladeRunner {
-	
-	class ActorCombat
-	{
-		BladeRunnerEngine *_vm;
-	private:
-		int _actorId;
-		int _combatOn;
-		int _field2;
-		int _field3;
-		int _otherActorId;
-		int _field5;
-		int _field6;
-		int _field7;
-		int _field8;
-		int _field9;
-		int _field10;
-		int _field11;
-		int _field12;
-		int _actorHp;
-		int _field14;
-		int _field15;
-		Vector3 actorPosition;
-		Vector3 otherActorPosition;
-		int _availableCoversCount;
-		int _availableFleeWaypointsCount;
-		int _field24;
 
-	public:
-		ActorCombat(BladeRunnerEngine *vm);
-		~ActorCombat();
-		
-		void setup();
+class ActorCombat
+{
+	BladeRunnerEngine *_vm;
 
-		void hitAttempt();
-		
-		void combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int a10, int a11, int a12);
-		void combatOff();
+private:
+	int _actorId;
+	int _combatOn;
+	int _field2;
+	int _field3;
+	int _otherActorId;
+	int _field5;
+	int _field6;
+	int _field7;
+	int _field8;
+	int _field9;
+	int _field10;
+	int _field11;
+	int _field12;
+	int _actorHp;
+	int _field14;
+	int _field15;
+	Vector3 actorPosition;
+	Vector3 otherActorPosition;
+	int _availableCoversCount;
+	int _availableFleeWaypointsCount;
+	int _field24;
 
-	};
-}
+public:
+	ActorCombat(BladeRunnerEngine *vm);
+	~ActorCombat();
+
+	void setup();
+
+	void hitAttempt();
+
+	void combatOn(int actorId, int a3, int a4, int otherActorId, int a6, int a7, int a8, int a9, int a10, int a11, int a12);
+	void combatOff();
+};
+
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index e814180..5b23736 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -1,40 +1,234 @@
+/* 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 "bladerunner/actor_walk.h"
+
+#include "bladerunner/bladerunner.h"
+
 #include "bladerunner/actor.h"
 #include "bladerunner/scene_objects.h"
 
-namespace BladeRunner
-{
+namespace BladeRunner {
 
-	ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
+static int angle_1024(float x1, float z1, float x2, float z2);
+static int angle_1024(Vector3 &v1, Vector3 &v2);
+float distance(float x1, float x2, float z1, float z2);
+float distance(Vector3 &v1, Vector3 &v2);
+
+ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
 	_vm = vm;
+
+	_walking =  0;
+	_running =  0;
+	_facing  = -1;
+	_status  =  0;
 }
 
 ActorWalk::~ActorWalk() {
 }
 
-bool ActorWalk::isWalking() {
-	return _walking;
+int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2)
+{
+	Vector3 next;
+
+	*unk2 = 0;
+	int r = nextOnPath(actorId, from, to, &next);
+
+	if (r == 0) {
+		if (actorId != 0)
+		{
+			_current = from;
+			_destination = to;
+			stop(actorId, false);
+		}
+		else
+		{
+			stop(actorId, true);
+		}
+		return 0;
+	}
+	if (r == -1)
+	{
+		stop(actorId, true);
+		*unk2 = 1;
+		return 0;
+	}
+
+	// TODO: Init array
+	// TODO: Update screen index
+	// Set actor field e8
+
+	if (_running)
+	{
+		run = true;
+	}
+
+	int animationMode;
+	if (_vm->_actors[actorId]->inCombat())
+	{
+		animationMode = run ? 8 : 7;
+	}
+	else
+	{
+		animationMode = run ? 2 : 1;
+	}
+
+	_vm->_actors[actorId]->changeAnimationMode(animationMode);
+
+	_destination = to;
+	_current = from;
+	_next = next;
+
+	if (next.x != _current.x || next.z != _current.z)
+	{
+		_facing = angle_1024(_current, next);
+		_walking = true;
+		_running = run;
+		_status = 2;
+
+		return 1;
+	}
+
+	stop(actorId, true);
+	return 0;
+}
+
+bool ActorWalk::tick(int actorId, float stepDistance, bool flag)
+{
+	if (_status == 5)
+	{
+		if (flag)
+		{
+			stop(actorId, true);
+			return true;
+		}
+
+		if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1)
+		{
+			return false;
+		}
+		_status = 3;
+	}
+	// TODO: Handle collisions?
+
+	if (stepDistance > distance(_current, _destination))
+	{
+		stop(actorId, true);
+		_current = _destination;
+		// TODO: Update y from walkbox
+		return true;
+	}
+
+	float angle_rad = _facing / 512.0 * M_PI;
+
+	_current = Vector3(
+		_current.x + stepDistance * sinf(angle_rad),
+		_current.y,                    // TODO: Update from walkbox
+		_current.z - stepDistance * cosf(angle_rad)
+	);
+
+	return false;
+}
+
+void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing)
+{
+	*pos    = _current;
+	*facing = _facing;
+}
+
+void ActorWalk::setRunning()
+{
+	_running = true;
+	// TODO: Set animation mode
 }
 
 void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused) {
-	_vm->_sceneObjects->setMoving(actorId, 0); 
+	_vm->_sceneObjects->setMoving(actorId, 0);
 	_vm->_actors[actorId]->setMoving(0);
 
-	if(_vm->_actors[actorId]->inCombat()) {
+	if (_vm->_actors[actorId]->inCombat()) {
 		_vm->_actors[actorId]->changeAnimationMode(animationMode, 0);
 	} else {
 		_vm->_actors[actorId]->changeAnimationMode(notused, 0);
 	}
-	
-	if(unknown) {
-		_walking = 0;
-		_running = 0;
+
+	if (unknown) {
+		_walking = false;
+		_running = false;
 		_status = 0;
-	}else {
-		_walking = 1;
-		_running = 0;
+	} else {
+		_walking = true;
+		_running = false;
 		_status = 5;
 	}
 }
 
-}
\ No newline at end of file
+int ActorWalk::nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next)
+{
+	if (distance(from, to) < 6.0)
+	{
+		return -1;
+	}
+
+	// if (_vm->_actors[actorId]->getImmunityToObstacles()) {
+		*next = to;
+		return 1;
+	// }
+
+	error("TODO!");
+}
+
+static
+int angle_1024(float x1, float z1, float x2, float z2)
+{
+	float angle_rad = atan2(x2 - x1, z1 - z2);
+	int a = int(512.0 * angle_rad / M_PI);
+	return (a + 1024) % 1024;
+}
+
+static
+int angle_1024(Vector3 &v1, Vector3 &v2)
+{
+	return angle_1024(v1.x, v1.z, v2.x, v2.z);
+}
+
+float distance(float x1, float z1, float x2, float z2)
+{
+	float dx = x1 - x2;
+	float dz = z1 - z2;
+	float d = sqrt(dx*dx + dz*dz);
+
+	float int_part = (int)d;
+	float frac_part = d - int_part;
+
+	if (frac_part < 0.001)
+		frac_part = 0.0;
+
+	return int_part + frac_part;
+}
+
+float distance(Vector3 &v1, Vector3 &v2)
+{
+	return distance(v1.x, v1.z, v2.x, v2.z);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index c382189..8b343bb 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -23,40 +23,53 @@
 #ifndef BLADERUNNER_ACTOR_WALK_H
 #define BLADERUNNER_ACTOR_WALK_H
 
-#include "bladerunner/bladerunner.h"
 #include "bladerunner/vector.h"
 
-namespace BladeRunner
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+struct ActorWalkEntry
+{
+	int _actorId;
+	int _present;
+};
+
+class ActorWalk
 {
-	struct ActorWalkEntry
-	{
-		int _actorId;
-		int _present;
-	};
-
-	class ActorWalk
-	{
-		BladeRunnerEngine *_vm;
-	private:
-		int _walking;
-		int _running;
-		Vector3 _wanted;
-		Vector3 _unknown;
-		Vector3 _start;
-		Vector3 _end;
-		int facing;
-		ActorWalkEntry _actors[20];
-		int _actorsCount;
-		int _field15;
-		int _status;
-	public:
-		ActorWalk(BladeRunnerEngine *vm);
-		~ActorWalk();
-
-		bool isWalking();
-		void stop(int actorId, bool unknown, int animationMode, int notused);
-
-	};
-}
+	BladeRunnerEngine *_vm;
+
+private:
+	int     _walking;
+	int     _running;
+	Vector3 _destination;
+	Vector3 _unknown;
+	Vector3 _current;
+	Vector3 _next;
+	int     _facing;
+	ActorWalkEntry _actors[20];
+	int     _actorsCount;
+	int     _field15;
+	int     _status;
+
+public:
+	ActorWalk(BladeRunnerEngine *vm);
+	~ActorWalk();
+
+	int setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2);
+	void getCurrentPosition(int actorId, Vector3 *pos, int *facing);
+	bool tick(int actorId, float stepDistance, bool flag);
+
+	bool isWalking() { return _walking; }
+	bool isRunning() { return _running; }
+	void setRunning();
+
+	void stop(int actorId, bool unknown, int animationMode = 4, int notused = 0);
+	// void setWalkingMode(int actorId, int active, int unk2 = 4, int unk3 = 0);
+
+	int nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next);
+};
+
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
index 051fcd8..464ca15 100644
--- a/engines/bladerunner/archive.cpp
+++ b/engines/bladerunner/archive.cpp
@@ -65,7 +65,7 @@ bool MIXArchive::open(const Common::String &filename) {
 		return false;
 	}
 
-	debug("MIXArchive::open: Opened archive %s", filename.c_str());
+	// debug("MIXArchive::open: Opened archive %s", filename.c_str());
 
 	return true;
 }
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index b8df01c..851b0bc 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -165,21 +165,20 @@ void AudioPlayer::fadeAndStopTrack(Track *track, int time)
 
 int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, int panTo, int priority, byte flags) {
 	/* Find first available track or, alternatively, the lowest priority playing track */
-	int    trackId = -1;
 	Track *track = NULL;
-	int    lowestPriority = 100;
+	int    lowestPriority;
 	Track *lowestPriorityTrack = NULL;
 
 	for (int i = 0; i != 6; ++i) {
-		track = &_tracks[i];
-		if (!isTrackActive(track)) {
-			trackId = 1;
+		Track *ti = &_tracks[i];
+		if (!isTrackActive(ti)) {
+			track = ti;
 			break;
 		}
 
-		if (track->priority < lowestPriority) {
-			lowestPriority = track->priority;
-			lowestPriorityTrack = track;
+		if (lowestPriorityTrack == NULL || ti->priority < lowestPriority) {
+			lowestPriority = ti->priority;
+			lowestPriorityTrack = ti;
 		}
 	}
 
@@ -222,7 +221,7 @@ int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, in
 
 	Audio::SoundHandle soundHandle;
 
-	debug("PlayStream: %s", name.c_str());
+	// debug("PlayStream: %s", name.c_str());
 
 	int balance = panFrom;
 
@@ -240,7 +239,7 @@ int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, in
 	track->hash          = hash;
 	track->volume        = volume;
 
-	return trackId;
+	return track - &_tracks[0];
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/audio_speech.cpp b/engines/bladerunner/audio_speech.cpp
index 6fa9c94..7e7e4f0 100644
--- a/engines/bladerunner/audio_speech.cpp
+++ b/engines/bladerunner/audio_speech.cpp
@@ -44,16 +44,16 @@ AudioSpeech::~AudioSpeech() {
 }
 
 bool AudioSpeech::playSpeech(const char *name, int balance) {
-
+	// debug("AudioSpeech::playSpeech(\"%s\")", name);
 	Common::ScopedPtr<Common::SeekableReadStream> r(_vm->getResourceStream(name));
 
 	if (!r) {
-		debug("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name);
+		warning("AudioSpeech::playSpeech: AUD resource \"%s\" not found", name);
 		return false;
 	}
 
 	if (r->size() > BUFFER_SIZE) {
-		debug("AudioSpeech::playSpeech: AUD larger than buffer size (%d > %d)", r->size(), BUFFER_SIZE);
+		warning("AudioSpeech::playSpeech: AUD larger than buffer size (%d > %d)", r->size(), BUFFER_SIZE);
 		return false;
 	}
 
@@ -63,7 +63,7 @@ bool AudioSpeech::playSpeech(const char *name, int balance) {
 
 	r->read(_data, r->size());
 	if (r->err()) {
-		debug("AudioSpeech::playSpeech: Error reading resource \"%s\"", name);
+		warning("AudioSpeech::playSpeech: Error reading resource \"%s\"", name);
 		return false;
 	}
 
diff --git a/engines/bladerunner/audio_speech.h b/engines/bladerunner/audio_speech.h
index e122422..ae70658 100644
--- a/engines/bladerunner/audio_speech.h
+++ b/engines/bladerunner/audio_speech.h
@@ -41,7 +41,7 @@ public:
 	AudioSpeech(BladeRunnerEngine *vm);
 	~AudioSpeech();
 
-	bool playSpeech(const char *name, int balance = 50);
+	bool playSpeech(const char *name, int balance = 0);
 	void stopSpeech();
 	bool isPlaying();
 	void setVolume(int volume) { _volume = volume; }
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 0f5f320..bd38fe7 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -29,9 +29,12 @@
 #include "bladerunner/audio_speech.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/clues.h"
+#include "bladerunner/combat.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
+#include "bladerunner/items.h"
+#include "bladerunner/lights.h"
 #include "bladerunner/mouse.h"
 #include "bladerunner/outtake.h"
 #include "bladerunner/scene.h"
@@ -45,8 +48,6 @@
 #include "bladerunner/text_resource.h"
 #include "bladerunner/vqa_decoder.h"
 #include "bladerunner/waypoints.h"
-#include "bladerunner/items.h"
-#include "bladerunner/combat.h"
 
 #include "common/array.h"
 #include "common/error.h"
@@ -67,6 +68,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_gameIsRunning  = true;
 	_playerLosesControlCounter = 0;
 
+	_clues = NULL;
 	_script = new Script(this);
 	_settings = new Settings(this);
 	_lights = new Lights(this);
@@ -94,9 +96,6 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
 
-	delete _combat;
-	delete _waypoints;
-	delete _lights;
 	delete _settings;
 	delete _script;
 }
@@ -171,7 +170,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	// TODO: Sine and cosine lookup tables for intervals of 1.0, 4.0, and 12.0
 
-	_view = new View(this);
+	_view = new View();
 
 	_sceneObjects = new SceneObjects(this, _view);
 
@@ -215,10 +214,13 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 	assert(actorCount < 99);
 	for (int i = 0; i != actorCount; ++i) {
 		_actors[i] = new Actor(this, i);
+		_actors[i]->setup(i);
 	}
 	_voiceoverActor = new Actor(this, 99);
 	_playerActor = _actors[_gameInfo->getPlayerId()];
 
+	_playerActor->setFPS(15);
+
 	// TODO: set _playerActor countdown timer 6
 
 	// TODO: Set actor ids (redundant?)
@@ -310,6 +312,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 	initScript.SCRIPT_Initialize_Game();
 
 	// TODO: Load AI-ACT1.DLL
+	_aiScripts = new AIScripts(this);
 
 	initChapterAndScene();
 
@@ -318,6 +321,11 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 void BladeRunnerEngine::initChapterAndScene() {
 	// TODO: Init actors...
+	for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i)
+		_aiScripts->Initialize(i);
+
+	for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i)
+		_actors[i]->changeAnimationMode(i);
 
 	_settings->setChapter(1);
 	_settings->setNewSetAndScene(_gameInfo->getInitialSetId(), _gameInfo->getInitialSceneId());
@@ -424,7 +432,8 @@ void BladeRunnerEngine::shutdown() {
 	delete[] _gameVars;
 	_gameVars = 0;
 
-	// TODO: Delete World waypoints
+	delete _waypoints;
+	_waypoints = 0;
 
 	// TODO: Delete Cover waypoints
 
@@ -488,7 +497,7 @@ void BladeRunnerEngine::gameLoop() {
 	do {
 		/* TODO: check player death */
 		gameTick();
-	} while (_gameIsRunning && !shouldQuit());
+	} while (_gameIsRunning);
 }
 
 void BladeRunnerEngine::gameTick() {
@@ -505,7 +514,10 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: VK
 		// TODO: Elevators
 		// TODO: Scores
-		// TODO: Call Script_Player_Walked_In if applicable
+
+		if (_scene->didPlayerWalkIn()) {
+			_script->PlayerWalkedIn();
+		}
 		// TODO: Gun range announcements
 		// TODO: ZBUF repair dirty rects
 
@@ -521,26 +533,45 @@ void BladeRunnerEngine::gameTick() {
 		_surface2.copyFrom(_surface1);
 		memcpy(_zBuffer2, _zBuffer1, 640*480*2);
 
-		// TODO: Render overlays (mostly in Replicant)
-		// TODO: Tick Actor AI and Timers (timers in Replicant)
+#if 0
+		{
+			for (int y = 0; y != 480; ++y) {
+				for (int x = 0; x != 640; ++x) {
+					if (_scene->_regions->getRegionAtXY(x, y) >= 0) {
+						uint16 *p = (uint16*)_surface2.getBasePtr(x, y);
+						*p = 0x7C00;
+					}
+					if (_scene->_exits->getRegionAtXY(x, y) >= 0) {
+						uint16 *p = (uint16*)_surface2.getBasePtr(x, y);
+						*p = 0x7C08;
+					}
+				}
+			}
+		}
+#endif
+
+		// TODO: Render overlays
+		// TODO: Tick Actor AI and Timers
 
 		if (_settings->getNewScene() == -1 || _script->_inScriptCounter /* || in_ai */) {
 
-			// TODO: Tick and draw all actors in current set (drawing works in Replicant)
+			_sliceRenderer->setView(_scene->_view);
 
-			// HACK to draw McCoy
-			//_sliceRenderer->setView(&_scene->_view);
-			_playerActor->draw();
+			// Tick and draw all actors in current set
+			for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
+				if (i == 0 || i == 23) // Currently limited to McCoy and Officer Leroy
+					_actors[i]->tick(backgroundChanged);
+			}
 
-			// TODO: Draw items (drawing works in Replicant)
-			// TODO: Draw item pickup (understood, drawing works in Replicant)
+			// TODO: Draw items
+			// TODO: Draw item pickup
 			// TODO: Draw dialogue menu
 
 			Common::Point p = _eventMan->getMousePos();
 			_mouse->tick(p.x, p.y);
 			_mouse->draw(_surface2, p.x, p.y);
 
-			// TODO: Process AUD (audio in Replicant)
+			// TODO: Process AUD
 			// TODO: Footstep sound
 
 			_system->copyRectToScreen((const byte *)_surface2.getBasePtr(0, 0), _surface2.pitch, 0, 0, 640, 480);
@@ -551,12 +582,60 @@ void BladeRunnerEngine::gameTick() {
 }
 
 void BladeRunnerEngine::handleEvents() {
+	if (shouldQuit()) {
+		_gameIsRunning = false;
+		return;
+	}
+
 	Common::Event event;
 	Common::EventManager *eventMan = _system->getEventManager();
 	while (eventMan->pollEvent(event)) {
+		switch (event.type) {
+			case Common::EVENT_LBUTTONDOWN:
+			case Common::EVENT_RBUTTONDOWN:
+				handleMouseClick(event.mouse.x, event.mouse.y);
+			default:
+				;
+		}
 	}
 }
 
+void BladeRunnerEngine::handleMouseClick(int x, int y) {
+	if (!playerHasControl() || _mouse->isDisabled())
+		return;
+
+	Vector3 mousePosition = _mouse->getXYZ(x, y);
+
+	int isClickable;
+	int isObstacle;
+	int isTarget;
+
+	int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
+	int exitType      = _scene->_exits->getTypeAtXY(x, y);
+
+	debug("%d %d", sceneObjectId, exitType);
+
+	if ((sceneObjectId < 0 || sceneObjectId > 73) && exitType >= 0) {
+		// clickedOnExit(exitType, x, y);
+		debug("clicked on exit %d %d %d", exitType, x, y);
+		return;
+	}
+
+	int regionIndex = _scene->_regions->getRegionAtXY(x, y);
+	if (regionIndex >= 0) {
+		debug("clicked on region %d %d %d", regionIndex, x, y);
+		_script->ClickedOn2DRegion(regionIndex);
+	}
+
+	if (sceneObjectId >= 198 && sceneObjectId <= 293) {
+		const char *objectName = _scene->objectGetName(sceneObjectId - 198);
+		debug("%s", objectName);
+		_script->ClickedOn3DObject(objectName);
+		return;
+	}
+
+}
+
 void BladeRunnerEngine::gameWaitForActive() {
 	while(!_windowIsActive) {
 		handleEvents();
@@ -571,11 +650,17 @@ void BladeRunnerEngine::loopActorSpeaking() {
 
 	do {
 		gameTick();
-	} while (_audioSpeech->isPlaying());
+	} while (_gameIsRunning && _audioSpeech->isPlaying());
 
 	playerGainsControl();
 }
 
+void BladeRunnerEngine::loopActorWalkToXYZ(int actorId, float x, float y, float z, int a4, int a5, int a6, int a7) {
+	Actor *actor = _actors[actorId];
+
+	actor->loopWalkToXYZ(Vector3(x, y, z));
+}
+
 void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
 	Common::String name = _gameInfo->getOuttake(id);
 
@@ -655,7 +740,7 @@ void BladeRunnerEngine::playerLosesControl() {
 	if (++_playerLosesControlCounter == 1) {
 		_mouse->disable();
 	}
-	debug("Player Lost Control (%d)", _playerLosesControlCounter);
+	// debug("Player Lost Control (%d)", _playerLosesControlCounter);
 }
 
 void BladeRunnerEngine::playerGainsControl() {
@@ -666,7 +751,7 @@ void BladeRunnerEngine::playerGainsControl() {
 	if (_playerLosesControlCounter > 0)
 		--_playerLosesControlCounter;
 
-	debug("Player Gained Control (%d)", _playerLosesControlCounter);
+	// debug("Player Gained Control (%d)", _playerLosesControlCounter);
 
 	if (_playerLosesControlCounter == 0) {
 		_mouse->enable();
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index e90889a..fba793c 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -37,13 +37,17 @@
 namespace BladeRunner {
 
 class Actor;
+class AIScripts;
 class AmbientSounds;
 class AudioPlayer;
 class AudioSpeech;
 class Chapters;
 class Clues;
-class GameInfo;
+class Combat;
 class GameFlags;
+class GameInfo;
+class Items;
+class Lights;
 class Mouse;
 class Scene;
 class SceneObjects;
@@ -53,12 +57,8 @@ class Shape;
 class SliceAnimations;
 class SliceRenderer;
 class TextResource;
-class Lights;
 class View;
 class Waypoints;
-class Items;
-class Combat;
-
 
 class BladeRunnerEngine : public Engine {
 public:
@@ -66,6 +66,7 @@ public:
 	bool      _windowIsActive;
 	int       _playerLosesControlCounter;
 
+	AIScripts       *_aiScripts;
 	AmbientSounds   *_ambientSounds;
 	AudioPlayer     *_audioPlayer;
 	AudioSpeech     *_audioSpeech;
@@ -74,13 +75,13 @@ public:
 	GameFlags       *_gameFlags;
 	GameInfo        *_gameInfo;
 	Mouse           *_mouse;
-	View            *_view;
 	Scene           *_scene;
 	SceneObjects    *_sceneObjects;
 	Script          *_script;
 	Settings        *_settings;
 	SliceAnimations *_sliceAnimations;
 	SliceRenderer   *_sliceRenderer;
+	View            *_view;
 	int             *_gameVars;
 
 	Lights          *_lights;
@@ -118,7 +119,7 @@ public:
 	int  _gameAutoSave;
 	bool _gameIsLoading;
 	bool _sceneIsLoading;
-	
+
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
@@ -137,13 +138,16 @@ public:
 
 	bool loadSplash();
 	bool init2();
-	
+
 	void gameLoop();
 	void gameTick();
 	void handleEvents();
+	void handleMouseClick(int x, int y);
 	void gameWaitForActive();
 	void loopActorSpeaking();
 
+	void loopActorWalkToXYZ(int actorId, float x, float y, float z, int a4, int a5, int a6, int a7);
+
 	void outtakePlay(int id, bool no_localization, int container = -1);
 
 	bool openArchive(const Common::String &name);
diff --git a/engines/bladerunner/boundingbox.cpp b/engines/bladerunner/boundingbox.cpp
index 9b36eab..0294426 100644
--- a/engines/bladerunner/boundingbox.cpp
+++ b/engines/bladerunner/boundingbox.cpp
@@ -44,16 +44,13 @@ void BoundingBox::expand(float x0, float y0, float z0, float x1, float y1, float
 	_vertices[1].z += z1;
 }
 
-
 bool BoundingBox::inside(float x, float y, float z) {
-	return
-		x >= _vertices[0].x && x <= _vertices[1].x
-		&& y >= _vertices[0].y && y <= _vertices[1].y
-		&& z >= _vertices[0].z && z <= _vertices[1].z;
+	return x >= _vertices[0].x && x <= _vertices[1].x
+	    && y >= _vertices[0].y && y <= _vertices[1].y
+	    && z >= _vertices[0].z && z <= _vertices[1].z;
 }
 
-
-void BoundingBox::setXyz(float x0, float y0, float z0, float x1, float y1, float z1) {
+void BoundingBox::setXYZ(float x0, float y0, float z0, float x1, float y1, float z1) {
 	_vertices[0].x = x0;
 	_vertices[0].y = y0;
 	_vertices[0].z = z0;
@@ -63,7 +60,7 @@ void BoundingBox::setXyz(float x0, float y0, float z0, float x1, float y1, float
 	_vertices[1].z = z1;
 }
 
-void BoundingBox::getXyz(float *x0, float *y0, float *z0, float *x1, float *y1, float *z1) {
+void BoundingBox::getXYZ(float *x0, float *y0, float *z0, float *x1, float *y1, float *z1) {
 	*x0 = _vertices[0].x;
 	*y0 = _vertices[0].y;
 	*z0 = _vertices[0].z;
@@ -73,7 +70,6 @@ void BoundingBox::getXyz(float *x0, float *y0, float *z0, float *x1, float *y1,
 	*z1 = _vertices[1].z;
 }
 
-
 float BoundingBox::getZ0() {
 	return _vertices[0].z;
 }
@@ -81,4 +77,5 @@ float BoundingBox::getZ0() {
 float BoundingBox::getZ1() {
 	return _vertices[1].z;
 }
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
index d9f7df6..5031ce5 100644
--- a/engines/bladerunner/boundingbox.h
+++ b/engines/bladerunner/boundingbox.h
@@ -23,12 +23,11 @@
 #ifndef BLADERUNNER_BOUNDING_BOX_H
 #define BLADERUNNER_BOUNDING_BOX_H
 
-#include "vector.h"
+#include "bladerunner/vector.h"
 
 namespace BladeRunner {
 
 class BoundingBox {
-private:
 	Vector3 _vertices[2];
 
 public:
@@ -37,8 +36,10 @@ public:
 
 	void expand(float x0, float y0, float z0, float x1, float y1, float z1);
 	bool inside(float x, float y, float z);
-	void setXyz(float x0, float y0, float z0, float x1, float y1, float z1);
-	void getXyz(float* x0, float* y0, float* z0, float* x1, float* y1, float* z1);
+
+	void setXYZ(float x0, float y0, float z0, float x1, float y1, float z1);
+	void getXYZ(float* x0, float* y0, float* z0, float* x1, float* y1, float* z1);
+
 	float getZ0();
 	float getZ1();
 };
diff --git a/engines/bladerunner/clues.cpp b/engines/bladerunner/clues.cpp
index 5b1ce97..cbdf536 100644
--- a/engines/bladerunner/clues.cpp
+++ b/engines/bladerunner/clues.cpp
@@ -23,11 +23,12 @@
 #include "bladerunner/clues.h"
 
 #include "bladerunner/bladerunner.h"
+
 #include "bladerunner/text_resource.h"
 
 namespace BladeRunner {
 
-Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, uint32 clueCount)
+Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, int clueCount)
 	: _clueCount(clueCount)
 {
 	// reset();
@@ -38,14 +39,14 @@ Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, uint32 clueCount)
 	_cluesText = new TextResource(vm);
 	_cluesText->open(cluesResource);
 
-	for (uint32 i = 0; i != _clueCount; ++i) {
+	for (int i = 0; i != _clueCount; ++i) {
 		_crimes[i] = -1;
 		_assetTypes[i] = -1;
 	}
 }
 
 Clues::~Clues() {
-	delete _cluesText;
+	delete   _cluesText;
 	delete[] _assetTypes;
 	delete[] _crimes;
 }
diff --git a/engines/bladerunner/clues.h b/engines/bladerunner/clues.h
index 2ffcbd2..4afdef6 100644
--- a/engines/bladerunner/clues.h
+++ b/engines/bladerunner/clues.h
@@ -23,21 +23,19 @@
 #ifndef BLADERUNNER_CLUES_H
 #define BLADERUNNER_CLUES_H
 
-#include "common/scummsys.h"
-
 namespace BladeRunner {
 
 class BladeRunnerEngine;
 class TextResource;
 
 class Clues {
-	uint32        _clueCount;
+	int           _clueCount;
 	int          *_crimes;
 	int          *_assetTypes;
 	TextResource *_cluesText;
 
 public:
-	Clues(BladeRunnerEngine *vm, const char *cluesResource, uint32 clueCount);
+	Clues(BladeRunnerEngine *vm, const char *cluesResource, int clueCount);
 	~Clues();
 
 	const char *getClueText(int id);
diff --git a/engines/bladerunner/color.h b/engines/bladerunner/color.h
index 54983b4..eebe2dc 100644
--- a/engines/bladerunner/color.h
+++ b/engines/bladerunner/color.h
@@ -1,37 +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.
-*
-*/
+ *
+ * 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 BLADERUNNER_COLOR_H
 #define BLADERUNNER_COLOR_H
 
 namespace BladeRunner {
 
-	struct Color
-	{
-		float r;
-		float g;
-		float b;
-	};
-}
+struct Color
+{
+	float r;
+	float g;
+	float b;
+};
 
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/combat.cpp b/engines/bladerunner/combat.cpp
index 5fe2e3f..1f61d7b 100644
--- a/engines/bladerunner/combat.cpp
+++ b/engines/bladerunner/combat.cpp
@@ -1,19 +1,23 @@
 #include "bladerunner/combat.h"
+
 #include "bladerunner/bladerunner.h"
+
 #include "bladerunner/actor.h"
 #include "bladerunner/settings.h"
 
 namespace BladeRunner {
 
-
 Combat::Combat(BladeRunnerEngine* vm) {
 	_vm = vm;
 
 	_active = false;
 	_enabled = true;
 
-	int i;
-	for (i = 0; i < 9; i++) {
+	_ammoDamage[0] = 10;
+	_ammoDamage[1] = 20;
+	_ammoDamage[2] = 30;
+
+	for (int i = 0; i < 9; i++) {
 		_hitSoundId[i] = -1;
 		_missSoundId[i] = -1;
 	}
@@ -48,7 +52,6 @@ void Combat::disable() {
 	_enabled = false;
 }
 
-
 void Combat::setHitSoundId(int row, int column, int soundId) {
 	_hitSoundId[row * 3 + column] = soundId;
 }
@@ -56,4 +59,5 @@ void Combat::setHitSoundId(int row, int column, int soundId) {
 void Combat::setMissSoundId(int row, int column, int soundId) {
 	_missSoundId[row * 3 + column] = soundId;
 }
-}
\ No newline at end of file
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h
index 5860fd7..79de69d 100644
--- a/engines/bladerunner/combat.h
+++ b/engines/bladerunner/combat.h
@@ -23,10 +23,10 @@
 #ifndef BLADERUNNER_COMBAT_H
 #define BLADERUNNER_COMBAT_H
 
-#include "bladerunner/bladerunner.h"
-
 namespace BladeRunner {
 
+class BladeRunnerEngine;
+
 class Combat {
 	BladeRunnerEngine *_vm;
 
@@ -38,7 +38,7 @@ class Combat {
 	int _random2;
 
 public:
-	int _ammoDamage[3] = { 10, 20, 30 };
+	int _ammoDamage[3];
 
 public:
 	Combat(BladeRunnerEngine *vm);
@@ -53,9 +53,8 @@ public:
 
 	void setHitSoundId(int row, int column, int soundId);
 	void setMissSoundId(int row, int column, int soundId);
-
 };
 
-}
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/detection_tables.h b/engines/bladerunner/detection_tables.h
index 90f27ff..940c854 100644
--- a/engines/bladerunner/detection_tables.h
+++ b/engines/bladerunner/detection_tables.h
@@ -42,6 +42,6 @@ static const ADGameDescription gameDescriptions[] = {
 	AD_TABLE_END_MARKER
 };
 
-} // End of namespace Hopkins
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
index 5951ba8..ead7c91 100644
--- a/engines/bladerunner/fog.cpp
+++ b/engines/bladerunner/fog.cpp
@@ -1,94 +1,96 @@
 #include "bladerunner/fog.h"
 
-namespace BladeRunner
+#include "common/stream.h"
+
+namespace BladeRunner {
+
+Fog::Fog()
 {
-	Fog::Fog()
-	{
-	}
+}
 
-	Fog::~Fog()
-	{
-	}
+Fog::~Fog()
+{
+}
 
-	int Fog::readCommon(Common::ReadStream* stream)
-	{
-		int offset = stream->readUint32LE();
-		stream->read(_name, 20);
-		_fogColor.r = stream->readFloatLE();
-		_fogColor.g = stream->readFloatLE();
-		_fogColor.b = stream->readFloatLE();
-		_fogDensity = stream->readFloatLE();
-		return offset;
-	}
+int Fog::readCommon(Common::ReadStream* stream)
+{
+	int offset = stream->readUint32LE();
+	stream->read(_name, 20);
+	_fogColor.r = stream->readFloatLE();
+	_fogColor.g = stream->readFloatLE();
+	_fogColor.b = stream->readFloatLE();
+	_fogDensity = stream->readFloatLE();
+	return offset;
+}
 
+void Fog::readAnimationData(Common::ReadStream* stream, int size)
+{
+	_animatedParameters = stream->readUint32LE();
+	_animationData = new float[size / sizeof(float)];
+	stream->read(_animationData, size);
 
-	void Fog::readAnimationData(Common::ReadStream* stream, int size)
-	{
-		_animatedParameters = stream->readUint32LE();
-		_animationData = new float[size / sizeof(float)];
-		stream->read(_animationData, size);
-		
-		_m11ptr = _animationData;
-		_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? _framesCount : 1);
-		_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? _framesCount : 1);
-		_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? _framesCount : 1);
-		_m21ptr = _m14ptr + (_animatedParameters & 0x08 ? _framesCount : 1);
-		_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? _framesCount : 1);
-		_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? _framesCount : 1);
-		_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? _framesCount : 1);
-		_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? _framesCount : 1);
-		_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? _framesCount : 1);
-		_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? _framesCount : 1);
-		_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? _framesCount : 1);
+	_m11ptr = _animationData;
+	_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? _framesCount : 1);
+	_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? _framesCount : 1);
+	_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? _framesCount : 1);
+	_m21ptr = _m14ptr + (_animatedParameters & 0x08 ? _framesCount : 1);
+	_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? _framesCount : 1);
+	_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? _framesCount : 1);
+	_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? _framesCount : 1);
+	_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? _framesCount : 1);
+	_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? _framesCount : 1);
+	_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? _framesCount : 1);
+	_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? _framesCount : 1);
 
-		setupFrame(0);
-	}
+	setupFrame(0);
+}
 
-	void Fog::reset()
-	{
-	}
+void Fog::reset()
+{
+}
 
-	void Fog::setupFrame(int frame)
-	{
-		int offset = frame % _framesCount;
-		_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
-		_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
-		_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
-		_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
-		_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
-		_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
-		_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
-		_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
-		_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
-		_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
-		_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
-		_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
-		_inverted = invertMatrix(_matrix);
-	}
+void Fog::setupFrame(int frame)
+{
+	int offset = frame % _framesCount;
+	_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
+	_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
+	_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
+	_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
+	_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
+	_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
+	_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
+	_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
+	_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
+	_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
+	_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
+	_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
+	_inverted = invertMatrix(_matrix);
+}
 
-	void FogCone::read(Common::ReadStream* stream, int framesCount)
-	{
-		_framesCount = framesCount;
-		int size = readCommon(stream);
-		_parameter1 = stream->readFloatLE();
-		readAnimationData(stream, size - 52);
-	}
+void FogCone::read(Common::ReadStream* stream, int framesCount)
+{
+	_framesCount = framesCount;
+	int size = readCommon(stream);
+	_parameter1 = stream->readFloatLE();
+	readAnimationData(stream, size - 52);
+}
 
-	void FogSphere::read(Common::ReadStream* stream, int framesCount)
-	{
-		_framesCount = framesCount;
-		int size = readCommon(stream);
-		_parameter1 = stream->readFloatLE();
-		readAnimationData(stream, size - 52);
-	}
+void FogSphere::read(Common::ReadStream* stream, int framesCount)
+{
+	_framesCount = framesCount;
+	int size = readCommon(stream);
+	_parameter1 = stream->readFloatLE();
+	readAnimationData(stream, size - 52);
+}
+
+void FogBox::read(Common::ReadStream* stream, int framesCount)
+{
+	_framesCount = framesCount;
+	int size = readCommon(stream);
+	_parameter1 = stream->readFloatLE();
+	_parameter2 = stream->readFloatLE();
+	_parameter3 = stream->readFloatLE();
+	readAnimationData(stream, size - 60);
+}
 
-	void FogBox::read(Common::ReadStream* stream, int framesCount)
-	{
-		_framesCount = framesCount;
-		int size = readCommon(stream);
-		_parameter1 = stream->readFloatLE();
-		_parameter2 = stream->readFloatLE();
-		_parameter3 = stream->readFloatLE();
-		readAnimationData(stream, size - 60);
-	}
-}
\ No newline at end of file
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h
index 627e8f1..db291e3 100644
--- a/engines/bladerunner/fog.h
+++ b/engines/bladerunner/fog.h
@@ -1,104 +1,102 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_FOG_H
 #define BLADERUNNER_FOG_H
 
-#include "bladerunner/bladerunner.h"
 #include "bladerunner/color.h"
 #include "bladerunner/matrix.h"
 
-#include "common/stream.h"
-
+namespace Common {
+	class ReadStream;
+}
 
 namespace BladeRunner {
 
-	class SetEffects;
-
-	class Fog
-	{
-		friend class SetEffects;
-
-	protected:
-		char _name[20];
-		int _framesCount;
-		int _animatedParameters;
-		Matrix4x3 _matrix;
-		Matrix4x3 _inverted;
-		Color _fogColor;
-		float _fogDensity;
-		float *_animationData;
-		float *_m11ptr;
-		float *_m12ptr;
-		float *_m13ptr;
-		float *_m14ptr;
-		float *_m21ptr;
-		float *_m22ptr;
-		float *_m23ptr;
-		float *_m24ptr;
-		float *_m31ptr;
-		float *_m32ptr;
-		float *_m33ptr;
-		float *_m34ptr;
-		
-		float _parameter1;
-		float _parameter2;
-		float _parameter3;
-
-		Fog *_next;
-
-	public:
-		Fog();
-		~Fog();
-
-		virtual void read(Common::ReadStream *stream, int framesCount) = 0;
-
-		void reset();
-
-		void setupFrame(int frame);
-
-	private:
-	protected:
-		int readCommon(Common::ReadStream *stream);
-		void readAnimationData(Common::ReadStream *stream, int count);
-
-	};
-
-	class FogCone : public Fog
-	{
-		void read(Common::ReadStream *stream, int framesCount);
-	};
-
-	class FogSphere : public Fog
-	{
-		void read(Common::ReadStream *stream, int framesCount);
-	};
-
-	class FogBox : public Fog
-	{
-		void read(Common::ReadStream *stream, int framesCount);
-	};
-
+class SetEffects;
+
+class Fog
+{
+	friend class SetEffects;
+
+protected:
+	char       _name[20];
+	int        _framesCount;
+	int        _animatedParameters;
+	Matrix4x3  _matrix;
+	Matrix4x3  _inverted;
+	Color      _fogColor;
+	float      _fogDensity;
+	float     *_animationData;
+	float     *_m11ptr;
+	float     *_m12ptr;
+	float     *_m13ptr;
+	float     *_m14ptr;
+	float     *_m21ptr;
+	float     *_m22ptr;
+	float     *_m23ptr;
+	float     *_m24ptr;
+	float     *_m31ptr;
+	float     *_m32ptr;
+	float     *_m33ptr;
+	float     *_m34ptr;
+
+	float      _parameter1;
+	float      _parameter2;
+	float      _parameter3;
+
+	Fog       *_next;
+
+public:
+	Fog();
+	virtual ~Fog();
+
+	virtual void read(Common::ReadStream *stream, int framesCount) = 0;
+
+	void reset();
+
+	void setupFrame(int frame);
+
+protected:
+	int readCommon(Common::ReadStream *stream);
+	void readAnimationData(Common::ReadStream *stream, int count);
+
+};
+
+class FogCone : public Fog
+{
+	void read(Common::ReadStream *stream, int framesCount);
+};
+
+class FogSphere : public Fog
+{
+	void read(Common::ReadStream *stream, int framesCount);
+};
+
+class FogBox : public Fog
+{
+	void read(Common::ReadStream *stream, int framesCount);
+};
+
+} // End of namespace BladeRunner
 
-
-}
 #endif
diff --git a/engines/bladerunner/gameflags.cpp b/engines/bladerunner/gameflags.cpp
index 3704271..087292e 100644
--- a/engines/bladerunner/gameflags.cpp
+++ b/engines/bladerunner/gameflags.cpp
@@ -38,8 +38,6 @@ GameFlags::~GameFlags() {
 void GameFlags::setFlagCount(int count) {
 	assert(count > 0);
 
-	debug("flagCount: %d", count);
-
 	flagCount = count;
 	flags = new uint32[count / 32 + 1];
 
@@ -48,18 +46,21 @@ void GameFlags::setFlagCount(int count) {
 }
 
 void GameFlags::set(int flag) {
+	debug("GameFlags::set(%d)", flag);
 	assert(flag >= 0 && flag <= flagCount);
 
 	flags[flag / 32] |= (1 << (flag % 32));
 }
 
 void GameFlags::reset(int flag) {
+	debug("GameFlags::reset(%d)", flag);
 	assert(flag >= 0 && flag <= flagCount);
 
 	flags[flag / 32] &= ~(1 << (flag % 32));
 }
 
 bool GameFlags::query(int flag) {
+	debug("GameFlags::query(%d): %d", flag, !!(flags[flag / 32] & (1 << (flag % 32))));
 	assert(flag >= 0 && flag <= flagCount);
 
 	return !!(flags[flag / 32] & (1 << (flag % 32)));
diff --git a/engines/bladerunner/image.cpp b/engines/bladerunner/image.cpp
index 157e443..abdd6ff 100644
--- a/engines/bladerunner/image.cpp
+++ b/engines/bladerunner/image.cpp
@@ -23,6 +23,7 @@
 #include "bladerunner/image.h"
 
 #include "bladerunner/bladerunner.h"
+
 #include "bladerunner/decompress_lcw.h"
 
 #include "common/rect.h"
diff --git a/engines/bladerunner/image.h b/engines/bladerunner/image.h
index 75991d0..376f996 100644
--- a/engines/bladerunner/image.h
+++ b/engines/bladerunner/image.h
@@ -23,11 +23,12 @@
 #ifndef BLADERUNNER_IMAGE_H
 #define BLADERUNNER_IMAGE_H
 
-#include "common/debug.h"
-#include "common/substream.h"
-
 #include "graphics/surface.h"
 
+namespace Common {
+	class String;
+}
+
 namespace BladeRunner {
 
 class BladeRunnerEngine;
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index 7a3ec92..7017997 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -11,10 +11,10 @@ Item::Item() {
 Item::~Item() {
 }
 
-
-void Item::getXyz(float* x, float* y, float* z) {
+void Item::getXYZ(float *x, float *y, float *z) {
 	*x = _position.x;
 	*y = _position.y;
 	*z = _position.z;
 }
-}
\ No newline at end of file
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index a4a9282..5bb8e54 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_ITEM_H
 #define BLADERUNNER_ITEM_H
@@ -59,7 +59,7 @@ namespace BladeRunner {
 		Item();
 		~Item();
 
-		void getXyz(float *x, float *y, float *z);
+		void getXYZ(float *x, float *y, float *z);
 	};
 
 }
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index be03b9b..da3e74c 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -9,20 +9,19 @@ Items::Items(BladeRunnerEngine *vm) {
 Items::~Items() {
 }
 
-
-void Items::getXyz(int itemId, float* x, float* y, float* z) {
+void Items::getXYZ(int itemId, float* x, float* y, float* z) {
 	int itemIndex = findItem(itemId);
 	assert(itemIndex != -1);
 
-	_items[itemIndex].getXyz(x, y, z);
+	_items[itemIndex].getXYZ(x, y, z);
 }
 
 int Items::findItem(int itemId) {
-	int i;
-	for (i = 0; i < (int)_items.size(); i++) {
+	for (int i = 0; i < (int)_items.size(); i++) {
 		if (_items[i]._itemId == itemId)
 			return i;
 	}
 	return -1;
 }
-}
\ No newline at end of file
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index 39f574c..08d2a2b 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_ITEMS_H
 #define BLADERUNNER_ITEMS_H
@@ -29,22 +29,24 @@
 #include "common/array.h"
 #include "common/rect.h"
 
-namespace BladeRunner {	
+namespace BladeRunner {
 
-	class Items {
-		BladeRunnerEngine *_vm;
-	private:
-		Common::Array<Item> _items;
+class Items {
+	BladeRunnerEngine *_vm;
 
-	public:
-		Items(BladeRunnerEngine *vm);
-		~Items();
-		
-		void getXyz(int itemId, float *x, float *y, float *z);
+private:
+	Common::Array<Item> _items;
 
-	private:
-		int findItem(int itemId);
-	};
-}
+public:
+	Items(BladeRunnerEngine *vm);
+	~Items();
+
+	void getXYZ(int itemId, float *x, float *y, float *z);
+
+private:
+	int findItem(int itemId);
+};
+
+} // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index 6bc97f8..3689ab4 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -1,84 +1,85 @@
 #include "bladerunner/light.h"
 
-namespace BladeRunner
+namespace BladeRunner {
+
+Light::Light()
 {
-	Light::Light()
-	{
-	}
+}
 
-	Light::~Light()
-	{
-	}
+Light::~Light()
+{
+}
 
-	void Light::read(Common::ReadStream* stream, int framesCount, int frame, int animated)
-	{
-		_framesCount = framesCount;
-		_animated = animated;
+void Light::read(Common::ReadStream* stream, int framesCount, int frame, int animated)
+{
+	_framesCount = framesCount;
+	_animated = animated;
 
-		int size = stream->readUint32LE();
-		size = size - 32;
+	int size = stream->readUint32LE();
+	size = size - 32;
 
-		stream->read(_name, 20);
+	stream->read(_name, 20);
 
-		_animatedParameters = stream->readUint32LE();
+	_animatedParameters = stream->readUint32LE();
 
-		_animationData = new float[size / sizeof(float)];
-		stream->read(_animationData, size);
+	_animationData = new float[size / sizeof(float)];
+	stream->read(_animationData, size);
 
-		_m11ptr = _animationData;
-		_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? framesCount : 1);
-		_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? framesCount : 1);
-		_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? framesCount : 1);
-		_m21ptr = _m14ptr + (_animatedParameters & 0x8 ? framesCount : 1);
-		_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? framesCount : 1);
-		_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? framesCount : 1);
-		_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? framesCount : 1);
-		_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? framesCount : 1);
-		_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? framesCount : 1);
-		_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? framesCount : 1);
-		_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? framesCount : 1);
-		_colorRPtr = _m34ptr + (_animatedParameters & 0x800 ? framesCount : 1);
-		_colorGPtr = _colorRPtr + (_animatedParameters & 0x1000 ? framesCount : 1);
-		_colorBPtr = _colorGPtr + (_animatedParameters & 0x2000 ? framesCount : 1);
-		_field16ptr = _colorGPtr + (_animatedParameters & 0x4000 ? framesCount : 1);
-		_field17ptr = _field16ptr + (_animatedParameters & 0x8000 ? framesCount : 1);
-		_field18ptr = _field17ptr + (_animatedParameters & 0x10000 ? framesCount : 1);
-		_field19ptr = _field18ptr + (_animatedParameters & 0x20000 ? framesCount : 1);
+	_m11ptr = _animationData;
+	_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? framesCount : 1);
+	_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? framesCount : 1);
+	_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? framesCount : 1);
+	_m21ptr = _m14ptr + (_animatedParameters & 0x8 ? framesCount : 1);
+	_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? framesCount : 1);
+	_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? framesCount : 1);
+	_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? framesCount : 1);
+	_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? framesCount : 1);
+	_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? framesCount : 1);
+	_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? framesCount : 1);
+	_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? framesCount : 1);
+	_colorRPtr = _m34ptr + (_animatedParameters & 0x800 ? framesCount : 1);
+	_colorGPtr = _colorRPtr + (_animatedParameters & 0x1000 ? framesCount : 1);
+	_colorBPtr = _colorGPtr + (_animatedParameters & 0x2000 ? framesCount : 1);
+	_field16ptr = _colorGPtr + (_animatedParameters & 0x4000 ? framesCount : 1);
+	_field17ptr = _field16ptr + (_animatedParameters & 0x8000 ? framesCount : 1);
+	_field18ptr = _field17ptr + (_animatedParameters & 0x10000 ? framesCount : 1);
+	_field19ptr = _field18ptr + (_animatedParameters & 0x20000 ? framesCount : 1);
 
-		setupFrame(frame);
-	}
+	setupFrame(frame);
+}
 
-	void Light::readVqa(Common::ReadStream* stream)
-	{
-	}
+void Light::readVqa(Common::ReadStream* stream)
+{
+}
 
-	void Light::setupFrame(int frame)
-	{
-		int offset = frame % _framesCount;
-		_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
-		_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
-		_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
-		_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
-		_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
-		_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
-		_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
-		_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
-		_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
-		_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
-		_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
-		_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
-		_color.r = (_animatedParameters & 0x1000 ? _colorRPtr[offset] : *_colorRPtr);
-		_color.g = (_animatedParameters & 0x2000 ? _colorGPtr[offset] : *_colorGPtr);
-		_color.b = (_animatedParameters & 0x4000 ? _colorBPtr[offset] : *_colorBPtr);
-		_field16 = (_animatedParameters & 0x8000 ? _field16ptr[offset] : *_field16ptr);
-		_field17 = (_animatedParameters & 0x10000 ? _field17ptr[offset] : *_field17ptr);
-		_field18 = (_animatedParameters & 0x20000 ? _field18ptr[offset] : *_field18ptr);
-		_field19 = (_animatedParameters & 0x40000 ? _field19ptr[offset] : *_field19ptr);
+void Light::setupFrame(int frame)
+{
+	int offset = frame % _framesCount;
+	_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
+	_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
+	_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
+	_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
+	_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
+	_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
+	_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
+	_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
+	_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
+	_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
+	_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
+	_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
+	_color.r = (_animatedParameters & 0x1000 ? _colorRPtr[offset] : *_colorRPtr);
+	_color.g = (_animatedParameters & 0x2000 ? _colorGPtr[offset] : *_colorGPtr);
+	_color.b = (_animatedParameters & 0x4000 ? _colorBPtr[offset] : *_colorBPtr);
+	_field16 = (_animatedParameters & 0x8000 ? _field16ptr[offset] : *_field16ptr);
+	_field17 = (_animatedParameters & 0x10000 ? _field17ptr[offset] : *_field17ptr);
+	_field18 = (_animatedParameters & 0x20000 ? _field18ptr[offset] : *_field18ptr);
+	_field19 = (_animatedParameters & 0x40000 ? _field19ptr[offset] : *_field19ptr);
+
+}
 
-	}
+float Light::attenuation(float min, float max, float distance)
+{
+	return 0.0;
+}
 
-	float Light::attenuation(float min, float max, float distance)
-	{
-		return 0.0;
-	}
-}
\ No newline at end of file
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index f4c142e..bfece07 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -33,72 +33,77 @@ namespace Common{
 }
 
 namespace BladeRunner {
-	class Lights;
-
-	class Light
-	{
-		friend class Lights;
-	private:
-		char _name[20];
-		int _framesCount;
-		int _animated;
-		int _animatedParameters;
-		Matrix4x3 _matrix;
-		Color _color;
-		float _field16;
-		float _field17;
-		float _field18;
-		float _field19;
-		float *_animationData;
-		float *_m11ptr;
-		float *_m12ptr;
-		float *_m13ptr;
-		float *_m14ptr;
-		float *_m21ptr;
-		float *_m22ptr;
-		float *_m23ptr;
-		float *_m24ptr;
-		float *_m31ptr;
-		float *_m32ptr;
-		float *_m33ptr;
-		float *_m34ptr;
-		float *_colorRPtr;
-		float *_colorGPtr;
-		float *_colorBPtr;
-		float *_field16ptr;
-		float *_field17ptr;
-		float *_field18ptr;
-		float *_field19ptr;
-		Light *_next;
-	public:
-		Light();
-		~Light();
-		void read(Common::ReadStream *stream, int framesCount, int frame, int animated);
-		void readVqa(Common::ReadStream *stream);
-
-		void setupFrame(int frame);
-	private:
-		static float attenuation(float min, float max, float distance);
-	};
-
-	class Light1 : public Light {
-
-	};
-
-	class Light2 : public Light {
-
-	};
-
-	class Light3 : public Light {
-
-	};
-
-	class Light4 : public Light {
-
-	};
-
-	class Light5 : public Light {
-
-	};
-}
+
+class Lights;
+
+class Light
+{
+	friend class Lights;
+
+	char _name[20];
+	int _framesCount;
+	int _animated;
+	int _animatedParameters;
+	Matrix4x3 _matrix;
+	Color _color;
+	float _field16;
+	float _field17;
+	float _field18;
+	float _field19;
+	float *_animationData;
+	float *_m11ptr;
+	float *_m12ptr;
+	float *_m13ptr;
+	float *_m14ptr;
+	float *_m21ptr;
+	float *_m22ptr;
+	float *_m23ptr;
+	float *_m24ptr;
+	float *_m31ptr;
+	float *_m32ptr;
+	float *_m33ptr;
+	float *_m34ptr;
+	float *_colorRPtr;
+	float *_colorGPtr;
+	float *_colorBPtr;
+	float *_field16ptr;
+	float *_field17ptr;
+	float *_field18ptr;
+	float *_field19ptr;
+	Light *_next;
+
+public:
+	Light();
+	~Light();
+
+	void read(Common::ReadStream *stream, int framesCount, int frame, int animated);
+	void readVqa(Common::ReadStream *stream);
+
+	void setupFrame(int frame);
+
+private:
+	static float attenuation(float min, float max, float distance);
+};
+
+class Light1 : public Light {
+
+};
+
+class Light2 : public Light {
+
+};
+
+class Light3 : public Light {
+
+};
+
+class Light4 : public Light {
+
+};
+
+class Light5 : public Light {
+
+};
+
+} // End of namespace BladeRunner
 #endif
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index 33ee3d1..29e4c2f 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -1,100 +1,101 @@
 #include "bladerunner/lights.h"
 
 namespace BladeRunner {
-	Lights::Lights(BladeRunnerEngine *vm)
-	{
-		_vm = vm;
 
-		_ambientLightColor.r = 1.0;
-		_ambientLightColor.g = 0.0;
-		_ambientLightColor.b = 0.0;
+Lights::Lights(BladeRunnerEngine *vm)
+{
+	_vm = vm;
 
-		_lights = NULL;
-		_frame = 0;
-	}
+	_ambientLightColor.r = 1.0;
+	_ambientLightColor.g = 0.0;
+	_ambientLightColor.b = 0.0;
 
-	Lights::~Lights()
-	{
-		reset();
-	}
+	_lights = NULL;
+	_frame = 0;
+}
 
-	void Lights::read(Common::ReadStream* stream, int framesCount)
-	{
-		_ambientLightColor.r = stream->readFloatLE();
-		_ambientLightColor.g = stream->readFloatLE();
-		_ambientLightColor.b = stream->readFloatLE();
+Lights::~Lights()
+{
+	reset();
+}
 
-		_lightsCount = stream->readUint32LE();
-		int i;
-		for (i = 0; i < _lightsCount; i++)
-		{
-			Light *light;
-			int type = stream->readUint32LE();
-			switch (type)
-			{
-			case 1:
-				light = new Light1();
-				break;
-			case 2:
-				light = new Light2();
-				break;
-			case 3:
-				light = new Light3();
-				break;
-			case 4:
-				light = new Light4();
-				break;
-			case 5:
-				light = new Light5();
-				break;
-			default:
-				light = new Light();
-			}
-			
-			light->read(stream, framesCount, _frame, 0);
-			light->_next = _lights;
-			_lights = light;
-		}
-	}
+void Lights::read(Common::ReadStream* stream, int framesCount)
+{
+	_ambientLightColor.r = stream->readFloatLE();
+	_ambientLightColor.g = stream->readFloatLE();
+	_ambientLightColor.b = stream->readFloatLE();
 
-	void Lights::readVqa(Common::ReadStream* stream)
+	_lightsCount = stream->readUint32LE();
+	int i;
+	for (i = 0; i < _lightsCount; i++)
 	{
-		reset();
-		//int framesCount = stream->readUint32LE();
-		//int count = stream->readUint32LE();
+		Light *light;
+		int type = stream->readUint32LE();
+		switch (type)
+		{
+		case 1:
+			light = new Light1();
+			break;
+		case 2:
+			light = new Light2();
+			break;
+		case 3:
+			light = new Light3();
+			break;
+		case 4:
+			light = new Light4();
+			break;
+		case 5:
+			light = new Light5();
+			break;
+		default:
+			light = new Light();
+		}
 
+		light->read(stream, framesCount, _frame, 0);
+		light->_next = _lights;
+		_lights = light;
 	}
+}
 
-	void Lights::setupFrame(int frame)
-	{
-		Light *light;
+void Lights::readVqa(Common::ReadStream* stream)
+{
+	reset();
+	//int framesCount = stream->readUint32LE();
+	//int count = stream->readUint32LE();
+}
 
-		if (frame == _frame)
-			return;
+void Lights::setupFrame(int frame)
+{
+	Light *light;
 
-		if (!_lights)
-			return;
+	if (frame == _frame)
+		return;
 
-		for (light = _lights; light; light = light->_next)
-		{
-			light->setupFrame(frame);
-		}
-	}
+	if (!_lights)
+		return;
 
-	void Lights::reset()
+	for (light = _lights; light; light = light->_next)
 	{
-		Light *light;
-		Light *nextLight;
+		light->setupFrame(frame);
+	}
+}
 
-		if (!_lights)
-			return;
+void Lights::reset()
+{
+	Light *light;
+	Light *nextLight;
 
-		do
-		{
-			light = _lights;
-			nextLight = light->_next;
-			delete light;
-			_lights = nextLight;
-		} while (nextLight);
-	}
-}
\ No newline at end of file
+	if (!_lights)
+		return;
+
+	do
+	{
+		light = _lights;
+		nextLight = light->_next;
+		delete light;
+		_lights = nextLight;
+	} while (nextLight);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index d6ff7f5..71e6d21 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -29,36 +29,31 @@
 
 #include "common/stream.h"
 
-
 namespace BladeRunner {
 
-	class Lights
-	{
-		BladeRunnerEngine *_vm;
+class Lights {
+	BladeRunnerEngine *_vm;
 
-	private:
-		Color _ambientLightColor;
+	Color _ambientLightColor;
 
-		int _lightsCount;
-		Light *_lights;
-		
-		int _frame;
-		//char gap[28];
+	int _lightsCount;
+	Light *_lights;
 
-	public:
-		Lights(BladeRunnerEngine *vm);
-		~Lights();
+	int _frame;
+	//char gap[28];
 
-		void read(Common::ReadStream *stream, int framesCount);
-		void readVqa(Common::ReadStream *stream);
+public:
+	Lights(BladeRunnerEngine *vm);
+	~Lights();
 
-		void reset();
+	void read(Common::ReadStream *stream, int framesCount);
+	void readVqa(Common::ReadStream *stream);
 
-		void setupFrame(int frame);
+	void reset();
 
-	private:
+	void setupFrame(int frame);
+};
 
-	};
+} // End of namespace BladeRunner
 
-}
 #endif
diff --git a/engines/bladerunner/matrix.cpp b/engines/bladerunner/matrix.cpp
index fae8e43..db4d4d5 100644
--- a/engines/bladerunner/matrix.cpp
+++ b/engines/bladerunner/matrix.cpp
@@ -166,16 +166,20 @@ Matrix4x3 invertMatrix(const Matrix4x3 &m)
 	return result;
 }
 
-
 void Matrix4x3::unknown()
 {
-	float m14 = _m[0][3];
-	float m24 = _m[1][3];
-	float m34 = _m[2][3];
+	Matrix4x3 t;
 
-	_m[0][3] = -(m34 * _m[0][2]) - m24 * _m[0][1] - m14 * _m[0][0];
-	_m[1][3] = -(m34 * _m[1][2]) - m24 * _m[1][1] - m14 * _m[1][0];
-	_m[2][3] = -(m34 * _m[2][2]) - m24 * _m[2][1] - m14 * _m[2][0];
+	// Transpose the 3x3 top left submatrix
+	for (int r = 0; r != 3; ++r)
+		for (int c = 0; c != 3; ++c)
+			t(r, c) = _m[c][r];
 
+	t(0,3) = -(_m[0][3] * _m[0][0] + _m[1][3] * _m[1][0] + _m[2][3] * _m[2][0]);
+	t(1,3) = -(_m[0][3] * _m[0][1] + _m[1][3] * _m[1][1] + _m[2][3] * _m[2][1]);
+	t(2,3) = -(_m[0][3] * _m[0][2] + _m[1][3] * _m[1][2] + _m[2][3] * _m[2][2]);
+
+	*this = t;
 }
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/matrix.h b/engines/bladerunner/matrix.h
index cb7bc2f..4450306 100644
--- a/engines/bladerunner/matrix.h
+++ b/engines/bladerunner/matrix.h
@@ -93,6 +93,7 @@ public:
 
 	      float &operator()(int r, int c)       { assert(r >= 0 && r < 3); assert(c >= 0 && c < 4); return _m[r][c]; }
 	const float &operator()(int r, int c) const { assert(r >= 0 && r < 3); assert(c >= 0 && c < 4); return _m[r][c]; }
+
 	void unknown();
 };
 
@@ -128,8 +129,6 @@ Vector3 operator*(const Matrix4x3 &m, const Vector3 &v)
 	return r;
 }
 
-
-
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 7ec48f6..e6b8e43 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -2,6 +2,9 @@ MODULE := engines/bladerunner
 
 MODULE_OBJS = \
 	actor.o \
+	actor_clues.o \
+	actor_combat.o \
+	actor_walk.o \
 	adpcm_decoder.o \
 	ambient_sounds.o \
 	archive.o \
@@ -12,28 +15,41 @@ MODULE_OBJS = \
 	boundingbox.o \
 	chapters.o \
 	clues.o \
+	combat.o \
 	decompress_lcw.o \
 	decompress_lzo.o \
 	detection.o \
+	fog.o \
 	gameflags.o \
 	gameinfo.o \
 	image.o \
+	item.o \
+	items.o \
+	light.o \
+	lights.o \
 	matrix.o \
 	mouse.o \
+	movement_track.o \
 	outtake.o \
+	regions.o \
 	scene.o \
+	scene_objects.o \
+	script/ai_00_mccoy.o \
+	script/aiscript_officer_leroy.o \
 	script/init.o \
 	script/rc01.o \
 	script/script.o \
 	set.o \
 	settings.o \
+	set_effects.o \
 	shape.o \
 	slice_animations.o \
 	slice_renderer.o \
 	text_resource.o \
 	view.o \
 	vqa_decoder.o \
-	vqa_player.o
+	vqa_player.o \
+	waypoints.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_BLADERUNNER), DYNAMIC_PLUGIN)
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 64c64b2..ba747c2 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -23,11 +23,11 @@
 #include "bladerunner/mouse.h"
 
 #include "bladerunner/bladerunner.h"
-#include "bladerunner/shape.h"
 #include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
+#include "bladerunner/shape.h"
 
 #include "graphics/surface.h"
-#include "common/rect.h"
 
 namespace BladeRunner {
 
@@ -169,7 +169,6 @@ void Mouse::draw(Graphics::Surface &surface, int x, int y) {
 	_x = CLIP(x, 0, surface.w - 1);
 	_y = CLIP(y, 0, surface.h - 1);
 
-
 	if (_cursor < 0 || (uint)_cursor >= _vm->_shapes.size()) {
 		return;
 	}
@@ -254,43 +253,78 @@ void Mouse::tick(int x, int y)
 	if (!_vm->playerHasControl() || isDisabled())
 		return;
 
-	Vector3 mousePosition;
+	Vector3 mousePosition = getXYZ(x, y);
+	int cursorId = 0;
 
-	getXYZ(x, y, &mousePosition);
 	int isClickable = 0;
-	int isObstacle = 0;
-	int isCombatTarget = 0;
-	int sceneObjectId = _vm->_sceneObjects->findByXYZ(&isClickable, &isObstacle, &isCombatTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
-	//debug("mouse tick: objectid = %d", sceneObjectId);
+	int isObstacle  = 0;
+	int isTarget    = 0;
+
+	int sceneObjectId = _vm->_sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
+	int exitType = _vm->_scene->_exits->getTypeAtXY(x, y);
+
+	if (sceneObjectId >= 0 && sceneObjectId <= 74) {
+		exitType = -1;
+	}
+
+	if (exitType != -1) {
+		switch (exitType) {
+			case 1:
+				cursorId = 13;
+				break;
+			case 2:
+				cursorId = 14;
+				break;
+			case 3:
+				cursorId = 15;
+				break;
+			default:
+				cursorId = 12;
+		}
+		setCursor(cursorId);
+		return;
+	}
+
+	if (true /* not in combat */) {
+		if (sceneObjectId == 0
+		 || (sceneObjectId >= 0 && isClickable)
+		 || _vm->_scene->_regions->getRegionAtXY(x, y) >= 0)
+		{
+			cursorId = 1;
+		}
+		setCursor(cursorId);
+		return;
+	}
+
+	setCursor(cursorId);
 }
 
-void Mouse::getXYZ(int x, int y, Vector3* mousePosition)
+// TEST: RC01 after intro: [290, 216] -> [-204.589249 51.450668 7.659241]
+Vector3 Mouse::getXYZ(int x, int y)
 {
-	if (_vm->_scene->_setId == -1)
-		return;
+	if (_vm->_scene->getSetId() == -1)
+		return Vector3();
 
 	int screenRight = 640 - x;
-	int screenDown = 480 - y;
-	
-	float zcoef = 1.0f / tan(_vm->_view->_fovX / 2.0f);
+	int screenDown  = 480 - y;
+
+	float zcoef = 1.0f / tan(_vm->_scene->_view._fovX / 2.0f);
+
+	float x3d = (2.0f / 640.0f * screenRight - 1.0f);
+	float y3d = (2.0f / 480.0f * screenDown  - 1.0f) * 0.75f;
 
-	float x3d = (2.0f / 640.0f * screenRight - 1)  * zcoef / (1*zcoef);
-	float y3d = (2.0f / 480.0f * screenDown- 1) / (4/3 * zcoef) * zcoef;
+	uint16 zbufval = _vm->_zBuffer1[x + y * 640];
 
-	uint16 zbufval = _vm->_zBuffer1[x + y * 480];
+	Vector3 pos;
+	pos.z = zbufval / 25.5f;
+	pos.x = pos.z / zcoef * x3d;
+	pos.y = pos.z / zcoef * y3d;
 
-	Vector3 vector;
-	vector.z = zbufval / 25.5f;
-	vector.x = vector.z / zcoef * x3d;
-	vector.y = vector.z / zcoef * y3d;
+	Matrix4x3 matrix = _vm->_scene->_view._frameViewMatrix;
 
-	Matrix4x3 matrix = _vm->_view->_frameViewMatrix;
 	matrix.unknown();
-	vector = matrix * vector;
 
-	mousePosition->x = vector.x;
-	mousePosition->y = vector.y;
-	mousePosition->z = vector.z;
+	return matrix * pos;
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/mouse.h b/engines/bladerunner/mouse.h
index d708960..8fb5f32 100644
--- a/engines/bladerunner/mouse.h
+++ b/engines/bladerunner/mouse.h
@@ -23,14 +23,15 @@
 #ifndef BLADERUNNER_MOUSE_H
 #define BLADERUNNER_MOUSE_H
 
+#include "bladerunner/vector.h"
+
 namespace Graphics {
 	struct Surface;
 }
 
 namespace BladeRunner {
-	class Vector3;
 
-	class BladeRunnerEngine;
+class BladeRunnerEngine;
 
 class Mouse {
 	BladeRunnerEngine *_vm;
@@ -59,8 +60,9 @@ public:
 	void updateCursorFrame();
 
 	void tick(int x, int y);
-private:
-	void Mouse::getXYZ(int x, int y, Vector3* mousePosition);
+
+// private:
+	Vector3 getXYZ(int x, int y);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
index 01dff24..0913e77 100644
--- a/engines/bladerunner/movement_track.cpp
+++ b/engines/bladerunner/movement_track.cpp
@@ -23,102 +23,105 @@
 #include "bladerunner/movement_track.h"
 
 namespace BladeRunner {
-	MovementTrack::MovementTrack()
-	{
-		reset();
-	}
 
-	MovementTrack::~MovementTrack()
-	{
-		reset();
-	}
+MovementTrack::MovementTrack()
+{
+	reset();
+}
 
-	void MovementTrack::reset()
-	{
-		_currentIndex = -1;
-		_lastIndex = -1;
-		_hasNext = 0;
-		_paused = 0;
-		for (int i = 0; i < 100; i++)
-		{
-			_entries[i].waypointId = -1;
-			_entries[i].delay = -1;
-			_entries[i].angle = -1;
-			_entries[i].running = 0;
-		}
-	}
+MovementTrack::~MovementTrack()
+{
+	reset();
+}
 
-	int MovementTrack::append(int waypointId, int delay, int running)
+void MovementTrack::reset()
+{
+	_currentIndex = -1;
+	_lastIndex = -1;
+	_hasNext = 0;
+	_paused = 0;
+	for (int i = 0; i < 100; i++)
 	{
-		return append(waypointId, delay, -1, running);
+		_entries[i].waypointId = -1;
+		_entries[i].delay = -1;
+		_entries[i].angle = -1;
+		_entries[i].running = 0;
 	}
+}
 
-	int MovementTrack::append(int waypointId, int delay, int angle, int running)
-	{
-		if (_lastIndex > sizeof(_entries))
-			return 0;
-		_entries[_lastIndex].waypointId = waypointId;
-		_entries[_lastIndex].delay = delay;
-		_entries[_lastIndex].angle = angle;
-		_entries[_lastIndex].running = running;
-
-		_lastIndex++;
-		_hasNext = 1;
-		_currentIndex = 0;
-		return 1;
-	}
+int MovementTrack::append(int waypointId, int delay, int running)
+{
+	return append(waypointId, delay, -1, running);
+}
 
-	void MovementTrack::flush()
-	{
-		reset();
-	}
+int MovementTrack::append(int waypointId, int delay, int angle, int running)
+{
+	if (_lastIndex > ARRAYSIZE(_entries))
+		return 0;
 
-	void MovementTrack::repeat()
-	{
-		_currentIndex = 0;
-		_hasNext = 1;
-	}
+	_entries[_lastIndex].waypointId = waypointId;
+	_entries[_lastIndex].delay = delay;
+	_entries[_lastIndex].angle = angle;
+	_entries[_lastIndex].running = running;
 
-	int MovementTrack::pause()
-	{
-		_paused = 1;
-		return 1;
-	}
+	_lastIndex++;
+	_hasNext = 1;
+	_currentIndex = 0;
+	return 1;
+}
 
-	int MovementTrack::unpause()
-	{
-		_paused = 0;
-		return 1;
-	}
+void MovementTrack::flush()
+{
+	reset();
+}
 
-	int MovementTrack::isPaused()
-	{
-		return _paused;
-	}
+void MovementTrack::repeat()
+{
+	_currentIndex = 0;
+	_hasNext = 1;
+}
+
+int MovementTrack::pause()
+{
+	_paused = 1;
+	return 1;
+}
 
-	int MovementTrack::hasNext()
+int MovementTrack::unpause()
+{
+	_paused = 0;
+	return 1;
+}
+
+int MovementTrack::isPaused()
+{
+	return _paused;
+}
+
+int MovementTrack::hasNext()
+{
+	return _hasNext;
+}
+
+int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running)
+{
+	if (_currentIndex < _lastIndex && this->_hasNext)
 	{
-		return _hasNext;
+		*waypointId = _entries[_currentIndex].waypointId;
+		*delay = _entries[_currentIndex].delay;
+		*angle = _entries[_currentIndex].angle;
+		*running = _entries[_currentIndex++].running;
+		return 1;
 	}
-
-	int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running)
+	else
 	{
-		if (_currentIndex < _lastIndex && this->_hasNext)
-		{
-			*waypointId = _entries[_currentIndex].waypointId;
-			*delay = _entries[_currentIndex].delay;
-			*angle = _entries[_currentIndex].angle;
-			*running = _entries[_currentIndex++].running;
-			return 1;
-		}
-		else
-		{
-			*waypointId = -1;
-			*delay = -1;
-			*angle = -1;
-			*running = 0;
-			_hasNext = 0;
-			return 0;
-		}
+		*waypointId = -1;
+		*delay = -1;
+		*angle = -1;
+		*running = 0;
+		_hasNext = 0;
+		return 0;
 	}
-}
\ No newline at end of file
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
index 491de80..30ac07e 100644
--- a/engines/bladerunner/movement_track.h
+++ b/engines/bladerunner/movement_track.h
@@ -25,46 +25,46 @@
 
 #include "bladerunner/bladerunner.h"
 
-
 namespace BladeRunner {
 
-	class BladeRunnerEngine;
-	class BoundingBox;
+class BladeRunnerEngine;
+class BoundingBox;
+
+struct MovementTrackEntry
+{
+	int waypointId;
+	int delay;
+	int angle;
+	int running;
+};
 
-	struct MovementTrackEntry
-	{
-		int waypointId;
-		int delay;
-		int angle;
-		int running;
-	};
+class MovementTrack {
+	BladeRunnerEngine *_vm;
 
-	class MovementTrack {
-		BladeRunnerEngine *_vm;
+private:
+	int _currentIndex;
+	int _lastIndex;
+	int _hasNext;
+	int _paused;
+	MovementTrackEntry _entries[100];
+	void reset();
 
-	private:
-		int _currentIndex;
-		int _lastIndex;
-		int _hasNext;
-		int _paused;
-		MovementTrackEntry _entries[100];
-		void reset();
+public:
+	MovementTrack();
+	~MovementTrack();
+	int append(int waypointId, int delay, int running);
+	int append(int waypointId, int delay, int angle, int running);
+	void flush();
+	void repeat();
+	int pause();
+	int unpause();
+	int isPaused();
+	int hasNext();
+	int next(int *waypointId, int *delay, int *angle, int *running);
 
-	public:
-		MovementTrack();
-		~MovementTrack();
-		int append(int waypointId, int delay, int running);
-		int append(int waypointId, int delay, int angle, int running);
-		void flush();
-		void repeat();
-		int pause();
-		int unpause();
-		int isPaused();
-		int hasNext();
-		int next(int *waypointId, int *delay, int *angle, int *running);
+	//int saveGame();
+};
 
-		//int saveGame();
-	};
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/outtake.cpp b/engines/bladerunner/outtake.cpp
index 3ffc964..b81b212 100644
--- a/engines/bladerunner/outtake.cpp
+++ b/engines/bladerunner/outtake.cpp
@@ -43,7 +43,7 @@ void OuttakePlayer::play(const Common::String &name, bool noLocalization, int co
 	else
 		resName = name + "_E.VQA";
 
-	VQAPlayer vqa_player(_vm, _vm->_view);
+	VQAPlayer vqa_player(_vm);
 
 	vqa_player.open(resName);
 
diff --git a/engines/bladerunner/regions.cpp b/engines/bladerunner/regions.cpp
index fe817e0..f75be0f 100644
--- a/engines/bladerunner/regions.cpp
+++ b/engines/bladerunner/regions.cpp
@@ -1,47 +1,84 @@
 #include "bladerunner/regions.h"
 
 namespace BladeRunner {
-	Regions::Regions() {
-		_enabled = true;
-		_regions = new Region[10];
-	}
 
-	Regions::~Regions() {
-		delete[] _regions;
-	}
+Regions::Regions() {
+	_enabled = true;
+	_regions = new Region[10];
+	clear();
+}
 
-	bool Regions::add(int index, Common::Rect rect, int type) {
-		if (index <= 0 || index >= 10)
-			return false;
+Regions::~Regions() {
+	delete[] _regions;
+}
 
-		if (_regions[index]._present)
-			return false;
+void BladeRunner::Regions::clear() {
+	for (int i = 0; i < 10; ++i)
+		remove(i);
+}
 
-		_regions[index]._rectangle = rect;
-		_regions[index]._type = type;
-		_regions[index]._present = 1;
+bool Regions::add(int index, Common::Rect rect, int type) {
+	if (index < 0 || index >= 10)
+		return false;
 
-		return true;
-	}
+	if (_regions[index]._present)
+		return false;
 
-	bool Regions::remove(int index) {
-		if (index <= 0 || index >= 10)
-			return false;
+	_regions[index]._rectangle = rect;
+	_regions[index]._type = type;
+	_regions[index]._present = 1;
 
-		_regions[index]._rectangle = Common::Rect(-1, -1, -1, -1);
-		_regions[index]._type = -1;
-		_regions[index]._present = 0;
+	return true;
+}
 
-		return true;
-	}
+bool Regions::remove(int index) {
+	if (index < 0 || index >= 10)
+		return false;
 
-	void BladeRunner::Regions::clear() {
-		int i;
-		for (i = 0; i < 10; i++)
-			remove(i);
-	}
+	_regions[index]._rectangle = Common::Rect(-1, -1, -1, -1);
+	_regions[index]._type = -1;
+	_regions[index]._present = 0;
+
+	return true;
+}
+
+int Regions::getTypeAtXY(int x, int y) {
+	int index = getRegionAtXY(x, y);
+
+	if (index == -1)
+		return -1;
 
-	void Regions::setEnabled(bool enabled) {
-		_enabled = enabled;
+	return _regions[index]._type;
+}
+
+int Regions::getRegionAtXY(int x, int y) {
+	if (!_enabled)
+		return -1;
+
+	for (int i = 0; i != 10; ++i) {
+		if (!_regions[i]._present)
+			continue;
+
+		// Common::Rect::contains is exclusive of right and bottom but
+		// Blade Runner wants inclusive, so we adjust the edges.
+		// TODO: Roll our own rect class?
+		Common::Rect r = _regions[i]._rectangle;
+		r.right++;
+		r.bottom++;
+
+		if (r.contains(x, y))
+			return i;
 	}
-}
\ No newline at end of file
+
+	return -1;
+}
+
+void Regions::setEnabled(bool enabled) {
+	_enabled = enabled;
+}
+
+void Regions::enable() {
+	_enabled = true;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
index e92e812..8a65aed 100644
--- a/engines/bladerunner/regions.h
+++ b/engines/bladerunner/regions.h
@@ -27,29 +27,35 @@
 
 #include "common/rect.h"
 
-
 namespace BladeRunner {
-	struct Region
-	{
-		Common::Rect _rectangle;
-		int _type;
-		int _present;
-	};
-
-	class Regions
-	{
-	private:
-		Region* _regions;
-		bool _enabled;
-	public:
-		Regions();
-		~Regions();
-
-		bool add(int index, Common::Rect rect, int type);
-		bool remove(int index);
-		void clear();
-
-		void setEnabled(bool enabled);
-	};
-}
+
+struct Region
+{
+	Common::Rect _rectangle;
+	int _type;
+	int _present;
+};
+
+class Regions
+{
+private:
+	Region* _regions;
+	bool _enabled;
+public:
+	Regions();
+	~Regions();
+
+	void clear();
+	bool add(int index, Common::Rect rect, int type);
+	bool remove(int index);
+
+	int getTypeAtXY(int x, int y);
+	int getRegionAtXY(int x, int y);
+
+	void setEnabled(bool enabled);
+	void enable();
+};
+
+} // End of namespace BladeRunner
+
 #endif
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 3c04ee8..ba4ca44 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -27,9 +27,9 @@
 #include "bladerunner/actor.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
+#include "bladerunner/scene_objects.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/slice_renderer.h"
-#include "bladerunner/scene_objects.h"
 
 #include "common/str.h"
 #include "common/stream.h"
@@ -40,7 +40,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (!isLoadingGame) {
 		// flush ADQ
 	}
-	// reset mouse button status
+
 	_setId = setId;
 	_sceneId = sceneId;
 
@@ -51,11 +51,15 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	} else {
 		_regions->clear();
 		_exits->clear();
-		// reset aesc
+		// TODO: Reset aesc
+		// TODO: Clear regions
 		// TODO: Destroy all overlays
-		_defaultLoop = 0;
-		_frame = -1;
-		//_loopStartSpecial = -1;
+		_defaultLoop         =  0;
+		_defaultLoopSet      =  0;
+		_field_20_loop_stuff =  0;
+		_specialLoopMode     = -1;
+		_specialLoop         = -1;
+		_frame               = -1;
 	}
 
 	Common::String vqaName;
@@ -80,26 +84,26 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (!_set->open(setResourceName))
 		return false;
 
-	_vm->_sliceRenderer->setView(_vm->_view);
+	_vm->_sliceRenderer->setView(*_vm->_view);
 
 	if (isLoadingGame) {
-		// resume()
-		if (sceneId >= 73 && sceneId <= 76) {
-			_vm->_script->SceneLoaded();
-			return true;
-		}
+		// TODO: Advance VQA frame
+		if (sceneId >= 73 && sceneId <= 76)
+			_vm->_script->InitializeScene();
+		return true;
 	}
 
 	// TODO: set VQADecoder parameters
 
 	// TODO: Set actor position from scene info
-	//advance frame 0
-	_vm->_playerActor->set_at_xyz(_actorStartPosition, _actorStartFacing, false, 0, 0);
+	_vm->_playerActor->setAtXYZ(_actorStartPosition, _actorStartFacing);
+
 	// TODO: Set actor set
+
 	_vm->_script->SceneLoaded();
 
 	_vm->_sceneObjects->clear();
-	
+
 	// Init click map
 	int actorCount = _vm->_gameInfo->getActorCount();
 	for (int i = 0; i != actorCount; ++i) {
@@ -115,15 +119,15 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 				actor->isRetired());
 		}
 	}
-	
+
 	_set->addObjectsToScene(_vm->_sceneObjects);
-	//add all items to scene
-	//calculate walking obstacles??
+	// TODO: add all items to scene
+	// TODO: calculate walking obstacles??
+
+	// if (_playerWalkedIn) { // TODO: Not _playerWalkedIn
+	// 	_vm->_script->PlayerWalkedIn();
+	// }
 
-	 if (_playerWalkedIn) {
-		//_vm->_script->PlayerWalkedIn();
-	 }
-	
 	return true;
 }
 
@@ -132,9 +136,23 @@ int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer.getSurface());
 		memcpy(zBuffer, _vqaPlayer.getZBuffer(), 640*480*2);
+		_view = _vqaPlayer.getView();
+	}
 
-		memcpy(surface.getPixels(), _vqaPlayer.getZBuffer(), 640 * 480 * 2);
+	if (frame < 0) {
+		return frame;
 	}
+	_frame = frame;
+
+	if (_specialLoopMode == 0 && frame == _vqaPlayer.getLoopEndFrame(_specialLoop)) {
+		_playerWalkedIn = true;
+		_specialLoopMode = -1;
+	}
+	if (_specialLoopMode == 0 && !_defaultLoopSet) {
+		_vqaPlayer.setLoop(_defaultLoop + 1);
+		_defaultLoopSet = true;
+	}
+
 	return frame;
 }
 
@@ -143,17 +161,29 @@ void Scene::setActorStart(Vector3 position, int facing) {
 	_actorStartFacing = facing;
 }
 
-
-int Scene::getSetId() {
-	return _setId;
+void Scene::loopSetDefault(int a) {
+	// warning("\t\t\tScene::loopSetDefault(%d)", a);
+	_defaultLoop = a;
 }
 
+void Scene::loopStartSpecial(int a, int b, int c) {
+	// warning("\t\t\tScene::loopStartSpecial(%d, %d, %d)", a, b, c);
+	_specialLoopMode = a;
+	_specialLoop = b;
 
-int Scene::getSceneId() {
-	return _sceneId;
+	if (_specialLoop == 1) {
+		// a1->on_loop_end_switch_to_set_id = sub_42BE08_options_get_set_enter_arg_1(&unk_48E910_options);
+		// a1->on_loop_end_switch_to_scene_id = sub_42BE00_options_get_set_enter_arg_2(&unk_48E910_options);
+	}
+
+	if (c) {
+		// _field_20_loop_stuff = 1;
+		// v6 = a1->_field_28_loop_special_loop_number;
+		// sub_453434_scene_method_loop(a1);
+	}
 }
 
-int Scene::findObject(char* objectName) {
+int Scene::findObject(const char *objectName) {
 	return _set->findObject(objectName);
 }
 
@@ -184,7 +214,7 @@ void Scene::objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded,
 
 void Scene::objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded) {
 	int i;
-	for (i = 0; i < (int)_set->_objectCount; i++) {
+	for (i = 0; i < (int)_set->getObjectCount(); i++) {
 		_set->objectSetIsObstacle(i, isObstacle);
 		if (sceneLoaded) {
 			_vm->_sceneObjects->setIsObstacle(i + 198, isObstacle);
@@ -192,11 +222,15 @@ void Scene::objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded) {
 	}
 }
 
-void Scene::objectSetIsCombatTarget(int objectId, bool isCombatTarget, bool sceneLoaded) {
-	_set->objectSetIsCombatTarget(objectId, isCombatTarget);
+void Scene::objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded) {
+	_set->objectSetIsTarget(objectId, isTarget);
 	if (sceneLoaded) {
-		_vm->_sceneObjects->setIsCombatTarget(objectId + 198, isCombatTarget);
+		_vm->_sceneObjects->setIsTarget(objectId + 198, isTarget);
 	}
 }
 
+const char *Scene::objectGetName(int objectId) {
+	return _set->objectGetName(objectId);
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index cabd912..1a3c9f3 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -25,10 +25,10 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/regions.h"
 #include "bladerunner/set.h"
-//#include "bladerunner/view.h"
+#include "bladerunner/view.h"
 #include "bladerunner/vqa_player.h"
-#include "bladerunner/regions.h"
 
 namespace BladeRunner {
 
@@ -42,27 +42,41 @@ public:
 	int         _setId;
 	int         _sceneId;
 	VQAPlayer   _vqaPlayer;
+
 	int         _defaultLoop;
+	int         _defaultLoopSet;
+	int         _field_20_loop_stuff;
+	int         _specialLoopMode;
+	int         _specialLoop;
+	int         _introFinished;
 	int         _nextSetId;
 	int         _nextSceneId;
 	int         _frame;
+
 	Vector3     _actorStartPosition;
 	int         _actorStartFacing;
 	bool        _playerWalkedIn;
+	View        _view;
+
 	Regions*    _regions;
 	Regions*    _exits;
 
+	// _default_loop_id = 0;
+	// _scene_vqa_frame_number = -1;
+
+
 public:
 	Scene(BladeRunnerEngine *vm)
 		: _vm(vm),
 		  _set(new Set(vm)),
 		  _setId(-1),
 		  _sceneId(-1),
-		  _vqaPlayer(vm, vm->_view),
+		  _vqaPlayer(vm),
 		  _defaultLoop(0),
 		  _nextSetId(-1),
 		  _nextSceneId(-1),
 		  _playerWalkedIn(false),
+		  _introFinished(false),
 		  _regions(new Regions()),
 		  _exits(new Regions())
 	{}
@@ -76,15 +90,23 @@ public:
 	bool open(int setId, int sceneId, bool isLoadingGame);
 	int  advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer);
 	void setActorStart(Vector3 position, int facing);
-	int getSetId();
-	int getSceneId();
-	int findObject(char *objectName);
+
+	void loopSetDefault(int a);
+	void loopStartSpecial(int a, int b, int c);
+
+	int getSetId()   { return _setId; }
+	int getSceneId() { return _sceneId; }
+
+	bool didPlayerWalkIn() { bool r = _playerWalkedIn; _playerWalkedIn = false; return r; }
+
+	int findObject(const char *objectName);
 	bool objectSetHotMouse(int objectId);
 	bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
 	void objectSetIsClickable(int objectId, bool isClickable, bool sceneLoaded);
 	void objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded, bool updateWalkpath);
 	void objectSetIsObstacleAll(bool isObstacle, bool sceneLoaded);
-	void objectSetIsCombatTarget(int objectId, bool isCombatTarget, bool sceneLoaded);
+	void objectSetIsTarget(int objectId, bool isTarget, bool sceneLoaded);
+	const char *objectGetName(int objectId);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index ec9e247..ba09edf 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -1,5 +1,29 @@
+/* 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 "bladerunner/scene_objects.h"
 
+#include "bladerunner/view.h"
+
 namespace BladeRunner {
 
 SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
@@ -10,8 +34,7 @@ SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
 	_sceneObjects = new SceneObject[SCENE_OBJECTS_COUNT];
 	_sceneObjectsSortedByDistance = new int[SCENE_OBJECTS_COUNT];
 
-	int i;
-	for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+	for (int i = 0; i < SCENE_OBJECTS_COUNT; ++i) {
 		_sceneObjectsSortedByDistance[i] = -1;
 	}
 }
@@ -25,10 +48,8 @@ SceneObjects::~SceneObjects() {
 	delete[] _sceneObjects;
 }
 
-
 void SceneObjects::clear() {
-	int i;
-	for (i = 0; i < SCENE_OBJECTS_COUNT; i++) {
+	for (int i = 0; i < SCENE_OBJECTS_COUNT; ++i) {
 		_sceneObjects[i]._sceneObjectId = -1;
 		_sceneObjects[i]._sceneObjectType = SceneObjectTypeUnknown;
 		_sceneObjects[i]._distanceToCamera = 0;
@@ -36,39 +57,39 @@ void SceneObjects::clear() {
 		_sceneObjects[i]._isClickable = 0;
 		_sceneObjects[i]._isObstacle = 0;
 		_sceneObjects[i]._unknown1 = 0;
-		_sceneObjects[i]._isCombatTarget = 0;
+		_sceneObjects[i]._isTarget = 0;
 		_sceneObjects[i]._isMoving = 0;
 		_sceneObjects[i]._isRetired = 0;
 	}
 }
 
-bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isCombatTarget, uint8 isRetired) {
-	return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isCombatTarget, isMoving, isRetired);
+bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isTarget, uint8 isRetired) {
+	return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isTarget, isMoving, isRetired);
 }
 
-bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget) {
+bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget) {
 	Common::Rect rect(-1, -1, -1, -1);
-	return addSceneObject(sceneObjectId, SceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isCombatTarget, 0, 0);
+	return addSceneObject(sceneObjectId, SceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isTarget, 0, 0);
 }
 
-bool SceneObjects::addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle) {
-	return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isCombatTarget, 0, 0);
+bool SceneObjects::addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isTarget, uint8 isObstacle) {
+	return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isTarget, 0, 0);
 }
 
 bool SceneObjects::remove(int sceneObjectId)
 {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return false;
 	}
+
 	int j;
-	for (j = 0; j < _count; j++) {
+	for (j = 0; j < _count; ++j) {
 		if (_sceneObjectsSortedByDistance[j] == i) {
 			break;
 		}
 	}
-	int k;
-	for (k = j; k < _count - 1; k++) {
+	for (int k = j; k < _count - 1; ++k) {
 		_sceneObjectsSortedByDistance[k] = _sceneObjectsSortedByDistance[k + 1];
 	}
 
@@ -76,36 +97,33 @@ bool SceneObjects::remove(int sceneObjectId)
 	return true;
 }
 
-int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget) {
-	BoundingBox boundingBox;
+int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isTarget, float x, float y, float z, int findClickables, int findObstacles, int findTargets) {
 	*isClickable = 0;
-	*isObstacle = 0;
-	*isCombatTarget = 0;
+	*isObstacle  = 0;
+	*isTarget    = 0;
 
-	if (!_count)
-		return -1;
+	for (int i = 0; i < _count; ++i) {
+		assert(_sceneObjectsSortedByDistance[i] < _count);
 
-	int i;
-	for (i = 0; i < _count; i++) {
-		//assert(_sceneObjectsSortedByDistance[i] < _count);
-		SceneObject *sceneObject = &_sceneObjects[_sceneObjectsSortedByDistance[i]];
-		if ((mustBeClickable && !sceneObject->_isClickable)
-			|| (mustBeObstacle && !sceneObject->_isObstacle)
-			|| (mustBeCombatTarget && !sceneObject->_isCombatTarget)) {
-			continue;
-		}
+		SceneObject &sceneObject = _sceneObjects[_sceneObjectsSortedByDistance[i]];
 
-		boundingBox = sceneObject->_boundingBox;
+		if ((findClickables && sceneObject._isClickable) ||
+		    (findObstacles  && sceneObject._isObstacle)  ||
+		    (findTargets    && sceneObject._isTarget))
+		{
+			BoundingBox boundingBox = sceneObject._boundingBox;
 
-		if (sceneObject->_sceneObjectType == SceneObjectTypeObject || sceneObject->_sceneObjectType == SceneObjectTypeItem) {
-			boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
-		}
+			if (sceneObject._sceneObjectType == SceneObjectTypeObject || sceneObject._sceneObjectType == SceneObjectTypeItem) {
+				boundingBox.expand(-4.0, 0.0, -4.0, 4.0, 0.0, 4.0);
+			}
+
+			if (boundingBox.inside(x, y, z)) {
+				*isClickable = sceneObject._isClickable;
+				*isObstacle  = sceneObject._isObstacle;
+				*isTarget    = sceneObject._isTarget;
 
-		if (boundingBox.inside(x, y, z)) {
-			*isClickable = sceneObject->_isClickable;
-			*isObstacle = sceneObject->_isObstacle;
-			*isCombatTarget = sceneObject->_isCombatTarget;
-			return sceneObject->_sceneObjectId;
+				return sceneObject._sceneObjectId;
+			}
 		}
 	}
 
@@ -114,8 +132,7 @@ int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarg
 
 int SceneObjects::findById(int sceneObjectId)
 {
-	int i;
-	for (i = 0; i < _count; i++) {
+	for (int i = 0; i < _count; ++i) {
 		if (_sceneObjects[i]._present && _sceneObjects[i]._sceneObjectId == sceneObjectId) {
 			return i;
 		}
@@ -123,23 +140,23 @@ int SceneObjects::findById(int sceneObjectId)
 	return -1;
 }
 
-bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint isMoving, uint isRetired) {
+bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget, uint isMoving, uint isRetired) {
 	int index = findEmpty();
-	if (_count >= SCENE_OBJECTS_COUNT || index == -1) {
+	if (index == -1) {
 		return false;
 	}
 
-	_sceneObjects[index]._sceneObjectId = sceneObjectId;
+	_sceneObjects[index]._sceneObjectId   = sceneObjectId;
 	_sceneObjects[index]._sceneObjectType = sceneObjectType;
-	_sceneObjects[index]._present = 1;
-	_sceneObjects[index]._boundingBox = *boundingBox;
+	_sceneObjects[index]._present         = 1;
+	_sceneObjects[index]._boundingBox     = *boundingBox;
 	_sceneObjects[index]._screenRectangle = *screenRectangle;
-	_sceneObjects[index]._isClickable = isClickable;
-	_sceneObjects[index]._isObstacle = isObstacle;
-	_sceneObjects[index]._unknown1 = unknown1;
-	_sceneObjects[index]._isCombatTarget = isCombatTarget;
-	_sceneObjects[index]._isMoving = isMoving;
-	_sceneObjects[index]._isRetired = isRetired;
+	_sceneObjects[index]._isClickable     = isClickable;
+	_sceneObjects[index]._isObstacle      = isObstacle;
+	_sceneObjects[index]._unknown1        = unknown1;
+	_sceneObjects[index]._isTarget        = isTarget;
+	_sceneObjects[index]._isMoving        = isMoving;
+	_sceneObjects[index]._isRetired       = isRetired;
 
 	float centerZ = (_sceneObjects[index]._boundingBox.getZ0() + _sceneObjects[index]._boundingBox.getZ1()) / 2.0;
 
@@ -147,14 +164,13 @@ bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObject
 	_sceneObjects[index]._distanceToCamera = distanceToCamera;
 
 	// insert according to distance from camera
-	int i, j;
-	for (i = 0; i < _count; i++) {
+	int i;
+	for (i = 0; i < _count; ++i) {
 		if (distanceToCamera < _sceneObjects[_sceneObjectsSortedByDistance[i]]._distanceToCamera) {
 			break;
 		}
 	}
-
-	for (j = _count - 1; j >= i; j--) {
+	for (int j = _count - 1; j >= i; --j) {
 		_sceneObjectsSortedByDistance[j + 1] = _sceneObjectsSortedByDistance[j];
 	}
 
@@ -164,9 +180,7 @@ bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObject
 }
 
 int SceneObjects::findEmpty() {
-	int i;
-	for (i = 0; i < SCENE_OBJECTS_COUNT; i++)
-	{
+	for (int i = 0; i < SCENE_OBJECTS_COUNT; ++i) {
 		if (!_sceneObjects[i]._present)
 			return i;
 	}
@@ -175,7 +189,7 @@ int SceneObjects::findEmpty() {
 
 void SceneObjects::setMoving(int sceneObjectId, bool isMoving) {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return;
 	}
 	_sceneObjects[i]._isMoving = isMoving;
@@ -183,7 +197,7 @@ void SceneObjects::setMoving(int sceneObjectId, bool isMoving) {
 
 void SceneObjects::setRetired(int sceneObjectId, bool isRetired) {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return;
 	}
 	_sceneObjects[i]._isRetired = isRetired;
@@ -191,12 +205,12 @@ void SceneObjects::setRetired(int sceneObjectId, bool isRetired) {
 
 bool SceneObjects::isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2) {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return false;
 	}
 
 	float objectX1, objectY1, objectZ1, objectX2, objectY2, objectZ2;
-	_sceneObjects[i]._boundingBox.getXyz(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
+	_sceneObjects[i]._boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
 
 	//TODO
 //		if (!lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ1, objectX2, objectZ1, &intersectionX, &intersectionY, &v18)
@@ -210,7 +224,7 @@ bool SceneObjects::isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x
 
 void SceneObjects::setIsClickable(int sceneObjectId, bool isClickable) {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return;
 	}
 	_sceneObjects[i]._isClickable = isClickable;
@@ -218,18 +232,18 @@ void SceneObjects::setIsClickable(int sceneObjectId, bool isClickable) {
 
 void SceneObjects::setIsObstacle(int sceneObjectId, bool isObstacle) {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return;
 	}
 	_sceneObjects[i]._isObstacle = isObstacle;
 }
 
-void SceneObjects::setIsCombatTarget(int sceneObjectId, bool isCombatTarget) {
+void SceneObjects::setIsTarget(int sceneObjectId, bool isTarget) {
 	int i = findById(sceneObjectId);
-	if (i == -1 || !_sceneObjects[i]._present) {
+	if (i == -1) {
 		return;
 	}
-	_sceneObjects[i]._isCombatTarget = isCombatTarget;
+	_sceneObjects[i]._isTarget = isTarget;
 }
 
 
@@ -237,4 +251,4 @@ void SceneObjects::updateWalkpath() {
 	//TODO: implement
 }
 
-}
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index bccb2ea..047301d 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -23,76 +23,76 @@
 #ifndef BLADERUNNER_SCENE_OBJECTS_H
 #define BLADERUNNER_SCENE_OBJECTS_H
 
-#include "bladerunner/bladerunner.h"
-
 #include "bladerunner/boundingbox.h"
-#include "bladerunner/view.h"
 
 #include "common/rect.h"
 
 namespace BladeRunner {
-	class BladeRunnerEngine;
 
-	enum SceneObjectType
-	{
-		SceneObjectTypeUnknown = -1,
-		SceneObjectTypeActor = 0,
-		SceneObjectTypeObject = 1,
-		SceneObjectTypeItem = 2,
-	};
+class BladeRunnerEngine;
+class View;
+
+enum SceneObjectType
+{
+	SceneObjectTypeUnknown = -1,
+	SceneObjectTypeActor = 0,
+	SceneObjectTypeObject = 1,
+	SceneObjectTypeItem = 2
+};
 
 #define SCENE_OBJECTS_COUNT 115
 #define SCENE_OBJECTS_ACTORS_OFFSET 0
 #define SCENE_OBJECTS_ITEMS_OFFSET 74
 #define SCENE_OBJECTS_OBJECTS_OFFSET 198
 
-	struct SceneObject
-	{
-		int _sceneObjectId;
-		SceneObjectType _sceneObjectType;
-		BoundingBox _boundingBox;
-		Common::Rect _screenRectangle;
-		float _distanceToCamera;
-		int _present;
-		int _isClickable;
-		int _isObstacle;
-		int _unknown1;
-		int _isCombatTarget;
-		int _isMoving;
-		int _isRetired;
-	};
+struct SceneObject
+{
+	int             _sceneObjectId;
+	SceneObjectType _sceneObjectType;
+	BoundingBox     _boundingBox;
+	Common::Rect    _screenRectangle;
+	float           _distanceToCamera;
+	int             _present;
+	int             _isClickable;
+	int             _isObstacle;
+	int             _unknown1;
+	int             _isTarget;
+	int             _isMoving;
+	int             _isRetired;
+};
+
+class SceneObjects {
+	BladeRunnerEngine *_vm;
 
+private:
+	View        *_view;
+	int          _count;
+	SceneObject *_sceneObjects;
+	int         *_sceneObjectsSortedByDistance;
 
-	class SceneObjects {
-		BladeRunnerEngine *_vm;
-	private:
-		View *_view;
-		int _count;
-		SceneObject *_sceneObjects;
-		int *_sceneObjectsSortedByDistance;
+public:
+	SceneObjects(BladeRunnerEngine *vm, View *view);
+	~SceneObjects();
+	bool addActor(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, uint8 isClickable, uint8 unknown1, uint8 isTarget, uint8 isRetired);
+	bool addObject(int sceneObjectId, BoundingBox *boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget);
+	bool addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, uint8 isTarget, uint8 isObstacle);
+	bool remove(int sceneObjectId);
+	void clear();
+	int findByXYZ(int *isClickable, int *isObstacle, int *isTarget, float x, float y, float z, int findClickables, int findObstacles, int findTargets);
+	void setMoving(int sceneObjectId, bool isMoving);
+	void setRetired(int sceneObjectId, bool isRetired);
+	bool isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2);
+	void setIsClickable(int sceneObjectId, bool isClickable);
+	void setIsObstacle(int sceneObjectId, bool isObstacle);
+	void setIsTarget(int sceneObjectId, bool isTarget);
+	void updateWalkpath();
 
-	public:
-		SceneObjects(BladeRunnerEngine *vm, View *view);
-		~SceneObjects();
-		bool addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 unknown1, uint8 isCombatTarget, uint8 isRetired);
-		bool addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget);
-		bool addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isCombatTarget, uint8 isObstacle);
-		bool remove(int sceneObjectId);
-		void clear();
-		int findByXYZ(int *isClickable, int *isObstacle, int *isCombatTarget, float x, float y, float z, int mustBeClickable, int mustBeObstacle, int mustBeCombatTarget);
-		void setMoving(int sceneObjectId, bool isMoving);
-		void setRetired(int sceneObjectId, bool isRetired);
-		bool isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2);
-		void setIsClickable(int sceneObjectId, bool isClickable);
-		void setIsObstacle(int sceneObjectId, bool isObstacle);
-		void setIsCombatTarget(int sceneObjectId, bool isCombatTarget);
-		void updateWalkpath();
-	private:
-		int findById(int sceneObjectId);
-		bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isCombatTarget, uint unknown2, uint isRetired);
-		int findEmpty();
-	};
+private:
+	int findById(int sceneObjectId);
+	bool addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget, uint unknown2, uint isRetired);
+	int findEmpty();
+};
 
+} // End of namespace BladeRunner
 
-}
 #endif
diff --git a/engines/bladerunner/script/ai_00_mccoy.cpp b/engines/bladerunner/script/ai_00_mccoy.cpp
new file mode 100644
index 0000000..2d722f1
--- /dev/null
+++ b/engines/bladerunner/script/ai_00_mccoy.cpp
@@ -0,0 +1,174 @@
+/* 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 "bladerunner/script/ai_00_mccoy.h"
+
+namespace BladeRunner {
+
+AIScript_McCoy::AIScript_McCoy(BladeRunnerEngine *vm)
+	: AIScriptBase(vm)
+{}
+
+void AIScript_McCoy::Initialize()
+{
+	dword_45A0D0_animation_state = 0;
+	dword_45A0D4 = 0;
+	dword_45A0D8 = 0;
+	dword_45A0DC = 30;
+	dword_45A0E0 = 1;
+	dword_45A0E4 = 0;
+	dword_45A0E8 = 3;
+}
+
+void AIScript_McCoy::UpdateAnimation(int *animation, int *frame)
+{
+	*animation = *frame = 0;
+	switch (dword_45A0D0_animation_state)
+	{
+		case 0:
+			*animation = 19;
+			if (dword_45A0D8 < dword_45A0DC)
+			{
+				*frame = dword_45A0E8;
+				dword_45A0D4 += dword_45A0E0;
+				if (dword_45A0D4 > dword_45A0E8)
+				{
+					dword_45A0D4 = dword_45A0E8;
+					dword_45A0E0 = -1;
+				}
+				else
+				{
+					*frame = dword_45A0D4;
+					if (dword_45A0D4 < dword_45A0E4)
+					{
+						dword_45A0D4 = dword_45A0E4;
+						dword_45A0E0 = 1;
+						*frame = dword_45A0E4;
+					}
+				}
+				dword_45A0D8++;
+			}
+			else
+			{
+				dword_45A0D4 += dword_45A0E0;
+				dword_45A0DC = 0;
+				if (dword_45A0D4 == 18 && Random_Query(0, 2))
+				{
+					dword_45A0E0 = -1;
+					dword_45A0D8 = 0;
+					dword_45A0E4 = 14;
+					dword_45A0E8 = 18;
+					dword_45A0DC = Random_Query(0, 30);
+				}
+				if (dword_45A0D4 == 26)
+				{
+					if (Random_Query(0, 2))
+					{
+						dword_45A0E0 = -1;
+						dword_45A0D8 = 0;
+						dword_45A0E4 = 23;
+						dword_45A0E8 = 26;
+						dword_45A0DC = Random_Query(0, 30);
+						}
+				}
+				if (dword_45A0D4 >= Slice_Animation_Query_Number_Of_Frames(19))
+				{
+					dword_45A0D4 = 0;
+					if (Random_Query(0, 2))
+					{
+						dword_45A0D8 = 0;
+						dword_45A0E4 = 0;
+						dword_45A0E8 = 3;
+						dword_45A0DC = Random_Query(0, 45);
+					}
+				}
+				*frame = dword_45A0D4;
+				if (dword_45A0D4 < 0)
+				{
+					*frame = Slice_Animation_Query_Number_Of_Frames(19) - 1;
+					dword_45A0D4 = *frame;
+				}
+			}
+			break;
+
+		// Continue walking (follows state 32)
+		case 30:
+			*animation = 13;
+			if (++dword_45A0D4 >= Slice_Animation_Query_Number_Of_Frames(13))
+				dword_45A0D4 = 0;
+			*frame = dword_45A0D4;
+
+			if (dword_45A0D4 == 2)
+				; //Sound_Right_Footstep_Walk(0);
+			else if (dword_45A0D4 == 10)
+				; //Sound_Left_Footstep_Walk(0);
+
+			break;
+
+		// Start walking
+		case 32:
+			dword_45A0D4 = 1;
+			dword_45A0D0_animation_state = 30;
+			*animation = 13;
+			*frame = 1;
+			break;
+
+		case 58:
+			*animation = 47;
+			if (dword_45A0D4++ == 5) {
+				int stepSound;
+				switch (Random_Query(0, 2)) {
+				case 0:
+					stepSound = 595;
+					break;
+				case 1:
+					stepSound = 594;
+					break;
+				default:
+					stepSound = 593;
+				}
+				(void)stepSound;
+				// Ambient_Sounds_Play_Sound(stepSound, 39, 0, 0, 99);
+			}
+			if (dword_45A0D4 > Slice_Animation_Query_Number_Of_Frames(*animation) - 2)
+				dword_45A0D4 = 0;
+			*frame = dword_45A0D4;
+			break;
+	}
+}
+
+void AIScript_McCoy::ChangeAnimationMode(int mode)
+{
+	switch (mode)
+	{
+		case 0:
+			dword_45A0D0_animation_state = 0;
+			dword_45A0D4 = 0;
+			break;
+
+		case 1:
+			dword_45A0D0_animation_state = 32;
+			break;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai_00_mccoy.h b/engines/bladerunner/script/ai_00_mccoy.h
new file mode 100644
index 0000000..11c9f1d
--- /dev/null
+++ b/engines/bladerunner/script/ai_00_mccoy.h
@@ -0,0 +1,45 @@
+/* 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 "bladerunner/script/script.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+class AIScript_McCoy : public AIScriptBase {
+	int dword_45A0D0_animation_state;
+	int dword_45A0D4;
+	int dword_45A0D8;
+	int dword_45A0DC;
+	int dword_45A0E0;
+	int dword_45A0E4;
+	int dword_45A0E8;
+public:
+	AIScript_McCoy(BladeRunnerEngine *vm);
+
+	void Initialize();
+	void UpdateAnimation(int *animation, int *frame);
+	void ChangeAnimationMode(int mode);
+};
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/aiscript_officer_leroy.cpp b/engines/bladerunner/script/aiscript_officer_leroy.cpp
new file mode 100644
index 0000000..1acb096
--- /dev/null
+++ b/engines/bladerunner/script/aiscript_officer_leroy.cpp
@@ -0,0 +1,87 @@
+/* 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 "bladerunner/script/aiscript_officer_leroy.h"
+
+namespace BladeRunner {
+
+AIScript_Officer_Leroy::AIScript_Officer_Leroy(BladeRunnerEngine *vm)
+	: AIScriptBase(vm)
+{}
+
+void AIScript_Officer_Leroy::Initialize()
+{
+	var_45D5B0_animation_state = 0;
+	var_45D5B4_frame = 0;
+	var_45D5B8 = 0;
+
+	Actor_Put_In_Set(23, 69);
+	Actor_Set_At_XYZ(23, -261.80f, 6.00f, 79.58f, 512);
+	// Actor_Set_Goal_Number(23, 0);
+	// Actor_Set_Frame_Rate_FPS(23, 8);
+}
+
+void AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
+{
+	if (var_45D5B8 == 0) {
+		*animation = 589;
+		var_45D5B4_frame++;
+
+		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(589))
+		{
+			var_45D5B4_frame = 0;
+			var_45D5B8 = Random_Query(0, 2);
+		}
+	} else if (var_45D5B8 == 1) {
+		*animation = 590;
+		var_45D5B4_frame++;
+
+		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(590))
+		{
+			var_45D5B4_frame = 0;
+			var_45D5B8 = Random_Query(0, 2);
+		}
+	} else if (var_45D5B8 == 2) {
+		*animation = 591;
+		var_45D5B4_frame++;
+
+		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(591))
+		{
+			var_45D5B4_frame = 0;
+			var_45D5B8 = Random_Query(0, 2);
+		}
+	}
+
+	*frame = var_45D5B4_frame;
+}
+
+void AIScript_Officer_Leroy::ChangeAnimationMode(int mode)
+{
+	switch (mode)
+	{
+		case 1:
+			var_45D5B0_animation_state = 32;
+			break;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/aiscript_officer_leroy.h b/engines/bladerunner/script/aiscript_officer_leroy.h
new file mode 100644
index 0000000..7d81b62
--- /dev/null
+++ b/engines/bladerunner/script/aiscript_officer_leroy.h
@@ -0,0 +1,41 @@
+/* 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 "bladerunner/script/script.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+class AIScript_Officer_Leroy : public AIScriptBase {
+	int var_45D5B0_animation_state;
+	int var_45D5B4_frame;
+	int var_45D5B8;
+public:
+	AIScript_Officer_Leroy(BladeRunnerEngine *vm);
+
+	void Initialize();
+	void UpdateAnimation(int *animation, int *frame);
+	void ChangeAnimationMode(int mode);
+};
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 73a5f89..fa1e42d 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -26,9 +26,12 @@
 #include "bladerunner/audio_player.h"
 #include "bladerunner/bladerunner.h"
 
+#include "common/debug.h"
+
 namespace BladeRunner {
 
 void ScriptRC01::InitializeScene() {
+	// Game_Flag_Set(24);
 	if (!Game_Flag_Query(24)) {
 		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
 		Ambient_Sounds_Remove_All_Looping_Sounds(1);
@@ -38,7 +41,7 @@ void ScriptRC01::InitializeScene() {
 		Outtake_Play(33, 1); // DSCENT_E.VQA
 	}
 
-	Game_Flag_Set(9); // Force flag 9 so McCoy will be in view
+	// Game_Flag_Set(9); // Force flag 9 so McCoy will be in view
 	if (Game_Flag_Query(9)) {
 		Setup_Scene_Information(-171.16,  5.55,  27.28, 616);
 	} else if (Game_Flag_Query(114)) {
@@ -46,6 +49,7 @@ void ScriptRC01::InitializeScene() {
 	} else {
 		Setup_Scene_Information( -10.98, -0.30, 318.15, 616);
 	}
+	// Setup_Scene_Information(-151.98, -0.30, 318.15, 616);
 
 	Scene_Exit_Add_2D_Exit(0, 314, 145, 340, 255, 0);
 	if (Game_Flag_Query(249))
@@ -118,7 +122,67 @@ void ScriptRC01::InitializeScene() {
 }
 
 void ScriptRC01::SceneLoaded() {
-	if (!Game_Flag_Query(24)){
+	Obstacle_Object("HYDRANT02", 1);
+	Obstacle_Object("PARKING METER 04", 1);
+	Obstacle_Object("CHEVY PROP", 1);
+	Obstacle_Object("PARKING METER 01", 1);
+	Obstacle_Object("T-CAN01", 1);
+	Obstacle_Object("BARICADE01", 1);
+	Obstacle_Object("BARICADE02", 1);
+	Obstacle_Object("DOOR LEFT", 1);
+	Unobstacle_Object("BOX06", 1);
+	Clickable_Object("DOORWAY01");
+	Clickable_Object("DOOR LEFT");
+	Clickable_Object("HYDRANT02");
+	Clickable_Object("T-CAN01");
+	Clickable_Object("BARICADE01");
+	Clickable_Object("70_1");
+	Clickable_Object("70_2");
+	Clickable_Object("70_3");
+	Clickable_Object("70_5");
+	Clickable_Object("70_6");
+	Unclickable_Object("BARICADE02");
+	Unclickable_Object("BARICADE05");
+	Unclickable_Object("SPINNER BODY");
+	Unclickable_Object("HORSE01");
+	Unclickable_Object("DOORWAY01");
+	Unobstacle_Object("DOORWAY01", 1);
+
+	if (Game_Flag_Query(186)) {
+		Unclickable_Object("70_1");
+		Unclickable_Object("70_2");
+		Unclickable_Object("70_3");
+		Unclickable_Object("70_5");
+		Unclickable_Object("70_6");
+		Unclickable_Object("BARICADE01");
+		Unclickable_Object("BARICADE03");
+		Unclickable_Object("BARICADE04");
+		Unobstacle_Object("70_1", 1);
+		Unobstacle_Object("70_2", 1);
+		Unobstacle_Object("70_3", 1);
+		Unobstacle_Object("70_5", 1);
+		Unobstacle_Object("70_6", 1);
+		Unobstacle_Object("BARICADE01", 1);
+		Unobstacle_Object("BARICADE02", 1);
+		Unobstacle_Object("BARICADE03", 1);
+		Unobstacle_Object("BARICADE04", 1);
+		Unobstacle_Object("BARICADE05", 1);
+	}
+
+	if (!Game_Flag_Query(186)) {
+		Preload(13);
+		Preload(14);
+		Preload(19);
+		Preload(582);
+		Preload(589);
+	}
+
+	/*
+	if (!Game_Flag_Query(163))
+		Item_Add_To_World(66, 938, 69, -148.60f, -0.30f, 225.15f, 256, 24, 24, 0, 1, 0, 1);
+	*/
+
+	if (!Game_Flag_Query(24)) {
 		// ADQ_Flush();
 		Actor_Voice_Over(1830, 99);
 		Actor_Voice_Over(1850, 99);
@@ -131,6 +195,99 @@ void ScriptRC01::SceneLoaded() {
 	}
 }
 
+void ScriptRC01::sub_403850()
+{
+	if (Game_Flag_Query(186))
+		return;
+
+	if (Loop_Actor_Walk_To_Scene_Object(0, "BARICADE03", 36, 1, 0))
+		return;
+
+	Actor_Set_Goal_Number(23, 0);
+	Actor_Face_Object(0, "BARICADE03", 1);
+	// Loop_Actor_Walk_To_Actor(23, 0, 36, 1, 0);
+	Actor_Face_Actor(23, 0, 1);
+	Actor_Says(0, 4500, 14);
+	I_Sez("MG: We don't want any of that abstract art oozing out onto the street.");
+	Actor_Says(23, 10, 14);
+	Actor_Set_Goal_Number(23, 1);
+}
+
+bool ScriptRC01::ClickedOn3DObject(const char *objectName) {
+	if (Object_Query_Click("BARICADE01", objectName)
+	 || Object_Query_Click("BARICADE03", objectName)
+	 || Object_Query_Click("BARICADE04", objectName)
+	 || Object_Query_Click("70_1", objectName)
+	 || Object_Query_Click("70_2", objectName)
+	 || Object_Query_Click("70_3", objectName)
+	 || Object_Query_Click("70_5", objectName)
+	 || Object_Query_Click("70_6", objectName))
+	{
+		sub_403850();
+		return true;
+	}
+
+	if (Object_Query_Click("HYDRANT02", objectName)) {
+		if (Loop_Actor_Walk_To_Scene_Object(0, "HYDRANT02", 60, 1, 0) == 0) {
+			if (Actor_Clue_Query(0, 26)) {
+				Actor_Says(0, 6975, 3);
+			} else {
+				Actor_Face_Object(0, "HYDRANT02", 1);
+				Actor_Voice_Over(1880, 99);
+				Actor_Voice_Over(1890, 99);
+				I_Sez("JM: That McCoy--he's one funny guy! Jet-black fire truck, hehehehe...");
+				Actor_Clue_Acquire(0, 26, 1, -1);
+			}
+		}
+		return true;
+	}
+
+	if (Object_Query_Click("DOOR LEFT", objectName))
+	{
+		if (!Loop_Actor_Walk_To_Scene_Object(0, "DOOR LEFT", 48, 1, 0))
+		{
+			Actor_Face_Object(0, "DOOR LEFT", 1);
+			if (Actor_Clue_Query(0, 2) || !Actor_Query_In_Set(23, 69) || Global_Variable_Query(1) != 1)
+			{
+				Actor_Says(0, 8570, 14);
+			}
+			else
+			{
+				Actor_Set_Goal_Number(23, 0);
+				Actor_Face_Actor(23, 0, 1);
+				Actor_Says(23, 0, 12);
+				Actor_Says(0, 4495, 13);
+				Actor_Clue_Acquire(0, 2, 1, 23);
+			}
+			Actor_Clue_Acquire(0, 1, 1, -1);
+		}
+		return true;
+	}
+
+	if (Object_Query_Click("T-CAN01", objectName))
+	{
+		if (!Loop_Actor_Walk_To_Scene_Object(0, "T-CAN01", 24, 1, 0))
+		{
+			Actor_Face_Object(0, "T-CAN01", 1);
+			Actor_Voice_Over(1810, 99);
+			Actor_Voice_Over(1820, 99);
+		}
+		return true;
+	}
+
+	return false;
+}
+
+bool ScriptRC01::ClickedOn2DRegion(int region) {
+	if (region == 0) {
+		sub_403850();
+		return 1;
+	}
+
+	return 0;
+}
+
+
 void ScriptRC01::SceneFrameAdvanced(int frame) {
 	if (frame == 1)
 		Sound_Play(118, 40, 0, 0, 50);    // CARDOWN3.AUD
@@ -154,11 +311,41 @@ void ScriptRC01::SceneFrameAdvanced(int frame) {
 		Sound_Play(118, 40, 80, 80, 50);  // CARDOWN3.AUD
 }
 
-
 void ScriptRC01::SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
-
 }
 
+void ScriptRC01::PlayerWalkedIn()
+{
+	if (Game_Flag_Query(249) && !Game_Flag_Query(9) && !Game_Flag_Query(114)) {
+		// Extract to sub_4037AC():
+		Player_Loses_Control();
+		Game_Flag_Set(182);
+		Actor_Set_Immunity_To_Obstacles(0, true);
+		Loop_Actor_Walk_To_XYZ(0, -151.98, -0.30, 318.15, 0, 0, 0, 0);
+		Actor_Set_Immunity_To_Obstacles(0, false);
+		Player_Gains_Control();
+	}
+
+	if (Game_Flag_Query(114)) {
+		Player_Loses_Control();
+		Loop_Actor_Walk_To_XYZ(0, -415.98, -0.30, 262.15, 0, 0, 0, 0);
+		Player_Gains_Control();
+		Game_Flag_Reset(114);
+	}
+
+	if (Game_Flag_Query(9)) {
+		Player_Loses_Control();
+		Loop_Actor_Walk_To_XYZ(0, -203.45, 5.55, 85.05, 0, 0, 0, 0);
+		Player_Gains_Control();
+		Game_Flag_Reset(9);
 
+		if (Game_Flag_Query(1) && !Game_Flag_Query(4)) {
+			Actor_Voice_Over(1910, 99);
+			Actor_Voice_Over(1920, 99);
+			Actor_Voice_Over(1930, 99);
+			Game_Flag_Set(4);
+		}
+	}
+}
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index c71326d..c93c5db 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -24,21 +24,27 @@
 
 #include "bladerunner/bladerunner.h"
 
+#include "bladerunner/actor.h"
+#include "bladerunner/actor_combat.h"
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/audio_speech.h"
 #include "bladerunner/clues.h"
+#include "bladerunner/combat.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
+#include "bladerunner/settings.h"
+#include "bladerunner/set_effects.h"
 #include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
+#include "bladerunner/slice_animations.h"
+#include "bladerunner/slice_renderer.h"
 #include "bladerunner/text_resource.h"
 #include "bladerunner/vector.h"
-#include "bladerunner/slice_renderer.h"
-#include "bladerunner/actor.h"
 #include "bladerunner/waypoints.h"
-#include "bladerunner/slice_animations.h"
-#include "bladerunner/combat.h"
-#include "bladerunner/settings.h"
+
+#include "bladerunner/script/ai_00_mccoy.h"
+#include "bladerunner/script/aiscript_officer_leroy.h"
 
 namespace BladeRunner {
 
@@ -47,8 +53,6 @@ bool Script::open(const Common::String &name) {
 
 	if (name == "RC01") { _currentScript = new ScriptRC01(_vm); return true; }
 
-	_currentScript = new ScriptRC01(_vm); return true;
-
 	return false;
 }
 
@@ -68,6 +72,26 @@ void Script::SceneLoaded() {
 	_inScriptCounter--;
 }
 
+bool Script::ClickedOn3DObject(const char *objectName) {
+	if (_inScriptCounter > 0)
+		return true;
+
+	_inScriptCounter++;
+	bool result = _currentScript->ClickedOn3DObject(objectName);
+	_inScriptCounter--;
+	return result;
+}
+
+bool Script::ClickedOn2DRegion(int region) {
+	if (_inScriptCounter > 0)
+		return true;
+
+	_inScriptCounter++;
+	bool result = _currentScript->ClickedOn2DRegion(region);
+	_inScriptCounter--;
+	return result;
+}
+
 void Script::SceneFrameAdvanced(int frame) {
 	_inScriptCounter++;
 	_currentScript->SceneFrameAdvanced(frame);
@@ -80,6 +104,12 @@ void Script::SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool c
 	_inScriptCounter--;
 }
 
+void Script::PlayerWalkedIn() {
+	_inScriptCounter++;
+	_currentScript->PlayerWalkedIn();
+	_inScriptCounter--;
+}
+
 void ScriptBase::Preload(int animationId) {
 	_vm->_sliceRenderer->preload(animationId);
 }
@@ -88,12 +118,12 @@ void ScriptBase::Actor_Put_In_Set(int actorId, int setId) {
 	_vm->_actors[actorId]->setSetId(setId);
 }
 
-void ScriptBase::Actor_Set_At_XYZ(int actorId, float x, float y, float z, int angle) {
-	_vm->_actors[actorId]->set_at_xyz(Vector3(x, y, z), angle, true, 0, 0);
+void ScriptBase::Actor_Set_At_XYZ(int actorId, float x, float y, float z, int direction) {
+	_vm->_actors[actorId]->setAtXYZ(Vector3(x, y, z), direction);
 }
 
 void ScriptBase::Actor_Set_At_Waypoint(int actorId, int waypointId, int angle) {
-	_vm->_actors[actorId]->set_at_waypoint(waypointId, angle, 0, 0);
+	_vm->_actors[actorId]->setAtWaypoint(waypointId, angle, 0, 0);
 }
 
 bool ScriptBase::Region_Check(int left, int top, int right, int down) {
@@ -101,10 +131,16 @@ bool ScriptBase::Region_Check(int left, int top, int right, int down) {
 	return false;
 }
 
-// ScriptBase::Object_Query_Click
-// ScriptBase::Object_Do_Ground_Click
+bool ScriptBase::Object_Query_Click(const char *objectName1, const char *objectName2) {
+	return strcmp(objectName1, objectName2) == 0;
+}
+
+void ScriptBase::Object_Do_Ground_Click() {
+	//This is not implemented in game
+	return;
+}
 
-bool ScriptBase::Object_Mark_For_Hot_Mouse(char *objectName) {
+bool ScriptBase::Object_Mark_For_Hot_Mouse(const char *objectName) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return false;
@@ -115,7 +151,7 @@ void ScriptBase::Actor_Face_Actor(int actorId, int otherActorId, bool animate) {
 	_vm->_actors[actorId]->faceActor(otherActorId, animate);
 }
 
-void ScriptBase::Actor_Face_Object(int actorId, char *objectName, bool animate) {
+void ScriptBase::Actor_Face_Object(int actorId, const char *objectName, bool animate) {
 	_vm->_actors[actorId]->faceObject(objectName, animate);
 }
 
@@ -242,7 +278,7 @@ void ScriptBase::Actor_Set_Health(int actorId, int hp, int maxHp) {
 
 void ScriptBase::Actor_Set_Targetable(int actorId, bool targetable) {
 	_vm->_actors[actorId]->setTargetable(targetable);
-	
+
 }
 
 void ScriptBase::Actor_Says(int actorId, int sentenceId, int animationMode){
@@ -302,6 +338,29 @@ void ScriptBase::Actor_Says_With_Pause(int actorId, int sentenceId, float pause,
 	Player_Gains_Control();
 }
 
+#if 0
+void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
+	// Wait for any existing speech to end
+	_vm->loopActorSpeaking();
+
+	// TODO: Hack - This needs to go through the actor class
+	char name[13];
+	sprintf(name, "%02d-%04d.AUD", actorId, sentenceId);
+	_vm->_audioSpeech->playSpeech(name);
+
+	// warning("start voice over loop");
+	while (true)
+	{
+		_vm->gameTick();
+		if (_vm->shouldQuit())
+			break;
+		if (!_vm->_audioSpeech->isPlaying())
+			break;
+	}
+	// warning("end voice over loop");
+}
+#endif
+
 void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
 	_vm->gameWaitForActive();
 	_vm->loopActorSpeaking();
@@ -328,7 +387,7 @@ void ScriptBase::Actor_Start_Speech_Sample(int actorId, int sentenceId) {
 }
 
 void ScriptBase::Actor_Start_Voice_Over_Sample(int sentenceId) {
-	_vm->loopActorSpeaking();	
+	_vm->loopActorSpeaking();
 	_vm->_voiceoverActor->speechPlay(sentenceId, true);
 }
 
@@ -397,11 +456,11 @@ int ScriptBase::Actor_Query_Facing_1024(int actorId) {
 }
 
 void ScriptBase::Actor_Set_Frame_Rate_FPS(int actorId, int fps) {
-	_vm->_actors[actorId]->setFps(fps);
+	_vm->_actors[actorId]->setFPS(fps);
 }
 
-int ScriptBase::Slice_Animation_Query_Number_Of_Frames(int animationId) {
-	return _vm->_sliceAnimations->getNumberOfFrames(animationId);
+int ScriptBase::Slice_Animation_Query_Number_Of_Frames(int animation) {
+	return _vm->_sliceAnimations->getFrameCount(animation);
 }
 
 void ScriptBase::Actor_Change_Animation_Mode(int actorId, int animationMode) {
@@ -414,9 +473,21 @@ int ScriptBase::Actor_Query_Animation_Mode(int actorId) {
 
 // ScriptBase::Loop_Actor_Walk_To_Actor
 // ScriptBase::Loop_Actor_Walk_To_Item
-// ScriptBase::Loop_Actor_Walk_To_Scene_Object
+
+bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, int a4, int a5) {
+	_vm->gameWaitForActive();
+
+	_vm->_actors[actorId]->loopWalkToSceneObject(objectName);
+
+	return false;
+}
+
 // ScriptBase::Loop_Actor_Walk_To_Waypoint
-// ScriptBase::Loop_Actor_Walk_To_XYZ
+
+void ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, int a6, int a7) {
+	_vm->loopActorWalkToXYZ(actorId, x, y, z, a4, a5, a6, a7);
+}
+
 // ScriptBase::Async_Actor_Walk_To_Waypoint
 // ScriptBase::Async_Actor_Walk_To_XYZ
 // ScriptBase::Actor_Force_Stop_Walking
@@ -487,30 +558,28 @@ int ScriptBase::Animation_Skip_To_Frame() {
 	return 0;
 }
 
-
 void ScriptBase::Delay(int miliseconds) {
 	Player_Loses_Control();
 	int endTime = _vm->getTotalPlayTime() + miliseconds;
 	while ((int)_vm->getTotalPlayTime() < endTime)
 		_vm->gameTick();
 	Player_Gains_Control();
-	
 }
 
 void ScriptBase::Player_Loses_Control() {
-	_vm->playerLosesControl();
+		_vm->playerLosesControl();
 }
 
 void ScriptBase::Player_Gains_Control() {
-	_vm->playerGainsControl();
+		_vm->playerGainsControl();
 }
 
 void ScriptBase::Player_Set_Combat_Mode(bool activate) {
-	if(!_vm->_combat->isActive() || activate) {
-		if(_vm->_combat->isActive() && activate) {
+	if (!_vm->_combat->isActive() || activate) {
+		if (_vm->_combat->isActive() && activate) {
 			_vm->_combat->activate();
 		}
-	}else {
+	} else {
 		_vm->_combat->deactivate();
 	}
 }
@@ -520,9 +589,9 @@ bool ScriptBase::Player_Query_Combat_Mode() {
 }
 
 void ScriptBase::Player_Set_Combat_Mode_Access(bool enable) {
-	if(enable) {
+	if (enable) {
 		_vm->_combat->enable();
-	}else {
+	} else {
 		_vm->_combat->disable();
 	}
 }
@@ -547,6 +616,7 @@ int ScriptBase::Query_Difficulty_Level() {
 	return _vm->_settings->getDifficulty();
 }
 
+
 void ScriptBase::Game_Flag_Set(int flag) {
 	_vm->_gameFlags->set(flag);
 }
@@ -614,11 +684,17 @@ void ScriptBase::Sound_Play(int id, int volume, int panFrom, int panTo, int prio
 // ScriptBase::Overlay_Remove
 
 void ScriptBase::Scene_Loop_Set_Default(int a) {
-	debug("Scene_Loop_Set_Default(%d)", a);
+	// debug("Scene_Loop_Set_Default(%d)", a);
+
+	_vm->_scene->loopSetDefault(a);
+	// _vm->_scene->_defaultLoop = a;
 }
 
 void ScriptBase::Scene_Loop_Start_Special(int a, int b, int c) {
-	debug("Scene_Loop_Start_Special(%d, %d, %d)", a, b, c);
+	// debug("Scene_Loop_Start_Special(%d, %d, %d)", a, b, c);
+
+	_vm->_scene->loopStartSpecial(a, b, c);
+	// _vm->_scene->_field_24_loop_start_special_param_1 = a;
 }
 
 void ScriptBase::Outtake_Play(int id, int noLocalization, int container) {
@@ -725,7 +801,7 @@ void ScriptBase::Scene_2D_Region_Remove(int index) {
 // ScriptBase::Query_Score
 
 void ScriptBase::Set_Score(int a0, int a1) {
-	debug("STUB: Set_Score(%d, %d)", a0, a1);
+	// debug("STUB: Set_Score(%d, %d)", a0, a1);
 }
 
 void ScriptBase::Give_McCoy_Ammo(int ammoType, int ammo) {
@@ -757,32 +833,32 @@ void ScriptBase::Actor_Retired_Here(int actorId, int width, int height, int reti
 	Vector3 actorPosition;
 	actor->getXYZ(&actorPosition.x, &actorPosition.y, &actorPosition.z);
 	actor->retire(retired, width, height, retiredByActorId);
-	actor->set_at_xyz(actorPosition, actor->getFacing(), true, 0, true);
+	actor->setAtXYZ(actorPosition, actor->getFacing(), true, 0, true);
 	_vm->_sceneObjects->setRetired(actorId, true);
 }
 
-void ScriptBase::Clickable_Object(char *objectName) {
+void ScriptBase::Clickable_Object(const char *objectName) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return;
 	_vm->_scene->objectSetIsClickable(objectId, true, !_vm->_sceneIsLoading);
 }
 
-void ScriptBase::Unclickable_Object(char *objectName) {
+void ScriptBase::Unclickable_Object(const char *objectName) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return;
 	_vm->_scene->objectSetIsClickable(objectId, false, !_vm->_sceneIsLoading);
 }
 
-void ScriptBase::Obstacle_Object(char *objectName, bool updateWalkpath) {
+void ScriptBase::Obstacle_Object(const char *objectName, bool updateWalkpath) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return;
 	_vm->_scene->objectSetIsObstacle(objectId, true, !_vm->_sceneIsLoading, !_vm->_sceneIsLoading && updateWalkpath);
 }
 
-void ScriptBase::Unobstacle_Object(char *objectName, bool updateWalkpath) {
+void ScriptBase::Unobstacle_Object(const char *objectName, bool updateWalkpath) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return;
@@ -793,18 +869,18 @@ void ScriptBase::Obstacle_Flag_All_Objects(bool isObstacle) {
 	_vm->_scene->objectSetIsObstacleAll(isObstacle, !_vm->_sceneIsLoading);
 }
 
-void ScriptBase::Combat_Target_Object(char *objectName) {
+void ScriptBase::Combat_Target_Object(const char *objectName) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return;
-	_vm->_scene->objectSetIsCombatTarget(objectId, true, !_vm->_sceneIsLoading);
+	_vm->_scene->objectSetIsTarget(objectId, true, !_vm->_sceneIsLoading);
 }
 
-void ScriptBase::Un_Combat_Target_Object(char *objectName) {
+void ScriptBase::Un_Combat_Target_Object(const char *objectName) {
 	int objectId = _vm->_scene->findObject(objectName);
 	if (objectId == -1)
 		return;
-	_vm->_scene->objectSetIsCombatTarget(objectId, true, !_vm->_sceneIsLoading);
+	_vm->_scene->objectSetIsTarget(objectId, true, !_vm->_sceneIsLoading);
 }
 
 void ScriptBase::Set_Fade_Color(float r, float g, float b) {
@@ -841,5 +917,37 @@ void ScriptBase::I_Sez(const char *str) {
 	_vm->ISez(str);
 }
 
+AIScripts::AIScripts(BladeRunnerEngine *vm)
+	: _vm(vm),
+	  _inScriptCounter(0)
+{
+	for (int i = 0; i != 100; ++i)
+		_AIScripts[i] = 0;
+
+	_AIScripts[0]  = new AIScript_McCoy(_vm);
+	_AIScripts[23] = new AIScript_Officer_Leroy(_vm);
+}
+
+void AIScripts::Initialize(int actor)
+{
+	if (_AIScripts[actor])
+		_AIScripts[actor]->Initialize();
+}
+
+void AIScripts::UpdateAnimation(int actor, int *animation, int *frame)
+{
+	_inScriptCounter++;
+	if (_AIScripts[actor])
+		_AIScripts[actor]->UpdateAnimation(animation, frame);
+	_inScriptCounter--;
+}
+
+void AIScripts::ChangeAnimationMode(int actor, int mode)
+{
+	_inScriptCounter++;
+	if (_AIScripts[actor])
+		_AIScripts[actor]->ChangeAnimationMode(mode);
+	_inScriptCounter--;
+}
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 97db6eb..8f38657 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -42,15 +42,15 @@ public:
 
 protected:
 	void Preload(int animationId);
-	void Actor_Put_In_Set(int actorId, int setId);
-	void Actor_Set_At_XYZ(int actorId, float x, float y, float z, int angle);
+	void Actor_Put_In_Set(int id, int set);
+	void Actor_Set_At_XYZ(int actorId, float x, float y, float z, int direction);
 	void Actor_Set_At_Waypoint(int actorId, int waypointId, int angle);
 	bool Region_Check(int left, int top, int right, int down);
-	// Object_Query_Click
-	// Object_Do_Ground_Click
-	bool Object_Mark_For_Hot_Mouse(char *objectName);
+	bool Object_Query_Click(const char *objectName1, const char *objectName2);
+	void Object_Do_Ground_Click();
+	bool Object_Mark_For_Hot_Mouse(const char *objectName);
 	void Actor_Face_Actor(int actorId, int otherActorId, bool animate);
-	void Actor_Face_Object(int actorId, char *objectName, bool animate);
+	void Actor_Face_Object(int actorId, const char *objectName, bool animate);
 	void Actor_Face_Item(int actorId, int itemId, bool animate);
 	void Actor_Face_Waypoint(int actorId, int waypointId, bool animate);
 	void Actor_Face_XYZ(int actorId, float x, float y, float z, bool animate);
@@ -103,9 +103,9 @@ protected:
 	int Actor_Query_Animation_Mode(int actorId);
 	// Loop_Actor_Walk_To_Actor
 	// Loop_Actor_Walk_To_Item
-	// Loop_Actor_Walk_To_Scene_Object
+	bool Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, int a4, int a5);
 	// Loop_Actor_Walk_To_Waypoint
-	// Loop_Actor_Walk_To_XYZ
+	void Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, int a6, int a7);
 	// Async_Actor_Walk_To_Waypoint
 	// Async_Actor_Walk_To_XYZ
 	// Actor_Force_Stop_Walking
@@ -241,13 +241,13 @@ protected:
 	void Disable_Shadows(int *animationsIdsList, int listSize);
 	bool Query_System_Currently_Loading_Game();
 	void Actor_Retired_Here(int actorId, int width, int height, int retired, int retiredByActorId);
-	void Clickable_Object(char *objectName);
-	void Unclickable_Object(char *objectName);
-	void Obstacle_Object(char *objectName, bool updateWalkpath);
-	void Unobstacle_Object(char *objectName, bool updateWalkpath);
+	void Clickable_Object(const char *objectName);
+	void Unclickable_Object(const char *objectName);
+	void Obstacle_Object(const char *objectName, bool updateWalkpath);
+	void Unobstacle_Object(const char *objectName, bool updateWalkpath);
 	void Obstacle_Flag_All_Objects(bool isObstacle);
-	void Combat_Target_Object(char *objectName);
-	void Un_Combat_Target_Object(char *objectName);
+	void Combat_Target_Object(const char *objectName);
+	void Un_Combat_Target_Object(const char *objectName);
 	void Set_Fade_Color(float r, float g, float b);
 	void Set_Fade_Density(float density);
 	void Set_Fog_Color(char* fogName, float r, float g, float b);
@@ -268,10 +268,17 @@ public:
 
 	virtual void InitializeScene() = 0;
 	virtual void SceneLoaded() = 0;
+	virtual bool ClickedOn3DObject(const char *objectName) = 0;
+	virtual bool ClickedOn2DRegion(int region) = 0;
 	virtual void SceneFrameAdvanced(int frame) = 0;
 	virtual void SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) = 0;
+	virtual void PlayerWalkedIn() = 0;
 };
 
+/*
+ * Scene Scripts
+ */
+
 class Script {
 public:
 	BladeRunnerEngine *_vm;
@@ -289,8 +296,11 @@ public:
 
 	void InitializeScene();
 	void SceneLoaded();
+	bool ClickedOn3DObject(const char *objectName);
+	bool ClickedOn2DRegion(int region);
 	void SceneFrameAdvanced(int frame);
 	void SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet);
+	void PlayerWalkedIn();
 };
 
 #define DECLARE_SCRIPT(name) \
@@ -301,14 +311,49 @@ public: \
 	{} \
 	void InitializeScene(); \
 	void SceneLoaded(); \
+	bool ClickedOn3DObject(const char *objectName); \
+	bool ClickedOn2DRegion(int region); \
 	void SceneFrameAdvanced(int frame); \
 	void SceneActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet); \
-};
+	void PlayerWalkedIn(); \
+private:
+#define END_SCRIPT };
 
 DECLARE_SCRIPT(RC01)
+	void sub_403850();
+END_SCRIPT
 
 #undef DECLARE_SCRIPT
 
+/*
+ * Actor Scripts
+ */
+
+class AIScriptBase : public ScriptBase {
+public:
+	AIScriptBase(BladeRunnerEngine *vm)
+		: ScriptBase(vm)
+	{}
+
+	virtual void Initialize() = 0;
+	virtual void UpdateAnimation(int *animation, int *frame) = 0;
+	virtual void ChangeAnimationMode(int mode) = 0;
+};
+
+class AIScripts {
+public:
+	BladeRunnerEngine *_vm;
+	int                _inScriptCounter;
+	AIScriptBase      *_AIScripts[100];
+
+	AIScripts(BladeRunnerEngine *vm);
+	~AIScripts();
+
+	void Initialize(int actor);
+	void UpdateAnimation(int actor, int *animation, int *frame);
+	void ChangeAnimationMode(int actor, int mode);
+};
+
 } // End of namespace BladeRunner
 
 #endif
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index 070fd64..e07a37a 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -23,14 +23,13 @@
 #include "bladerunner/set.h"
 
 #include "bladerunner/bladerunner.h"
-#include "bladerunner/slice_renderer.h"
+#include "bladerunner/scene_objects.h"
 
 #include "common/debug.h"
 #include "common/ptr.h"
 #include "common/str.h"
 #include "common/stream.h"
 
-
 namespace BladeRunner {
 
 #define kSet0 0x53657430
@@ -40,12 +39,9 @@ Set::Set(BladeRunnerEngine *vm) : _vm(vm) {
 	_walkboxCount = 0;
 	_objects = new Object[85];
 	_walkboxes = new Walkbox[95];
-	_footstepSoundOverride = -1;
-	_effects = new SetEffects(vm);
 }
 
 Set::~Set() {
-	delete _effects;
 	delete[] _objects;
 	delete[] _walkboxes;
 }
@@ -57,7 +53,7 @@ bool Set::open(const Common::String &name) {
 	if (sig != kSet0)
 		return false;
 
-	int framesCount = s->readUint32LE();
+	s->skip(4); // TODO: LITE length
 
 	_objectCount = s->readUint32LE();
 	assert(_objectCount <= 85);
@@ -78,10 +74,10 @@ bool Set::open(const Common::String &name) {
 		_objects[i]._isObstacle = s->readByte();
 		_objects[i]._isClickable = s->readByte();
 		_objects[i]._isHotMouse = 0;
-		_objects[i]._isCombatTarget = 0;
+		_objects[i]._isTarget = 0;
 		s->skip(4);
 
-		// debug("OBJECT: %s", _objects[i]._name);
+		// debug("OBJECT: %s [%d%d%d%d]", _objects[i]._name, _objects[i]._isObstacle, _objects[i]._isClickable, _objects[i]._isHotMouse, _objects[i]._isTarget);
 	}
 
 	_walkboxCount = s->readUint32LE();
@@ -106,51 +102,49 @@ bool Set::open(const Common::String &name) {
 		// debug("WALKBOX: %s", _walkboxes[i]._name);
 	}
 
-	_vm->_lights->reset();
-	_vm->_lights->read(s.get(), framesCount);
-	_vm->_sliceRenderer->setLights(_vm->_lights);
-	_effects->reset();
-	_effects->read(s.get(), framesCount);
-	_vm->_sliceRenderer->setSetEffects(_effects);
+	// TODO: Read LITE
 
 	return true;
 }
 
-
 void Set::addObjectsToScene(SceneObjects* sceneObjects)
 {
 	uint32 i;
 	for (i = 0; i < _objectCount; i++) {
-		sceneObjects->addObject(i + SCENE_OBJECTS_OBJECTS_OFFSET, &_objects[i]._bbox, _objects[i]._isClickable, _objects[i]._isObstacle, _objects[i]._unknown1, _objects[i]._isCombatTarget);
+		sceneObjects->addObject(i + SCENE_OBJECTS_OBJECTS_OFFSET, &_objects[i]._bbox, _objects[i]._isClickable, _objects[i]._isObstacle, _objects[i]._unknown1, _objects[i]._isTarget);
 	}
 }
 
-
-int Set::findWalkbox(float x, float z) {
-	int i;
-	float altitude = 0.0f;
-	int foundWalkboxId = -1;
-	for (i = 0; i < (int)_walkboxCount; i++) {
-		if (isXzInWalkbox(x, z, &_walkboxes[i])) {
-			if (foundWalkboxId == -1 || altitude < _walkboxes[i]._altitude) {
-				altitude = _walkboxes[i]._altitude;
-				foundWalkboxId = i;
-			}
+// Source: http://www.faqs.org/faqs/graphics/algorithms-faq/ section 2.03
+/*
+static
+bool pointInWalkbox(float x, float z, const Walkbox &w)
+{
+	uint32 i, j;
+	bool c = false;
+
+	for (i = 0, j = w._vertexCount - 1; i < w._vertexCount; j = i++) {
+		if ((((w._vertices[i].z <= z) && (z < w._vertices[j].z)) ||
+		     ((w._vertices[j].z <= z) && (z < w._vertices[i].z))) &&
+		    (x < (w._vertices[j].x - w._vertices[i].x) * (z - w._vertices[i].z) / (w._vertices[j].z - w._vertices[i].z) + w._vertices[i].x))
+		{
+			c = !c;
 		}
 	}
-	return foundWalkboxId;
+	return c;
 }
+*/
 
-bool Set::isXzInWalkbox(float x, float z, Walkbox* walkbox) {
+static
+bool isXZInWalkbox(float x, float z, const Walkbox &walkbox) {
 	int found = 0;
 	int i;
 
-	float lastX = walkbox->_vertices[walkbox->_vertexCount - 1].x;
-	float lastZ = walkbox->_vertices[walkbox->_vertexCount - 1].z;
-	for (i = 0; i < (int)walkbox->_vertexCount; i++) {
-
-		float currentX = walkbox->_vertices[i].x;
-		float currentZ = walkbox->_vertices[i].z;
+	float lastX = walkbox._vertices[walkbox._vertexCount - 1].x;
+	float lastZ = walkbox._vertices[walkbox._vertexCount - 1].z;
+	for (i = 0; i < (int)walkbox._vertexCount; i++) {
+		float currentX = walkbox._vertices[i].x;
+		float currentZ = walkbox._vertices[i].z;
 
 		if ((currentZ > z && z >= lastZ) || (currentZ <= z && z < lastZ)) {
 			float lineX = (lastX - currentX) / (lastZ - currentZ) * (z - currentZ) + currentX;
@@ -162,14 +156,50 @@ bool Set::isXzInWalkbox(float x, float z, Walkbox* walkbox) {
 	return found & 1;
 }
 
+float Set::getAltitudeAtXZ(float x, float z, bool *inWalkbox) {
+	float altitude = _walkboxes[0]._altitude;
+	*inWalkbox = false;
+
+	for (uint32 i = 0; i != _walkboxCount; ++i) {
+		const Walkbox &w = _walkboxes[i];
+
+		if (isXZInWalkbox(x, z, w)) {
+			*inWalkbox = true;
+			if (w._altitude > altitude) {
+				altitude = w._altitude;
+			}
+		}
+	}
+
+	return altitude;
+}
+
+int Set::findWalkbox(float x, float z) {
+	int result = -1;
+
+	for (uint32 i = 0; i != _walkboxCount; ++i) {
+		const Walkbox &w = _walkboxes[i];
+
+		if (isXZInWalkbox(x, z, w)) {
+			if (result == -1 || w._altitude > _walkboxes[result]._altitude) {
+				result = i;
+			}
+		}
+	}
+
+	return result;
+}
 
-int Set::findObject(char* objectName) {
-	int i;	
+int Set::findObject(const char *objectName) {
+	int i;
 	for (i = 0; i < (int)_objectCount; i++) {
 		if (scumm_stricmp(objectName, _objects[i]._name) == 0) {
 			return i;
 		}
 	}
+
+	debug("Set::findObject didn't find \"%s\"", objectName);
+
 	return -1;
 }
 
@@ -177,22 +207,22 @@ bool Set::objectSetHotMouse(int objectId) {
 	if(!_objects || objectId < 0 || objectId >= (int)_objectCount) {
 		return false;
 	}
-	
+
 	_objects[objectId]._isHotMouse = true;
 	return true;
 }
 
-bool Set::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
+bool Set::objectGetBoundingBox(int objectId, BoundingBox *boundingBox) {
 	assert(boundingBox);
 
 	if (!_objects || objectId < 0 || objectId >= (int)_objectCount) {
-		boundingBox->setXyz(0, 0, 0, 0, 0, 0);
+		boundingBox->setXYZ(0, 0, 0, 0, 0, 0);
 		return false;
 	}
 	float x0, y0, z0, x1, y1, z1;
 
-	_objects[objectId]._bbox.getXyz(&x0, &y0, &z0, &x1, &y1, &z1);
-	boundingBox->setXyz(x0, y0, z0, x1, y1, z1);
+	_objects[objectId]._bbox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
+	boundingBox->setXYZ(x0, y0, z0, x1, y1, z1);
 
 	return true;
 }
@@ -205,8 +235,12 @@ void Set::objectSetIsObstacle(int objectId, bool isObstacle) {
 	_objects[objectId]._isObstacle = isObstacle;
 }
 
-void Set::objectSetIsCombatTarget(int objectId, bool isCombatTarget) {
-	_objects[objectId]._isCombatTarget = isCombatTarget;
+void Set::objectSetIsTarget(int objectId, bool isTarget) {
+	_objects[objectId]._isTarget = isTarget;
+}
+
+const char *Set::objectGetName(int objectId) {
+	return _objects[objectId]._name;
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index 2db9c82..18fde76 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -24,10 +24,6 @@
 #define BLADERUNNER_SET_H
 
 #include "bladerunner/boundingbox.h"
-#include "bladerunner/set_effects.h"
-#include "bladerunner/lights.h"
-#include "bladerunner/scene_objects.h"
-
 
 #include "common/scummsys.h"
 #include "common/str.h"
@@ -35,8 +31,10 @@
 namespace BladeRunner {
 
 class BladeRunnerEngine;
+
 class VQADecoder;
-class Scene;
+class SetEffects;
+class SceneObjects;
 
 struct Object {
 	char        _name[20];
@@ -44,7 +42,7 @@ struct Object {
 	uint8       _isObstacle;
 	uint8       _isClickable;
 	uint8       _isHotMouse;
-	uint8       _isCombatTarget;
+	uint8       _isTarget;
 	uint8       _unknown1;
 };
 
@@ -56,8 +54,6 @@ struct Walkbox {
 };
 
 class Set {
-	friend class Scene;
-
 	BladeRunnerEngine *_vm;
 
 	uint32      _objectCount;
@@ -66,6 +62,7 @@ class Set {
 	Walkbox    *_walkboxes;
 	int         _walkboxStepSound[85];
 	int         _footstepSoundOverride;
+	float       _unknown[10];
 public:
 	SetEffects *_effects;
 
@@ -74,20 +71,21 @@ public:
 	~Set();
 
 	bool open(const Common::String &name);
+
 	void addObjectsToScene(SceneObjects *sceneObjects);
+	uint32 getObjectCount() { return _objectCount; }
+
+	float getAltitudeAtXZ(float x, float z, bool *inWalkbox);
 
 	int findWalkbox(float x, float z);
-	int findObject(char* objectName);
+	int findObject(const char *objectName);
 
 	bool objectSetHotMouse(int objectId);
 	bool objectGetBoundingBox(int objectId, BoundingBox *boundingBox);
 	void objectSetIsClickable(int objectId, bool isClickable);
 	void objectSetIsObstacle(int objectId, bool isObstacle);
-	void objectSetIsCombatTarget(int objectId, bool isCombatTarget);
-
-private:
-	bool isXzInWalkbox(float x, float z, Walkbox* walkbox);
-
+	void objectSetIsTarget(int objectId, bool isTarget);
+	const char *objectGetName(int objectId);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
index 6db81ce..bc10a0f 100644
--- a/engines/bladerunner/set_effects.cpp
+++ b/engines/bladerunner/set_effects.cpp
@@ -1,7 +1,6 @@
 #include "bladerunner/set_effects.h"
 
-namespace BladeRunner
-{
+namespace BladeRunner {
 
 SetEffects::SetEffects(BladeRunnerEngine* vm) {
 	_vm = vm;
@@ -119,4 +118,4 @@ Fog* SetEffects::findFog(char* fogName) {
 	return fog;
 }
 
-}
\ No newline at end of file
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
index 8f62807..16317ed 100644
--- a/engines/bladerunner/set_effects.h
+++ b/engines/bladerunner/set_effects.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_SET_EFFECTS_H
 #define BLADERUNNER_SET_EFFECTS_H
@@ -63,5 +63,6 @@ private:
 
 };
 
-}
+} // End of namespace BladeRunner
+
 #endif
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index 100f492..0c3a774 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -95,7 +95,6 @@ bool Settings::openNewScene() {
 	return true;
 }
 
-
 int Settings::getAmmoType() {
 	return _ammoType;
 }
@@ -122,6 +121,4 @@ void Settings::setPlayerAgenda(int agenda) {
 	_playerAgenda = agenda;
 }
 
-
-
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/settings.h b/engines/bladerunner/settings.h
index e45eb32..de9846a 100644
--- a/engines/bladerunner/settings.h
+++ b/engines/bladerunner/settings.h
@@ -46,7 +46,7 @@ class Settings {
 
 	int   _difficulty;
 	int   _playerAgenda;
-	
+
 	int   _ammoType;
 	int   _ammoAmounts[3];
 
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index b813c13..7061dd9 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -63,14 +63,14 @@ bool SliceAnimations::open(const Common::String &name) {
 	_animations.resize(animationCount);
 
 	for (uint32 i = 0; i != animationCount; ++i) {
-		_animations[i].frameCount       = file.readUint32LE();
-		_animations[i].frameSize        = file.readUint32LE();
-		_animations[i].fps              = file.readFloatLE();
-		_animations[i].positionChange.x = file.readFloatLE();
-		_animations[i].positionChange.y = file.readFloatLE();
-		_animations[i].positionChange.z = file.readFloatLE();
-		_animations[i].facingChange     = file.readFloatLE();
-		_animations[i].offset           = file.readUint32LE();
+		_animations[i].frameCount = file.readUint32LE();
+		_animations[i].frameSize  = file.readUint32LE();
+		_animations[i].fps        = file.readFloatLE();
+		_animations[i].unk0       = file.readFloatLE();
+		_animations[i].unk1       = file.readFloatLE();
+		_animations[i].unk2       = file.readFloatLE();
+		_animations[i].unk3       = file.readFloatLE();
+		_animations[i].offset     = file.readUint32LE();
 
 #if 0
 		debug("%4d  %6d %6x  %7.2g %7.2g %7.2g %7.2g %7.2g %8x",
@@ -128,7 +128,7 @@ bool SliceAnimations::PageFile::open(const Common::String &name) {
 		_pageOffsets[pageNumber] = dataOffset + i * _sliceAnimations->_pageSize;
 	}
 
-	debug("PageFile::Open: page file \"%s\" opened with %d pages", name.c_str(), pageCount);
+	// debug("PageFile::Open: page file \"%s\" opened with %d pages", name.c_str(), pageCount);
 
 	return true;
 }
@@ -170,18 +170,4 @@ void *SliceAnimations::getFramePtr(uint32 animation, uint32 frame) {
 	return (byte*)_pages[page]._data + pageOffset;
 }
 
-
-int SliceAnimations::getNumberOfFrames(int animationId) {
-	if (animationId > (int)_animations.size())
-		return 0;
-	return _animations[animationId].frameCount;
-}
-
-
-float SliceAnimations::getFps(int animationId) {
-	if (animationId > (int)_animations.size())
-		return 15.0f;
-	return _animations[animationId].fps;
-}
-
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index 9af12e4..ac254d4 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -23,8 +23,6 @@
 #ifndef BLADERUNNER_SLICE_ANIMATIONS_H
 #define BLADERUNNER_SLICE_ANIMATIONS_H
 
-#include "bladerunner/vector.h"
-
 #include "common/array.h"
 #include "common/file.h"
 #include "common/str.h"
@@ -48,8 +46,10 @@ class SliceAnimations {
 		uint32 frameCount;
 		uint32 frameSize;
 		float  fps;
-		Vector3 positionChange;
-		float facingChange;
+		float  unk0;
+		float  unk1;
+		float  unk2;
+		float  unk3;
 		uint32 offset;
 	};
 
@@ -102,10 +102,11 @@ public:
 	bool openCoreAnim();
 	bool openHDFrames();
 
-	SlicePalette &getPalette(int i) { return _palettes[i]; }
+	SlicePalette &getPalette(int i) { return _palettes[i]; };
 	void *getFramePtr(uint32 animation, uint32 frame);
-	int getNumberOfFrames(int animationId);
-	float getFps(int animationId);
+
+	float getFrameCount(int animation){ return _animations[animation].frameCount; }
+	float getFPS(int animation){ return _animations[animation].fps; }
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 389d818..581bed2 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -23,10 +23,9 @@
 #include "bladerunner/slice_renderer.h"
 
 #include "bladerunner/bladerunner.h"
-#include "bladerunner/slice_animations.h"
 #include "bladerunner/lights.h"
-#include "bladerunner/scene.h"
-#include "bladerunner/set.h"
+#include "bladerunner/set_effects.h"
+#include "bladerunner/slice_animations.h"
 
 #include "common/debug.h"
 #include "common/memstream.h"
@@ -54,10 +53,9 @@ void dump(const char *str, Matrix4x3 m) {
 }
 #endif
 
-
 SliceRenderer::SliceRenderer(BladeRunnerEngine* vm) {
 	_vm = vm;
-	int i; 
+	int i;
 
 	for (i = 0; i < 942; i++) { // yes, its going just to 942 and not 997
 		_animationsShadowEnabled[i] = true;
@@ -67,10 +65,18 @@ SliceRenderer::SliceRenderer(BladeRunnerEngine* vm) {
 SliceRenderer::~SliceRenderer() {
 }
 
-void SliceRenderer::setView(View *view) {
+void SliceRenderer::setView(const View &view) {
 	_view = view;
 }
 
+void SliceRenderer::setLights(Lights* lights){
+	_lights = lights;
+}
+
+void SliceRenderer::setSetEffects(SetEffects* setEffects){
+	_setEffects = setEffects;
+}
+
 void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float facing, float scale) {
 	_animation = animation;
 	_frame = frame;
@@ -97,7 +103,7 @@ void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float
 Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
 	assert(_sliceFramePtr);
 
-	Matrix4x3 viewMatrix = _view->_sliceViewMatrix;
+	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
 	Vector3 viewPos = viewMatrix * _position;
 	float dir = atan2f(viewPos.x, viewPos.z) + _facing;
 	float s = sinf(dir);
@@ -120,7 +126,7 @@ void SliceRenderer::calculateBoundingRect() {
 	_minY = 0.0f;
 	_maxY = 0.0f;
 
-	Matrix4x3 viewMatrix = _view->_sliceViewMatrix;
+	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
 
 	Vector3 frameBottom = Vector3(0.0f, 0.0f, _frameBottomZ);
 	Vector3 frameTop    = Vector3(0.0f, 0.0f, _frameBottomZ + _frameSliceCount * _frameSliceHeight);
@@ -135,7 +141,7 @@ void SliceRenderer::calculateBoundingRect() {
 
 	Matrix3x2 facingRotation = calculateFacingRotationMatrix();
 
-	Matrix3x2 m4(_view->_viewportDistance / bottom.z,  0.0f, 0.0f,
+	Matrix3x2 m4(_view._viewportDistance / bottom.z,  0.0f, 0.0f,
 	                                           0.0f, 25.5f, 0.0f);
 
 	Matrix3x2 m2(_frameFront.x,          0.0f, _framePos.x,
@@ -143,13 +149,13 @@ void SliceRenderer::calculateBoundingRect() {
 
 	_field_109E = m4 * (facingRotation * m2);
 
-	Vector4 B6(_view->_viewportHalfWidth   + top.x / top.z * _view->_viewportDistance,
-	           _view->_viewportHalfHeight  + top.y / top.z * _view->_viewportDistance,
+	Vector4 B6(_view._viewportHalfWidth   + top.x / top.z * _view._viewportDistance,
+	           _view._viewportHalfHeight  + top.y / top.z * _view._viewportDistance,
 	           1.0f / top.z,
 	           _frameSliceCount * (1.0f / top.z));
 
-	Vector4 C2(_view->_viewportHalfWidth   + bottom.x / bottom.z * _view->_viewportDistance,
-	           _view->_viewportHalfHeight  + bottom.y / bottom.z * _view->_viewportDistance,
+	Vector4 C2(_view._viewportHalfWidth   + bottom.x / bottom.z * _view._viewportDistance,
+	           _view._viewportHalfHeight  + bottom.y / bottom.z * _view._viewportDistance,
 	           1.0f / bottom.z,
 	           0.0f);
 
@@ -337,9 +343,6 @@ void setupLookupTable(int t[256], int inc) {
 
 void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) {
 	assert(_sliceFramePtr);
-	assert(_lights);
-	assert(_setEffects);
-	assert(_view);
 
 	SliceLineIterator sliceLineIterator;
 	sliceLineIterator.setup(
@@ -349,9 +352,6 @@ void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) {
 		_field_109E              // 3x2 matrix
 		);
 
-	_lights->setupFrame(_view->_frame);
-	_setEffects->setupFrame(_view->_frame);
-	
 	setupLookupTable(_t1, sliceLineIterator._field_00[0][0]);
 	setupLookupTable(_t2, sliceLineIterator._field_00[0][1]);
 	setupLookupTable(_t4, sliceLineIterator._field_00[1][0]);
@@ -426,17 +426,10 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 	}
 }
 
-void SliceRenderer::setLights(Lights* lights){
-	_lights = lights;
-}
-
-void SliceRenderer::setSetEffects(SetEffects* setEffects){
-	_setEffects = setEffects;
-}
-
 void SliceRenderer::preload(int animationId) {
 	int i;
-	for (i = 0; i < _vm->_sliceAnimations->getNumberOfFrames(animationId); i++)
+	int frameCount = _vm->_sliceAnimations->getFrameCount(animationId);
+	for (i = 0; i < frameCount; i++)
 		_vm->_sliceAnimations->getFramePtr(animationId, i);
 }
 
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index c702616..3dcd922 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -26,8 +26,6 @@
 #include "bladerunner/vector.h"
 #include "bladerunner/view.h"
 #include "bladerunner/matrix.h"
-#include "bladerunner/lights.h"
-#include "bladerunner/set_effects.h"
 
 #include "graphics/surface.h"
 
@@ -36,9 +34,10 @@ namespace Common {
 }
 
 namespace BladeRunner {
-	class SetEffects;
 
-	class BladeRunnerEngine;
+class BladeRunnerEngine;
+class Lights;
+class SetEffects;
 
 class SliceRenderer {
 	BladeRunnerEngine *_vm;
@@ -49,7 +48,7 @@ class SliceRenderer {
 	float     _facing;
 	float     _scale;
 
-	View       *_view;
+	View      _view;
 	Lights     *_lights;
 	SetEffects *_setEffects;
 
@@ -89,7 +88,7 @@ public:
 	SliceRenderer(BladeRunnerEngine *vm);
 	~SliceRenderer();
 
-	void setView(View *view);
+	void setView(const View &view);
 	void setLights(Lights *lights);
 	void setSetEffects(SetEffects *setEffects);
 
diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp
index 3c074ee..801808d 100644
--- a/engines/bladerunner/text_resource.cpp
+++ b/engines/bladerunner/text_resource.cpp
@@ -80,6 +80,13 @@ bool TextResource::open(const char *name) {
 
 	s->read(_strings, remain);
 
+#if 0
+	debug("\n%s\n----------------", resName);
+	for (uint32 i = 0; i != (uint32)_count; ++i) {
+		debug("%3d: %s", i, getText(i));
+	}
+#endif
+
 	return true;
 }
 
@@ -90,7 +97,7 @@ const char *TextResource::getText(uint32 id) {
 		}
 	}
 
-	return nullptr;
+	return "";
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index 029f829..b3b6ad8 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -27,11 +27,6 @@
 
 namespace BladeRunner {
 
-View::View(BladeRunnerEngine* vm)
-{
-	_vm = vm;
-}
-
 bool View::read(Common::ReadStream *stream) {
 	uint32 frame;
 	frame = stream->readUint32LE();
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
index 3e3a0e8..511ea66 100644
--- a/engines/bladerunner/view.h
+++ b/engines/bladerunner/view.h
@@ -23,8 +23,6 @@
 #ifndef BLADERUNNER_VIEW_H
 #define BLADERUNNER_VIEW_H
 
-#include "bladerunner/bladerunner.h"
-
 #include "matrix.h"
 
 namespace Common {
@@ -34,7 +32,6 @@ namespace Common {
 namespace BladeRunner {
 
 class View {
-	BladeRunnerEngine *_vm;
 public:
 	float     _fovX;
 	Matrix4x3 _frameViewMatrix;
@@ -47,12 +44,8 @@ public:
 	float     _viewportHalfHeight;
 	float     _viewportDistance;
 
-	View(BladeRunnerEngine *vm);
-
 	bool read(Common::ReadStream *stream);
 
-
-
 private:
 	void setFovX(float fovX);
 	void calculateSliceViewMatrix();
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index 63378dc..06036e7 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -30,7 +30,6 @@
 
 #include "common/array.h"
 #include "common/util.h"
-#include "common/memstream.h"
 
 namespace BladeRunner {
 
@@ -181,14 +180,14 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
 	_videoTrack = new VQAVideoTrack(this);
 	_audioTrack = new VQAAudioTrack(this);
 
-	/*
+#if 0
 	for (int i = 0; i != _loopInfo.loopCount; ++i) {
 		debug("LOOP %2d: %4d %4d %s", i,
 			_loopInfo.loops[i].begin,
 			_loopInfo.loops[i].end,
 			_loopInfo.loops[i].name.c_str());
 	}
-	*/
+#endif
 
 	return true;
 }
@@ -244,6 +243,16 @@ void VQADecoder::readNextPacket() {
 	} while (chd.id != kVQFR);
 }
 
+void VQADecoder::readPacket(int frame) {
+	if (frame < 0 || frame >= numFrames()) {
+		error("frame %d out of bounds, frame count is %d", frame, numFrames());
+	}
+
+	uint32 frameOffset = 2 * (_frameInfo[frame] & 0x0FFFFFFF);
+	_s->seek(frameOffset);
+	readNextPacket();
+}
+
 bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 42)
@@ -515,6 +524,18 @@ bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size)
 	return true;
 }
 
+bool VQADecoder::getLoopBeginAndEndFrame(int loop, int *begin, int *end) {
+	assert(begin && end);
+
+	if (loop < 0 || loop >= _loopInfo.loopCount)
+		return false;
+
+	*begin = _loopInfo.loops[loop].begin;
+	*end   = _loopInfo.loops[loop].end;
+
+	return true;
+}
+
 bool VQADecoder::readCLIP(Common::SeekableReadStream *s, uint32 size) {
 	s->skip(roundup(size));
 	return true;
@@ -525,12 +546,7 @@ bool VQADecoder::readMFCI(Common::SeekableReadStream *s, uint32 size) {
 	return true;
 }
 
-void VQADecoder::decodeView(View* view)
-{
-	_videoTrack->decodeView(view);
-}
-
-	VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
+VQADecoder::VQAVideoTrack::VQAVideoTrack(VQADecoder *vqaDecoder) {
 	VQADecoder::Header *header = &vqaDecoder->_header;
 
 	_surface = nullptr;
@@ -566,8 +582,6 @@ void VQADecoder::decodeView(View* view)
 
 	_surface = new Graphics::Surface();
 	_surface->create(_width, _height, createRGB555());
-
-	_viewData = new uint8[56];
 }
 
 VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
@@ -575,12 +589,11 @@ VQADecoder::VQAVideoTrack::~VQAVideoTrack() {
 	delete[] _cbfz;
 	delete[] _zbufChunk;
 	delete[] _vpointer;
-	delete[] _viewData;
 
 	if (_surface)
 		_surface->free();
 	delete _surface;
-	delete _zbuffer;
+	delete[] _zbuffer;
 }
 
 uint16 VQADecoder::VQAVideoTrack::getWidth() const {
@@ -752,29 +765,18 @@ const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 	return _zbuffer;
 }
 
-
-void VQADecoder::VQAVideoTrack::decodeView(View* view)
-{
-	assert(_viewData);
-	assert(view);
-	
-	Common::MemoryReadStream s(_viewData, 56);
-	view->read(&s);
-}
-
-	bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
+bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
 {
 	if (size != 56)
 		return false;
 
-	s->read(_viewData, 56);
+	_view.read(s);
 
 	return true;
 }
 
 bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size)
 {
-	// some screen (2d not 3d) effects for transparency
 	s->skip(roundup(size));
 	return true;
 }
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index c573720..fecc14d 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -48,12 +48,13 @@ public:
 	bool loadStream(Common::SeekableReadStream *s);
 
 	void readNextPacket();
+	void readPacket(int frame);
 
 	const Graphics::Surface    *decodeVideoFrame();
 	const uint16               *decodeZBuffer();
 	Audio::SeekableAudioStream *decodeAudioFrame();
-	void                        decodeView(View *view);
-	//const View &getView() { return _videoTrack->getView(); }
+
+	const View &getView() { return _videoTrack->getView(); }
 
 	uint16 numFrames() const { return _header.numFrames; }
 	uint8  frameRate() const { return _header.frameRate; }
@@ -64,6 +65,8 @@ public:
 	bool   hasAudio() const { return _header.channels != 0; }
 	uint16 frequency() const { return _header.freq; }
 
+	bool getLoopBeginAndEndFrame(int loop, int *begin, int *end);
+
 protected:
 
 private:
@@ -163,7 +166,7 @@ private:
 		int getFrameCount() const;
 		const Graphics::Surface *decodeVideoFrame();
 		const uint16 *decodeZBuffer();
-		void decodeView(View *view);
+		const View &getView() { return _view; }
 
 		bool readVQFR(Common::SeekableReadStream *s, uint32 size);
 		bool readVPTR(Common::SeekableReadStream *s, uint32 size);
@@ -207,7 +210,7 @@ private:
 
 		int      _curFrame;
 
-		uint8   *_viewData;
+		View     _view;
 
 		void VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha = false);
 		bool decodeFrame(uint16 *frame);
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 0a04d1b..d7b53ff 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -60,17 +60,17 @@ int VQAPlayer::update() {
 	if (_curFrame == -1) {
 		_curFrame = 0;
 		if (_curFrame >= 0) {
-			_decoder.readNextPacket();
+			_decoder.readPacket(_curFrame);
 			if (_hasAudio)
 				queueAudioFrame(_decoder.decodeAudioFrame());
 			_surface = _decoder.decodeVideoFrame();
 			_zBuffer = _decoder.decodeZBuffer();
-			_decoder.decodeView(_view);
+			_view = _decoder.getView();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
 		if (_decodedFrame >= 0) {
-			_decoder.readNextPacket();
+			_decoder.readPacket(_decodedFrame);
 			if (_hasAudio)
 				queueAudioFrame(_decoder.decodeAudioFrame());
 		}
@@ -89,12 +89,12 @@ int VQAPlayer::update() {
 		if (_curFrame >= 0) {
 			_surface = _decoder.decodeVideoFrame();
 			_zBuffer = _decoder.decodeZBuffer();
-			_decoder.decodeView(_view);
+			_view = _decoder.getView();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
 		if (_decodedFrame >= 0) {
-			_decoder.readNextPacket();
+			_decoder.readPacket(_decodedFrame);
 			if (_hasAudio)
 				queueAudioFrame(_decoder.decodeAudioFrame());
 		}
@@ -115,21 +115,46 @@ const uint16 *VQAPlayer::getZBuffer() const {
 	return _zBuffer;
 }
 
-void VQAPlayer::setLoopSpecial(int loop, bool wait) {
-	_loopSpecial = loop;
-	if (!wait)
-		_curLoop = -1;
+bool VQAPlayer::setLoop(int loop) {
+	int begin, end;
+	if (!_decoder.getLoopBeginAndEndFrame(loop, &begin, &end)) {
+		return false;
+	}
+
+	_curLoop   = loop;
+	_loopBegin = begin;
+	_loopEnd   = end;
+
+	// warning("\t\t\tActive Loop: %d - %d\n", begin, end);
+
+	return true;
 }
 
-void VQAPlayer::setLoopDefault(int loop) {
-	_loopDefault = loop;
+int VQAPlayer::getLoopBeginFrame(int loop) {
+	int begin, end;
+	if (!_decoder.getLoopBeginAndEndFrame(loop, &begin, &end)) {
+		return -1;
+	}
+	return begin;
+}
+
+int VQAPlayer::getLoopEndFrame(int loop) {
+	int begin, end;
+	if (!_decoder.getLoopBeginAndEndFrame(loop, &begin, &end)) {
+		return -1;
+	}
+	return end;
 }
 
 int VQAPlayer::calcNextFrame(int frame) const {
 	if (frame < 0)
 		return -3;
 
-	frame += 1;
+	if (_curLoop != -1 && frame >= _loopEnd) {
+		frame = _loopBegin;
+	} else {
+		frame++;
+	}
 
 	if (frame == _decoder.numFrames())
 		frame = -3;
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 98f1fcf..cc29832 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -42,13 +42,13 @@ class VQAPlayer {
 	const uint16                *_zBuffer;
 	Audio::QueuingAudioStream   *_audioStream;
 
-	View                        *_view;
-
 	int _curFrame;
 	int _decodedFrame;
 	int _curLoop;
-	int _loopSpecial;
-	int _loopDefault;
+	int _loopBegin;
+	int _loopEnd;
+
+	View _view;
 
 	uint32 _nextFrameTime;
 	bool   _hasAudio;
@@ -57,7 +57,7 @@ class VQAPlayer {
 
 public:
 
-	VQAPlayer(BladeRunnerEngine *vm, View *view)
+	VQAPlayer(BladeRunnerEngine *vm)
 		: _vm(vm),
 		  _s(nullptr),
 		  _surface(nullptr),
@@ -65,12 +65,11 @@ public:
 		  _curFrame(-1),
 		  _decodedFrame(-1),
 		  _curLoop(-1),
-		  _loopSpecial(-1),
-		  _loopDefault(-1),
+		  _loopBegin(-1),
+		  _loopEnd(-1),
 		  _nextFrameTime(0),
 		  _hasAudio(false),
-		  _audioStarted(false),
-		  _view(view)
+		  _audioStarted(false)
 	{}
 
 	~VQAPlayer() {
@@ -83,9 +82,14 @@ public:
 	int  update();
 	const Graphics::Surface *getSurface() const;
 	const uint16 *getZBuffer() const;
+	const View &getView() const { return _view; }
+
+	bool setLoop(int loop);
+	// void setLoopSpecial(int loop, bool wait);
+	// void setLoopDefault(int loop);
 
-	void setLoopSpecial(int loop, bool wait);
-	void setLoopDefault(int loop);
+	int getLoopBeginFrame(int loop);
+	int getLoopEndFrame(int loop);
 
 private:
 	int calcNextFrame(int frame) const;
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
index 60d3422..3229aaf 100644
--- a/engines/bladerunner/waypoints.cpp
+++ b/engines/bladerunner/waypoints.cpp
@@ -9,7 +9,7 @@ Waypoints::Waypoints(BladeRunnerEngine* vm, int count) {
 Waypoints::~Waypoints() {
 }
 
-void Waypoints::getXyz(int waypointId, float *x, float *y, float *z) {
+void Waypoints::getXYZ(int waypointId, float *x, float *y, float *z) {
 	*x = 0;
 	*y = 0;
 	*z = 0;
@@ -64,4 +64,4 @@ float Waypoints::getZ(int waypointId) {
 	return _waypoints[waypointId]._position.z;
 }
 
-}
\ No newline at end of file
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
index 5ee4696..6f58b63 100644
--- a/engines/bladerunner/waypoints.h
+++ b/engines/bladerunner/waypoints.h
@@ -28,33 +28,35 @@
 
 #include "common/array.h"
 
-
 namespace BladeRunner {
 
-	struct Waypoint {
-		int _setId;
-		Vector3 _position;
-		bool _present;
-	};
-
-	class Waypoints {
-		BladeRunnerEngine *_vm;
-	private:
-		int       _count;
-		Waypoint *_waypoints;
-	public:
-		Waypoints(BladeRunnerEngine *vm, int count);
-		~Waypoints();
-
-		void getXyz(int waypointId, float *x, float *y, float *z);
-		float getX(int waypointId);
-		float getY(int waypointId);
-		float getZ(int waypointId);
-		int getSetId(int waypointId);
-
-		bool set(int waypointId, int setId, Vector3 position);
-		bool reset(int waypointId);
-	};
-}
+struct Waypoint {
+	int _setId;
+	Vector3 _position;
+	bool _present;
+};
+
+class Waypoints {
+	BladeRunnerEngine *_vm;
+
+private:
+	int       _count;
+	Waypoint *_waypoints;
+
+public:
+	Waypoints(BladeRunnerEngine *vm, int count);
+	~Waypoints();
+
+	void getXYZ(int waypointId, float *x, float *y, float *z);
+	float getX(int waypointId);
+	float getY(int waypointId);
+	float getZ(int waypointId);
+	int getSetId(int waypointId);
+
+	bool set(int waypointId, int setId, Vector3 position);
+	bool reset(int waypointId);
+};
+
+} // End of namespace BladeRunner
 
 #endif


Commit: bf44e97d79019c926b214f9f6b109a192d46e2ec
    https://github.com/scummvm/scummvm/commit/bf44e97d79019c926b214f9f6b109a192d46e2ec
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:41+02:00

Commit Message:
BLADERUNNER: added all scene scripts, esper script, kia script, vk script, completed init script. Added decoding of lights from VQA. Moved view from scene.

Changed paths:
  A engines/bladerunner/script/ar01.cpp
  A engines/bladerunner/script/ar02.cpp
  A engines/bladerunner/script/bb01.cpp
  A engines/bladerunner/script/bb02.cpp
  A engines/bladerunner/script/bb03.cpp
  A engines/bladerunner/script/bb04.cpp
  A engines/bladerunner/script/bb05.cpp
  A engines/bladerunner/script/bb06.cpp
  A engines/bladerunner/script/bb07.cpp
  A engines/bladerunner/script/bb08.cpp
  A engines/bladerunner/script/bb09.cpp
  A engines/bladerunner/script/bb10.cpp
  A engines/bladerunner/script/bb11.cpp
  A engines/bladerunner/script/bb12.cpp
  A engines/bladerunner/script/bb51.cpp
  A engines/bladerunner/script/ct01.cpp
  A engines/bladerunner/script/ct02.cpp
  A engines/bladerunner/script/ct03.cpp
  A engines/bladerunner/script/ct04.cpp
  A engines/bladerunner/script/ct05.cpp
  A engines/bladerunner/script/ct06.cpp
  A engines/bladerunner/script/ct07.cpp
  A engines/bladerunner/script/ct08.cpp
  A engines/bladerunner/script/ct09.cpp
  A engines/bladerunner/script/ct10.cpp
  A engines/bladerunner/script/ct11.cpp
  A engines/bladerunner/script/ct12.cpp
  A engines/bladerunner/script/ct51.cpp
  A engines/bladerunner/script/dr01.cpp
  A engines/bladerunner/script/dr02.cpp
  A engines/bladerunner/script/dr03.cpp
  A engines/bladerunner/script/dr04.cpp
  A engines/bladerunner/script/dr05.cpp
  A engines/bladerunner/script/dr06.cpp
  A engines/bladerunner/script/esper.cpp
  A engines/bladerunner/script/esper.h
  A engines/bladerunner/script/hc01.cpp
  A engines/bladerunner/script/hc02.cpp
  A engines/bladerunner/script/hc03.cpp
  A engines/bladerunner/script/hc04.cpp
  A engines/bladerunner/script/hf01.cpp
  A engines/bladerunner/script/hf02.cpp
  A engines/bladerunner/script/hf03.cpp
  A engines/bladerunner/script/hf04.cpp
  A engines/bladerunner/script/hf05.cpp
  A engines/bladerunner/script/hf06.cpp
  A engines/bladerunner/script/hf07.cpp
  A engines/bladerunner/script/kia.cpp
  A engines/bladerunner/script/kia.h
  A engines/bladerunner/script/kp01.cpp
  A engines/bladerunner/script/kp02.cpp
  A engines/bladerunner/script/kp03.cpp
  A engines/bladerunner/script/kp04.cpp
  A engines/bladerunner/script/kp05.cpp
  A engines/bladerunner/script/kp06.cpp
  A engines/bladerunner/script/kp07.cpp
  A engines/bladerunner/script/ma01.cpp
  A engines/bladerunner/script/ma02.cpp
  A engines/bladerunner/script/ma04.cpp
  A engines/bladerunner/script/ma05.cpp
  A engines/bladerunner/script/ma06.cpp
  A engines/bladerunner/script/ma07.cpp
  A engines/bladerunner/script/ma08.cpp
  A engines/bladerunner/script/nr01.cpp
  A engines/bladerunner/script/nr02.cpp
  A engines/bladerunner/script/nr03.cpp
  A engines/bladerunner/script/nr04.cpp
  A engines/bladerunner/script/nr05.cpp
  A engines/bladerunner/script/nr06.cpp
  A engines/bladerunner/script/nr07.cpp
  A engines/bladerunner/script/nr08.cpp
  A engines/bladerunner/script/nr09.cpp
  A engines/bladerunner/script/nr10.cpp
  A engines/bladerunner/script/nr11.cpp
  A engines/bladerunner/script/ps01.cpp
  A engines/bladerunner/script/ps02.cpp
  A engines/bladerunner/script/ps03.cpp
  A engines/bladerunner/script/ps04.cpp
  A engines/bladerunner/script/ps05.cpp
  A engines/bladerunner/script/ps06.cpp
  A engines/bladerunner/script/ps07.cpp
  A engines/bladerunner/script/ps09.cpp
  A engines/bladerunner/script/ps10.cpp
  A engines/bladerunner/script/ps11.cpp
  A engines/bladerunner/script/ps12.cpp
  A engines/bladerunner/script/ps13.cpp
  A engines/bladerunner/script/ps14.cpp
  A engines/bladerunner/script/ps15.cpp
  A engines/bladerunner/script/rc02.cpp
  A engines/bladerunner/script/rc03.cpp
  A engines/bladerunner/script/rc04.cpp
  A engines/bladerunner/script/rc51.cpp
  A engines/bladerunner/script/tb02.cpp
  A engines/bladerunner/script/tb03.cpp
  A engines/bladerunner/script/tb05.cpp
  A engines/bladerunner/script/tb06.cpp
  A engines/bladerunner/script/tb07.cpp
  A engines/bladerunner/script/ug01.cpp
  A engines/bladerunner/script/ug02.cpp
  A engines/bladerunner/script/ug03.cpp
  A engines/bladerunner/script/ug04.cpp
  A engines/bladerunner/script/ug05.cpp
  A engines/bladerunner/script/ug06.cpp
  A engines/bladerunner/script/ug07.cpp
  A engines/bladerunner/script/ug08.cpp
  A engines/bladerunner/script/ug09.cpp
  A engines/bladerunner/script/ug10.cpp
  A engines/bladerunner/script/ug12.cpp
  A engines/bladerunner/script/ug13.cpp
  A engines/bladerunner/script/ug14.cpp
  A engines/bladerunner/script/ug15.cpp
  A engines/bladerunner/script/ug16.cpp
  A engines/bladerunner/script/ug17.cpp
  A engines/bladerunner/script/ug18.cpp
  A engines/bladerunner/script/ug19.cpp
  A engines/bladerunner/script/vk.cpp
  A engines/bladerunner/script/vk.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/audio_player.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/light.cpp
    engines/bladerunner/light.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/module.mk
    engines/bladerunner/mouse.cpp
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/script/init.cpp
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/set.cpp
    engines/bladerunner/shape.cpp
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index b4bdd68..4b893c6 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -186,6 +186,10 @@ void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired)
 	setAtXYZ(waypointPosition, angle, true, moving, retired);
 }
 
+void Actor::loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7) {
+	this->loopWalkToXYZ(Vector3(x, y, z));
+}
+
 void Actor::loopWalkToXYZ(Vector3 destination)
 {
 	int unk1;
@@ -660,7 +664,7 @@ void Actor::setGoal(int goalNumber) {
 
 	//TODO: _vm->actorScript->GoalChanged(_id, _goalNumber, goalNumber);
 
-	_vm->_script->SceneActorChangedGoal(_id, goalNumber, _goalNumber, _vm->_scene->getSetId() == _setId);
+	_vm->_script->ActorChangedGoal(_id, goalNumber, _goalNumber, _vm->_scene->getSetId() == _setId);
 }
 
 int Actor::getGoal() {
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 34d8a5a..7827141 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -121,6 +121,7 @@ public:
 	void setFPS(int fps);
 
 	void loopWalkToXYZ(Vector3 destination);
+	void loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7);
 	void loopWalkToSceneObject(const char *objectName, int destinationOffset = 0);
 
 	bool tick(bool forceUpdate);
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index 851b0bc..1698bfb 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -166,7 +166,7 @@ void AudioPlayer::fadeAndStopTrack(Track *track, int time)
 int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, int panTo, int priority, byte flags) {
 	/* Find first available track or, alternatively, the lowest priority playing track */
 	Track *track = NULL;
-	int    lowestPriority;
+	int    lowestPriority = INT_MAX;
 	Track *lowestPriorityTrack = NULL;
 
 	for (int i = 0; i != 6; ++i) {
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index bd38fe7..bf9077f 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -555,7 +555,7 @@ void BladeRunnerEngine::gameTick() {
 
 		if (_settings->getNewScene() == -1 || _script->_inScriptCounter /* || in_ai */) {
 
-			_sliceRenderer->setView(_scene->_view);
+			_sliceRenderer->setView(*_view);
 
 			// Tick and draw all actors in current set
 			for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
@@ -611,29 +611,66 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 	int isTarget;
 
 	int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
-	int exitType      = _scene->_exits->getTypeAtXY(x, y);
+	int exitIndex     = _scene->_exits->getTypeAtXY(x, y);
 
-	debug("%d %d", sceneObjectId, exitType);
+	debug("%d %d", sceneObjectId, exitIndex);
 
-	if ((sceneObjectId < 0 || sceneObjectId > 73) && exitType >= 0) {
-		// clickedOnExit(exitType, x, y);
-		debug("clicked on exit %d %d %d", exitType, x, y);
+	if ((sceneObjectId < 0 || sceneObjectId > 73) && exitIndex >= 0) {
+		handleMouseClickExit(x, y, exitIndex);
 		return;
 	}
 
 	int regionIndex = _scene->_regions->getRegionAtXY(x, y);
 	if (regionIndex >= 0) {
-		debug("clicked on region %d %d %d", regionIndex, x, y);
-		_script->ClickedOn2DRegion(regionIndex);
+		handleMouseClickRegion(x, y, regionIndex);
+		return;
 	}
 
-	if (sceneObjectId >= 198 && sceneObjectId <= 293) {
-		const char *objectName = _scene->objectGetName(sceneObjectId - 198);
-		debug("%s", objectName);
-		_script->ClickedOn3DObject(objectName);
+	if (sceneObjectId == -1) {
+		debug("Clicked on nothing");
+		return;
+	} else if (sceneObjectId >= 0 && sceneObjectId <= 73) {
+		handleMouseClickActor(x, y, sceneObjectId);
+		return;
+	} else if (sceneObjectId >= 74 && sceneObjectId <= 197) {
+		handleMouseClickItem(x, y, sceneObjectId - 74);
+		return;
+	} else if (sceneObjectId >= 198 && sceneObjectId <= 293) {
+		handleMouseClick3DObject(x, y, sceneObjectId - 198, isClickable, isTarget);
 		return;
 	}
+}
+
+void BladeRunnerEngine::handleMouseClickExit(int x, int y, int exitIndex)
+{
+	// clickedOnExit(exitType, x, y);
+	debug("clicked on exit %d %d %d", exitIndex, x, y);
+	_script->ClickedOnExit(exitIndex);
+}
+
+void BladeRunnerEngine::handleMouseClickRegion(int x, int y, int regionIndex)
+{
+	debug("clicked on region %d %d %d", regionIndex, x, y);
+	_script->ClickedOn2DRegion(regionIndex);
+}
+
+void BladeRunnerEngine::handleMouseClick3DObject(int x, int y, int objectId, bool isClickable, bool isTarget)
+{
+	const char *objectName = _scene->objectGetName(objectId);
+	debug("Clicked on object %s", objectName);
+	_script->ClickedOn3DObject(objectName, false);
+}
+
+void BladeRunnerEngine::handleMouseClickItem(int x, int y, int itemId)
+{
+	debug("Clicked on item %d", itemId);
+	_script->ClickedOnItem(itemId, false);
+}
 
+void BladeRunnerEngine::handleMouseClickActor(int x, int y, int actorId)
+{	
+	debug("Clicked on actor %d", actorId);
+	_script->ClickedOnActor(actorId);
 }
 
 void BladeRunnerEngine::gameWaitForActive() {
@@ -655,12 +692,6 @@ void BladeRunnerEngine::loopActorSpeaking() {
 	playerGainsControl();
 }
 
-void BladeRunnerEngine::loopActorWalkToXYZ(int actorId, float x, float y, float z, int a4, int a5, int a6, int a7) {
-	Actor *actor = _actors[actorId];
-
-	actor->loopWalkToXYZ(Vector3(x, y, z));
-}
-
 void BladeRunnerEngine::outtakePlay(int id, bool noLocalization, int container) {
 	Common::String name = _gameInfo->getOuttake(id);
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index fba793c..082617e 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -143,11 +143,14 @@ public:
 	void gameTick();
 	void handleEvents();
 	void handleMouseClick(int x, int y);
+	void handleMouseClickExit(int x, int y, int exitIndex);
+	void handleMouseClickRegion(int x, int y, int regionIndex);
+	void handleMouseClickItem(int x, int y, int itemId);
+	void handleMouseClickActor(int x, int y, int actorId);
+	void handleMouseClick3DObject(int x, int y, int objectId, bool isClickable, bool isTarget);
 	void gameWaitForActive();
 	void loopActorSpeaking();
 
-	void loopActorWalkToXYZ(int actorId, float x, float y, float z, int a4, int a5, int a6, int a7);
-
 	void outtakePlay(int id, bool no_localization, int container = -1);
 
 	bool openArchive(const Common::String &name);
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index 3689ab4..d1d79b8 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -48,8 +48,39 @@ void Light::read(Common::ReadStream* stream, int framesCount, int frame, int ani
 	setupFrame(frame);
 }
 
-void Light::readVqa(Common::ReadStream* stream)
+void Light::readVqa(Common::ReadStream* stream, int framesCount, int frame, int animated)
 {
+	_framesCount = framesCount;
+	_animated = animated;
+
+	_animatedParameters = stream->readUint32LE();
+
+	int size = stream->readUint32LE();
+
+	_animationData = new float[size / sizeof(float)];
+	stream->read(_animationData, size);
+
+	_m11ptr = _animationData;
+	_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? framesCount : 1);
+	_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? framesCount : 1);
+	_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? framesCount : 1);
+	_m21ptr = _m14ptr + (_animatedParameters & 0x8 ? framesCount : 1);
+	_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? framesCount : 1);
+	_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? framesCount : 1);
+	_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? framesCount : 1);
+	_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? framesCount : 1);
+	_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? framesCount : 1);
+	_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? framesCount : 1);
+	_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? framesCount : 1);
+	_colorRPtr = _m34ptr + (_animatedParameters & 0x800 ? framesCount : 1);
+	_colorGPtr = _colorRPtr + (_animatedParameters & 0x1000 ? framesCount : 1);
+	_colorBPtr = _colorGPtr + (_animatedParameters & 0x2000 ? framesCount : 1);
+	_field16ptr = _colorGPtr + (_animatedParameters & 0x4000 ? framesCount : 1);
+	_field17ptr = _field16ptr + (_animatedParameters & 0x8000 ? framesCount : 1);
+	_field18ptr = _field17ptr + (_animatedParameters & 0x10000 ? framesCount : 1);
+	_field19ptr = _field18ptr + (_animatedParameters & 0x20000 ? framesCount : 1);
+
+	setupFrame(frame);
 }
 
 void Light::setupFrame(int frame)
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index bfece07..b075c91 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -77,7 +77,7 @@ public:
 	~Light();
 
 	void read(Common::ReadStream *stream, int framesCount, int frame, int animated);
-	void readVqa(Common::ReadStream *stream);
+	void readVqa(Common::ReadStream *stream, int framesCount, int frame, int animated);
 
 	void setupFrame(int frame);
 
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index 29e4c2f..7a6be94 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -19,7 +19,7 @@ Lights::~Lights()
 	reset();
 }
 
-void Lights::read(Common::ReadStream* stream, int framesCount)
+void Lights::read(Common::ReadStream *stream, int framesCount)
 {
 	_ambientLightColor.r = stream->readFloatLE();
 	_ambientLightColor.g = stream->readFloatLE();
@@ -58,11 +58,66 @@ void Lights::read(Common::ReadStream* stream, int framesCount)
 	}
 }
 
-void Lights::readVqa(Common::ReadStream* stream)
+void Lights::removeAnimated()
 {
-	reset();
-	//int framesCount = stream->readUint32LE();
-	//int count = stream->readUint32LE();
+	Light **nextLight;
+	Light *light; 
+
+	nextLight = &this->_lights;
+	light = this->_lights;
+	if (light)
+	{
+		do
+		{
+			if (light->_animated)
+			{
+				*nextLight = light->_next;
+				delete light;
+			}
+			else
+			{
+				nextLight = &light->_next;
+			}
+			light = *nextLight;
+		} while (*nextLight);
+	}
+}
+
+void Lights::readVqa(Common::ReadStream *stream)
+{
+	removeAnimated();
+	if (stream->eos())
+		return;
+
+	int framesCount = stream->readUint32LE();
+	int count = stream->readUint32LE();
+	for (int i = 0; i < count; i++) {
+		int lightType = stream->readUint32LE();
+		Light* light;
+		switch(lightType)
+		{
+			case 5:
+				light = new Light5();
+				break;
+			case 4:
+				light = new Light4();
+				break;
+			case 3:
+				light = new Light3();
+				break;
+			case 2:
+				light = new Light2();
+				break;
+			case 1:
+				light = new Light1();
+				break;
+			default:
+				light = new Light();
+		}
+		light->readVqa(stream, framesCount, _frame, 1);
+		light->_next = _lights;
+		_lights = light;
+	}
 }
 
 void Lights::setupFrame(int frame)
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index 71e6d21..0db7a07 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -52,6 +52,8 @@ public:
 	void reset();
 
 	void setupFrame(int frame);
+private: 
+	void removeAnimated();
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index e6b8e43..60bea4a 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -37,7 +37,120 @@ MODULE_OBJS = \
 	script/ai_00_mccoy.o \
 	script/aiscript_officer_leroy.o \
 	script/init.o \
+	script/kia.o \
+	script/vk.o \
+	script/esper.o \
+	script/ar01.o \
+	script/ar02.o \
+	script/bb01.o \
+	script/bb02.o \
+	script/bb03.o \
+	script/bb04.o \
+	script/bb05.o \
+	script/bb06.o \
+	script/bb07.o \
+	script/bb08.o \
+	script/bb09.o \
+	script/bb10.o \
+	script/bb11.o \
+	script/bb12.o \
+	script/bb51.o \
+	script/ct01.o \
+	script/ct02.o \
+	script/ct03.o \
+	script/ct04.o \
+	script/ct05.o \
+	script/ct06.o \
+	script/ct07.o \
+	script/ct08.o \
+	script/ct09.o \
+	script/ct10.o \
+	script/ct11.o \
+	script/ct12.o \
+	script/ct51.o \
+	script/dr01.o \
+	script/dr02.o \
+	script/dr03.o \
+	script/dr04.o \
+	script/dr05.o \
+	script/dr06.o \
+	script/hc01.o \
+	script/hc02.o \
+	script/hc03.o \
+	script/hc04.o \
+	script/hf01.o \
+	script/hf02.o \
+	script/hf03.o \
+	script/hf04.o \
+	script/hf05.o \
+	script/hf06.o \
+	script/kp01.o \
+	script/kp02.o \
+	script/kp03.o \
+	script/kp04.o \
+	script/kp05.o \
+	script/kp06.o \
+	script/kp07.o \
+	script/ma01.o \
+	script/ma02.o \
+	script/ma04.o \
+	script/ma05.o \
+	script/ma06.o \
+	script/ma07.o \
+	script/ma08.o \
+	script/nr01.o \
+	script/nr02.o \
+	script/nr03.o \
+	script/nr04.o \
+	script/nr05.o \
+	script/nr06.o \
+	script/nr07.o \
+	script/nr08.o \
+	script/nr09.o \
+	script/nr10.o \
+	script/nr11.o \
+	script/ps01.o \
+	script/ps02.o \
+	script/ps03.o \
+	script/ps04.o \
+	script/ps05.o \
+	script/ps06.o \
+	script/ps07.o \
+	script/ps09.o \
+	script/ps10.o \
+	script/ps11.o \
+	script/ps12.o \
+	script/ps13.o \
+	script/ps14.o \
+	script/ps15.o \
 	script/rc01.o \
+	script/rc02.o \
+	script/rc03.o \
+	script/rc04.o \
+	script/rc51.o \
+	script/tb02.o \
+	script/tb03.o \
+	script/tb05.o \
+	script/tb06.o \
+	script/tb07.o \
+	script/ug01.o \
+	script/ug02.o \
+	script/ug03.o \
+	script/ug04.o \
+	script/ug05.o \
+	script/ug06.o \
+	script/ug07.o \
+	script/ug08.o \
+	script/ug09.o \
+	script/ug10.o \
+	script/ug12.o \
+	script/ug13.o \
+	script/ug14.o \
+	script/ug15.o \
+	script/ug16.o \
+	script/ug17.o \
+	script/ug18.o \
+	script/ug19.o \
 	script/script.o \
 	set.o \
 	settings.o \
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index ba747c2..14a2151 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -308,7 +308,7 @@ Vector3 Mouse::getXYZ(int x, int y)
 	int screenRight = 640 - x;
 	int screenDown  = 480 - y;
 
-	float zcoef = 1.0f / tan(_vm->_scene->_view._fovX / 2.0f);
+	float zcoef = 1.0f / tan(_vm->_view->_fovX / 2.0f);
 
 	float x3d = (2.0f / 640.0f * screenRight - 1.0f);
 	float y3d = (2.0f / 480.0f * screenDown  - 1.0f) * 0.75f;
@@ -320,7 +320,7 @@ Vector3 Mouse::getXYZ(int x, int y)
 	pos.x = pos.z / zcoef * x3d;
 	pos.y = pos.z / zcoef * y3d;
 
-	Matrix4x3 matrix = _vm->_scene->_view._frameViewMatrix;
+	Matrix4x3 matrix = _vm->_view->_frameViewMatrix;
 
 	matrix.unknown();
 
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index ba4ca44..29d73f3 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -136,7 +136,8 @@ int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer.getSurface());
 		memcpy(zBuffer, _vqaPlayer.getZBuffer(), 640*480*2);
-		_view = _vqaPlayer.getView();
+		_vqaPlayer.updateView(_vm->_view);
+		_vqaPlayer.updateLights(_vm->_lights);
 	}
 
 	if (frame < 0) {
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index 1a3c9f3..e4a2406 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -56,7 +56,6 @@ public:
 	Vector3     _actorStartPosition;
 	int         _actorStartFacing;
 	bool        _playerWalkedIn;
-	View        _view;
 
 	Regions*    _regions;
 	Regions*    _exits;
@@ -64,7 +63,6 @@ public:
 	// _default_loop_id = 0;
 	// _scene_vqa_frame_number = -1;
 
-
 public:
 	Scene(BladeRunnerEngine *vm)
 		: _vm(vm),
diff --git a/engines/bladerunner/script/ar01.cpp b/engines/bladerunner/script/ar01.cpp
new file mode 100644
index 0000000..dda8a8c
--- /dev/null
+++ b/engines/bladerunner/script/ar01.cpp
@@ -0,0 +1,361 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptAR01::InitializeScene() {
+	Music_Play(0, 25, 0, 2, -1, 1, 2);
+	if (Game_Flag_Query(323)) {
+		Setup_Scene_Information(-477.0f, 0.0f, -149.0f, 333);
+	} else if (Game_Flag_Query(321) == 1) {
+		Setup_Scene_Information(-182.0f, 0.0f, -551.0f, 518);
+	} else {
+		Setup_Scene_Information(-152.0f, 0.0f, 332.0f, 545);
+	}
+	Scene_Exit_Add_2D_Exit(0, 134, 165, 177, 290, 3);
+	Scene_Exit_Add_2D_Exit(1, 319, 0, 639, 207, 0);
+	if (Game_Flag_Query(252)) {
+		Scene_Exit_Add_2D_Exit(2, 0, 404, 99, 479, 2);
+	}
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(81, 60, 100, 1);
+	Ambient_Sounds_Add_Looping_Sound(241, 50, 1, 1);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(242, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(243, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(244, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(245, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(246, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(247, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(248, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(249, 3, 30, 11, 11, 50, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(68, 10, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 10, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Game_Flag_Query(252) && !Game_Flag_Query(321) && !Game_Flag_Query(323)) {
+		Actor_Set_Invisible(0, true);
+		Game_Flag_Set(273);
+		Scene_Loop_Start_Special(0, 1, 0);
+		Scene_Loop_Set_Default(2);
+	} else if (Game_Flag_Query(252) && Game_Flag_Query(321)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(2);
+		Game_Flag_Reset(321);
+	} else if (!Game_Flag_Query(252) && Game_Flag_Query(321)) {
+		Scene_Loop_Start_Special(0, 6, 0);
+		Scene_Loop_Set_Default(7);
+		Game_Flag_Reset(321);
+	} else if (Game_Flag_Query(252) && Game_Flag_Query(323)) {
+		Scene_Loop_Set_Default(2);
+	} else if (!Game_Flag_Query(252) && Game_Flag_Query(323)) {
+		Scene_Loop_Set_Default(7);
+	} else {
+		Scene_Loop_Set_Default(7);
+	}
+}
+
+void ScriptAR01::SceneLoaded() {
+	Obstacle_Object("DF_BOOTH", true);
+	Unobstacle_Object("SPINNER BODY", true);
+}
+
+bool ScriptAR01::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptAR01::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptAR01::ClickedOnActor(int actorId) {
+	if (actorId == 16 || actorId == 20) {
+		Actor_Face_Actor(0, actorId, true);
+		Actor_Says(0, 8910, 14);
+		return true;
+	}
+	if (actorId == 29) {
+		Actor_Set_Goal_Number(29, 2);
+		if (!Loop_Actor_Walk_To_XYZ(0, -120.73f, 0.0f, 219.17f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 29, true);
+			Actor_Face_Actor(29, 0, true);
+			if (Game_Flag_Query(328)) {
+				if (Actor_Clue_Query(0, 93) && !Actor_Clue_Query(0, 64)) {
+					Actor_Says(0, 40, 11);
+					Actor_Says(29, 120, 14);
+					Actor_Says(0, 45, 17);
+					Actor_Says(29, 130, 14);
+					Actor_Says(29, 140, 14);
+					Actor_Says(0, 50, 13);
+					Actor_Says(29, 150, 14);
+					Actor_Clue_Acquire(0, 64, 1, 0);
+				} else {
+					if (Random_Query(1, 2) == 1) {
+						Actor_Says(0, 30, 17);
+						Actor_Says(29, 100, 14);
+						Actor_Says(29, 110, 14);
+						Actor_Says(0, 35, 13);
+					} else {
+						Actor_Says(0, 30, 17);
+						Actor_Says(29, 220, 14);
+					}
+				}
+				Actor_Set_Goal_Number(29, 1);
+			} else {
+				Actor_Says(0, 0, 18);
+				Actor_Says(29, 0, 14);
+				Actor_Says(29, 10, 14);
+				Actor_Says(29, 20, 14);
+				Actor_Says(29, 30, 14);
+				Actor_Says(0, 5, 17);
+				Actor_Says(29, 40, 14);
+				Actor_Says(0, 10, 13);
+				Actor_Says(29, 50, 14);
+				Actor_Says(0, 15, 17);
+				Actor_Says(29, 60, 14);
+				Actor_Says(29, 70, 14);
+				Actor_Says(29, 80, 14);
+				Actor_Says(29, 90, 14);
+				Actor_Says(0, 25, 13);
+				Game_Flag_Set(328);
+				Actor_Set_Goal_Number(29, 1);
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
+bool ScriptAR01::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptAR01::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -358.0, 0.0, -149.0, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, -477.0, 0.0, -149.0, 0, 0, false, 0);
+			Game_Flag_Set(322);
+			Game_Flag_Set(464);
+			Game_Flag_Reset(180);
+			Game_Flag_Set(479);
+			Set_Enter(8, 31);
+			Actor_Set_Goal_Number(29, 3);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -182.0, 0.0, -551.0, 0, 1, false, 0)) {
+			Game_Flag_Set(320);
+			Async_Actor_Walk_To_XYZ(0, -222.0, 0.0, -690.0, 0, false);
+			Set_Enter(0, 1);
+			Actor_Set_Goal_Number(29, 3);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (Game_Flag_Query(486) == 1) {
+			Spinner_Set_Selectable_Destination_Flag(6, 1);
+		}
+		int v1 = Loop_Actor_Walk_To_XYZ(0, -164.0f, 0.0f, 332.0f, 0, 1, false, 0);
+		Actor_Face_Heading(0, 545, false);
+		if (Actor_Query_Goal_Number(7) >= 2 && Actor_Query_Goal_Number(7) <= 103) {
+			Player_Loses_Control();
+			Actor_Put_In_Set(7, 0);
+			Actor_Set_At_XYZ(7, -448.0, 0.0, 130.0, 0);
+			Loop_Actor_Walk_To_XYZ(7, -323.0f, 0.64f, 101.74f, 48, 0, true, 0);
+			Loop_Actor_Walk_To_Actor(7, 0, 48, 0, true);
+			Actor_Face_Actor(7, 0, true);
+			Actor_Change_Animation_Mode(7, 6);
+			Actor_Says(0, 1800, 21);
+			Actor_Change_Animation_Mode(0, 48);
+			Player_Gains_Control();
+			Actor_Retired_Here(0, 12, 48, 1, 7);
+		} else if (!v1) {
+			if (Game_Flag_Query(486) && !Game_Flag_Query(660)) {
+				Actor_Voice_Over(4310, 99);
+				Actor_Voice_Over(4320, 99);
+				Actor_Voice_Over(4330, 99);
+				Actor_Voice_Over(4340, 99);
+				Actor_Voice_Over(4350, 99);
+				Game_Flag_Set(660);
+			}
+			Game_Flag_Reset(176);
+			Game_Flag_Reset(182);
+			Game_Flag_Reset(179);
+			Game_Flag_Reset(178);
+			Game_Flag_Reset(258);
+			Game_Flag_Reset(257);
+			Game_Flag_Reset(180);
+
+			int spinnerDest = Spinner_Interface_Choose_Dest(4, 0);
+			Actor_Face_Heading(0, 545, 0);
+
+			switch (spinnerDest) {
+			case 0:
+				Game_Flag_Set(178);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(251);
+				Set_Enter(61, 65);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 1:
+				Game_Flag_Set(179);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(250);
+				Set_Enter(49, 48);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 2:
+				Game_Flag_Set(182);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(249);
+				Set_Enter(69, 78);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 3:
+				Game_Flag_Set(176);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(248);
+				Set_Enter(4, 13);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 5:
+				Game_Flag_Set(261);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(307);
+				Set_Enter(17, 82);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 6:
+				Game_Flag_Set(177);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(253);
+				Set_Enter(7, 25);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 7:
+				Game_Flag_Set(258);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(254);
+				Set_Enter(20, 2);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 8:
+				Game_Flag_Set(181);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(255);
+				Set_Enter(54, 54);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 9:
+				Game_Flag_Set(257);
+				Game_Flag_Reset(252);
+				Game_Flag_Set(256);
+				Set_Enter(37, 34);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			default:
+				Game_Flag_Set(180);
+				Actor_Set_Invisible(0, 0);
+				break;
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptAR01::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptAR01::SceneFrameAdvanced(int frame) {
+	if (frame == 16) {
+		Ambient_Sounds_Play_Sound(118, 40, 0, 0, 99);
+	}
+	if (frame == 78 || frame == 199) {
+		Ambient_Sounds_Play_Sound(116, 100, -50, -50, 99);
+	}
+	if (frame == 122 || frame == 242) {
+		Ambient_Sounds_Play_Sound(119, 100, -50, -50, 99);
+	}
+	if (frame == 256) {
+		Ambient_Sounds_Play_Sound(117, 40, -50, 80, 99);
+	}
+	if ((frame == 75 || frame == 196) && Game_Flag_Query(273)) {
+		Actor_Face_Heading(0, 545, false);
+		Actor_Change_Animation_Mode(0, 42);
+		Game_Flag_Reset(273);
+	} else if (frame == 196 && !Game_Flag_Query(273)) {
+		Actor_Change_Animation_Mode(0, 41);
+	}
+}
+
+void ScriptAR01::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptAR01::PlayerWalkedIn() {
+	if (!Game_Flag_Query(710)) {
+		Game_Flag_Set(710);
+	}
+	if (Game_Flag_Query(323) == 1) {
+		Loop_Actor_Walk_To_XYZ(0, -358.0f, 0.0f, -149.0f, 0, 1, false, 0);
+		Game_Flag_Reset(323);
+	}
+	if (Actor_Query_Goal_Number(37) < 199) {
+		Actor_Set_Goal_Number(37, 199);
+	}
+}
+
+void ScriptAR01::PlayerWalkedOut() {
+	Actor_Set_Invisible(0, 0);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+	if (!Game_Flag_Query(479)) {
+		Music_Stop(2);
+	}
+	if (!Game_Flag_Query(322) && !Game_Flag_Query(320)) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Outtake_Play(38, 1, -1);
+	}
+}
+
+void ScriptAR01::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ar02.cpp b/engines/bladerunner/script/ar02.cpp
new file mode 100644
index 0000000..5b6be5f
--- /dev/null
+++ b/engines/bladerunner/script/ar02.cpp
@@ -0,0 +1,390 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptAR02::InitializeScene() {
+	Music_Play(0, 22, 0, 2, -1, 1, 2);
+	if (Game_Flag_Query(116)) {
+		Setup_Scene_Information(-560.0f, 0.0f, -799.0f, 333);
+	} else {
+		Setup_Scene_Information(-182.0f, 0.0f, -551.0f, 973);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 439, 212, 479, 2);
+	Scene_Exit_Add_2D_Exit(1, 81, 202, 215, 406, 3);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(81, 60, 100, 1);
+	Ambient_Sounds_Add_Looping_Sound(241, 50, 1, 1);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(242, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(243, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(244, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(245, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(246, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(247, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(248, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(249, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(68, 10, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 10, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Game_Flag_Query(252) && Game_Flag_Query(320)) {
+		Scene_Loop_Start_Special(0, 1, 0);
+		Scene_Loop_Set_Default(2);
+		Game_Flag_Reset(320);
+	} else if (!Game_Flag_Query(252) && Game_Flag_Query(320)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(2);
+		Game_Flag_Reset(320);
+	} else {
+		Scene_Loop_Set_Default(2);
+	}
+}
+
+void ScriptAR02::SceneLoaded() {
+	Obstacle_Object("DF_BOOTH", true);
+	if (!Game_Flag_Query(374)) {
+		Item_Add_To_World(106, 976, 0, -442.84f, 36.77f, -1144.51f, 360, 36, 36, false, true, false, true);
+	}
+	if (Global_Variable_Query(1) == 4 && !Game_Flag_Query(374)) {
+		Game_Flag_Set(0);
+		Item_Remove_From_World(106);
+	}
+}
+
+bool ScriptAR02::MouseClick(int x, int y) {
+	return Region_Check(250, 215, 325, 260);
+}
+
+bool ScriptAR02::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptAR02::ClickedOnActor(int actorId) {
+	if (actorId == 16) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -386.96f, 0.0f, -1078.45f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 16, true);
+			Actor_Face_Actor(16, 0, true);
+			if (Global_Variable_Query(1) == 2) {
+				if (Game_Flag_Query(329) && !Game_Flag_Query(366)) {
+					Game_Flag_Set(366);
+					Player_Loses_Control();
+					ADQ_Flush();
+					ADQ_Add(16, 210, 14);
+					Loop_Actor_Walk_To_XYZ(0, -350.66f, 0.0f, -1117.19f, 0, 0, false, 0);
+					Actor_Face_Actor(0, 16,true);
+					Actor_Says(0, 110, 18);
+					Actor_Says(16, 230, 14);
+					Actor_Says(0, 115, 18);
+					Actor_Says(16, 240, 14);
+					Item_Pickup_Spin_Effect(956, 288, 257);
+					Actor_Says(16, 250, 14);
+					Player_Gains_Control();
+					sub_402AE0();
+				} else if (Game_Flag_Query(329)) {
+					Actor_Says(0, 75, 18);
+					Actor_Says(16, 60, 12);
+					Actor_Says(16, 70, 14);
+				} else {
+					sub_402694();
+				}
+			} else if (Global_Variable_Query(1) > 2) {
+				if (Actor_Clue_Query(0, 56) && !Actor_Clue_Query(0, 90)) {
+					Actor_Says(0, 205, 16);
+					Actor_Says(16, 290, 12);
+					Actor_Says(16, 300, 13);
+					Actor_Says(0, 210, 15);
+					Actor_Says(16, 310, 12);
+					Actor_Says(0, 215, 13);
+					if (Game_Flag_Query(374)) {
+						Actor_Says(0, 220, 14);
+						Actor_Says(16, 320, 12);
+						Actor_Says(0, 225, 13);
+						Actor_Says(16, 330, 14);
+						Actor_Says(0, 230, 19);
+						Actor_Says(16, 340, 13);
+						Actor_Says(16, 350, 12);
+						Actor_Says(0, 235, 16);
+						Actor_Clue_Acquire(0, 79, 0, 16);
+					}
+					Actor_Clue_Acquire(0, 90, 0, 16);
+				} else {
+					Actor_Says(0, 240, 17);
+					Actor_Says(16, 360, 13);
+					Actor_Says(16, 370, 14);
+					Actor_Says(0, 245, 13);
+				}
+			}
+			return true;
+		}
+	}
+	if (actorId == 20 && Global_Variable_Query(1) == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -240.79f, 0.0f, -1328.89f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 20, true);
+			Actor_Face_Actor(20, 0, true);
+			if (Game_Flag_Query(330)) {
+				sub_402CE4();
+				return false;
+			}
+			Actor_Says(20, 0, 14);
+			Actor_Says(0, 140, 18);
+			Game_Flag_Set(330);
+			return true;
+		}
+	}
+	return false;
+}
+
+bool ScriptAR02::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 106) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -386.96f, 0.0f, -1078.45f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 16, true);
+			if (!Game_Flag_Query(331)) {
+				Actor_Says(16, 0, 14);
+				Actor_Says(0, 55, 18);
+				Actor_Says(16, 10, 14);
+				Actor_Says(0, 60, 18);
+				Actor_Says(16, 20, 14);
+				Game_Flag_Set(331);
+			} else if (Game_Flag_Query(331) && !Game_Flag_Query(367)) {
+				Actor_Says(0, 65, 21);
+				Actor_Says(16, 30, 14);
+				Actor_Says(16, 40, 14);
+				Actor_Says(0, 70, 18);
+				Actor_Says(16, 50, 14);
+				Game_Flag_Set(367);
+			} else {
+				Actor_Says(0, 8527, 14);
+			}
+			return true;
+		}
+	}
+	return false;
+}
+
+bool ScriptAR02::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -182.0f, 0.0f, -551.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(321);
+			Async_Actor_Walk_To_XYZ(0, -182.0f, 0.0f, -407.0f, 0, false);
+			Set_Enter(0, 0);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -465.0f, 0.0f, -799.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, -560.0f, 0.0f, -799.0f, 0, 0, false, 0);
+			Game_Flag_Set(117);
+			Game_Flag_Reset(180);
+			Game_Flag_Set(182);
+			Music_Stop(3);
+			Set_Enter(70, 80);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptAR02::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptAR02::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptAR02::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptAR02::PlayerWalkedIn() {
+	if (Game_Flag_Query(116) == 1) {
+		Loop_Actor_Walk_To_XYZ(0, -465.0f, 0.0f, -799.0f, 0, 0, false, 0);
+		Game_Flag_Reset(116);
+	}
+	Game_Flag_Set(726);
+}
+
+void ScriptAR02::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptAR02::DialogueQueueFlushed(int a1) {
+}
+
+void ScriptAR02::sub_402694() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 44) || Actor_Clue_Query(0, 47)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(490, 3, 5, 5);
+	}
+	if (Actor_Clue_Query(0, 14) && !Actor_Clue_Query(0, 44) && !Actor_Clue_Query(0, 47)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(500, 3, 5, 5);
+	}
+	DM_Add_To_List_Never_Repeat_Once_Selected(510, 8, 3, -1);
+	Dialogue_Menu_Add_DONE_To_List(520);
+	Dialogue_Menu_Appear(320, 240);
+	int answerValue = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answerValue) {
+	case 490:
+	case 500:
+		if (answerValue == 490) {
+			Actor_Says(0, 145, 15);
+		} else {
+			Actor_Says(0, 150, 15);
+		}
+		Actor_Says(16, 80, 14);
+		Actor_Says(0, 80, 16);
+		Actor_Says(16, 90, 12);
+		Actor_Says(0, 85, 17);
+		Actor_Says(16, 100, 14);
+		Actor_Says(16, 110, 12);
+		Actor_Says(16, 120, 12);
+		Actor_Says(0, 90, 13);
+		Actor_Says(16, 130, 12);
+		Actor_Says(16, 140, 14);
+		Actor_Says(0, 95, 15);
+		Actor_Says(16, 150, 12);
+		Actor_Says(16, 160, 13);
+		Actor_Says(16, 170, 14);
+		Actor_Says(0, 100, 16);
+		Actor_Says(16, 180, 13);
+		Game_Flag_Set(329);
+		Actor_Clue_Acquire(0, 56, 1, 16);
+		break;
+	case 510:
+		Actor_Says(0, 8475, 12);
+		Actor_Says(16, 190, 12);
+		Actor_Says(0, 105, 15);
+		Actor_Says(16, 200, 14);
+		break;
+	case 520:
+		Actor_Says(0, 215, 16);
+		break;
+	}
+}
+
+void ScriptAR02::sub_402AE0() {
+	Dialogue_Menu_Clear_List();
+	if (Global_Variable_Query(2) >= 15 || !Query_Difficulty_Level()) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(530, 7, 5, 3);
+	}
+	DM_Add_To_List_Never_Repeat_Once_Selected(540, 3, 5, 7);
+	Dialogue_Menu_Appear(320, 240);
+	int answerValue = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	if (answerValue == 530) {
+		Actor_Says(0, 120, 12);
+		if (Query_Difficulty_Level()) {
+			Global_Variable_Decrement(2, 15);
+		}
+		Actor_Clue_Acquire(0, 75, 1, 16);
+		Actor_Modify_Friendliness_To_Other(16, 0, 5);
+	} else if (answerValue == 540) {
+		Actor_Says(0, 125, 13);
+		Actor_Says(16, 260, 3);
+		Actor_Says(0, 130, 15);
+		Actor_Says(16, 270, 3);
+		Actor_Says(16, 280, 3);
+		Actor_Says(0, 135, 11);
+		Actor_Modify_Friendliness_To_Other(16, 0, -5);
+	}
+}
+
+void ScriptAR02::sub_402CE4() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 93)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(550, 8, 5, 2);
+	}
+	if (Actor_Clue_Query(0, 44)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(560, 6, 5, 7);
+	}
+	Dialogue_Menu_Add_DONE_To_List(570);
+	Dialogue_Menu_Appear(320, 240);
+	int answerValue = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answerValue) {
+	case 550:
+		Actor_Says(0, 145, 11);
+		Actor_Says(20, 30, 11);
+		Actor_Says(0, 160, 11);
+		Actor_Says(20, 40, 11);
+		Actor_Says(0, 165, 11);
+		Actor_Says(20, 50, 11);
+		Actor_Says(0, 170, 11);
+		Actor_Says(20, 60, 11);
+		Actor_Says(0, 175, 11);
+		Game_Flag_Set(370);
+		break;
+	case 560:
+		Actor_Says(0, 150, 11);
+		Actor_Says(20, 140, 11);
+		Actor_Says(0, 185, 11);
+		Actor_Says(20, 150, 11);
+		Actor_Says(20, 160, 11);
+		Actor_Says(0, 190, 11);
+		Actor_Says(20, 170, 11);
+		Actor_Says(0, 195, 11);
+		Actor_Says(20, 180, 11);
+		Actor_Says(20, 190, 11);
+		Actor_Says(20, 200, 11);
+		Actor_Says(0, 200, 11);
+		Actor_Says(20, 210, 11);
+		Actor_Says(20, 220, 11);
+		Actor_Says(20, 230, 11);
+		Game_Flag_Set(370);
+		break;
+	case 570:
+		if (Actor_Clue_Query(0, 57)) {
+			Actor_Says(0, 1315, 11);
+		} else {
+			Actor_Says(0, 940, 13);
+			Actor_Says(20, 70, 12);
+			Actor_Says(20, 90, 12);
+			Actor_Says(0, 180, 15);
+			Actor_Says(20, 100, 14);
+			Actor_Says(20, 110, 12);
+			Actor_Says(20, 120, 13);
+			Actor_Modify_Friendliness_To_Other(20, 0, -1);
+			Actor_Clue_Acquire(0, 57, 0, 20);
+		}
+		break;
+	}
+}
+
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb01.cpp b/engines/bladerunner/script/bb01.cpp
new file mode 100644
index 0000000..6024a42
--- /dev/null
+++ b/engines/bladerunner/script/bb01.cpp
@@ -0,0 +1,231 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB01::InitializeScene() {
+	if (Game_Flag_Query(265)) {
+		Setup_Scene_Information(-253.0f, 9.0f, 715.0f, 266);
+	} else if (Game_Flag_Query(263)) {
+		Setup_Scene_Information(-128.0f, 9.0f, 342.0f, 266);
+	} else {
+		Setup_Scene_Information(43.0f, 0.0f, 1058.0f, 0);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 0, 72, 299, 3);
+	Scene_Exit_Add_2D_Exit(1, 151, 218, 322, 290, 3);
+	if (Game_Flag_Query(254)) {
+		Scene_Exit_Add_2D_Exit(2, 0, 311, 312, 479, 2);
+	}
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 25, -100, 0);
+	Ambient_Sounds_Add_Sound(82, 5, 60, 40, 60, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(83, 5, 60, 40, 65, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(84, 5, 60, 40, 60, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(67, 5, 80, 20, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(66, 5, 80, 20, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(378, 5, 120, 25, 33, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 5, 120, 25, 33, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 5, 120, 25, 33, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	if (Game_Flag_Query(254) && !Game_Flag_Query(265) && !Game_Flag_Query(263)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+	} else if (Game_Flag_Query(254) && Game_Flag_Query(265)) {
+		Scene_Loop_Set_Default(1);
+	} else if (Game_Flag_Query(254) && Game_Flag_Query(263)) {
+		Scene_Loop_Set_Default(1);
+	} else {
+		Scene_Loop_Set_Default(5);
+	}
+}
+
+void ScriptBB01::SceneLoaded() {
+	Obstacle_Object("COLUME", true);
+}
+
+bool ScriptBB01::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB01::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB01::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB01::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB01::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		Loop_Actor_Walk_To_XYZ(0, -140.0f, 9.0f, 818.0f, 0, 1, false, 0);
+		if (!Loop_Actor_Walk_To_XYZ(0, -233.0f, 9.0f, 846.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(264);
+			Game_Flag_Reset(258);
+			Game_Flag_Set(177);
+			Set_Enter(7, 26);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -125.39f, 9.0f, 372.45f, 0, 1, false, 0)) {
+			Game_Flag_Set(262);
+			Set_Enter(1, 3);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 43.0f, 0.0f, 1062.0f, 0, 1, false, 0)) {
+			Game_Flag_Reset(176);
+			Game_Flag_Reset(182);
+			Game_Flag_Reset(179);
+			Game_Flag_Reset(178);
+			Game_Flag_Reset(258);
+			int spinnerDest = Spinner_Interface_Choose_Dest(3, 0);
+			switch (spinnerDest) {
+			case 0:
+				Game_Flag_Set(178);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(251);
+				Set_Enter(61, 65);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 1:
+				Game_Flag_Set(179);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(250);
+				Set_Enter(49, 48);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 2:
+				Game_Flag_Set(182);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(249);
+				Set_Enter(69, 78);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 3:
+				Game_Flag_Set(176);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(248);
+				Set_Enter(4, 13);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 5:
+				Game_Flag_Set(261);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(307);
+				Set_Enter(17, 82);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 4:
+				Game_Flag_Set(180);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(252);
+				Set_Enter(0, 0);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 6:
+				Game_Flag_Set(177);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(253);
+				Set_Enter(7, 25);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 8:
+				Game_Flag_Set(181);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(255);
+				Set_Enter(54, 54);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 9:
+				Game_Flag_Set(257);
+				Game_Flag_Reset(254);
+				Game_Flag_Set(256);
+				Set_Enter(37, 34);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			default:
+				Game_Flag_Set(258);
+				Scene_Loop_Start_Special(2, 3, 1);
+				break;
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB01::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB01::SceneFrameAdvanced(int frame) {
+	if (frame == 193) {
+		Sound_Play(118, 40, 0, 0, 50);
+	}
+	if (frame == 241 || frame == 363) {
+		Sound_Play(116, 100, -50, -50, 50);
+	}
+	if (frame == 286 || frame == 407) {
+		Sound_Play(119, 100, -50, -50, 50);
+	}
+	if (frame == 433) {
+		Sound_Play(117, 40, -50, 80, 50);
+	}
+	if (frame == 120) {
+		Sound_Play(286, Random_Query(33, 33), 100, -100, 50);
+	}
+}
+
+void ScriptBB01::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB01::PlayerWalkedIn() {
+	Spinner_Set_Selectable_Destination_Flag(7, 1);
+	if (Game_Flag_Query(265)) {
+		Game_Flag_Reset(265);
+	} else if (Game_Flag_Query(263)) {
+		Game_Flag_Reset(263);
+	} else {
+		Loop_Actor_Walk_To_XYZ(0, 43.0f, 0.0f, 954.0f, 0, 0, false, 0);
+	}
+}
+
+void ScriptBB01::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptBB01::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb02.cpp b/engines/bladerunner/script/bb02.cpp
new file mode 100644
index 0000000..0fa6b0c
--- /dev/null
+++ b/engines/bladerunner/script/bb02.cpp
@@ -0,0 +1,159 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB02::InitializeScene() {
+	if (Game_Flag_Query(281)) {
+		Setup_Scene_Information(179.0f, -415.06f, 274.0f, 904);
+	} else if (Game_Flag_Query(333)) {
+		Setup_Scene_Information(-12.0f, -415.06f, -27.0f, 264);
+		Scene_Loop_Start_Special(0, 0, 0);
+	} else {
+		Setup_Scene_Information(98.0f, -415.06f, -593.0f, 530);
+		Game_Flag_Reset(262);
+	}
+	Scene_Exit_Add_2D_Exit(0, 313, 137, 353, 173, 0);
+	Scene_Exit_Add_2D_Exit(1, 207, 291, 275, 443, 3);
+	Scene_Exit_Add_2D_Exit(2, 303, 422, 639, 479, 2);
+	Ambient_Sounds_Add_Looping_Sound(54, 20, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(103, 40, 0, 1);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(82, 5, 60, 20, 40, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(83, 5, 60, 20, 45, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(84, 5, 60, 20, 40, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(90, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(91, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(72, 5, 80, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(73, 5, 80, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(74, 5, 80, 14, 16, -100, 100, -101, -101, 0, 0);
+	if (!Game_Flag_Query(494)) {
+		Game_Flag_Set(493);
+		Game_Flag_Set(494);
+	}
+	if (Game_Flag_Query(493)) {
+		Scene_Loop_Set_Default(1);
+	} else {
+		Scene_Loop_Set_Default(4);
+	}
+}
+
+void ScriptBB02::SceneLoaded() {
+	Obstacle_Object("ELEVATOR01", true);
+	Obstacle_Object("U2 DOOR", true);
+}
+
+bool ScriptBB02::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB02::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB02::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB02::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB02::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 98.0f, -415.06f, -593.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(263);
+			Set_Enter(20, 2);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -12.0f, -415.06f, -27.0f, 0, 1, false, 0)) {
+			Player_Loses_Control();
+			if (!Game_Flag_Query(493)) {
+				Scene_Loop_Start_Special(2, 0, 1);
+			}
+			Game_Flag_Set(332);
+			Game_Flag_Reset(493);
+			Set_Enter(1, 5);
+			Scene_Loop_Start_Special(1, 3, 0);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 86.0f, -415.06f, 174.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 179.0f, -415.06f, 274.0f, 0, 0, false, 0);
+			Game_Flag_Set(282);
+			Game_Flag_Reset(493);
+			Set_Enter(21, 4);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB02::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB02::SceneFrameAdvanced(int frame) {
+	if (frame == 1) {
+		Ambient_Sounds_Play_Sound(434, 40, -50, -50, 0);
+	}
+	if (frame == 124) {
+		Ambient_Sounds_Play_Sound(434, 40, -50, -50, 0);
+	}
+}
+
+void ScriptBB02::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB02::PlayerWalkedIn() {
+	if (Game_Flag_Query(281)) {
+		Loop_Actor_Walk_To_XYZ(0, 86.0f, -415.06f, 174.0f, 0, 0, false, 0);
+		Game_Flag_Reset(281);
+	} else if (Game_Flag_Query(333)) {
+		Loop_Actor_Walk_To_XYZ(0, 35.0f, -415.06f, -27.0f, 0, 0, false, 0);
+		Player_Gains_Control();
+		Game_Flag_Reset(333);
+	}
+}
+
+void ScriptBB02::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptBB02::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb03.cpp b/engines/bladerunner/script/bb03.cpp
new file mode 100644
index 0000000..24b4332
--- /dev/null
+++ b/engines/bladerunner/script/bb03.cpp
@@ -0,0 +1,163 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB03::InitializeScene() {
+	Setup_Scene_Information(20.0f, 60.16f, 0.0f, 0);
+	Game_Flag_Reset(282);
+	if (Game_Flag_Query(284)) {
+		Setup_Scene_Information(176.0f, 60.16f, 0.0f, 900);
+	}
+	if (Game_Flag_Query(286)) {
+		Setup_Scene_Information(204.0f, 60.16f, -164.0f, 740);
+	}
+	Scene_Exit_Add_2D_Exit(0, 589, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(1, 167, 372, 439, 479, 2);
+	Scene_Exit_Add_2D_Exit(2, 451, 115, 547, 320, 1);
+	Ambient_Sounds_Add_Looping_Sound(54, 20, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(103, 40, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 34, 100, 1);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(90, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(91, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(72, 5, 80, 20, 20, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(73, 5, 80, 20, 20, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(74, 5, 80, 20, 20, -100, 100, -101, -101, 0, 0);
+}
+
+void ScriptBB03::SceneLoaded() {
+	Obstacle_Object("BACKWALL", true);
+	Unobstacle_Object("BOX08", true);
+}
+
+bool ScriptBB03::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB03::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB03::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB03::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB03::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 176.0f, 60.16f, -64.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 176.0f, 60.16f, 0.0f, 0, 0, false, 0);
+			Game_Flag_Set(283);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Set_Enter(1, 5);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 20.0f, 60.16f, 0.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(281);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Set_Enter(1, 3);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 204.0f, 60.16f, -164.0f, 0, 1, false, 0)) {
+			if (Global_Variable_Query(1) < 4) {
+				if (Actor_Query_Goal_Number(56) == 200) {
+					Actor_Says(56, 70, 3);
+					Actor_Says(0, 7010, 13);
+					Actor_Says(56, 80, 3);
+					Actor_Says(0, 7015, 12);
+					Actor_Says(56, 90, 3);
+					Actor_Says(0, 7020, 14);
+					Actor_Says(56, 100, 3);
+					Actor_Says(0, 7025, 15);
+					Actor_Says(56, 110, 3);
+					Actor_Set_Targetable(54, false);
+					Actor_Set_Targetable(58, false);
+				}
+				Game_Flag_Set(285);
+				Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+				Ambient_Sounds_Remove_All_Looping_Sounds(1);
+				Set_Enter(22, 6);
+			} else {
+				Actor_Says(0, 8522, 3);
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB03::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB03::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptBB03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB03::PlayerWalkedIn() {
+	if (Game_Flag_Query(286)) {
+		Loop_Actor_Walk_To_XYZ(0, 164.0f, 60.16f, -164.0f, 0, 0, false, 0);
+		Game_Flag_Reset(286);
+	}
+	if (Game_Flag_Query(284)) {
+		Loop_Actor_Walk_To_XYZ(0, 176.0f, 60.16f, -64.0f, 0, 0, false, 0);
+		Game_Flag_Reset(284);
+	}
+}
+
+void ScriptBB03::PlayerWalkedOut() {
+
+}
+
+void ScriptBB03::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb04.cpp b/engines/bladerunner/script/bb04.cpp
new file mode 100644
index 0000000..ca96c11
--- /dev/null
+++ b/engines/bladerunner/script/bb04.cpp
@@ -0,0 +1,132 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB04::InitializeScene() {
+	if (Game_Flag_Query(283)) {
+		Setup_Scene_Information(-107.0f, -26.6f, 397.0f, 29);
+		Game_Flag_Reset(283);
+	} else {
+		Setup_Scene_Information(-15.0f, -25.17f, 45.0f, 691);
+	}
+	Scene_Exit_Add_2D_Exit(0, 218, 102, 360, 254, 1);
+	Scene_Exit_Add_2D_Exit(1, 0, 334, 639, 479, 2);
+	Ambient_Sounds_Add_Looping_Sound(54, 20, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(103, 40, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 44, -100, 1);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(90, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(91, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(72, 5, 80, 20, 20, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(73, 5, 80, 20, 20, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(74, 5, 80, 20, 20, -100, 100, -101, -101, 0, 0);
+}
+
+void ScriptBB04::SceneLoaded() {
+	Obstacle_Object("DH TRASH", true);
+}
+
+bool ScriptBB04::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB04::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB04::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB04::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB04::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -92.0f, -26.6f, 45.0f, 0, 1, false, 0)) {
+			Player_Loses_Control();
+			Loop_Actor_Walk_To_XYZ(0, -15.0f, -25.17f, 45.0f, 0, 0, false, 0);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(333);
+			Game_Flag_Set(493);
+			Set_Enter(1, 3);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -107.0f, -26.6f, 397.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(284);
+			Set_Enter(21, 4);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB04::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB04::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptBB04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB04::PlayerWalkedIn() {
+	if (Game_Flag_Query(332)) {
+		Loop_Actor_Walk_To_XYZ(0, -92.0f, -26.6f, 45.0f, 0, 0, false, 0);
+		Player_Gains_Control();
+		Game_Flag_Reset(332);
+	}
+}
+
+void ScriptBB04::PlayerWalkedOut() {
+
+}
+
+void ScriptBB04::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb05.cpp b/engines/bladerunner/script/bb05.cpp
new file mode 100644
index 0000000..1f2b974
--- /dev/null
+++ b/engines/bladerunner/script/bb05.cpp
@@ -0,0 +1,215 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB05::InitializeScene() {
+	if (Game_Flag_Query(298)) {
+		Setup_Scene_Information(95.0f, -60.31f, 331.0f, 0);
+	} else if (Game_Flag_Query(302)) {
+		Setup_Scene_Information(87.0f, -60.34f, -96.0f, 0);
+	} else if (Game_Flag_Query(300)) {
+		Setup_Scene_Information(271.0f, -60.31f, 203.0f, 0);
+	} else {
+		Setup_Scene_Information(-212.0f, -60.31f, 131.0f, 0);
+	}
+	Scene_Exit_Add_2D_Exit(0, 92, 125, 187, 317, 3);
+	Scene_Exit_Add_2D_Exit(1, 0, 0, 30, 479, 3);
+	Scene_Exit_Add_2D_Exit(2, 589, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(3, 481, 113, 573, 307, 0);
+	Ambient_Sounds_Add_Looping_Sound(54, 12, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(103, 28, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 14, 0, 1);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(90, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(91, 5, 50, 17, 17, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(72, 5, 80, 14, 14, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(73, 5, 80, 14, 14, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(74, 5, 80, 14, 14, -100, 100, -101, -101, 0, 0);
+	if (!Game_Flag_Query(495)) {
+		Overlay_Play("BB05OVER", 0, 0, 0, 0);
+		Game_Flag_Set(495);
+	}
+}
+
+void ScriptBB05::SceneLoaded() {
+	Obstacle_Object("PINHEAD", true);
+	Obstacle_Object("X2WALLS&MOLDNG05", true);
+	Obstacle_Object("QUADPATCH04", true);
+	Unobstacle_Object("BOX16", true);
+	Clickable_Object("PINHEAD");
+	Clickable_Object("BOX06");
+	Unclickable_Object("BOX06");
+	Unclickable_Object("BOX14");
+	if (Actor_Query_Goal_Number(56) == 200) {
+		Actor_Set_Goal_Number(58, 299);
+		Actor_Put_In_Set(58, 97);
+		Actor_Set_At_Waypoint(58, 39, 0);
+	}
+}
+
+bool ScriptBB05::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB05::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB05::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB05::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB05::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -212.0f, -60.31f, 131.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(286);
+			Set_Enter(21, 4);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 95.0f, -60.31f, 331.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(297);
+			Set_Enter(2, 7);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 271.0f, -60.31f, 203.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(299);
+			Set_Enter(3, 8);
+		}
+		return true;
+	}
+	if (exitId == 3) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 151.0f, -60.34f, -108.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(301);
+			Set_Enter(102, 120);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB05::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB05::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptBB05::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB05::PlayerWalkedIn() {
+	if (Game_Flag_Query(298)) {
+		Loop_Actor_Walk_To_XYZ(0, 95.0f, -60.31f, 303.0f, 0, 0, false, 0);
+		Game_Flag_Reset(298);
+	} else if (Game_Flag_Query(300)) {
+		Loop_Actor_Walk_To_XYZ(0, 231.0f, -60.31f, 203.0f, 0, 0, false, 0);
+		Game_Flag_Reset(300);
+	} else if (Game_Flag_Query(302)) {
+		Loop_Actor_Walk_To_XYZ(0, 111.0f, -60.31f, -24.0f, 0, 0, false, 0);
+		Game_Flag_Reset(302);
+	} else {
+		Loop_Actor_Walk_To_XYZ(0, -76.0f, -60.31f, 131.0f, 0, 0, false, 0);
+		Game_Flag_Reset(285);
+	}
+	if (Actor_Query_Goal_Number(56) == 200) {
+		Actor_Face_Actor(56, 0, true);
+		Actor_Face_Actor(0, 56, true);
+		Actor_Says(56, 120, 13);
+		Actor_Says(0, 7030, 15);
+		Actor_Says(56, 130, 17);
+		Actor_Says(56, 140, 16);
+		Actor_Says(56, 150, 14);
+		Actor_Says(56, 160, 15);
+		Actor_Says(0, 7035, 14);
+		Actor_Says(56, 170, 12);
+		Actor_Says(0, 7040, 14);
+		Actor_Says(56, 180, 16);
+		Actor_Says(0, 7045, 14);
+		if (Game_Flag_Query(399)) {
+			Actor_Says(56, 190, 15);
+			Actor_Says(0, 7050, 17);
+			Actor_Says(56, 200, 16);
+			Actor_Says_With_Pause(56, 210, 1.5f, 14);
+			Actor_Says(0, 7055, 15);
+		} else {
+			Actor_Put_In_Set(58, 22);
+			Actor_Set_At_Waypoint(58, 134, 0);
+			Loop_Actor_Walk_To_Waypoint(58, 135, 0, 0, false);
+			Actor_Says(58, 0, 3);
+			Actor_Face_Actor(0, 58, true);
+			Actor_Face_Actor(56, 58, true);
+			Actor_Says(56, 220, 13);
+			Loop_Actor_Walk_To_Waypoint(58, 134, 0, 0, false);
+			Actor_Face_Actor(56, 0, true);
+			Actor_Face_Actor(0, 56, true);
+			Actor_Says(56, 230, 15);
+			Actor_Says(0, 7060, 17);
+			Actor_Says(56, 240, 12);
+		}
+		Actor_Says(0, 7065, 16);
+		Actor_Says(56, 250, 16);
+		Actor_Says(0, 7070, 18);
+		Actor_Set_Goal_Number(56, 205);
+		Actor_Set_Goal_Number(58, 201);
+		Actor_Set_Goal_Number(54, 101);
+		Actor_Set_Goal_Number(58, 200);
+	}
+}
+
+void ScriptBB05::PlayerWalkedOut() {
+
+}
+
+void ScriptBB05::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb06.cpp b/engines/bladerunner/script/bb06.cpp
new file mode 100644
index 0000000..d389fcc
--- /dev/null
+++ b/engines/bladerunner/script/bb06.cpp
@@ -0,0 +1,178 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB06::InitializeScene() {
+	if (Game_Flag_Query(394)) {
+		Setup_Scene_Information(76.0f, 0.0f, 79.0f, 622);
+	} else if (Game_Flag_Query(395)) {
+		Setup_Scene_Information(55.0f, 0.0f, -96.0f, 761);
+	} else if (Game_Flag_Query(362)) {
+		Setup_Scene_Information(-115.0f, 0.0f, -103.0f, 375);
+		Game_Flag_Reset(362);
+	} else {
+		Setup_Scene_Information(-37.0f, 0.0f, 178.0f, 0);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 43, 14, 478, 3);
+	Scene_Exit_Add_2D_Exit(1, 425, 0, 639, 361, 0);
+	Scene_Exit_Add_2D_Exit(3, 195, 164, 239, 280, 3);
+	Ambient_Sounds_Add_Looping_Sound(103, 28, 0, 1);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(394) || Game_Flag_Query(395)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+		Game_Flag_Reset(394);
+		Game_Flag_Reset(395);
+	} else {
+		Scene_Loop_Set_Default(1);
+	}
+	if (Game_Flag_Query(410)) {
+		Overlay_Play("BB06OVER", 1, 1, 0, 0);
+	}
+}
+
+void ScriptBB06::SceneLoaded() {
+	Obstacle_Object("V2CHESSTBL01", true);
+	Clickable_Object("BOX31");
+	Item_Add_To_World(77, 931, 2, -127.0f, 68.42f, 57.0f, 0, 8, 8, true, true, false, true);
+}
+
+bool ScriptBB06::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB06::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("BOX31", objectName)) {
+		if (!Loop_Actor_Walk_To_Scene_Object(0, "BOX31", 24, 1, false)) {
+			Actor_Face_Object(0, "BOX31", true);
+			if (Game_Flag_Query(410)) {
+				Actor_Voice_Over(60, 99);
+				Actor_Voice_Over(70, 99);
+			} else {
+				Actor_Voice_Over(50, 99);
+			}
+		}
+	}
+	return false;
+}
+
+bool ScriptBB06::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB06::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 77) {
+		if (Player_Query_Combat_Mode()) {
+			Overlay_Play("BB06OVER", 1, 1, 1, 0);
+			Game_Flag_Set(410);
+			Item_Remove_From_World(77);
+			return true;
+		}
+	}
+	return false;
+}
+
+bool ScriptBB06::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -37.0f, 0.0f, 178.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(298);
+			Set_Enter(22, 6);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 101.0f, 0.0f, -25.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(393);
+			Set_Enter(1, 104);
+		}
+		return true;
+	}
+	if (exitId == 3) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -115.0f, 0.0f, -103.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(363);
+			Set_Enter(2, 8);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB06::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB06::SceneFrameAdvanced(int frame) {
+	if (frame == 34) {
+		Ambient_Sounds_Play_Sound(447, 40, -50, -50, 10);
+	}
+	if (frame == 16) {
+		Ambient_Sounds_Play_Sound(448, 20, -50, -50, 10);
+	}
+	if (frame == 20) {
+		Ambient_Sounds_Play_Sound(448, 20, -50, -50, 10);
+	}
+	if (frame == 25) {
+		Ambient_Sounds_Play_Sound(448, 20, -50, -50, 10);
+	}
+	if (frame == 29) {
+		Ambient_Sounds_Play_Sound(448, 20, -50, -50, 10);
+	}
+}
+
+void ScriptBB06::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB06::PlayerWalkedIn() {
+	if (Game_Flag_Query(297)) {
+		Loop_Actor_Walk_To_XYZ(0, -36.0f, 0.0f, 145.0f, 0, 0, false, 0);
+		Game_Flag_Reset(297);
+	}
+}
+
+void ScriptBB06::PlayerWalkedOut() {
+
+}
+
+void ScriptBB06::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb07.cpp b/engines/bladerunner/script/bb07.cpp
new file mode 100644
index 0000000..3284df8
--- /dev/null
+++ b/engines/bladerunner/script/bb07.cpp
@@ -0,0 +1,186 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB07::InitializeScene() {
+	if (Game_Flag_Query(365)) {
+		Setup_Scene_Information(-655.0f, 252.59f, -1136.0f, 323);
+	} else if (Game_Flag_Query(363)) {
+		Setup_Scene_Information(-551.0f, 252.59f, -1004.0f, 29);
+		Game_Flag_Reset(363);
+	} else {
+		Setup_Scene_Information(-652.0f, 252.59f, -1018.0f, 268);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 16, 51, 426, 3);
+	Scene_Exit_Add_2D_Exit(1, 124, 101, 172, 305, 3);
+	Scene_Exit_Add_2D_Exit(2, 282, 408, 476, 479, 2);
+	Scene_2D_Region_Add(0, 308, 283, 354, 308);
+	Ambient_Sounds_Add_Looping_Sound(332, 44, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(331, 24, 0, 1);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Overlay_Play("BB07OVER", 0, 1, 0, 0);
+}
+
+void ScriptBB07::SceneLoaded() {
+	Obstacle_Object("COUCH", true);
+	Unobstacle_Object("X2MAINWALLLEFT01", true);
+	Clickable_Object("PRINTER");
+}
+
+bool ScriptBB07::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB07::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("PRINTER", objectName)) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -472.63f, 252.59f, -1086.81f, 0, 0, false, 0)) {
+			Actor_Face_Object(0, "PRINTER", true);
+			if (Game_Flag_Query(396) && !Game_Flag_Query(398)) {
+				Actor_Voice_Over(130, 99);
+				Item_Pickup_Spin_Effect(941, 439, 242);
+				Actor_Voice_Over(140, 99);
+				Game_Flag_Set(398);
+				Actor_Clue_Acquire(0, 148, 1, -1);
+			} else if (Game_Flag_Query(396) && Game_Flag_Query(398)) {
+				Actor_Face_Object(0, "PRINTER", true);
+				Actor_Says(0, 8570, 13);
+			} else {
+				Actor_Face_Object(0, "PRINTER", true);
+				Actor_Says(0, 8575, 13);
+			}
+		}
+	}
+	return false;
+}
+
+bool ScriptBB07::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB07::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 83) {
+		if (!Loop_Actor_Walk_To_Item(0, 83, 36, 1, false)) {
+			Actor_Face_Item(0, 83, true);
+			if (Game_Flag_Query(396) == 1) {
+				Actor_Voice_Over(150, 99);
+				Actor_Voice_Over(160, 99);
+				Actor_Voice_Over(170, 99);
+			}
+		}
+	}
+	return false;
+}
+
+bool ScriptBB07::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -615.0f, 252.59f, -1018.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Overlay_Remove("BB07OVER");
+			Game_Flag_Set(300);
+			Set_Enter(22, 6);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -619.0f, 252.59f, -1136.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Overlay_Remove("BB07OVER");
+			Game_Flag_Set(364);
+			Set_Enter(102, 120);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -551.0f, 252.59f, -1004.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Overlay_Remove("BB07OVER");
+			Game_Flag_Set(362);
+			Set_Enter(2, 7);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB07::ClickedOn2DRegion(int region) {
+	if (region == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -568.63f, 252.59f, -1114.81f, 0, 1, false, 0)) {
+			Actor_Face_Heading(0, 229, false);
+			if (Game_Flag_Query(396)) {
+				Actor_Says(0, 8585, 15);
+			} else {
+				Ambient_Sounds_Play_Sound(592, 40, 20, 20, 99);
+				Overlay_Play("BB07OVER", 1, 0, 1, 0);
+				Overlay_Play("BB07OVER", 2, 1, 0, 0);
+				Game_Flag_Set(396);
+				if (!Game_Flag_Query(398)) {
+					Actor_Says(39, 0, 3);
+				}
+			}
+		}
+	}
+	return false;
+}
+
+void ScriptBB07::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptBB07::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB07::PlayerWalkedIn() {
+	if (Game_Flag_Query(299)) {
+		Loop_Actor_Walk_To_XYZ(0, -594.0f, 252.59f, -1018.0f, 6, 0, false, 0);
+		Game_Flag_Reset(299);
+	}
+	if (Game_Flag_Query(365)) {
+		Loop_Actor_Walk_To_XYZ(0, -602.0f, 252.59f, -1124.0f, 6, 0, false, 0);
+		Game_Flag_Reset(365);
+	}
+}
+
+void ScriptBB07::PlayerWalkedOut() {
+
+}
+
+void ScriptBB07::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb08.cpp b/engines/bladerunner/script/bb08.cpp
new file mode 100644
index 0000000..cd05fe8
--- /dev/null
+++ b/engines/bladerunner/script/bb08.cpp
@@ -0,0 +1,138 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB08::InitializeScene() {
+	if (Game_Flag_Query(219)) {
+		Setup_Scene_Information(204.0f, 0.0f, 92.0f, 875);
+	} else {
+		Setup_Scene_Information(247.0f, 0.0f, 27.0f, 790);
+	}
+	Scene_Exit_Add_2D_Exit(0, 307, 0, 361, 238, 0);
+	Scene_Exit_Add_2D_Exit(1, 117, 38, 214, 245, 0);
+	Ambient_Sounds_Add_Looping_Sound(105, 44, 0, 1);
+	Ambient_Sounds_Add_Sound(291, 1, 20, 20, 25, -100, 100, -100, 100, 0, 0);
+	Ambient_Sounds_Add_Sound(292, 1, 20, 20, 25, -100, 100, -100, 100, 0, 0);
+	Ambient_Sounds_Add_Sound(293, 1, 20, 20, 25, -100, 100, -100, 100, 0, 0);
+	Ambient_Sounds_Add_Sound(294, 1, 20, 20, 25, -100, 100, -100, 100, 0, 0);
+	Ambient_Sounds_Add_Sound(295, 1, 20, 20, 25, -100, 100, -100, 100, 0, 0);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	if (!Game_Flag_Query(496)) {
+		Overlay_Play("BB08OVER", 0, 0, 0, 0);
+		Game_Flag_Set(496);
+	}
+}
+
+void ScriptBB08::SceneLoaded() {
+	Obstacle_Object("BATHTUB", true);
+	Unobstacle_Object("DOORWAY", true);
+	Unclickable_Object("BATHTUB");
+}
+
+bool ScriptBB08::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB08::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB08::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB08::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB08::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 204.0f, 0.1f, 94.0f, 0, 1, false, 0)) {
+			Actor_Face_Heading(0, 256, false);
+			Footstep_Sound_Override_On(2);
+			Loop_Actor_Travel_Ladder(0, 8, 1, 0);
+			Footstep_Sound_Override_Off();
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(218);
+			Set_Enter(24, 10);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 247.0f, 0.1f, 27.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(506);
+			Set_Enter(102, 120);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB08::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB08::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptBB08::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB08::PlayerWalkedIn() {
+	if (Game_Flag_Query(219)) {
+		Actor_Set_At_XYZ(0, 204.0f, 96.1f, 94.0f, 256);
+		Footstep_Sound_Override_On(2);
+		Loop_Actor_Travel_Ladder(0, 8, 0, 0);
+		Footstep_Sound_Override_Off();
+		Actor_Face_Heading(0, 768, false);
+		Game_Flag_Reset(219);
+	} else {
+		Loop_Actor_Walk_To_XYZ(0, 188.0f, 0.1f, 28.0f, 0, 0, false, 0);
+	}
+}
+
+void ScriptBB08::PlayerWalkedOut() {
+
+}
+
+void ScriptBB08::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb09.cpp b/engines/bladerunner/script/bb09.cpp
new file mode 100644
index 0000000..0d67261
--- /dev/null
+++ b/engines/bladerunner/script/bb09.cpp
@@ -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.
+ *
+ */
+
+#include "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB09::InitializeScene() {
+	Setup_Scene_Information(111.2f, -8.96f, 134.65f, 0);
+	if (Game_Flag_Query(221)) {
+		Game_Flag_Reset(221);
+		Setup_Scene_Information(115.45f, -8.96f, 134.0f, 628);
+	} else if (Game_Flag_Query(218)) {
+		Game_Flag_Reset(218);
+		Setup_Scene_Information(107.45f, -9.14f, 166.0f, 244);
+	}
+	Scene_Exit_Add_2D_Exit(0, 224, 213, 286, 353, 1);
+	Scene_Exit_Add_2D_Exit(1, 75, 450, 480, 479, 2);
+	Ambient_Sounds_Add_Looping_Sound(54, 20, 100, 1);
+	Ambient_Sounds_Add_Looping_Sound(103, 40, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 50, 55, 1);
+	Ambient_Sounds_Add_Sound(297, 5, 20, 20, 25, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(298, 5, 20, 20, 25, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(299, 5, 20, 20, 25, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Actor_Set_Targetable(8, true);
+}
+
+void ScriptBB09::SceneLoaded() {
+	Obstacle_Object("WICKER CHAIR ", true);
+	Unobstacle_Object("ROOM03 RIGHT WALL", true);
+	Unclickable_Object("WICKER CHAIR ");
+}
+
+bool ScriptBB09::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB09::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB09::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB09::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB09::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 454.56f, -9.0f, 190.31f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 450.56f, -9.0f, 250.31f, 0, 0, false, 0);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(216);
+			Game_Flag_Set(220);
+			Set_Enter(25, 11);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 71.0f, -9.0f, 136.0f, 72, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(219);
+			Set_Enter(23, 9);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB09::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB09::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptBB09::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB09::PlayerWalkedIn() {
+}
+
+void ScriptBB09::PlayerWalkedOut() {
+}
+
+void ScriptBB09::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb10.cpp b/engines/bladerunner/script/bb10.cpp
new file mode 100644
index 0000000..3a28ebb
--- /dev/null
+++ b/engines/bladerunner/script/bb10.cpp
@@ -0,0 +1,205 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB10::InitializeScene() {
+	if (Game_Flag_Query(223)) {
+		Setup_Scene_Information(255.29f, 90.24f, -103.0f, 830);
+	} else if (Game_Flag_Query(220)) {
+		Game_Flag_Reset(220);
+		Setup_Scene_Information(151.67f, 66.84f, -313.06f, 0);
+	} else {
+		Setup_Scene_Information(199.67f, 67.4f, -169.06f, 628);
+	}
+	if (Global_Variable_Query(36) > 2) {
+		Scene_Exit_Add_2D_Exit(0, 281, 0, 531, 115, 0);
+	}
+	Scene_Exit_Add_2D_Exit(1, 58, 91, 193, 401, 3);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Add_Looping_Sound(382, 76, 0, 1);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	if (!Game_Flag_Query(466)) {
+		Scene_2D_Region_Add(0, 458, 99, 522, 133);
+		Overlay_Play("BB10OVR1", 0, 1, 0, 0);
+	}
+	if (!Game_Flag_Query(467)) {
+		Scene_2D_Region_Add(1, 459, 164, 522, 193);
+		Overlay_Play("BB10OVR2", 0, 1, 0, 0);
+	}
+	if (!Game_Flag_Query(468)) {
+		Scene_2D_Region_Add(2, 458, 194, 522, 223);
+		Overlay_Play("BB10OVR3", 0, 1, 0, 0);
+	}
+	if (!Game_Flag_Query(469)) {
+		Scene_2D_Region_Add(3, 458, 255, 522, 278);
+		Overlay_Play("BB10OVR4", 0, 1, 0, 0);
+	}
+	if (!Game_Flag_Query(470)) {
+		Scene_2D_Region_Add(4, 458, 316, 522, 335);
+		Overlay_Play("BB10OVR5", 0, 1, 0, 0);
+	}
+}
+
+void ScriptBB10::SceneLoaded() {
+	Obstacle_Object("BARB NIGHT", true);
+	Unclickable_Object("BARB NIGHT");
+	Unobstacle_Object("Box-Floor Hole01", true);
+	Unobstacle_Object("Box-Floor Hole02", true);
+	Unobstacle_Object("Box-Floor Hole03", true);
+}
+
+bool ScriptBB10::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB10::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB10::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB10::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB10::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 225.58f, 67.2f, -102.1f, 0, 1, false, 0)) {
+			Player_Set_Combat_Mode(false);
+			Actor_Face_Heading(0, 274, false);
+			Footstep_Sound_Override_On(2);
+			Loop_Actor_Travel_Stairs(0, 2, 1, 0);
+			Footstep_Sound_Override_Off();
+			Footstep_Sound_Override_On(2);
+			Loop_Actor_Travel_Ladder(0, 3, 1, 0);
+			Footstep_Sound_Override_Off();
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(222);
+			Set_Enter(26, 12);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 206.01f, 66.84f, -261.62f, 0, 1, false, 0) && !Loop_Actor_Walk_To_XYZ(0, 151.67f, 66.84f, -313.06f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Reset(216);
+			Game_Flag_Set(221);
+			Set_Enter(24, 10);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB10::ClickedOn2DRegion(int region) {
+	if (!Loop_Actor_Walk_To_XYZ(0, 225.58f, 67.2f, -102.1f, 0, 1, false, 0)) {
+		Actor_Face_Heading(0, 274, false);
+		Sound_Play(Random_Query(289, 290), 40, 70, 70, 50);
+		switch (region) {
+		case 4:
+			Overlay_Remove("BB10OVR5");
+			Game_Flag_Set(470);
+			Scene_2D_Region_Remove(4);
+			break;
+		case 3:
+			Overlay_Remove("BB10OVR4");
+			Game_Flag_Set(469);
+			Scene_2D_Region_Remove(3);
+			break;
+		case 2:
+			Overlay_Remove("BB10OVR3");
+			Game_Flag_Set(468);
+			Scene_2D_Region_Remove(2);
+			break;
+		case 1:
+			Overlay_Remove("BB10OVR2");
+			Game_Flag_Set(467);
+			Scene_2D_Region_Remove(1);
+			break;
+		case 0:
+			Overlay_Remove("BB10OVR1");
+			Game_Flag_Set(466);
+			Scene_2D_Region_Remove(0);
+			break;
+		default:
+			break;
+		}
+		Global_Variable_Increment(36, 1);
+		if (Global_Variable_Query(36) > 4) {
+			Scene_Exit_Add_2D_Exit(0, 281, 0, 531, 115, 0);
+		}
+		return false;
+	}
+	return true;
+}
+
+void ScriptBB10::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptBB10::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB10::PlayerWalkedIn() {
+	if (Game_Flag_Query(216)) {
+		Player_Loses_Control();
+		Actor_Set_At_XYZ(0, 214.01f, 66.84f, -349.62f, 462);
+		Loop_Actor_Walk_To_XYZ(0, 206.01f, 66.84f, -261.62f, 0, 0, false, 0);
+		Player_Gains_Control();
+		Game_Flag_Reset(216);
+	} else if (Game_Flag_Query(223)) {
+		Actor_Set_At_XYZ(0, 249.58f, 127.2f, -102.1f, 256);
+		Footstep_Sound_Override_On(2);
+		Loop_Actor_Travel_Ladder(0, 3, 0, 0);
+		Footstep_Sound_Override_Off();
+		Actor_Face_Heading(0, 768, false);
+		Footstep_Sound_Override_On(2);
+		Loop_Actor_Travel_Stairs(0, 3, 0, 0);
+		Footstep_Sound_Override_Off();
+		Game_Flag_Reset(223);
+	}
+}
+
+void ScriptBB10::PlayerWalkedOut() {
+}
+
+void ScriptBB10::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb11.cpp b/engines/bladerunner/script/bb11.cpp
new file mode 100644
index 0000000..686172d
--- /dev/null
+++ b/engines/bladerunner/script/bb11.cpp
@@ -0,0 +1,132 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB11::InitializeScene() {
+	Setup_Scene_Information(43.39f, -10.27f, -20.52f, 200);
+	if (!Game_Flag_Query(509)) {
+		Scene_Exit_Add_2D_Exit(0, 280, 154, 388, 247, 2);
+	}
+	Ambient_Sounds_Add_Looping_Sound(101, 90, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(99, 45, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(100, 76, 0, 1);
+	Ambient_Sounds_Add_Sound(68, 5, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 5, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 5, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Game_Flag_Query(509)) {
+		Preload(19);
+		Preload(220);
+		Preload(227);
+		Preload(328);
+		Preload(343);
+		Preload(344);
+		Preload(17);
+		Preload(14);
+		Preload(324);
+		Preload(323);
+		Preload(18);
+		Preload(345);
+	}
+}
+
+void ScriptBB11::SceneLoaded() {
+	Obstacle_Object("X2AIRCON01", true);
+	Unclickable_Object("X2AIRCON01");
+	if (Game_Flag_Query(509)) {
+		Unobstacle_Object("X2PIPES01", true);
+		Unobstacle_Object("X2PIPES02", true);
+		Unobstacle_Object("X2PIPES03", true);
+		Unobstacle_Object("X2_VENTS05", true);
+		Unobstacle_Object("X2_VENTSCYL05", true);
+	}
+}
+
+bool ScriptBB11::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB11::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB11::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB11::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB11::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 43.39f, -10.27f, -68.52f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(223);
+			Set_Enter(25, 11);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB11::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB11::SceneFrameAdvanced(int frame) {
+	if (Actor_Query_Goal_Number(8) == 105 && !Game_Flag_Query(375)) {
+		Actor_Change_Animation_Mode(0, 48);
+		Game_Flag_Set(375);
+	} else {
+		if (frame == 1) {
+			Sound_Play(74, 10, -100, 100, 50);
+		}
+	}
+}
+
+void ScriptBB11::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB11::PlayerWalkedIn() {
+	if (Actor_Query_Goal_Number(8) == 102 && Global_Variable_Query(1) == 2) {
+		Actor_Set_Invisible(0, true);
+		Actor_Set_Goal_Number(8, 103);
+		Music_Play(11, 61, 0, 1, -1, 0, 0);
+		Player_Loses_Control();
+	}
+}
+
+void ScriptBB11::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptBB11::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb12.cpp b/engines/bladerunner/script/bb12.cpp
new file mode 100644
index 0000000..336b059
--- /dev/null
+++ b/engines/bladerunner/script/bb12.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.
+ *
+ */
+
+#include "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB12::InitializeScene() {
+	if (Game_Flag_Query(364)) {
+		Setup_Scene_Information(138.0f, 0.0f, 104.0f, 760);
+	} else if (Game_Flag_Query(506)) {
+		Setup_Scene_Information(-129.0f, 0.0f, 64.0f, 307);
+	} else {
+		Setup_Scene_Information(54.0f, 0.0f, 200.0f, 0);
+		Game_Flag_Reset(301);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 0, 30, 479, 3);
+	Scene_Exit_Add_2D_Exit(1, 589, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(2, 377, 374, 533, 479, 2);
+	Ambient_Sounds_Add_Looping_Sound(103, 28, 0, 1);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 27, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 25, 25, -100, 100, -101, -101, 0, 0);
+	if (!Game_Flag_Query(497)) {
+		Overlay_Play("BB12OVER", 0, 0, 0, 0);
+		Game_Flag_Set(497);
+	}
+}
+
+void ScriptBB12::SceneLoaded() {
+	Obstacle_Object("BALLS", true);
+	Unclickable_Object("BALLS");
+}
+
+bool ScriptBB12::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB12::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptBB12::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB12::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB12::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -129.0f, 0.0f, 64.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(507);
+			Set_Enter(23, 9);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 138.0f, 0.0f, 104.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(365);
+			Set_Enter(3, 8);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 54.0f, 0.0f, 200.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(302);
+			Set_Enter(22, 6);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB12::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB12::SceneFrameAdvanced(int frame) {
+	if (frame == 10 || frame == 22 || frame == 33 || frame == 41) {
+		Sound_Play(311, 17, -30, -30, 50);
+	}
+	if (frame == 3) {
+		Sound_Play(313, 16, -30, -30, 50);
+	}
+}
+
+void ScriptBB12::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB12::PlayerWalkedIn() {
+	if (Game_Flag_Query(364)) {
+		Loop_Actor_Walk_To_XYZ(0, 114.0f, 0.0f, 104.0f, 0, 0, false, 0);
+		Game_Flag_Reset(364);
+	} else if (Game_Flag_Query(506)) {
+		Loop_Actor_Walk_To_XYZ(0, -101.0f, 0.0f, 64.0f, 0, 0, false, 0);
+		Game_Flag_Reset(506);
+	}
+}
+
+void ScriptBB12::PlayerWalkedOut() {
+}
+
+void ScriptBB12::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb51.cpp b/engines/bladerunner/script/bb51.cpp
new file mode 100644
index 0000000..38079fa
--- /dev/null
+++ b/engines/bladerunner/script/bb51.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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptBB51::InitializeScene() {
+	Setup_Scene_Information(101.0f, 0.0f, -25.0f, 152);
+	Game_Flag_Reset(393);
+	Scene_Exit_Add_2D_Exit(0, 615, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(1, 0, 323, 241, 479, 2);
+	Ambient_Sounds_Add_Looping_Sound(103, 28, 0, 1);
+	Ambient_Sounds_Add_Sound(303, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(304, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(443, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(444, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(445, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(446, 2, 180, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(305, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(306, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(307, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(308, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(309, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(310, 5, 50, 17, 27, -100, 100, -101, -101, 0, 0);
+	Scene_Loop_Start_Special(0, 0, 0);
+	Scene_Loop_Set_Default(1);
+}
+
+void ScriptBB51::SceneLoaded() {
+	Obstacle_Object("V2CHESSTBL01", true);
+	Clickable_Object("V2CHESSTBL01");
+	Clickable_Object("TOP02");
+}
+
+bool ScriptBB51::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptBB51::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("V2CHESSTBL01", objectName)) {
+		Actor_Face_Object(0, "V2CHESSTBL01", true);
+		Actor_Voice_Over(80, 99);
+		Actor_Voice_Over(90, 99);
+	}
+	if (Object_Query_Click("TOP02", objectName)) {
+		Actor_Face_Object(0, "TOP02", true);
+		Actor_Voice_Over(100, 99);
+		Actor_Voice_Over(110, 99);
+		Actor_Voice_Over(120, 99);
+	}
+	return false;
+}
+
+bool ScriptBB51::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptBB51::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptBB51::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 76.0f, 0.0f, 79.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(394);
+			Set_Enter(1, 7);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 55.0f, 0.0f, -96.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(395);
+			Set_Enter(1, 7);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptBB51::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptBB51::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptBB51::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptBB51::PlayerWalkedIn() {
+}
+
+void ScriptBB51::PlayerWalkedOut() {
+}
+
+void ScriptBB51::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct01.cpp b/engines/bladerunner/script/ct01.cpp
new file mode 100644
index 0000000..88e41fa
--- /dev/null
+++ b/engines/bladerunner/script/ct01.cpp
@@ -0,0 +1,514 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT01::InitializeScene() {
+	Music_Play(3, 28, 0, 2, -1, 1, 0);
+	Game_Flag_Reset(247);
+	if (Game_Flag_Query(68)) {
+		Game_Flag_Reset(68);
+		Setup_Scene_Information(-35.2f, -6.5f, 352.28f, 603);
+	} else if (Game_Flag_Query(71)) {
+		Game_Flag_Reset(71);
+		Setup_Scene_Information(-311.0f, -6.5f, 710.0f, 878);
+	} else if (Game_Flag_Query(88)) {
+		Game_Flag_Reset(88);
+		Setup_Scene_Information(-419.0f, -6.5f, 696.0f, 28);
+		if (Global_Variable_Query(1) != 2 && Global_Variable_Query(1) != 3) {
+			if (Game_Flag_Query(248)) {
+				Scene_Loop_Start_Special(0, 0, 0);
+			} else {
+				Scene_Loop_Start_Special(0, 6, 0);
+			}
+		}
+	} else if (Game_Flag_Query(248)) {
+		Setup_Scene_Information(-530.0f, -6.5f, 241.0f, 506);
+		Game_Flag_Set(247);
+	} else {
+		Setup_Scene_Information(-397.0f, -6.5f, 471.0f, 250);
+	}
+	Scene_Exit_Add_2D_Exit(0, 290, 256, 360, 304, 1);
+	if (Actor_Clue_Query(0, 18)) {
+		Scene_Exit_Add_2D_Exit(1, 571, 233, 639, 367, 1);
+	}
+	if (Game_Flag_Query(94)) {
+		Scene_Exit_Add_2D_Exit(2, 506, 400, 639, 479, 2);
+	}
+	if (Game_Flag_Query(248)) {
+		Scene_Exit_Add_2D_Exit(3, 0, 286, 158, 350, 2);
+	}
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(55, 40, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 40, 100, 1);
+	Ambient_Sounds_Add_Sound(61, 10, 30, 16, 20, 0, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(62, 10, 30, 16, 20, 0, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(63, 10, 30, 16, 20, 0, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(64, 10, 30, 16, 20, 0, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(68, 10, 40, 33, 50, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 10, 40, 33, 50, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 20, 40, 33, 50, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 20, 40, 33, 50, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 20, 40, 33, 50, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(248)) {
+		Scene_Loop_Set_Default(2);
+	} else {
+		Scene_Loop_Set_Default(7);
+	}
+}
+
+void ScriptCT01::SceneLoaded() {
+	Obstacle_Object("HYDRANT02", true);
+	Obstacle_Object("HOWWALLRT", true);
+	Obstacle_Object("HOW-CHAIR1", true);
+	Obstacle_Object("HOWWALLLFT", true);
+	Obstacle_Object("HOWDOOR01", true);
+	Unobstacle_Object("SPINNER BODY", true);
+	Unobstacle_Object("HOWFLOOR", true);
+	Unobstacle_Object("PAPER11", true);
+	Unobstacle_Object("PAPER16", true);
+	Unclickable_Object("HYDRANT02");
+	Unclickable_Object("TURBINE");
+	Unclickable_Object("SPINNER BODY");
+	Unclickable_Object("OBJECT04");
+}
+
+bool ScriptCT01::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT01::ClickedOn3DObject(const char *objectName, bool a2) {
+	if ("ASIANSITTINGANDEATI" == objectName) { //bug?
+		Actor_Face_Object(0, "ASIANSITTINGANDEATI", true);
+		Actor_Says(0, 365, 13);
+		Actor_Says(28, 160, 13);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT01::ClickedOnActor(int actorId) {
+	if (actorId == 28) {
+		Actor_Set_Goal_Number(28, 50);
+		if (!Loop_Actor_Walk_To_XYZ(0, -335.23f, -6.5f, 578.97f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 28, true);
+			Actor_Face_Actor(28, 0, true);
+			if (!Game_Flag_Query(26)) {
+				Actor_Says(0, 260, 18);
+				Actor_Says(28, 0, 14);
+				Game_Flag_Set(26);
+				Actor_Set_Goal_Number(28, 0);
+			} else if (!Game_Flag_Query(30) && Actor_Query_Friendliness_To_Other(28, 0) >= 40) {
+				sub_40269C();
+				Actor_Set_Goal_Number(28, 0);
+			} else {
+				if (Game_Flag_Query(31)) {
+					Actor_Says(0, 330, 17);
+					Actor_Says(28, 130, 13);
+					Actor_Says(28, 140, 14);
+				} else if (Actor_Query_Friendliness_To_Other(28, 0) < 50) {
+					Actor_Says(0, 330, 13);
+					Actor_Says(28, 160, 15);
+				} else {
+					Actor_Says(0, 310, 11);
+					Actor_Says(28, 10, 16);
+				}
+				Actor_Set_Goal_Number(28, 0);
+			}
+			return true;
+		}
+	}
+	if (actorId == 19) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -335.23f, -6.5f, 578.97f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 19, true);
+			Actor_Says(0, 355, 18);
+			if (!Actor_Query_Goal_Number(19)) {
+				Actor_Says(19, 10, 16);
+				Actor_Face_Actor(28, 0, true);
+				Actor_Says(28, 150, 3);
+				Actor_Face_Actor(0, 28, true);
+				Actor_Says(0, 360, 13);
+				Actor_Modify_Friendliness_To_Other(28, 0, -5);
+				Actor_Modify_Friendliness_To_Other(19, 0, -4);
+			}
+			return true;
+		}
+	}
+	if (actorId == 2) {
+		//todo: some weird code in assembly EBP is used but may not be initialized, loc_401C78
+		if (!Actor_Query_Goal_Number(2)) {
+			if (Loop_Actor_Walk_To_XYZ(0, -338.1f, -6.5f, 419.65f, 6, 1, false, 0)) {
+				return false;
+			}
+		}
+
+		Actor_Face_Actor(0, 2, true);
+		if (!Game_Flag_Query(32)) {
+			Actor_Says(0, 335, 18);
+			Actor_Says(2, 20, 30);
+			Game_Flag_Set(32);
+			Actor_Clue_Acquire(2, 213, 1, 0);
+			Actor_Clue_Acquire(0, 214, 1, 0);
+			Actor_Modify_Friendliness_To_Other(2, 0, -1);
+		} else if (Actor_Query_Goal_Number(2)) {
+			Actor_Says(0, 365, 14);
+		} else {
+			Actor_Says(0, 340, 13);
+			Actor_Says(0, 345, 11);
+			Actor_Says(2, 30, 30);
+			Actor_Says(0, 350, 13);
+			Actor_Says(2, 40, 30);
+			Actor_Modify_Friendliness_To_Other(2, 0, -5);
+			Player_Loses_Control();
+		}
+		if (Actor_Query_Is_In_Current_Set(19)) {
+			Actor_Modify_Friendliness_To_Other(19, 0, -2);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT01::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT01::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -327.5f, -6.5f, 352.28f, 0, 1, false, 0)) {
+			Player_Loses_Control();
+			Loop_Actor_Walk_To_Waypoint(0, 106, 0, 0, false);
+			Player_Gains_Control();
+			Game_Flag_Reset(247);
+			Set_Enter(27, 14);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -259.0f, -6.5f, 710.0f, 0, 1, false, 0)) {
+			Game_Flag_Reset(247);
+			Set_Enter(5, 15);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -419.0f, -6.5f, 696.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(123);
+			Game_Flag_Reset(247);
+			Set_Enter(4, 24);
+		}
+		return true;
+	}
+	if (exitId == 3) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -314.0f, -6.5f, 326.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, -330.0f, -6.5f, 221.0f, 0, 0, true, 0);
+			Loop_Actor_Walk_To_XYZ(0, -530.0f, -6.5f, 241.0f, 0, 0, true, 0);
+			Game_Flag_Reset(176);
+			Game_Flag_Reset(182);
+			Game_Flag_Reset(179);
+			Game_Flag_Reset(178);
+			Game_Flag_Reset(180);
+			Game_Flag_Reset(261);
+			Game_Flag_Reset(177);
+			Game_Flag_Reset(258);
+			int spinnerDest = Spinner_Interface_Choose_Dest(-1, 0);
+
+			switch (spinnerDest) {
+			case 0:
+				Game_Flag_Set(178);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(251);
+				Set_Enter(61, 65);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 1:
+				Game_Flag_Set(179);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(250);
+				Set_Enter(49, 48);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 2:
+				Game_Flag_Set(182);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(249);
+				Set_Enter(69, 78);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 4:
+				Game_Flag_Set(180);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(252);
+				Set_Enter(0, 0);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 5:
+				Game_Flag_Set(261);
+				Game_Flag_Reset(248);
+				Game_Flag_Reset(247);
+				Game_Flag_Set(307);
+				Set_Enter(17, 82);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 6:
+				Game_Flag_Set(177);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(253);
+				Set_Enter(7, 25);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 7:
+				Game_Flag_Set(258);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(254);
+				Set_Enter(20, 2);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 8:
+				Game_Flag_Set(181);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(255);
+				Set_Enter(54, 54);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			case 9:
+				Game_Flag_Set(257);
+				Game_Flag_Reset(247);
+				Game_Flag_Reset(248);
+				Game_Flag_Set(256);
+				Set_Enter(37, 34);
+				Scene_Loop_Start_Special(1, 5, 1);
+				break;
+			default:
+				Game_Flag_Set(176);
+				Player_Loses_Control();
+				Loop_Actor_Walk_To_XYZ(0, -530.0f, -6.5f, 241.0f, 0, 0, true, 0);
+				Loop_Actor_Walk_To_XYZ(0, -330.0f, -6.5f, 221.0f, 0, 0, true, 0);
+				Loop_Actor_Walk_To_XYZ(0, -314.0f, -6.5f, 326.0f, 0, 0, false, 0);
+				Player_Gains_Control();
+				break;
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT01::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT01::SceneFrameAdvanced(int frame) {
+	if ((frame < 316 || frame > 435) && !((frame - 1) % 10)) {
+		/*int v1;
+		int v2 = Random_Query(0, 1);
+		if (v2 <= 1) {
+			if (v2) {
+				v1 = 60;
+			} else {
+				v1 = 59;
+			}
+		}*/
+		Ambient_Sounds_Play_Sound(/*v1*/Random_Query(59, 60), 25, 30, 30, 0);
+	}
+	if (frame == 23) {
+		Ambient_Sounds_Play_Sound(118, 40, 99, 0, 0);
+	}
+	if (frame == 316) {
+		Ambient_Sounds_Play_Sound(373, 50, -50, 100, 99);
+	}
+	if (frame == 196 || frame == 452) {
+		int v3 = Random_Query(0, 6);
+		if (v3 == 0) {
+			Overlay_Play("ct01spnr", 0, 0, 1, 0);
+			if (Random_Query(0, 1)) {
+				Ambient_Sounds_Play_Sound(68, Random_Query(33, 50), 0, 0, 0);
+			} else {
+				Ambient_Sounds_Play_Sound(67, Random_Query(33, 50), 0, 0, 0);
+			}
+		} else if (v3 == 1) {
+			Overlay_Play("ct01spnr", 1, 0, 1, 0);
+			if (Random_Query(0, 1)) {
+				Ambient_Sounds_Play_Sound(69, Random_Query(33, 50), 0, 0, 0);
+			} else {
+				Ambient_Sounds_Play_Sound(66, Random_Query(33, 50), 0, 0, 0);
+			}
+
+		}
+	}
+}
+
+void ScriptCT01::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT01::PlayerWalkedIn() {
+	if (Game_Flag_Query(234)) {
+		Loop_Actor_Walk_To_XYZ(0, -327.2f, -6.5f, 352.28f, 0, 0, false, 0);
+		Game_Flag_Reset(234);
+	} else {
+		if (!Game_Flag_Query(247)) {
+			Game_Flag_Reset(247);
+		}
+		Loop_Actor_Walk_To_XYZ(0, -330.0f, -6.5f, 221.0f, 0, 0, false, 0);
+		Loop_Actor_Walk_To_XYZ(0, -314.0f, -6.5f, 326.0f, 0, 0, false, 0);
+		if (!Game_Flag_Query(25)) {
+			Game_Flag_Set(25);
+			if (!Game_Flag_Query(378)) {
+				Actor_Voice_Over(200, 99);
+				Actor_Voice_Over(210, 99);
+				Actor_Voice_Over(220, 99);
+			}
+		}
+	}
+}
+
+void ScriptCT01::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	if (Game_Flag_Query(123)) {
+		Ambient_Sounds_Remove_Looping_Sound(55, true);
+		Ambient_Sounds_Remove_Looping_Sound(56, true);
+	} else {
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+	}
+	Music_Stop(5);
+	if (!Game_Flag_Query(176) && Global_Variable_Query(1)) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Outtake_Play(38, 1, -1);
+	}
+}
+
+void ScriptCT01::DialogueQueueFlushed(int a1) {
+}
+
+void ScriptCT01::sub_40269C() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 13)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(40, 4, 5, 6);
+	}
+	if ((Actor_Clue_Query(0, 8) || Actor_Clue_Query(0, 9)) && !Game_Flag_Query(27)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(50, 5, 5, 4);
+	}
+	if (Actor_Clue_Query(0, 8) && Actor_Clue_Query(0, 9) && Game_Flag_Query(27) && !Game_Flag_Query(28)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(60, 3, 5, 5);
+	}
+	if (Game_Flag_Query(293)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(80, 9, 9, 9);
+	} else if (Game_Flag_Query(29)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(80, 3, 4, 8);
+	}
+	if (Actor_Clue_Query(0, 30) && Actor_Clue_Query(0, 40) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(90, 5, 4, 5);
+	}
+	DM_Add_To_List_Never_Repeat_Once_Selected(70, 7, 3, -1);
+	Dialogue_Menu_Add_DONE_To_List(100);
+	Dialogue_Menu_Appear(320, 240);
+	int answer = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answer) {
+	case 40:
+		Actor_Says(0, 265, 11);
+		Actor_Says(28, 20, 14);
+		if (Actor_Query_Is_In_Current_Set(19)) {
+			if (!Actor_Query_Goal_Number(19)) {
+				Actor_Face_Actor(28, 19, true);
+				Actor_Says(28, 120, 14);
+				Actor_Face_Actor(19, 28, true);
+				Actor_Says(19, 40, 18);
+				Actor_Face_Heading(19, 103, false);
+				Actor_Face_Actor(28, 0, true);
+				Actor_Modify_Friendliness_To_Other(19, 0, -2);
+				if (Actor_Query_Is_In_Current_Set(2)) {
+					Actor_Modify_Friendliness_To_Other(2, 0, -3);
+					Actor_Clue_Acquire(2, 213, 1, 0);
+				}
+			}
+		}
+		break;
+	case 50:
+		if (Actor_Clue_Query(0, 8) == 1) {
+			Actor_Says(0, 270, 11);
+			Actor_Says(28, 30, 16);
+		} else {
+			Actor_Says(0, 280, 11);
+			Actor_Says(28, 40, 14);
+		}
+		Game_Flag_Set(27);
+		break;
+	case 60:
+		if (Actor_Clue_Query(0, 9) == 1) {
+			Actor_Says(0, 270, 11);
+			Actor_Says(28, 40, 15);
+		} else {
+			Actor_Says(0, 270, 11);
+			Actor_Says(28, 30, 14);
+		}
+		Actor_Modify_Friendliness_To_Other(28, 0, 5);
+		Game_Flag_Set(28);
+		break;
+	case 70:
+		Actor_Says(0, 290, 13);
+		if (Actor_Query_Friendliness_To_Other(28, 0) <= 49 || Global_Variable_Query(2) <= 10 && Query_Difficulty_Level()) {
+			Actor_Says(28, 130, 15);
+		} else {
+			Actor_Says(28, 50, 3);
+			Actor_Says(28, 60, 3);
+			Actor_Face_Actor(28, 0, true);
+			Actor_Says(28, 70, 16);
+			Actor_Says(0, 325, 13);
+			if (Query_Difficulty_Level()) {
+				Global_Variable_Decrement(2, 10);
+			}
+			Game_Flag_Set(192);
+		}
+		break;
+	case 80:
+		Actor_Says(0, 295, 11);
+		Actor_Says(28, 90, 14);
+		Actor_Says(28, 100, 13);
+		Actor_Clue_Acquire(0, 25, 1, 28);
+		Actor_Modify_Friendliness_To_Other(28, 0, -3);
+		break;
+	case 90:
+		Actor_Says(0, 300, 13);
+		Actor_Says(28, 110, 16);
+		break;
+	case 100:
+		Actor_Says(0, 305, 18);
+		break;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct02.cpp b/engines/bladerunner/script/ct02.cpp
new file mode 100644
index 0000000..aecf291
--- /dev/null
+++ b/engines/bladerunner/script/ct02.cpp
@@ -0,0 +1,294 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT02::InitializeScene() {
+	if (Game_Flag_Query(70)) {
+		Game_Flag_Reset(70);
+		Setup_Scene_Information(-154.83f, -145.11f, 9.39f, 516);
+	} else if (Game_Flag_Query(720)) {
+		Setup_Scene_Information(-213.82f, -145.11f, 214.43f, 82);
+	} else {
+		Setup_Scene_Information(-119.02f, -145.11f, 240.99f, 768);
+	}
+	Scene_Exit_Add_2D_Exit(0, 590, 0, 639, 479, 1);
+	if (Actor_Clue_Query(0, 18)) {
+		Scene_Exit_Add_2D_Exit(1, 332, 163, 404, 297, 0);
+	} else {
+		Overlay_Play("ct02over", 0, 1, 0, 0);
+	}
+	Ambient_Sounds_Add_Looping_Sound(96, 25, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 38, 100, 1);
+	Ambient_Sounds_Add_Looping_Sound(95, 32, 0, 1);
+	Ambient_Sounds_Add_Sound(61, 10, 30, 8, 8, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(62, 10, 30, 7, 7, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(63, 10, 30, 8, 8, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(64, 10, 30, 7, 7, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 19, 100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 19, 100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 19, 100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 19, 100, 100, -101, -101, 1, 1);
+	if (Game_Flag_Query(293)) {
+		Scene_Loop_Set_Default(3);
+	} else {
+		Scene_Loop_Set_Default(0);
+	}
+}
+
+void ScriptCT02::SceneLoaded() {
+	Obstacle_Object("STOVE-1", true);
+	Unobstacle_Object("BACK-DOOR", true);
+	Unclickable_Object("STOVE-1");
+	Unclickable_Object("STOVE-2");
+	Unclickable_Object("STOVE-3");
+	Unclickable_Object("STOVE-4");
+	Unclickable_Object("BIGPOT");
+	Unclickable_Object("SOUP-BOWL");
+	Unclickable_Object("HOWCOUNTRM");
+	Unclickable_Object("LFTSTOVE-1");
+	Unclickable_Object("FRIDGE-1");
+	Unclickable_Object("LEFTWALL");
+	Unclickable_Object("RIGHTWALL");
+	Unclickable_Object("BACKWALL");
+	Unclickable_Object("TABLE-1");
+	Unclickable_Object("COUNTER-2");
+	Unclickable_Object("COFFEJUG IN FOREGRO");
+	Unclickable_Object("BACK-DOOR");
+	if (!Game_Flag_Query(293)) {
+		Preload(0);
+		Preload(3);
+		Preload(3);
+		Preload(28);
+		Preload(400);
+		Preload(419);
+		Preload(420);
+	}
+	if (Game_Flag_Query(720)) {
+		Game_Flag_Reset(720);
+		Actor_Change_Animation_Mode(0, 0);
+		Player_Set_Combat_Mode(true);
+		Player_Gains_Control();
+	}
+}
+
+bool ScriptCT02::MouseClick(int x, int y) {
+	if (Actor_Query_Goal_Number(19) == 8) {
+		Actor_Set_Goal_Number(0, 1);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT02::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+void ScriptCT02::sub_401ACC() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 13)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(270, 8, 5, 3);
+	}
+	if (Actor_Clue_Query(0, 22) && !Actor_Clue_Query(0, 13)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(280, 8, 5, 3);
+	}
+	int v0 = 0;
+	if (Actor_Clue_Query(0, 2)) {
+		v0 = 1;
+	}
+	if (Actor_Clue_Query(0, 10)) {
+		++v0;
+	}
+	if (Actor_Clue_Query(0, 3)) {
+		++v0;
+	}
+	if (Actor_Clue_Query(0, 16)) {
+		++v0;
+	}
+	if (Actor_Clue_Query(0, 25)) {
+		++v0;
+	}
+	if (v0 > 3) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(290, -1, 4, 8);
+	}
+	Dialogue_Menu_Add_DONE_To_List(300);
+	Dialogue_Menu_Appear(320, 240);
+	int answerValue = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answerValue) {
+	case 270:
+		Actor_Says(0, 380, 11);
+		Actor_Says(19, 30, 17);
+		Actor_Says(19, 40, 15);
+		Actor_Says(0, 410, 9);
+		Actor_Says(19, 50, 18);
+		Actor_Says(0, 415, 10);
+		Actor_Clue_Acquire(0, 19, 0, -1);
+		Actor_Modify_Friendliness_To_Other(19, 0, -5);
+		if (Actor_Query_Friendliness_To_Other(19, 0) < 44) {
+			Scene_Exits_Disable();
+			Actor_Clue_Acquire(0, 18, 1, -1);
+			Actor_Set_Goal_Number(19, 8);
+			Game_Flag_Set(293);
+			Scene_Loop_Set_Default(3);
+			Scene_Loop_Start_Special(2, 2, 1);
+		}
+		break;
+	case 280:
+		Actor_Says(0, 385, 9);
+		Actor_Says(19, 40, 19);
+		Actor_Modify_Friendliness_To_Other(19, 0, -2);
+		if (Actor_Query_Friendliness_To_Other(19, 0) < 44) {
+			Scene_Exits_Disable();
+			Actor_Clue_Acquire(0, 18, 1, -1);
+			Actor_Set_Goal_Number(19, 8);
+			Game_Flag_Set(293);
+			Scene_Loop_Set_Default(3);
+			Scene_Loop_Start_Special(2, 2, 1);
+		}
+		break;
+	case 290:
+		Actor_Says(0, 395, 9);
+		Actor_Says(0, 400, 9);
+		Actor_Says(19, 70, 17);
+		Actor_Says(0, 420, 10);
+		Actor_Says(19, 80, 14);
+		Actor_Modify_Friendliness_To_Other(19, 0, -10);
+		if (Actor_Query_Friendliness_To_Other(19, 0) < 44) {
+			Scene_Exits_Disable();
+			Actor_Clue_Acquire(0, 18, 1, -1);
+			Actor_Set_Goal_Number(19, 8);
+			Game_Flag_Set(293);
+			Scene_Loop_Set_Default(3);
+			Scene_Loop_Start_Special(2, 2, 1);
+		}
+		break;
+	case 300:
+		Actor_Says(0, 405, 11);
+		if (Actor_Query_Friendliness_To_Other(19, 0) < 44) {
+			Scene_Exits_Disable();
+			Actor_Clue_Acquire(0, 18, 1, -1);
+			Actor_Set_Goal_Number(19, 8);
+			Game_Flag_Set(293);
+			Scene_Loop_Set_Default(3);
+			Scene_Loop_Start_Special(2, 2, 1);
+		}
+		break;
+	}
+}
+
+bool ScriptCT02::ClickedOnActor(int actorId) {
+	if (actorId == 19 && Actor_Query_Goal_Number(19) == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -255.02f, -145.11f, 212.42f, 0, 1, false, 0)) {
+			Actor_Face_Actor(0, 19, true);
+			Actor_Face_Actor(19, 0, true);
+			if (!Game_Flag_Query(59)) {
+				Actor_Says(0, 370, 10);
+				Actor_Says(19, 20, 19);
+				Actor_Says(0, 375, 9);
+				Game_Flag_Set(59);
+			}
+			sub_401ACC();
+			return true;
+		}
+	}
+	return false;
+}
+
+bool ScriptCT02::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT02::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -111.2f, -145.11f, 243.28f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(234);
+			Game_Flag_Set(68);
+			Set_Enter(4, 13);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		bool v1;
+		if (Player_Query_Combat_Mode()) {
+			v1 = Loop_Actor_Walk_To_XYZ(0, -154.83f, -145.11f, -82.61f, 0, 1, true, 0);
+		} else {
+			v1 = Loop_Actor_Walk_To_XYZ(0, -154.83f, -145.11f, -82.61f, 0, 1, false, 0);
+		}
+		if (!v1) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(69);
+			Set_Enter(5, 15);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT02::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT02::SceneFrameAdvanced(int frame) {
+	if (frame == 6 || frame == 12 || frame == 19 || frame == 25 || frame == 46 || frame == 59) {
+		Sound_Play(97, Random_Query(25, 33), -70, -70, 50);
+	}
+	if (frame == 72) {
+		Sound_Play(200, 50, 0, 0, 50);
+	}
+	if (frame == 71) {
+		Sound_Play(204, 40, 0, 0, 50);
+	}
+	if (frame == 72) {
+		Sound_Play(203, 60, -20, 40, 50);
+	}
+	if (frame == 61) {
+		Music_Play(1, 50, 0, 2, -1, 0, 0);
+	}
+	if (frame == 81) {
+		Scene_Exit_Add_2D_Exit(1, 332, 163, 404, 297, 0);
+		Scene_Exits_Enable();
+	}
+}
+
+void ScriptCT02::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT02::PlayerWalkedIn() {
+}
+
+void ScriptCT02::PlayerWalkedOut() {
+	if (Actor_Clue_Query(0, 18)) {
+		return;
+	}
+	Overlay_Remove("ct02over");
+}
+
+void ScriptCT02::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct03.cpp b/engines/bladerunner/script/ct03.cpp
new file mode 100644
index 0000000..133c5d0
--- /dev/null
+++ b/engines/bladerunner/script/ct03.cpp
@@ -0,0 +1,133 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT03::InitializeScene() {
+	if (Game_Flag_Query(719)) {
+		Setup_Scene_Information(-852.58f, -621.3f, 285.6f, 0);
+	} else if (Game_Flag_Query(69)) {
+		Game_Flag_Reset(69);
+		Setup_Scene_Information(-557.1f, -616.31f, 224.29f, 249);
+	} else if (Game_Flag_Query(73)) {
+		Game_Flag_Reset(73);
+		Setup_Scene_Information(-173.99f, -619.19f, 347.54f, 808);
+	} else {
+		Setup_Scene_Information(-708.58f, -619.19f, 277.6f, 239);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 460, 639, 479, 2);
+	Scene_Exit_Add_2D_Exit(1, 40, 40, 134, 302, 3);
+	Scene_Exit_Add_2D_Exit(2, 390, 0, 539, 230, 1);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 22, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 34, -100, 1);
+	Ambient_Sounds_Add_Sound(68, 10, 40, 33, 50, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 10, 40, 33, 50, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(61, 3, 30, 8, 10, -100, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(62, 3, 30, 8, 10, -100, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(63, 3, 30, 8, 10, -100, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(64, 3, 30, 8, 10, -100, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 27, 47, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(376, 10, 60, 33, 50, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 10, 60, 33, 50, -100, 100, -101, -101, 0, 0);
+}
+
+void ScriptCT03::SceneLoaded() {
+	Obstacle_Object("TRASH CAN", true);
+	Unclickable_Object("TRASH CAN");
+	Footstep_Sounds_Set(0, 0);
+	Footstep_Sounds_Set(1, 1);
+}
+
+bool ScriptCT03::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT03::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptCT03::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT03::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT03::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -745.09f, -619.09f, 293.36f, 0, 1, false, 0)) {
+			Game_Flag_Set(71);
+			Set_Enter(4, 13);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -604.38f, -616.15f, 221.6f, 0, 1, false, 0)) {
+			Game_Flag_Set(70);
+			Set_Enter(27, 14);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -150.0f, -621.3f, 357.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(72);
+			Async_Actor_Walk_To_XYZ(0, -67.0f, -621.3f, 477.0f, 0, false);
+			Set_Enter(5, 16);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT03::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT03::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptCT03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT03::PlayerWalkedIn() {
+	if (Actor_Query_Goal_Number(19) == 2) {
+		Actor_Set_Goal_Number(19, 13);
+	}
+}
+
+void ScriptCT03::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptCT03::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct04.cpp b/engines/bladerunner/script/ct04.cpp
new file mode 100644
index 0000000..795cf94
--- /dev/null
+++ b/engines/bladerunner/script/ct04.cpp
@@ -0,0 +1,237 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT04::InitializeScene() {
+	if (Game_Flag_Query(72)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+		Setup_Scene_Information(-150.0f, -621.3f, 357.0f, 533);
+	} else {
+		Scene_Loop_Set_Default(1);
+		Setup_Scene_Information(-82.86f, -621.3f, 769.03f, 1020);
+	}
+	Scene_Exit_Add_2D_Exit(0, 590, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(1, 194, 84, 320, 274, 0);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 15, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(105, 34, 100, 1);
+	Ambient_Sounds_Add_Sound(68, 10, 40, 33, 50, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 10, 40, 33, 50, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(376, 10, 60, 33, 50, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 10, 60, 33, 50, -100, 100, -101, -101, 0, 0);
+}
+
+void ScriptCT04::SceneLoaded() {
+	Obstacle_Object("DUMPSTER", true);
+	Obstacle_Object("RIGHTWALL01", true);
+	Obstacle_Object("BACK-BLDNG", true);
+	Clickable_Object("DUMPSTER");
+	Footstep_Sounds_Set(0, 1);
+	if (Game_Flag_Query(72)) {
+		Game_Flag_Reset(72);
+	}
+	if (!Actor_Query_Goal_Number(12)) {
+		Actor_Change_Animation_Mode(12, 38);
+	}
+}
+
+bool ScriptCT04::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT04::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (objectName) {
+		if (!Game_Flag_Query(137) && !Game_Flag_Query(169) && !Actor_Query_Goal_Number(12)) {
+			Game_Flag_Set(137);
+			Actor_Set_Goal_Number(12, 2);
+		}
+		if (Game_Flag_Query(169) && !Game_Flag_Query(170) && !Game_Flag_Query(171) && !Game_Flag_Query(172) && Global_Variable_Query(1) == 1) {
+			if (!Loop_Actor_Walk_To_XYZ(0, -147.41f, -621.3f, 724.57f, 0, 1, false, 0)) {
+				Player_Loses_Control();
+				Actor_Face_Heading(0, 792, false);
+				Actor_Put_In_Set(12, 99);
+				Actor_Set_At_XYZ(12, 0, 0, 0, 0);
+				Actor_Change_Animation_Mode(0, 40);
+				Actor_Voice_Over(320, 99);
+				Actor_Voice_Over(330, 99);
+				Actor_Voice_Over(340, 99);
+				Game_Flag_Set(170);
+				Game_Flag_Set(173);
+			}
+			return false;
+		}
+		if (Game_Flag_Query(170)) {
+			if (Game_Flag_Query(172)) {
+				Actor_Voice_Over(270, 99);
+				Actor_Voice_Over(280, 99);
+			} else if (Game_Flag_Query(171)) {
+				Actor_Voice_Over(250, 99);
+				Actor_Voice_Over(260, 99);
+			} else {
+				Actor_Voice_Over(230, 99);
+				Actor_Voice_Over(240, 99);
+				Game_Flag_Reset(173);
+			}
+			return true;
+		}
+		if (Game_Flag_Query(174)) {
+			if (!Loop_Actor_Walk_To_Waypoint(0, 75, 0, 1, false)) {
+				Actor_Face_Heading(0, 707, false);
+				Actor_Change_Animation_Mode(0, 38);
+				Ambient_Sounds_Play_Sound(553, 45, 30, 30, 0);
+				Actor_Voice_Over(1810, 99);
+				Actor_Voice_Over(1820, 99);
+				return true;
+			}
+			return false;
+		}
+		if (!Loop_Actor_Walk_To_Waypoint(0, 75, 0, 1, false)) {
+			Actor_Face_Heading(0, 707, false);
+			Actor_Change_Animation_Mode(0, 38);
+			Actor_Clue_Acquire(0, 37, 1, -1);
+			Item_Pickup_Spin_Effect(952, 392, 225);
+			Game_Flag_Set(174);
+			return true;
+		}
+	}
+	return false;
+}
+
+void ScriptCT04::sub_401D4C() {
+	Dialogue_Menu_Clear_List();
+	if (Global_Variable_Query(2) > 10 || !Query_Difficulty_Level()) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(410, 8, 4, -1);
+	}
+	DM_Add_To_List_Never_Repeat_Once_Selected(420, 2, 6, 8);
+	Dialogue_Menu_Appear(320, 240);
+	int answer = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	if (answer == 410) {
+		Actor_Says(12, 10, 14);
+		Actor_Says(12, 20, 14);
+		Actor_Modify_Friendliness_To_Other(12, 0, 5);
+		if (Query_Difficulty_Level()) {
+			Global_Variable_Decrement(2, 10);
+		}
+	} else if (answer == 420) {
+		Actor_Says(0, 430, 3);
+		Actor_Says(12, 30, 14);
+		Actor_Modify_Friendliness_To_Other(12, 0, -5);
+	}
+}
+
+bool ScriptCT04::ClickedOnActor(int actorId) {
+	if (actorId == 12) {
+		if (Game_Flag_Query(169)) {
+			if (!Loop_Actor_Walk_To_Actor(0, 12, 36, 1, false)) {
+				Actor_Voice_Over(290, 99);
+				Actor_Voice_Over(300, 99);
+				Actor_Voice_Over(310, 99);
+			}
+		} else {
+			Actor_Set_Targetable(12, false);
+			if (!Loop_Actor_Walk_To_Actor(0, 12, 36, 1, false)) {
+				Actor_Face_Actor(0, 12, true);
+				if (!Game_Flag_Query(137)) {
+					if (Game_Flag_Query(40)) {
+						Actor_Says(0, 435, 3);
+						Actor_Set_Goal_Number(12, 2);
+					} else {
+						Music_Stop(3);
+						Actor_Says(0, 425, 3);
+						Actor_Says(12, 0, 13);
+						sub_401D4C();
+						Actor_Set_Goal_Number(12, 2);
+					}
+					Game_Flag_Set(137);
+				} else {
+					Actor_Face_Actor(0, 12, true);
+					Actor_Says(0, 435, 3);
+				}
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT04::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT04::ClickedOnExit(int exitId) {
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -82.86f, -621.3f, 769.03f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			if (!Actor_Query_Goal_Number(12)) {
+				Actor_Set_Goal_Number(12, 2);
+			}
+			Game_Flag_Set(74);
+			Set_Enter(28, 17);
+		}
+		return true;
+	}
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -187.0f, -621.3f, 437.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(73);
+			Set_Enter(5, 15);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT04::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT04::SceneFrameAdvanced(int frame) {
+	if (Game_Flag_Query(325)) {
+		Game_Flag_Reset(325);
+		Sound_Play(180, 100, 80, 80, 50);
+	}
+}
+
+void ScriptCT04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT04::PlayerWalkedIn() {
+}
+
+void ScriptCT04::PlayerWalkedOut() {
+}
+
+void ScriptCT04::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct05.cpp b/engines/bladerunner/script/ct05.cpp
new file mode 100644
index 0000000..0249110
--- /dev/null
+++ b/engines/bladerunner/script/ct05.cpp
@@ -0,0 +1,241 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT05::InitializeScene() {
+	if (Game_Flag_Query(90)) {
+		Game_Flag_Reset(90);
+		Setup_Scene_Information(-128.42f, -109.91f, 112.83f, 516);
+	} else if (Game_Flag_Query(78)) {
+		Setup_Scene_Information(192.35f, 43.09f, 128.97f, 768);
+	} else {
+		Setup_Scene_Information(-375.0f, -109.91f, 750.0f, 600);
+	}
+	if (Game_Flag_Query(94)) {
+		Scene_Exit_Add_2D_Exit(0, 228, 205, 293, 300, 0);
+	}
+	Scene_Exit_Add_2D_Exit(1, 320, 458, 639, 479, 2);
+	Scene_Exit_Add_2D_Exit(2, 380, 110, 542, 300, 0);
+	Ambient_Sounds_Add_Looping_Sound(106, 15, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(107, 15, 100, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 13, -100, 1);
+	Ambient_Sounds_Add_Sound(90, 5, 20, 8, 10, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(91, 5, 20, 8, 10, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(205, 5, 30, 18, 30, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(94)) {
+		Scene_Loop_Set_Default(2);
+	} else {
+		Scene_Loop_Set_Default(0);
+	}
+	if (Actor_Query_Goal_Number(53) == 1) {
+		Overlay_Play("ct05over", 0, 1, 0, 0);
+	}
+}
+
+void ScriptCT05::SceneLoaded() {
+	Obstacle_Object("STAIR 1", true);
+	Obstacle_Object("STAIR 2", true);
+	Obstacle_Object("GRGDOOR", true);
+	Obstacle_Object("GRGDOOR2", true);
+	Obstacle_Object("TURBINE", true);
+	Obstacle_Object("BARREL", true);
+	Obstacle_Object("GRNDPIPE", true);
+	Clickable_Object("TURBINE");
+	Clickable_Object("LFTDOOR");
+	Clickable_Object("BARREL");
+	Clickable_Object("GRNDPIPE");
+	Unclickable_Object("GDFRAME");
+	Unclickable_Object("GDFRAME2");
+	Unclickable_Object("WINFRAME1");
+	Unclickable_Object("WINFRAME2");
+	Unclickable_Object("STAIR 1");
+	Unclickable_Object("STAIR 2");
+	Unclickable_Object("LFTDOOR");
+	Unclickable_Object("LFTDOORFRM");
+}
+
+bool ScriptCT05::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT05::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("STAIR1", objectName)) {
+		Actor_Face_Object(0, objectName, true);
+		return true;
+	}
+	if (Object_Query_Click("STAIR2", objectName)) {
+		Actor_Face_Object(0, objectName, true);
+		return true;
+	}
+	if (Object_Query_Click("GRGDOOR", objectName)) {
+		Loop_Actor_Walk_To_Scene_Object(0, "GRGDOOR", 24, 1, false);
+		Actor_Face_Object(0, objectName, true);
+		Actor_Says(0, 8522, 12);
+		return true;
+	}
+	if (Object_Query_Click("GRGDOOR2", objectName)) {
+		Loop_Actor_Walk_To_Scene_Object(0, "GRGDOOR2", 24, 1, false);
+		Actor_Face_Object(0, objectName, true);
+		Actor_Says(0, 8522, 12);
+		return true;
+	}
+	if (Object_Query_Click("TURBINE", objectName)) {
+		Loop_Actor_Walk_To_Scene_Object(0, "TURBINE", 36, 1, false);
+		Actor_Face_Object(0, objectName, true);
+		Actor_Says(0, 8528, 12);
+		return true;
+	}
+	if (Object_Query_Click("LFTDOOR", objectName)) {
+		Actor_Face_Object(0, objectName, true);
+		Actor_Says(0, 8522, 12);
+		return true;
+	}
+	if (Object_Query_Click("BARREL", objectName)) {
+		Loop_Actor_Walk_To_Scene_Object(0, "BARREL", 36, 1, false);
+		Actor_Face_Object(0, objectName, true);
+		Actor_Says(0, 8529, 12);
+		return true;
+	}
+	if (Object_Query_Click("GRNDPIPE", objectName)) {
+		Loop_Actor_Walk_To_Scene_Object(0, "GRNDPIPE", 24, 1, false);
+		Actor_Face_Object(0, objectName, true);
+		Actor_Says(0, 8528, 12);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT05::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT05::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT05::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -128.42f, -109.91f, 112.83f, 0, 1, false, 0)) {
+			Game_Flag_Set(76);
+			if (Actor_Query_Goal_Number(53) == 1) {
+				Overlay_Remove("ct05over");
+			}
+			Set_Enter(4, 24);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -308.18f, -109.91f, 674.77f, 0, 1, false, 0)) {
+			Game_Flag_Set(75);
+			if (Actor_Query_Goal_Number(53) == 1) {
+				Overlay_Remove("ct05over");
+				Actor_Set_Goal_Number(53, 5);
+				Game_Flag_Set(409);
+			}
+			Set_Enter(5, 16);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 71.99f, -109.91f, 288.79f, 0, 1, false, 0)) {
+			Footstep_Sound_Override_On(2);
+			Actor_Face_Object(0, "STAIR 2", true);
+			Loop_Actor_Travel_Stairs(0, 9, 1, 0);
+			Actor_Set_At_XYZ(0, 99.73f, -19.91f, 134.97f, 256);
+			Loop_Actor_Travel_Stairs(0, 5, 1, 0);
+			Footstep_Sound_Override_Off();
+			Game_Flag_Set(77);
+			if (Actor_Query_Goal_Number(53) == 1) {
+				Overlay_Remove("ct05over");
+			}
+			Set_Enter(29, 18);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT05::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT05::SceneFrameAdvanced(int frame) {
+	if (frame == 7 || frame == 15 || frame == 29) {
+		switch (Random_Query(0, 4)) {
+		case 4:
+			Sound_Play(40, Random_Query(25, 50), -70, -70, 50);
+			break;
+		case 3:
+			Sound_Play(44, Random_Query(25, 50), -70, -70, 50);
+			break;
+		case 2:
+			Sound_Play(43, Random_Query(25, 50), -70, -70, 50);
+			break;
+		case 1:
+			Sound_Play(42, Random_Query(25, 50), -70, -70, 50);
+			break;
+		case 0:
+			Sound_Play(41, Random_Query(25, 50), -70, -70, 50);
+			break;
+		}
+	}
+}
+
+void ScriptCT05::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT05::PlayerWalkedIn() {
+	if (Game_Flag_Query(74)) {
+		Player_Loses_Control();
+		Game_Flag_Reset(74);
+		if (Player_Query_Combat_Mode()) {
+			Loop_Actor_Walk_To_XYZ(0, -308.18f, -109.91f, 674.77f, 0, 0, true, 0);
+		} else {
+			Loop_Actor_Walk_To_XYZ(0, -308.18f, -109.91f, 674.77f, 0, 0, false, 0);
+		}
+		Player_Gains_Control();
+	}
+	if (Game_Flag_Query(78)) {
+		Footstep_Sound_Override_On(2);
+		Loop_Actor_Travel_Stairs(0, 7, 0, 0);
+		Actor_Set_At_XYZ(0, 90.73f, -19.91f, 164.97f, 520);
+		Loop_Actor_Travel_Stairs(0, 10, 0, 0);
+		Game_Flag_Reset(78);
+		Footstep_Sound_Override_Off();
+		if (Actor_Query_Goal_Number(2) == 2 && Game_Flag_Query(145)) {
+			Actor_Set_Goal_Number(2, 3);
+		}
+	}
+}
+
+void ScriptCT05::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptCT05::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct06.cpp b/engines/bladerunner/script/ct06.cpp
new file mode 100644
index 0000000..30dfd19
--- /dev/null
+++ b/engines/bladerunner/script/ct06.cpp
@@ -0,0 +1,180 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT06::InitializeScene() {
+	if (Game_Flag_Query(77)) {
+		Setup_Scene_Information(20.41f, -58.23f, 2.17f, 247);
+		Game_Flag_Reset(77);
+	} else if (Game_Flag_Query(144)) {
+		Setup_Scene_Information(203.91f, -58.02f, 0.47f, 768);
+	} else {
+		Setup_Scene_Information(175.91f, -58.23f, 24.47f, 768);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 440, 639, 479, 2);
+	Scene_Exit_Add_2D_Exit(1, 401, 162, 536, 317, 0);
+	if (Game_Flag_Query(40) && Actor_Query_In_Set(19, 30)) {
+		Actor_Put_In_Set(19, 29);
+		Actor_Set_At_XYZ(19, 58.41f, -58.23f, -24.97f, 240);
+		Actor_Retired_Here(19, 72, 36, 1, 0);
+	}
+	Ambient_Sounds_Add_Looping_Sound(381, 100, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(205, 20, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(67, 80, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(68, 50, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 50, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 70, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 60, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Actor_Query_Goal_Number(19) == 13) {
+		Ambient_Sounds_Add_Sound(196, 1, 5, 25, 25, -100, 100, -101, -101, 0, 0);
+		Ambient_Sounds_Add_Sound(197, 1, 5, 25, 25, -100, 100, -101, -101, 0, 0);
+		Ambient_Sounds_Add_Sound(198, 1, 5, 25, 25, -100, 100, -101, -101, 0, 0);
+		Ambient_Sounds_Add_Sound(199, 1, 5, 25, 25, -100, 100, -101, -101, 0, 0);
+	}
+}
+
+void ScriptCT06::SceneLoaded() {
+	Obstacle_Object("BOX02", true);
+	Obstacle_Object("CB BOX01", true);
+	Obstacle_Object("CB BOX02", true);
+	Obstacle_Object("CB BOX03", true);
+	Unobstacle_Object("INSULPIP01", true);
+	Unobstacle_Object("CB BOX04", true);
+	Unclickable_Object("DOOR");
+	if (Actor_Query_Goal_Number(19) == 13) {
+		Preload(3);
+		Preload(4);
+		Preload(389);
+		Preload(390);
+		Preload(398);
+		Preload(421);
+		Preload(421);
+	}
+}
+
+bool ScriptCT06::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT06::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptCT06::ClickedOnActor(int actorId) {
+	if (actorId == 19) {
+		Loop_Actor_Walk_To_Actor(0, 19, 24, 1, false);
+		Actor_Face_Actor(0, 19, true);
+		if (Game_Flag_Query(145)) {
+			Actor_Says(0, 8570, 13);
+			return false;
+		}
+		Actor_Clue_Acquire(0, 20, 1, -1);
+		Item_Pickup_Spin_Effect(984, 340, 369);
+		Actor_Voice_Over(350, 99);
+		Actor_Voice_Over(360, 99);
+		Actor_Voice_Over(370, 99);
+		if (!Game_Flag_Query(378)) {
+			Actor_Voice_Over(380, 99);
+			Actor_Voice_Over(390, 99);
+			Actor_Voice_Over(400, 99);
+			Actor_Voice_Over(410, 99);
+		}
+		Game_Flag_Set(145);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT06::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT06::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 20.41f, -58.23f, -2.17f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(78);
+			Set_Enter(28, 17);
+			Game_Flag_Reset(212);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (Actor_Query_Goal_Number(19) == 13) {
+			if (!Loop_Actor_Walk_To_XYZ(0, 203.91f, -58.02f, 0.47f, 0, 1, false, 0)) {
+				Ambient_Sounds_Remove_Sound(196, true);
+				Ambient_Sounds_Remove_Sound(197, true);
+				Ambient_Sounds_Remove_Sound(198, true);
+				Ambient_Sounds_Remove_Sound(199, true);
+				Player_Loses_Control();
+				Actor_Set_Goal_Number(19, 11);
+				Game_Flag_Reset(212);
+			}
+			return true;
+		}
+		if (!Loop_Actor_Walk_To_XYZ(0, 203.91f, -58.02f, 0.47f, 0, 1, false, 0)) {
+			if (Global_Variable_Query(1) < 3) {
+				Actor_Face_Object(0, "DOOR", true);
+				Actor_Says(0, 8522, 12);
+			} else {
+				Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+				Ambient_Sounds_Remove_All_Looping_Sounds(1);
+				Game_Flag_Set(79);
+				Set_Enter(6, 20);
+				Game_Flag_Reset(212);
+			}
+		}
+	}
+	return false;
+}
+
+bool ScriptCT06::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT06::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptCT06::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT06::PlayerWalkedIn() {
+	if (Game_Flag_Query(144) == 1) {
+		Game_Flag_Reset(144);
+	}
+}
+
+void ScriptCT06::PlayerWalkedOut() {
+}
+
+void ScriptCT06::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct07.cpp b/engines/bladerunner/script/ct07.cpp
new file mode 100644
index 0000000..771d4be
--- /dev/null
+++ b/engines/bladerunner/script/ct07.cpp
@@ -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.
+ *
+ */
+
+#include "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT07::InitializeScene() {
+	Setup_Scene_Information(202.32f, -58.23f, -12.86f, 225);
+	Actor_Put_In_Set(19, 30);
+	Actor_Set_At_XYZ(19, -9.68f, -58.23f, 11.14f, 250);
+	Ambient_Sounds_Add_Looping_Sound(54, 30, 90, 1);
+	Ambient_Sounds_Add_Looping_Sound(205, 20, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 40, 100, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(67, 80, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(68, 50, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 10, 60, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 6, 50, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 10, 70, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(61, 10, 30, 12, 14, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(62, 10, 30, 12, 14, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(63, 10, 30, 12, 14, 100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(64, 10, 30, 12, 14, 100, 100, -101, -101, 0, 0);
+}
+
+void ScriptCT07::SceneLoaded() {
+	Obstacle_Object("BOX01", true);
+	Obstacle_Object("BOX02", true);
+	Obstacle_Object("BOX03", true);
+	Obstacle_Object("BOX04", true);
+	Unclickable_Object("BOX01");
+	Unclickable_Object("BOX02");
+	Unclickable_Object("BOX03");
+	Unclickable_Object("BOX04");
+}
+
+bool ScriptCT07::MouseClick(int x, int y) {
+	return true;
+}
+
+bool ScriptCT07::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptCT07::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT07::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT07::ClickedOnExit(int exitId) {
+	return false;
+}
+
+bool ScriptCT07::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT07::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptCT07::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT07::PlayerWalkedIn() {
+	Player_Gains_Control();
+	Non_Player_Actor_Combat_Mode_On(19, 0, 0, 0, 2, 4, 7, 8, 0, 0, 100, 15, 300, 0);
+	Game_Flag_Set(516);
+	Actor_Face_Actor(0, 19, true);
+}
+
+void ScriptCT07::PlayerWalkedOut() {
+	Music_Stop(2);
+}
+
+void ScriptCT07::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct08.cpp b/engines/bladerunner/script/ct08.cpp
new file mode 100644
index 0000000..42b924e
--- /dev/null
+++ b/engines/bladerunner/script/ct08.cpp
@@ -0,0 +1,196 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT08::InitializeScene() {
+	if (Game_Flag_Query(679)) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Outtake_Play(2, 0, -1);
+		if (Game_Flag_Query(46)) {
+			Outtake_Play(3, 0, -1);
+		} else if (Game_Flag_Query(47)) {
+			Outtake_Play(4, 0, -1);
+		} else {
+			Outtake_Play(5, 0, -1);
+		}
+		Outtake_Play(6, 0, -1);
+		Game_Flag_Reset(679);
+	}
+	Actor_Force_Stop_Walking(0);
+	if (Game_Flag_Query(380)) {
+		Setup_Scene_Information(-11.0f, 0.0f, -156.0f, 769);
+	} else if (Game_Flag_Query(79)) {
+		Setup_Scene_Information(-143.0f, 0.0f, -92.0f, 420);
+	} else {
+		Setup_Scene_Information(-183.0f, 0.0f, 128.0f, 205);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 0, 30, 479, 3);
+	Scene_Exit_Add_2D_Exit(1, 389, 0, 639, 303, 0);
+	Scene_Exit_Add_2D_Exit(2, 115, 87, 137, 267, 3);
+	if (Game_Flag_Query(550)) {
+		Scene_2D_Region_Add(0, 185, 185, 230, 230);
+	}
+	Ambient_Sounds_Add_Looping_Sound(381, 100, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(205, 20, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(67, 80, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(68, 50, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 5, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 5, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Game_Flag_Query(380)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+	} else {
+		Scene_Loop_Set_Default(1);
+	}
+}
+
+void ScriptCT08::SceneLoaded() {
+	Obstacle_Object("ASHTRAY", 1);
+	Unobstacle_Object("BLANKET03", 1);
+	if (!Actor_Clue_Query(0, 85)) {
+		Item_Add_To_World(85, 943, 6, 44.0f, 0.0f, -95.0f, 540, 12, 12, 0, 1, 0, 1);
+	}
+	if (!Actor_Clue_Query(0, 87)) {
+		Item_Add_To_World(81, 936, 6, -102.0f, 2.0f, 41.0f, 432, 6, 6, 0, 1, 0, 1);
+	}
+}
+
+bool ScriptCT08::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT08::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptCT08::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT08::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 81) {
+		if (!Loop_Actor_Walk_To_Item(0, 81, 36, 1, 0) && !Game_Flag_Query(550)) {
+			Actor_Clue_Acquire(0, 87, 1, -1);
+			Item_Pickup_Spin_Effect(936, 266, 328);
+			Item_Remove_From_World(81);
+			Actor_Voice_Over(480, 99);
+			Actor_Voice_Over(490, 99);
+			Actor_Voice_Over(500, 99);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT08::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -183.0f, 0.0f, 128.0f, 0, 1, 0, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(81);
+			Set_Enter(31, 21);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -11.0f, 0.0f, -156.0f, 0, 1, 0, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 0.0f, 0.0f, -102.0f, 0, 0, 0, 0);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(379);
+			Set_Enter(6, 105);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -143.0f, 0.0f, -92.0f, 0, 1, 0, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(80);
+			Set_Enter(29, 18);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT08::ClickedOn2DRegion(int region) {
+	if (region == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -108.0f, 0.0f, -178.0f, 0, 1, 0, 0)) {
+			Actor_Face_Heading(0, 512, 0);
+			Game_Flag_Reset(550);
+			Player_Set_Combat_Mode_Access(1);
+			Scene_Exits_Enable();
+			Ambient_Sounds_Play_Sound(564, 40, 99, 0, 0);
+			Scene_2D_Region_Remove(0);
+			Player_Loses_Control();
+		}
+		return true;
+	}
+	return false;
+}
+
+void ScriptCT08::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptCT08::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT08::PlayerWalkedIn() {
+	if (Game_Flag_Query(550)) {
+		Actor_Change_Animation_Mode(0, 3);
+		Actor_Change_Animation_Mode(0, 0);
+		Actor_Set_At_XYZ(0, -148.0f, 0.0f, 4.0f, 256);
+		Player_Set_Combat_Mode_Access(0);
+		Scene_Exits_Disable();
+		Game_Flag_Reset(380);
+		Game_Flag_Reset(79);
+		Autosave_Game(1);
+	} else if (Game_Flag_Query(380)) {
+		Game_Flag_Reset(380);
+	} else if (Game_Flag_Query(79)) {
+		Game_Flag_Reset(79);
+	} else {
+		Loop_Actor_Walk_To_XYZ(0, -156.0f, 0.0f, 128.0f, 0, 0, 0, 0);
+		Game_Flag_Reset(84);
+	}
+}
+
+void ScriptCT08::PlayerWalkedOut() {
+	if (!Actor_Clue_Query(0, 85)) {
+		Item_Remove_From_World(85);
+	}
+}
+
+void ScriptCT08::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct09.cpp b/engines/bladerunner/script/ct09.cpp
new file mode 100644
index 0000000..0cc9910
--- /dev/null
+++ b/engines/bladerunner/script/ct09.cpp
@@ -0,0 +1,214 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT09::InitializeScene() {
+	if (Game_Flag_Query(85)) {
+		Setup_Scene_Information(160.0f, 349.0f, 587.0f, 490);
+	} else if (Game_Flag_Query(81)) {
+		Setup_Scene_Information(235.0f, 3348.52f, 599.0f, 800);
+	} else {
+		Setup_Scene_Information(107.0f, 348.52f, 927.0f, 200);
+	}
+	Scene_Exit_Add_2D_Exit(0, 321, 164, 345, 309, 1);
+	Scene_Exit_Add_2D_Exit(1, 0, 0, 15, 479, 3);
+	Scene_Exit_Add_2D_Exit(2, 198, 177, 263, 311, 0);
+	Ambient_Sounds_Add_Looping_Sound(336, 28, 0, 1);
+	Ambient_Sounds_Add_Sound(375, 6, 180, 33, 33, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 33, 33, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 33, 33, 0, 0, -101, -101, 0, 0);
+}
+
+void ScriptCT09::SceneLoaded() {
+	Obstacle_Object("PHONE01", true);
+	Unobstacle_Object("MAINBEAM01", true);
+	Unobstacle_Object("MIDDLE WALL", true);
+	Clickable_Object("BELL");
+}
+
+bool ScriptCT09::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT09::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("BELL", objectName)) {
+		if (Actor_Query_Which_Set_In(62) != 31) {
+			if (!Loop_Actor_Walk_To_XYZ(0, 229.0f, 348.52f, 851.0f, 36, 1, false, 0)) {
+				Actor_Face_Object(0, "BELL", true);
+				Sound_Play(337, 100, 0, 0, 50);
+				if (!Actor_Query_Goal_Number(27)) {
+					Actor_Says(27, 160, 3);
+				}
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT09::ClickedOnActor(int actorId) {
+	if (actorId == 27) {
+		if (!Actor_Query_Goal_Number(27) && Actor_Query_Which_Set_In(62) != 31) {
+			if (!Loop_Actor_Walk_To_XYZ(0, 270.0f, 348.52f, 846.0f, 12, 1, false, 0)) {
+				Player_Loses_Control();
+				Actor_Face_Actor(0, 27, true);
+				if (Global_Variable_Query(1) < 3) {
+					Actor_Says(0, 650, 3);
+					Actor_Says(27, 250, 12);
+					Actor_Says(0, 665, 18);
+				} else if (Game_Flag_Query(540)) {
+					Actor_Says(0, 650, 18);
+					Actor_Says(27, 220, 15);
+				} else {
+					Game_Flag_Set(540);
+					Actor_Says(27, 170, 13);
+					Actor_Says(0, 630, 12);
+					Actor_Says(27, 180, 14);
+					Actor_Says(0, 635, 3);
+					Actor_Says(27, 190, 15);
+					Actor_Says(0, 640, 12);
+					Actor_Says(0, 645, 3);
+					Actor_Says(27, 200, 13);
+					Actor_Says(27, 210, 14);
+				}
+				Player_Gains_Control();
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT09::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT09::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 206.0f, 348.52f, 599.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 235.0f, 348.52f, 599.0f, 0, 0, false, 0);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(84);
+			Set_Enter(6, 20);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 107.0f, 348.52f, 927.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(83);
+			Set_Enter(33, 23);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 159.0f, 349.0f, 570.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(82);
+			Set_Enter(32, 22);
+		}
+		return true;
+	}
+	return false;;
+}
+
+bool ScriptCT09::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT09::SceneFrameAdvanced(int frame) {
+	if (frame == 6 || frame == 12 || frame == 19 || frame == 25 || frame == 46 || frame == 59) {
+		Sound_Play(97, Random_Query(47, 47), 70, 70, 50);
+	}
+}
+
+void ScriptCT09::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT09::PlayerWalkedIn() {
+	bool v0 = false;
+	if (Global_Variable_Query(1) == 3 && !Game_Flag_Query(538)) {
+		Game_Flag_Set(538);
+		Actor_Set_Goal_Number(62, 1);
+		v0 = true;
+	}
+	if (Game_Flag_Query(85)) {
+		Game_Flag_Reset(85);
+	} else if (Game_Flag_Query(81)) {
+		if (v0) {
+			Async_Actor_Walk_To_XYZ(0, 206.0f, 348.52f, 599.0f, 0, false);
+		} else {
+			Loop_Actor_Walk_To_XYZ(0, 206.0f, 348.52f, 599.0f, 0, 0, false, 0);
+		}
+		Game_Flag_Reset(81);
+	} else {
+		if (v0) {
+			Async_Actor_Walk_To_XYZ(0, 124.0f, 348.52f, 886.0f, 0, false);
+		} else {
+			Loop_Actor_Walk_To_XYZ(0, 124.0f, 348.52f, 886.0f, 0, 0, false, 0);
+		}
+		Game_Flag_Reset(304);
+	}
+	if (Actor_Query_Goal_Number(27) == 2) {
+		if (Game_Flag_Query(539)) {
+			Actor_Says(27, 70, 13);
+			Actor_Face_Actor(0, 27, true);
+			Actor_Says(0, 600, 17);
+			Actor_Says(27, 80, 14);
+			Actor_Says(0, 605, 13);
+			Actor_Says(27, 90, 15);
+		} else {
+			Actor_Says(27, 20, 12);
+			Actor_Face_Actor(0, 27, true);
+			Actor_Says(0, 585, 18);
+			Actor_Says(27, 40, 15);
+			Actor_Says(0, 590, 16);
+			Actor_Says(27, 50, 14);
+			Actor_Says(0, 595, 14);
+			Actor_Says(27, 60, 13);
+			Actor_Modify_Friendliness_To_Other(27, 0, -1);
+		}
+		Actor_Set_Goal_Number(27, 0);
+	}
+}
+
+void ScriptCT09::PlayerWalkedOut() {
+}
+
+void ScriptCT09::DialogueQueueFlushed(int a1) {
+	Actor_Force_Stop_Walking(0);
+	if (Actor_Query_Goal_Number(62) == 1 && !Game_Flag_Query(539)) {
+		Player_Loses_Control();
+		Actor_Set_Goal_Number(62, 2);
+		//return true;
+	} else {
+		//return false;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct10.cpp b/engines/bladerunner/script/ct10.cpp
new file mode 100644
index 0000000..1781394
--- /dev/null
+++ b/engines/bladerunner/script/ct10.cpp
@@ -0,0 +1,160 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT10::InitializeScene() {
+	Setup_Scene_Information(-121.0f, 0.0f, -78.0f, 446);
+	Game_Flag_Reset(84);
+	Scene_Exit_Add_2D_Exit(0, 135, 74, 238, 340, 0);
+	Ambient_Sounds_Add_Looping_Sound(336, 28, 0, 1);
+	Ambient_Sounds_Add_Sound(375, 6, 180, 33, 33, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 5, 180, 33, 33, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 5, 180, 33, 33, 0, 0, -101, -101, 0, 0);
+}
+
+void ScriptCT10::SceneLoaded() {
+	Obstacle_Object("BED", true);
+	Unobstacle_Object("WINDOW", true);
+	Unobstacle_Object("LOFT01", true);
+	Unobstacle_Object("LOFT02", true);
+	Unobstacle_Object("LOFT03", true);
+	Unobstacle_Object("LOFT04", true);
+	Unobstacle_Object("LOFT05", true);
+	Unobstacle_Object("LOFT06", true);
+	Unobstacle_Object("LOFT10", true);
+	Unobstacle_Object("LOFT11", true);
+	Unobstacle_Object("LOFT12", true);
+	Unobstacle_Object("LINE02", true);
+	Unobstacle_Object("CABINETFRONT", true);
+	Unobstacle_Object("CABINTESIDE", true);
+	Unobstacle_Object("BUSTEDTAPE2", true);
+	Unobstacle_Object("BOX CLOSET 1", true);
+	Clickable_Object("BED");
+	Clickable_Object("CABINETFRONT");
+	Clickable_Object("CABINETTOP");
+	Clickable_Object("TUB");
+	Scene_2D_Region_Add(0, 379, 229, 454, 375);
+}
+
+bool ScriptCT10::MouseClick(int x, int y) {
+	return false;
+}
+
+void ScriptCT10::sub_401844() {
+	if (!Loop_Actor_Walk_To_XYZ(0, 10.6f, 0.0f, -50.5f, 0, 1, false, 0)) {
+		Player_Loses_Control();
+		Actor_Face_Heading(0, 0, false);
+		Sound_Play(339, 100, 0, 0, 50);
+		Delay(1000);
+		if (Actor_Clue_Query(0, 110)) {
+			Actor_Voice_Over(3700, 99);
+		} else {
+			Item_Pickup_Spin_Effect(931, 435, 258);
+			Actor_Clue_Acquire(0, 110, 1, -1);
+		}
+		Player_Gains_Control();
+	}
+}
+
+bool ScriptCT10::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("TUB", objectName)) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -41.0f, 0.0f, -106.0f, 0, 1, false, 0)) {
+			Player_Loses_Control();
+			Actor_Face_Heading(0, 850, false);
+			Actor_Change_Animation_Mode(0, 38);
+			Delay(1000);
+			Sound_Play(338, 33, 0, 0, 50);
+			Delay(3000);
+			if (Actor_Clue_Query(0, 93)) {
+				Actor_Voice_Over(3700, 99);
+			} else {
+				Actor_Clue_Acquire(0, 93, 1, -1);
+				Item_Pickup_Spin_Effect(969, 364, 214);
+			}
+			Delay(1000);
+			Loop_Actor_Walk_To_XYZ(0, -41.0f, 0.0f, -82.0f, 0, 0, false, 1);
+			Player_Gains_Control();
+		}
+		return true;
+	}
+	if (Object_Query_Click("CABINETTOP", objectName) || Object_Query_Click("CABINETFRONT", objectName)) {
+		sub_401844();
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT10::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT10::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT10::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -93.0f, 0.0f, -38.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, -121.0f, 0.0f, -78.0f, 0, 0, false, 0);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(85);
+			Set_Enter(31, 21);
+		}
+	}
+	return false;
+}
+
+bool ScriptCT10::ClickedOn2DRegion(int region) {
+	if (region == 0) {
+		sub_401844();
+	}
+	return false;
+}
+
+void ScriptCT10::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptCT10::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT10::PlayerWalkedIn() {
+	Loop_Actor_Walk_To_XYZ(0, -93.0f, 0.0f, -38.0f, 0, 0, false, 0);
+	Loop_Actor_Walk_To_XYZ(0, -49.0f, 0.0f, -38.0f, 0, 0, false, 0);
+	if (!Game_Flag_Query(525)) {
+		Actor_Voice_Over(450, 99);
+		Actor_Voice_Over(460, 99);
+		Actor_Voice_Over(470, 99);
+		Game_Flag_Set(525);
+	}
+}
+
+void ScriptCT10::PlayerWalkedOut() {
+}
+
+void ScriptCT10::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct11.cpp b/engines/bladerunner/script/ct11.cpp
new file mode 100644
index 0000000..3ef0bec
--- /dev/null
+++ b/engines/bladerunner/script/ct11.cpp
@@ -0,0 +1,213 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT11::InitializeScene() {
+	if (Game_Flag_Query(91)) {
+		Setup_Scene_Information(-378.0f, 9.68f, -55.0f, 440);
+	} else if (Game_Flag_Query(558)) {
+		Setup_Scene_Information(315.0f, 0.0f, 628.0f, 0);
+	} else {
+		Setup_Scene_Information(152.0f, 9.68f, -8.0f, 0);
+	}
+	Scene_Exit_Add_2D_Exit(0, 257, 240, 364, 330, 1);
+	Scene_Exit_Add_2D_Exit(1, 97, 0, 155, 324, 0);
+	Scene_Exit_Add_2D_Exit(2, 0, 0, 20, 479, 3);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 0, 1);
+	Ambient_Sounds_Add_Sound(67, 5, 80, 16, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(66, 5, 80, 16, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(378, 5, 80, 50, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 5, 80, 50, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 5, 80, 50, 100, -100, 100, -101, -101, 0, 0);
+	if (Global_Variable_Query(1) <= 3) {
+		Scene_Loop_Set_Default(0);
+	} else {
+		Scene_Loop_Set_Default(2);
+	}
+}
+
+void ScriptCT11::SceneLoaded() {
+	Obstacle_Object("TRASH CAN", true);
+	Unobstacle_Object("BOX NORTHWEST 1", true);
+	Unobstacle_Object("BOX SOUTH 1", true);
+	if (Global_Variable_Query(1) < 4) {
+		if (!Game_Flag_Query(645)) {
+			Item_Add_To_World(115, 951, 33, 640.21002f, 30.0f, 470.0f, 512, 12, 12, false, true, false, true);
+			Scene_2D_Region_Add(0, 505, 316, 513, 321);
+			Game_Flag_Set(725);
+		}
+		if (!Actor_Clue_Query(0, 111)) {
+			Scene_2D_Region_Add(1, 412, 258, 552, 358);
+		}
+	} else {
+		if (Game_Flag_Query(725)) {
+			Item_Remove_From_World(115);
+			Game_Flag_Reset(725);
+			Game_Flag_Set(645);
+		}
+		Unobstacle_Object("BRIDGE SUPPORT", true);
+		Unobstacle_Object("BODY", true);
+		Unobstacle_Object("HEADLIGHTS", true);
+		Unobstacle_Object("LICENSE PLATE-FRONT", true);
+		Unobstacle_Object("LICENSE PLATE-REAR", true);
+		Unobstacle_Object("BRAKE DISC RF", true);
+		Unobstacle_Object("TIRE RF", true);
+		Unobstacle_Object("RIM RF", true);
+		Unobstacle_Object("DOOR RIGHT", true);
+		Unobstacle_Object("BUMPER REAR", true);
+	}
+	Unclickable_Object("TRASH CAN");
+}
+
+bool ScriptCT11::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT11::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptCT11::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT11::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT11::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 121.0f, 9.6800003f, -42.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(304);
+			Set_Enter(31, 21);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -300.0f, 9.6800003f, 66.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, -400.0f, 9.6800003f, -70.0f, 0, 1, false, 0);
+			Game_Flag_Set(86);
+			Set_Enter(4, 24);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 290.0f, 0.0f, 635.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(531);
+			Game_Flag_Reset(176);
+			Game_Flag_Set(177);
+			Set_Enter(7, 25);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT11::ClickedOn2DRegion(int region) {
+	if (region == 0 && Game_Flag_Query(725)) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 686.0f, 0.0f, 658.0f, 12, 1, false, 0)) {
+			Actor_Face_Heading(0, 47, false);
+			Item_Remove_From_World(115);
+			Actor_Clue_Acquire(0, 118, 0, -1);
+			Item_Pickup_Spin_Effect(951, 510, 319);
+			Game_Flag_Reset(725);
+			Game_Flag_Set(645);
+			Actor_Voice_Over(550, 99);
+			Actor_Voice_Over(560, 99);
+			Actor_Voice_Over(570, 99);
+			Actor_Voice_Over(580, 99);
+		}
+		return true;
+	}
+	if (region == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 686.0f, 0.0f, 658.0f, 12, 1, false, 0)) {
+			Actor_Face_Heading(0, 47, false);
+			int temp = 0;
+			if (Actor_Clue_Query(0, 17)) {
+				temp = 1;
+			}
+			if (Actor_Clue_Query(0, 26)) {
+				++temp;
+			}
+			if (Actor_Clue_Query(0, 39)) {
+				++temp;
+			}
+			if (Actor_Clue_Query(0, 37)) {
+				temp += 2;
+			}
+			if (Actor_Clue_Query(0, 30)) {
+				temp += 2;
+			}
+			if (Actor_Clue_Query(0, 31)) {
+				temp += 2;
+			}
+			if (temp <= 2 || Actor_Clue_Query(0, 111)) {
+				Actor_Says(0, 8525, 12);
+			} else {
+				Actor_Voice_Over(510, 99);
+				Actor_Voice_Over(520, 99);
+				Actor_Voice_Over(530, 99);
+				Actor_Voice_Over(540, 99);
+				Actor_Clue_Acquire(0, 111, 0, -1);
+				Scene_2D_Region_Remove(1);
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+void ScriptCT11::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptCT11::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT11::PlayerWalkedIn() {
+	if (Game_Flag_Query(91)) {
+		Loop_Actor_Walk_To_XYZ(0, -358.0f, 9.68f, 32.0f, 0, 0, false, 0);
+		Game_Flag_Reset(91);
+	} else if (Game_Flag_Query(558)) {
+		Loop_Actor_Walk_To_XYZ(0, 329.0f, 0.0f, 617.0f, 0, 0, false, 0);
+		Game_Flag_Reset(558);
+	} else {
+		Player_Loses_Control();
+		Actor_Set_Immunity_To_Obstacles(0, true);
+		Loop_Actor_Walk_To_XYZ(0, 125.0f, 9.68f, 74.0f, 0, 0, false, 0);
+		Actor_Set_Immunity_To_Obstacles(0, false);
+		Player_Gains_Control();
+		Game_Flag_Reset(83);
+	}
+}
+
+void ScriptCT11::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptCT11::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct12.cpp b/engines/bladerunner/script/ct12.cpp
new file mode 100644
index 0000000..eabd25b
--- /dev/null
+++ b/engines/bladerunner/script/ct12.cpp
@@ -0,0 +1,284 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT12::InitializeScene() {
+	if (Game_Flag_Query(123)) {
+		Setup_Scene_Information(-419.0f, -6.5f, 696.0f, 616);
+	} else if (Game_Flag_Query(432)) {
+		Setup_Scene_Information(-292.0f, -6.5f, 990.0f, 827);
+		if (!Game_Flag_Query(150)) {
+			Game_Flag_Set(150);
+		}
+		Game_Flag_Reset(432);
+	} else if (Game_Flag_Query(86)) {
+		Setup_Scene_Information(-493.0f, -6.5f, 1174.0f, 990);
+	} else {
+		Setup_Scene_Information(-386.13f, -6.5f, 1132.72f, 783);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 0, 40, 479, 3);
+	Scene_Exit_Add_2D_Exit(1, 78, 224, 162, 330, 0);
+	Scene_Exit_Add_2D_Exit(2, 500, 180, 619, 346, 0);
+	if (Global_Variable_Query(1) > 2) {
+		Scene_Exit_Add_2D_Exit(3, 620, 0, 639, 479, 1);
+	}
+	if (Global_Variable_Query(1) > 3) {
+		Scene_Exit_Add_2D_Exit(4, 324, 150, 435, 340, 0);
+	}
+	Ambient_Sounds_Add_Looping_Sound(54, 33, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(55, 20, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(56, 20, -100, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(68, 60, 180, 20, 33, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 60, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 60, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 50, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 50, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Global_Variable_Query(1) < 2 && Actor_Query_Goal_Number(53) == 1) {
+		Actor_Put_In_Set(53, 4);
+		Actor_Set_At_XYZ(53, -534.0f, -6.5f, 952.0f, 367);
+		Game_Flag_Set(294);
+	}
+	if (Game_Flag_Query(123) && Game_Flag_Query(248)) {
+		if (Global_Variable_Query(1) != 2 && Global_Variable_Query(1) != 3) {
+			Scene_Loop_Start_Special(0, 1, 0);
+		}
+		Scene_Loop_Set_Default(2);
+		Game_Flag_Reset(123);
+	} else if (Game_Flag_Query(123) && !Game_Flag_Query(248)) {
+		if (Global_Variable_Query(1) != 2 && Global_Variable_Query(1) != 3) {
+			Scene_Loop_Start_Special(0, 0, 0);
+		}
+		Scene_Loop_Set_Default(2);
+		Game_Flag_Reset(123);
+	} else if (Game_Flag_Query(76) && Game_Flag_Query(294)) {
+		Game_Flag_Reset(76);
+		Scene_Loop_Set_Default(4);
+	} else if (Game_Flag_Query(76) && !Game_Flag_Query(294)) {
+		Game_Flag_Reset(76);
+		Scene_Loop_Set_Default(2);
+	} else {
+		Scene_Loop_Set_Default(2);
+
+	}
+}
+
+void ScriptCT12::SceneLoaded() {
+	Obstacle_Object("BOX18", true);
+	Unobstacle_Object("SPINNER BODY", true);
+	Unobstacle_Object("HOWFLOOR", true);
+	Unclickable_Object("TURBINE");
+}
+
+bool ScriptCT12::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptCT12::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptCT12::ClickedOnActor(int actorId) {
+	if (actorId == 28) {
+		Actor_Face_Actor(0, 28, true);
+		Actor_Says(0, 8910, 16);
+	}
+	if (actorId == 24 && Global_Variable_Query(1) == 4 && Game_Flag_Query(671) && Game_Flag_Query(703)) {
+		Actor_Face_Actor(24, 0, true);
+		Actor_Face_Actor(0, 24, true);
+		Actor_Says(0, 710, 3);
+		Actor_Says(24, 20, 3);
+		Actor_Says(0, 715, 3);
+		Actor_Says(24, 30, 3);
+		Actor_Says(0, 720, 3);
+		Actor_Says(24, 40, 3);
+		Actor_Says(24, 50, 3);
+		Actor_Says(24, 60, 3);
+		Actor_Says(0, 725, 3);
+		Actor_Says(24, 70, 3);
+		Actor_Says(24, 80, 3);
+		Actor_Says(24, 90, 3);
+		Actor_Says(24, 100, 3);
+		Actor_Says(24, 110, 3);
+		Game_Flag_Set(629);
+		Game_Flag_Set(666);
+		Actor_Set_Goal_Number(0, 400);
+	}
+	return false;
+}
+
+bool ScriptCT12::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptCT12::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -419.14999f, -6.5f, 696.94f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Game_Flag_Set(88);
+			Set_Enter(4, 13);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -182.69f, -6.5f, 696.94f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(89);
+			Set_Enter(5, 15);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -386.13f, -6.5f, 1132.72f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(90);
+			Set_Enter(28, 17);
+		}
+		return true;
+	}
+	if (exitId == 3) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -493.0f, -6.5f, 1174.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(91);
+			Set_Enter(33, 23);
+		}
+		return true;
+	}
+	if (exitId == 4) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -292.0f, -6.5f, 990.0f, 0, 1, false, 0)) {
+			if (Global_Variable_Query(1) == 4) {
+				Game_Flag_Set(629);
+			}
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(433);
+			Set_Enter(82, 94);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT12::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT12::SceneFrameAdvanced(int frame) {
+	if (!((frame - 1) % 10)) {
+		/*int v2 = Random_Query(0, 1);
+		if (v2 <= 1)
+		{
+			if (v2)
+			{
+				v1 = 60;
+			}
+			else
+			{
+				v1 = 59;
+			}
+		}*/
+		Sound_Play(/*v1*/Random_Query(59, 60), 10, -80, -80, 50);
+	}
+	if (frame == 160) {
+		Actor_Change_Animation_Mode(53, 41);
+	}
+	if (frame == 152) {
+		Sound_Play(116, 100, 40, 0, 50);
+	}
+	if (frame == 203) {
+		Sound_Play(119, 100, 40, 0, 50);
+	}
+	if (frame == 212) {
+		Sound_Play(117, 40, 0, 0, 50);
+	}
+	if (frame == 269) {
+		Player_Gains_Control();
+		Player_Set_Combat_Mode(false);
+		Actor_Set_Invisible(53, false);
+	}
+}
+
+void ScriptCT12::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT12::PlayerWalkedIn() {
+	if (Global_Variable_Query(1) < 2 && !Game_Flag_Query(64) && Actor_Query_Goal_Number(53) == 1) {
+		Player_Loses_Control();
+		Loop_Actor_Walk_To_Actor(53, 0, 48, 0, false);
+		Actor_Face_Actor(53, 0, true);
+		Actor_Face_Actor(0, 53, true);
+		Actor_Says(53, 0, 3);
+		Actor_Says(0, 670, 3);
+		Actor_Says(53, 10, 3);
+		Actor_Says(0, 675, 3);
+		Actor_Says(53, 20, 3);
+		Actor_Says(0, 680, 3);
+		Actor_Says(53, 30, 3);
+		Actor_Says(0, 685, 3);
+		Actor_Says(53, 40, 3);
+		Actor_Says(0, 690, 3);
+		Actor_Clue_Acquire(0, 33, 1, 53);
+		Game_Flag_Set(64);
+		CDB_Set_Crime(20, 8);
+		if (Game_Flag_Query(64) && Game_Flag_Query(40)) {
+			Actor_Says(53, 50, 3);
+			Actor_Says(0, 695, 3);
+			Actor_Says(53, 60, 3);
+			Actor_Says(0, 700, 3);
+			Actor_Says(53, 70, 3);
+			Actor_Clue_Acquire(53, 222, 1, -1);
+		} else if (Game_Flag_Query(64) && Game_Flag_Query(41)) {
+			Actor_Says(53, 80, 3);
+			Actor_Says(53, 90, 3);
+			Actor_Says(0, 705, 3);
+			Actor_Says(53, 100, 3);
+			Actor_Clue_Acquire(53, 215, 1, -1);
+		}
+		Actor_Set_Goal_Number(53, 2);
+	}
+	if (Game_Flag_Query(86)) {
+		Loop_Actor_Walk_To_XYZ(0, -520.0f, -6.5f, 1103.0f, 0, 0, false, 0);
+		Game_Flag_Reset(86);
+	}
+}
+
+void ScriptCT12::PlayerWalkedOut() {
+	Game_Flag_Reset(443);
+	if (Game_Flag_Query(433)) {
+		Game_Flag_Reset(176);
+		Game_Flag_Set(259);
+	}
+}
+
+void ScriptCT12::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ct51.cpp b/engines/bladerunner/script/ct51.cpp
new file mode 100644
index 0000000..bc47ddd
--- /dev/null
+++ b/engines/bladerunner/script/ct51.cpp
@@ -0,0 +1,129 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptCT51::InitializeScene() {
+	Setup_Scene_Information(0.0f, 0.0f, -102.0f, 470);
+	Game_Flag_Reset(379);
+	Scene_Exit_Add_2D_Exit(1, 0, 0, 30, 479, 3);
+	Ambient_Sounds_Add_Looping_Sound(381, 100, 1, 1);
+	Ambient_Sounds_Add_Sound(68, 60, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 60, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 60, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 50, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 50, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Scene_Loop_Start_Special(0, 0, 0);
+	Scene_Loop_Set_Default(1);
+}
+
+void ScriptCT51::SceneLoaded() {
+	Unobstacle_Object("BLANKET03", true);
+	Clickable_Object("BED02");
+	if (!Actor_Clue_Query(0, 85)) {
+		Item_Add_To_World(85, 943, 6, 44.0f, 0.0f, -95.0f, 540, 24, 24, false, true, false, true);
+	}
+	if (!Actor_Clue_Query(0, 86)) {
+		Item_Add_To_World(120, 984, 6, 44.0f, 0.0f, -22.0f, 0, 12, 12, false, true, false, true);
+	}
+}
+
+bool ScriptCT51::MouseClick(int x, int y) {
+	return true;
+}
+
+bool ScriptCT51::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("BED02", objectName)) {
+		if (Actor_Clue_Query(0, 84)) {
+			Actor_Says(0, 8580, 12);
+			return false;
+		}
+		Item_Pickup_Spin_Effect(970, 203, 200);
+		Actor_Clue_Acquire(0, 84, 1, -1);
+		Actor_Voice_Over(420, 99);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT51::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptCT51::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 85) {
+		Actor_Clue_Acquire(0, 85, 1, -1);
+		Item_Pickup_Spin_Effect(943, 260, 200);
+		Ambient_Sounds_Play_Sound(563, 40, 99, 0, 0);
+		Item_Remove_From_World(85);
+		return true;
+	}
+	if (itemId == 120) {
+		Actor_Clue_Acquire(0, 86, 1, -1);
+		Item_Pickup_Spin_Effect(984, 490, 307);
+		Item_Remove_From_World(120);
+		Actor_Says(0, 8527, 3);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptCT51::ClickedOnExit(int exitId) {
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 0.0f, 0.0f, -102.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, -11.0f, 0.0f, -156.0f, 0, 0, false, 0);
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(380);
+			Set_Enter(6, 20);
+		}
+		return true;
+	}
+	return false;
+
+}
+
+bool ScriptCT51::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptCT51::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptCT51::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptCT51::PlayerWalkedIn() {
+}
+
+void ScriptCT51::PlayerWalkedOut() {
+	if (!Actor_Clue_Query(0, 85)) {
+		Item_Remove_From_World(85);
+	}
+}
+
+void ScriptCT51::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/dr01.cpp b/engines/bladerunner/script/dr01.cpp
new file mode 100644
index 0000000..e8d89a2
--- /dev/null
+++ b/engines/bladerunner/script/dr01.cpp
@@ -0,0 +1,262 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptDR01::InitializeScene() {
+	if (Game_Flag_Query(225)) {
+		Setup_Scene_Information(-835.0f, -0.04f, -118.0f, 664);
+	} else if (Game_Flag_Query(11)) {
+		Setup_Scene_Information(-711.0f, -0.04f, 70.0f, 307);
+	} else if (Game_Flag_Query(531)) {
+		Setup_Scene_Information(-1765.28f, -0.04f, -23.82f, 269);
+	} else {
+		Setup_Scene_Information(-386.0f, -0.04f, -82.0f, 792);
+	}
+	Scene_Exit_Add_2D_Exit(0, 240, 60, 450, 250, 0);
+	Scene_Exit_Add_2D_Exit(1, 0, 0, 30, 479, 3);
+	if (Game_Flag_Query(253) && Global_Variable_Query(1) < 4) {
+		Scene_Exit_Add_2D_Exit(2, 610, 0, 639, 479, 1);
+	}
+	if (Global_Variable_Query(1) >= 3) {
+		Scene_Exit_Add_2D_Exit(3, 0, 45, 142, 201, 0);
+	}
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(0);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(219, 12, 85, 1);
+	Ambient_Sounds_Add_Looping_Sound(98, 14, 85, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(67, 5, 80, 16, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(66, 5, 80, 16, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(378, 5, 80, 50, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 5, 80, 50, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 5, 80, 50, 100, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(272) && Game_Flag_Query(11)) {
+		Scene_Loop_Start_Special(0, 3, 0);
+		Scene_Loop_Set_Default(4);
+	} else if (!Game_Flag_Query(272) && Game_Flag_Query(11)) {
+		Scene_Loop_Start_Special(0, 2, 0);
+		Scene_Loop_Set_Default(4);
+	} else if (Game_Flag_Query(225)) {
+		Scene_Loop_Start_Special(0, 1, 0);
+		Scene_Loop_Set_Default(4);
+	} else if (Game_Flag_Query(531) == 1) {
+		Scene_Loop_Set_Default(4);
+	} else {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(4);
+	}
+}
+
+void ScriptDR01::SceneLoaded() {
+	Obstacle_Object("TRASH CAN WITH FIRE", true);
+	Obstacle_Object("V2PYLON02", true);
+	Obstacle_Object("V2PYLON04", true);
+	Obstacle_Object("U2 CHEWDOOR", true);
+	Obstacle_Object("MMTRASHCAN", true);
+	Obstacle_Object("PARKMETR02", true);
+	Obstacle_Object("TRANSFORMER 01", true);
+	Obstacle_Object("TRANSFORMER 02", true);
+	Obstacle_Object("PARKMETR01", true);
+	Obstacle_Object("Z2TRSHCAN", true);
+	Obstacle_Object("Z2ENTRYDR", true);
+	Obstacle_Object("Z2DR2", true);
+	Unobstacle_Object("V2 BUILD01", true);
+}
+
+bool ScriptDR01::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptDR01::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptDR01::ClickedOnActor(int actorId) {
+	return actorId == 50;
+}
+
+bool ScriptDR01::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptDR01::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -835.0f, -0.04f, -118.0f, 0, 1, false, 0)) {
+			Async_Actor_Walk_To_XYZ(0, -911.0f, -0.04f, -118.0f, 0, false);
+			Ambient_Sounds_Adjust_Looping_Sound(112, 10, -100, 1);
+			Game_Flag_Set(224);
+			Set_Enter(7, 26);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -711.0f, -0.04f, 70.0f, 0, 1, false, 0)) {
+			Async_Actor_Walk_To_XYZ(0, -796.0f, -0.04f, 166.0f, 0, false);
+			Game_Flag_Set(10);
+			Set_Enter(7, 28);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (Loop_Actor_Walk_To_XYZ(0, -372.0f, -0.04f, -82.0f, 0, 1, false, 0)) {
+			Game_Flag_Reset(176);
+			Game_Flag_Reset(182);
+			Game_Flag_Reset(179);
+			Game_Flag_Reset(178);
+			Game_Flag_Reset(180);
+			Game_Flag_Reset(261);
+			Game_Flag_Reset(177);
+			Game_Flag_Reset(258);
+			int spinnerDest = Spinner_Interface_Choose_Dest(-1, 0);
+			switch (spinnerDest) {
+			case 2:
+				Game_Flag_Set(182);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(249);
+				Set_Enter(69, 78);
+				break;
+			case 3:
+				Game_Flag_Set(176);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(248);
+				Set_Enter(4, 13);
+				break;
+			case 1:
+				Game_Flag_Set(179);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(250);
+				Set_Enter(49, 48);
+				break;
+			case 0:
+				Game_Flag_Set(178);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(251);
+				Set_Enter(61, 65);
+				break;
+			case 5:
+				Game_Flag_Set(261);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(307);
+				Set_Enter(17, 82);
+				break;
+			case 4:
+				Game_Flag_Set(180);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(252);
+				Set_Enter(0, 0);
+				break;
+			case 7:
+				Game_Flag_Set(258);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(254);
+				Set_Enter(20, 2);
+				break;
+			case 8:
+				Game_Flag_Set(181);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(255);
+				Set_Enter(54, 54);
+				break;
+			case 9:
+				Game_Flag_Set(257);
+				Game_Flag_Reset(253);
+				Game_Flag_Set(256);
+				Set_Enter(37, 34);
+				break;
+			default:
+				Player_Loses_Control();
+				Game_Flag_Set(177);
+				Loop_Actor_Walk_To_XYZ(0, -447.39f, 0.16f, -92.38f, 0, 0, true, 0);
+				Player_Gains_Control();
+				break;
+			}
+		}
+		return true;
+	}
+
+	if (exitId == 3) {
+		float x, y, z;
+		Actor_Query_XYZ(0, &x, &y, &z);
+		bool v7 = false;
+		if (-1200 < x) {
+			v7 = Loop_Actor_Walk_To_XYZ(0, -1236.4f, -0.04f, -13.91f, 0, 1, false, 0);
+		}
+		if (!v7) {
+			Game_Flag_Set(558);
+			Game_Flag_Set(176);
+			Game_Flag_Reset(177);
+			Set_Enter(33, 23);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR01::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptDR01::SceneFrameAdvanced(int frame) {
+	if (frame < 75) {
+		Actor_Set_Invisible(0, true);
+	} else {
+		Actor_Set_Invisible(0, false);
+	}
+	if (frame == 2) {
+		Ambient_Sounds_Play_Sound(487, 40, -40, 100, 99);
+	}
+}
+
+void ScriptDR01::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptDR01::PlayerWalkedIn() {
+	if (Game_Flag_Query(531)) {
+		Async_Actor_Walk_To_XYZ(0, -757.15f, -0.04f, 24.64f, 0, false);
+	} else if (!Game_Flag_Query(225) && !Game_Flag_Query(11)) {
+		Player_Loses_Control();
+		Loop_Actor_Walk_To_XYZ(0, -447.39f, 0.16f, -92.38f, 0, 0, false, 0);
+		Player_Gains_Control();
+	}
+	Game_Flag_Reset(225);
+	Game_Flag_Reset(11);
+	Game_Flag_Reset(531);
+}
+
+void ScriptDR01::PlayerWalkedOut() {
+	if (!Game_Flag_Query(10) && !Game_Flag_Query(224) && !Game_Flag_Query(558)) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Outtake_Play(35, 1, -1);
+	}
+}
+
+void ScriptDR01::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/dr02.cpp b/engines/bladerunner/script/dr02.cpp
new file mode 100644
index 0000000..c075d80
--- /dev/null
+++ b/engines/bladerunner/script/dr02.cpp
@@ -0,0 +1,183 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptDR02::InitializeScene() {
+	if (Game_Flag_Query(227)) {
+		Setup_Scene_Information(-1162.0f, 7.18f, -322.0f, 552);
+	} else if (Game_Flag_Query(224)) {
+		Setup_Scene_Information(-835.0f, -0.04f, -118.0f, 193);
+	} else if (Game_Flag_Query(264)) {
+		Setup_Scene_Information(-1258.0f, 7.18f, -314.0f, 400);
+	} else {
+		Setup_Scene_Information(168.78f, 0.16f, -775.71997f, 193);
+	}
+	Scene_Exit_Add_2D_Exit(0, 605, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(1, 222, 176, 279, 314, 0);
+	if (Game_Flag_Query(326)) {
+		Scene_Exit_Add_2D_Exit(2, 95, 0, 148, 292, 0);
+	}
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(0);
+	Ambient_Sounds_Remove_All_Looping_Sounds(0);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(219, 27, 85, 1);
+	Ambient_Sounds_Add_Looping_Sound(98, 38, 85, 1);
+	Ambient_Sounds_Add_Sound(378, 2, 50, 33, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 2, 50, 33, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 2, 50, 33, 100, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(67, 5, 100, 16, 25, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(66, 5, 100, 16, 25, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(224)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+	} else {
+		Scene_Loop_Set_Default(1);
+	}
+}
+
+void ScriptDR02::SceneLoaded() {
+	Obstacle_Object("TRASH CAN WITH FIRE", true);
+	Obstacle_Object("V2PYLON02", true);
+	Obstacle_Object("V2PYLON04", true);
+	Obstacle_Object("U2 CHEWDOOR", true);
+	Obstacle_Object("MMTRASHCAN", true);
+	Obstacle_Object("PARKMETR02", true);
+	Obstacle_Object("TRANSFORMER 01", true);
+	Obstacle_Object("TRANSFORMER 02", true);
+	Obstacle_Object("PARKMETR01", true);
+	Obstacle_Object("Z2ENTRYDR", true);
+	Obstacle_Object("Z2DR2", true);
+	Clickable_Object("TRASH CAN WITH FIRE");
+	Clickable_Object("U2 CHEWDOOR");
+	Clickable_Object("MMTRASHCAN");
+	Clickable_Object("U2 EYE");
+	Clickable_Object("U2 E");
+	Clickable_Object("MMNEWSP01");
+	Clickable_Object("MMNEWSP01");
+	Clickable_Object("MMNEWSP04");
+	Clickable_Object("MMNEWSP05");
+	Clickable_Object("MMNEWSP07");
+	Clickable_Object("PARKMETR02");
+	Clickable_Object("TRANSFORMER 01");
+	Clickable_Object("TRANSFORMER 02");
+	Clickable_Object("V2CANPIPE02");
+	Unclickable_Object("TRASH CAN WITH FIRE");
+	Unclickable_Object("U2 CHEWDOOR");
+	Unclickable_Object("MMTRASHCAN");
+	Unclickable_Object("U2 EYE");
+	Unclickable_Object("U2 E");
+	Unclickable_Object("MMNEWSP01");
+	Unclickable_Object("MMNEWSP02");
+	Unclickable_Object("MMNEWSP04");
+	Unclickable_Object("MMNEWSP06");
+	Unclickable_Object("MMNEWSP07");
+	Unclickable_Object("PARKMETR02");
+	Unclickable_Object("TRANSFORMER 01");
+	Unclickable_Object("TRANSFORMER 02");
+	Unclickable_Object("V2CANPIPE02");
+}
+
+bool ScriptDR02::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptDR02::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptDR02::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptDR02::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptDR02::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -835.0f, -0.04f, -118.0f, 0, 1, false, 0)) {
+			Async_Actor_Walk_To_XYZ(0, -727.0f, -0.04f, -118.0f, 0, false);
+			Game_Flag_Set(225);
+			Set_Enter(7, 25);
+		}
+		Ambient_Sounds_Adjust_Looping_Sound(219, 12, -101, 1);
+		Ambient_Sounds_Adjust_Looping_Sound(98, 14, -101, 1);
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -1162.0f, 7.18f, -322.0f, 0, 1, false, 0)) {
+			if (Global_Variable_Query(1) > 2) {
+				Actor_Says(0, 8522, 15);
+			} else {
+				Game_Flag_Set(226);
+				Set_Enter(34, 27);
+			}
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -1258.0f, 7.18f, -314.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(265);
+			Game_Flag_Reset(177);
+			Game_Flag_Set(258);
+			Set_Enter(20, 2);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR02::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptDR02::SceneFrameAdvanced(int frame) {
+	if (frame == 1) {
+		Sound_Play(1, 10, 85, 85, 50);
+	}
+}
+
+void ScriptDR02::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptDR02::PlayerWalkedIn() {
+	if (Game_Flag_Query(227)) {
+		Game_Flag_Reset(227);
+	}
+	if (Game_Flag_Query(224)) {
+		Game_Flag_Reset(224);
+	}
+	if (Game_Flag_Query(264)) {
+		Game_Flag_Reset(264);
+	}
+}
+
+void ScriptDR02::PlayerWalkedOut() {
+}
+
+void ScriptDR02::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/dr03.cpp b/engines/bladerunner/script/dr03.cpp
new file mode 100644
index 0000000..cea23b7
--- /dev/null
+++ b/engines/bladerunner/script/dr03.cpp
@@ -0,0 +1,288 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptDR03::InitializeScene() {
+	if (Game_Flag_Query(226)) {
+		Game_Flag_Reset(226);
+		Setup_Scene_Information(330.31f, 4.27f, -910.91f, 297);
+	}
+	Setup_Scene_Information(330.31f, 4.27f, -910.91f, 297);
+	Scene_Exit_Add_2D_Exit(0, 377, 122, 445, 266, 0);
+	if (Global_Variable_Query(1) == 3) {
+		Actor_Put_In_Set(52, 34);
+		Actor_Set_At_XYZ(52, 431.21f, 4.27f, -776.26f, 0);
+	} else {
+		Actor_Put_In_Set(52, 34);
+		Actor_Set_At_XYZ(52, 360.77f, 4.4f, -806.67f, 126);
+	}
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+	Ambient_Sounds_Add_Looping_Sound(110, 7, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(109, 50, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(95, 20, 70, 1);
+}
+
+void ScriptDR03::SceneLoaded() {
+	Obstacle_Object("W2-CENTCASE02", 1);
+	Obstacle_Object("W2-CARTTOP", 1);
+	Obstacle_Object("W2-TANKAFLUID01", 1);
+}
+
+bool ScriptDR03::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptDR03::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptDR03::ClickedOnActor(int actorId) {
+	if (actorId == 52) {
+		Actor_Face_Actor(0, 52, 1);
+		Actor_Face_Actor(52, 0, 1);
+		if (!Game_Flag_Query(267)) {
+			Actor_Says(0, 755, 18);
+			Actor_Says(52, 10, 14);
+			Actor_Says(0, 760, 18);
+			Actor_Says(52, 20, 14);
+			Actor_Says(0, 765, 18);
+			Actor_Says(52, 30, 14);
+			Game_Flag_Set(267);
+			return true;
+		}
+		if (Actor_Clue_Query(0, 67)) {
+			if (Game_Flag_Query(266) && Game_Flag_Query(267)) {
+				Actor_Says(0, 815, 18);
+				Actor_Says(52, 60, 14);
+				Actor_Says(52, 70, 14);
+				Actor_Says(52, 80, 14);
+				Actor_Says(0, 820, 18);
+				Actor_Says(52, 90, 14);
+				Actor_Says(0, 825, 18);
+				Actor_Says(52, 100, 14);
+				Game_Flag_Reset(266);
+				Game_Flag_Set(505);
+				return true;
+			}
+			if ((Actor_Clue_Query(0, 147) || Actor_Clue_Query(0, 71) || Actor_Clue_Query(0, 76) || Actor_Clue_Query(0, 67))
+				&& Game_Flag_Query(505)) {
+				sub_401B18();
+			} else {
+				Actor_Says(0, 810, 18);
+				Actor_Says(52, 40, 14);
+				Actor_Says(52, 50, 14);
+			}
+			return true;
+		}
+		Actor_Says(0, 770, 12);
+		Actor_Says(52, 110, 12);
+		Actor_Says(52, 120, 13);
+		Actor_Says(0, 835, 13);
+		Actor_Says(52, 130, 14);
+		Actor_Says(0, 840, 16);
+		Actor_Says(52, 140, 15);
+		if (!Game_Flag_Query(505)) {
+			Actor_Says(52, 150, 13);
+			Actor_Says(0, 845, 17);
+			Actor_Says(52, 170, 18);
+			Actor_Says(52, 180, 16);
+			Actor_Says(0, 850, 15);
+			Actor_Says(52, 190, 14);
+			Actor_Says(52, 200, 13);
+			Actor_Says(0, 855, 18);
+			Actor_Says(52, 210, 12);
+		}
+		Actor_Clue_Acquire(0, 67, 1, 52);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR03::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptDR03::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 330.31f, 4.27f, -910.91f, 24, 1, 0, 0)) {
+			Game_Flag_Set(227);
+			Set_Enter(7, 26);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR03::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptDR03::SceneFrameAdvanced(int frame) {
+	if (frame == 1 || frame == 4 || frame == 8 || frame == 10 || frame == 19 || frame == 21 || frame == 22 || frame == 23 || frame == 30 || frame == 31 || frame == 32 || frame == 33 || frame == 46 || frame == 49) {
+		if (Random_Query(0, 1)) {
+			Sound_Play(97, Random_Query(20, 33), 80, 80, 50);
+		} else {
+			Sound_Play(59, Random_Query(5, 6), 80, 80, 50);
+		}
+	}
+}
+
+void ScriptDR03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptDR03::PlayerWalkedIn() {
+	if (!Game_Flag_Query(226)) {
+		if (Random_Query(1, 2) == 1) {
+			Actor_Says(52, 660, 14);
+			Actor_Says(52, 680, 14);
+		} else if (Random_Query(1, 2) == 2) {
+			Actor_Says(52, 670, 14);
+			Actor_Says(52, 620, 14);
+		} else {
+			Actor_Says(52, 690, 14);
+			Actor_Says(52, 710, 14);
+		}
+	}
+}
+
+void ScriptDR03::PlayerWalkedOut() {
+}
+
+void ScriptDR03::DialogueQueueFlushed(int a1) {
+}
+
+void ScriptDR03::sub_401B18() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 67) || Actor_Clue_Query(0, 71) || Actor_Clue_Query(0, 68)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(650, 5, 5, 5);
+	}
+	if (Actor_Clue_Query(0, 67)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(660, 5, 5, 5);
+	}
+	if (Actor_Clue_Query(0, 279)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(670, 6, 5, 2);
+	}
+	if (Game_Flag_Query(505)) {
+		if (Actor_Clue_Query(0, 71)) {
+			DM_Add_To_List_Never_Repeat_Once_Selected(680, 8, 8, 8);
+		}
+		if (Actor_Clue_Query(0, 76)) {
+			DM_Add_To_List_Never_Repeat_Once_Selected(1270, 2, 5, 7);
+		}
+	}
+	Dialogue_Menu_Add_DONE_To_List(690);
+	Dialogue_Menu_Appear(320, 240);
+	int answer = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answer) {
+	case 640:
+		Actor_Says(0, 770, 12);
+		Actor_Says(52, 110, 12);
+		Actor_Says(52, 120, 13);
+		Actor_Says(0, 835, 13);
+		Actor_Says(52, 130, 14);
+		Actor_Says(0, 840, 16);
+		Actor_Says(52, 140, 15);
+		if (!Game_Flag_Query(505)) {
+			Actor_Says(52, 150, 13);
+			Actor_Says(0, 845, 17);
+			Actor_Says(52, 170, 18);
+			Actor_Says(52, 180, 16);
+			Actor_Says(0, 850, 15);
+			Actor_Says(52, 190, 14);
+			Actor_Says(52, 200, 13);
+			Actor_Says(0, 855, 18);
+			Actor_Says(52, 210, 12);
+		}
+		Actor_Clue_Acquire(0, 67, 1, 52);
+		break;
+	case 650:
+		Actor_Says(0, 775, 11);
+		Actor_Says(52, 220, 14);
+		Actor_Says(0, 860, 11);
+		Actor_Says(52, 230, 14);
+		Actor_Says(0, 865, 11);
+		Actor_Says(52, 240, 14);
+		Actor_Says(52, 250, 14);
+		break;
+	case 660:
+		Actor_Says(0, 780, 13);
+		if (Game_Flag_Query(505)) {
+			Actor_Says(52, 260, 14);
+			Actor_Says(52, 270, 13);
+			Actor_Says(52, 280, 12);
+		} else {
+			Actor_Says(52, 260, 14);
+			Actor_Says(52, 270, 13);
+			Actor_Says(52, 280, 12);
+			Actor_Says(0, 870, 18);
+			Actor_Says(52, 290, 15);
+			if (!Game_Flag_Query(266)) {
+				Actor_Says(52, 300, 12);
+			}
+		}
+		Actor_Clue_Acquire(0, 67, 1, 52);
+		break;
+	case 670:
+		Actor_Says(0, 765, 12);
+		Actor_Says(0, 790, 13);
+		Actor_Says(52, 310, 12);
+		Actor_Says(52, 320, 3);
+		break;
+	case 680:
+		Actor_Says(0, 795, 3);
+		if (Game_Flag_Query(505) == 1) {
+			Actor_Says(52, 330, 12);
+			Actor_Says(52, 340, 15);
+			Actor_Says(0, 875, 16);
+			Actor_Says(52, 350, 12);
+			Actor_Says(52, 360, 15);
+			Game_Flag_Set(326);
+		} else {
+			Actor_Says(52, 320, 13);
+			Actor_Says(52, 150, 14);
+			Game_Flag_Set(326);
+		}
+		break;
+	case 1270:
+		Actor_Says(0, 800, 16);
+		Actor_Says(52, 370, 3);
+		Actor_Says(0, 880, 15);
+		Actor_Says(52, 380, 13);
+		Actor_Says(52, 390, 12);
+		Actor_Says(0, 885, 14);
+		Actor_Says(52, 400, 13);
+		Actor_Says(52, 410, 15);
+		Actor_Says(0, 890, 18);
+		Actor_Says(52, 420, 13);
+		Actor_Says(52, 430, 12);
+		break;
+	case 690:
+		Actor_Says(0, 805, 3);
+		break;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/dr04.cpp b/engines/bladerunner/script/dr04.cpp
new file mode 100644
index 0000000..1cef91b
--- /dev/null
+++ b/engines/bladerunner/script/dr04.cpp
@@ -0,0 +1,269 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptDR04::InitializeScene() {
+	if (Game_Flag_Query(515)) {
+		Setup_Scene_Information(0.0f, 0.0f, 0.0f, 0);
+	} else if (Game_Flag_Query(10)) {
+		Setup_Scene_Information(-711.0f, -0.04f, 70.0f, 472);
+	} else if (Game_Flag_Query(229)) {
+		Setup_Scene_Information(-1067.0f, 7.18f, 421.0f, 125);
+	} else if (Game_Flag_Query(231)) {
+		Setup_Scene_Information(-897.75f, 134.45f, 569.75f, 512);
+	} else {
+		Setup_Scene_Information(-810.0f, -0.04f, 242.0f, 125);
+	}
+	Scene_Exit_Add_2D_Exit(0, 589, 0, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(1, 443, 264, 488, 353, 0);
+	Scene_Exit_Add_2D_Exit(2, 222, 110, 269, 207, 0);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(0);
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 1, 1);
+	Ambient_Sounds_Add_Looping_Sound(288, 55, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(217, 28, -100, 100);
+	Ambient_Sounds_Add_Speech_Sound(60, 0, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 20, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 40, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Speech_Sound(60, 50, 10, 260, 17, 24, -100, 100, -101, -101, 1, 1);
+	Ambient_Sounds_Add_Sound(67, 40, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(66, 40, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(378, 5, 80, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(379, 5, 80, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(380, 5, 80, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Game_Flag_Query(272)) {
+		Scene_Loop_Set_Default(1);
+	} else {
+		Scene_Loop_Set_Default(4);
+	}
+	if (Game_Flag_Query(10)) {
+		if (Game_Flag_Query(272)) {
+			Scene_Loop_Start_Special(0, 0, 0);
+		} else {
+			Scene_Loop_Start_Special(0, 3, 0);
+		}
+	}
+}
+
+void ScriptDR04::SceneLoaded() {
+	Obstacle_Object("TRASH CAN WITH FIRE", true);
+	Obstacle_Object("V2PYLON02", true);
+	Obstacle_Object("V2PYLON04", true);
+	Obstacle_Object("U2 CHEWDOOR", true);
+	Obstacle_Object("MMTRASHCAN", true);
+	Obstacle_Object("PARKMETR02", true);
+	Obstacle_Object("TRANSFORMER 01", true);
+	Obstacle_Object("TRANSFORMER 02", true);
+	Obstacle_Object("PARKMETR01", true);
+	Obstacle_Object("Z2ENTRYDR", true);
+	Obstacle_Object("Z2DR2", true);
+	Unclickable_Object("PARKMETR01");
+	Unclickable_Object("Z2ENTRYDR");
+	Unclickable_Object("Z2DR2");
+}
+
+bool ScriptDR04::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptDR04::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptDR04::ClickedOnActor(int actorId) {
+	if (actorId == 35 && !Player_Query_Combat_Mode()) {
+		if (Actor_Query_Goal_Number(35) != 21) {
+			if (Actor_Query_Goal_Number(35) == 23) {
+				if (!Loop_Actor_Walk_To_Actor(0, 35, 36, 1, false)) {
+					Actor_Set_Goal_Number(24, 106);
+					return true;
+				}
+			}
+			return false;
+		}
+		if (!Loop_Actor_Walk_To_Waypoint(0, 109, 0, 1, true)) {
+			Actor_Face_Actor(0, 35, true);
+			Actor_Says(0, 945, 13);
+			Actor_Says(35, 0, 3);
+			Actor_Says(35, 10, 3);
+			Actor_Says(0, 950, 13);
+			Actor_Says(35, 20, 3);
+			Actor_Says(35, 30, 3);
+			Actor_Says(0, 955, 13);
+			Actor_Says_With_Pause(35, 40, 0, 3);
+			Actor_Says(35, 50, 3);
+			Actor_Clue_Acquire(0, 68, 1, 35);
+			Actor_Set_Goal_Number(35, 22);
+			Actor_Set_Goal_Number(24, 101);
+			return true;
+		}
+		return false;
+	}
+	return false;
+}
+
+bool ScriptDR04::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptDR04::ClickedOnExit(int exitId) {
+	if (Actor_Query_Goal_Number(35) == 21) {
+		Actor_Force_Stop_Walking(0);
+		Actor_Set_Goal_Number(35, 22);
+		Actor_Set_Goal_Number(24, 101);
+		return true;
+	}
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -761.0f, -0.04f, 97.0f, 0, 1, false, 0)) {
+			Async_Actor_Walk_To_XYZ(0, -683.0f, -0.04f, 43.0f, 0, false);
+			Game_Flag_Set(11);
+			Set_Enter(7, 25);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -1067.0f, 7.18f, 421.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(232);
+			Game_Flag_Set(228);
+			Set_Enter(35, 29);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -851.0f, 6.98f, 560.0f, 0, 1, false, 0)) {
+			Footstep_Sound_Override_On(3);
+			Actor_Set_Immunity_To_Obstacles(0, true);
+			Actor_Face_Heading(0, 512, false);
+			Loop_Actor_Travel_Stairs(0, 7, 1, 0);
+			Loop_Actor_Walk_To_XYZ(0, -899.0f, 71.64f, 647.0f, 0, 0, false, 0);
+			Actor_Face_Heading(0, 0, false);
+			Loop_Actor_Travel_Stairs(0, 7, 1, 0);
+			Actor_Set_Immunity_To_Obstacles(0, false);
+			Footstep_Sound_Override_Off();
+			Game_Flag_Set(230);
+			Set_Enter(36, 30);
+		}
+		return true;
+	}
+	return true; //bug?
+}
+
+bool ScriptDR04::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+bool ScriptDR04::sub_401160() {
+	float x, y, z;
+	Actor_Query_XYZ(0, &x, &y, &z);
+	return (x + 1089.94f) * (x + 1089.94f) + (z - 443.49f) * (z - 443.49f) >= (360.0f * 360.0f);
+}
+
+void ScriptDR04::SceneFrameAdvanced(int frame) {
+	if (Game_Flag_Query(515)) {
+		Game_Flag_Reset(515);
+		Game_Flag_Reset(271);
+		Scene_Loop_Set_Default(1);
+		Scene_Loop_Start_Special(2, 6, 1);
+		Music_Stop(4);
+		Actor_Set_Goal_Number(35, 99);
+	} else {
+		if (Game_Flag_Query(271)) {
+			Game_Flag_Reset(271);
+			Game_Flag_Set(272);
+			Scene_Loop_Set_Default(1);
+			Scene_Loop_Start_Special(2, 6, 1);
+			Item_Remove_From_World(78);
+		}
+		switch (frame) {
+		case 193:
+			Sound_Play(301, 100, 0, 100, 50);
+			Actor_Set_Goal_Number(35, 30);
+			Player_Loses_Control();
+			Actor_Force_Stop_Walking(0);
+			if (sub_401160()) {
+				if (Player_Query_Combat_Mode()) {
+					Actor_Change_Animation_Mode(0, 22);
+				} else {
+					Actor_Change_Animation_Mode(0, 21);
+				}
+			} else {
+				Sound_Play_Speech_Line(0, 9905, 100, 0, 99);
+				Actor_Change_Animation_Mode(0, 48);
+				Actor_Retired_Here(0, 6, 6, 1, -1);
+			}
+			Player_Gains_Control();
+			break;
+		case 235:
+			if (Actor_Query_Goal_Number(35) != 20 && Actor_Query_Goal_Number(35) != 21 && Actor_Query_Goal_Number(35) != 99) {
+				Actor_Set_Goal_Number(24, 101);
+			}
+			Scene_Exits_Enable();
+			break;
+		case 237:
+			Overlay_Play("DR04OVER", 0, 1, 1, 0);
+			break;
+		}
+	}
+}
+
+void ScriptDR04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptDR04::PlayerWalkedIn() {
+	if (Game_Flag_Query(515)) {
+		Player_Loses_Control();
+		Delay(4000);
+		Actor_Retired_Here(0, 6, 6, 1, -1);
+	} else {
+		if (Game_Flag_Query(269) && !Game_Flag_Query(272)) {
+			Scene_Exits_Disable();
+		}
+		if (Game_Flag_Query(231)) {
+			Footstep_Sound_Override_On(3);
+			Actor_Set_Immunity_To_Obstacles(0, true);
+			Actor_Face_Heading(0, 512, false);
+			Loop_Actor_Travel_Stairs(0, 7, 0, 0);
+			Loop_Actor_Walk_To_XYZ(0, -851.0f, 71.64f, 647.0f, 0, 0, false, 0);
+			Actor_Face_Heading(0, 0, false);
+			Loop_Actor_Travel_Stairs(0, 7, 0, 0);
+			Loop_Actor_Walk_To_XYZ(0, -774.85f, 7.18f, 386.67001f, 0, 0, false, 0);
+			Actor_Set_Immunity_To_Obstacles(0, false);
+			Footstep_Sound_Override_Off();
+		}
+	}
+	Game_Flag_Reset(10);
+	Game_Flag_Reset(229);
+	Game_Flag_Reset(231);
+}
+
+void ScriptDR04::PlayerWalkedOut() {
+	Music_Stop(2);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptDR04::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/dr05.cpp b/engines/bladerunner/script/dr05.cpp
new file mode 100644
index 0000000..c7beafe
--- /dev/null
+++ b/engines/bladerunner/script/dr05.cpp
@@ -0,0 +1,189 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptDR05::InitializeScene() {
+	Setup_Scene_Information(-22.0f, 0.3f, 221.0f, 0);
+	Game_Flag_Reset(228);
+	Scene_Exit_Add_2D_Exit(0, 0, 38, 80, 467, 3);
+	Ambient_Sounds_Add_Looping_Sound(383, 25, 0, 1);
+	if (!Game_Flag_Query(272)) {
+		Overlay_Play("DR05OVER", 0, 1, 0, 0);
+	}
+	if (Game_Flag_Query(272)) {
+		Scene_Loop_Set_Default(2);
+	} else {
+		Scene_Loop_Set_Default(0);
+	}
+}
+
+void ScriptDR05::SceneLoaded() {
+	Obstacle_Object("MAN PROPHI", true);
+	Unobstacle_Object("BOX06", true);
+	Unobstacle_Object("BOX183", true);
+	Clickable_Object("T2 DOORWAY");
+	if (!Game_Flag_Query(272)) {
+		Item_Add_To_World(78, 932, 35, -1.57f, 31.33f, 75.21f, 540, 16, 16, true, true, false, true);
+		if (!Actor_Query_Goal_Number(35)) {
+			Item_Add_To_World(122, 931, 35, 37.35f, 1.59f, 46.72f, 0, 20, 20, true, true, false, true);
+		}
+	}
+}
+
+bool ScriptDR05::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptDR05::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("T2 DOORWAY", objectName)) {
+		if (Game_Flag_Query(276) || Actor_Query_Goal_Number(35)) {
+			if (!Loop_Actor_Walk_To_XYZ(0, 57.61f, 0.3f, 69.27f, 0, 1, false, 0)) {
+				Actor_Face_Object(0, "T2 DOORWAY", true);
+				Actor_Says(0, 8522, 13);
+				Actor_Says(0, 8521, 14);
+			}
+		} else {
+			Actor_Face_Object(0, "T2 DOORWAY", true);
+			Actor_Says(0, 1020, 14);
+			Actor_Says(35, 90, 13);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR05::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptDR05::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 78) {
+		if (Player_Query_Combat_Mode()) {
+			Game_Flag_Set(271);
+			Actor_Set_Goal_Number(35, 30);
+		} else if (!Game_Flag_Query(272) && !Loop_Actor_Walk_To_Item(0, 78, 24, 1, true) && Actor_Query_Goal_Number(35) != 11) {
+			if (!Actor_Query_Goal_Number(35)) {
+				Actor_Says_With_Pause(0, 1015, 0.1f, 12);
+				Actor_Says(35, 70, 13);
+			}
+			Actor_Set_Goal_Number(35, 30);
+		}
+		//return true; //bug?
+	}
+	if (itemId == 122 && Player_Query_Combat_Mode() && !Actor_Query_Goal_Number(35)) {
+		Overlay_Play("DR05OVER", 1, 0, 1, 0);
+		Item_Remove_From_World(122);
+		Game_Flag_Set(270);
+		Actor_Set_Goal_Number(35, 10);
+		Music_Play(18, 71, 0, 0, -1, 0, 2);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR05::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -22.0f, 0.3f, 221.0f, 0, 1, false, 0)) {
+			Game_Flag_Reset(232);
+			Game_Flag_Set(229);
+			Set_Enter(7, 28);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR05::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptDR05::SceneFrameAdvanced(int frame) {
+	if (frame == 49) {
+		Sound_Play(148, Random_Query(50, 50), 80, 80, 50);
+	}
+	if (Game_Flag_Query(271)) {
+		Item_Remove_From_World(78);
+		Game_Flag_Reset(271);
+		Game_Flag_Set(272);
+		Actor_Set_Goal_Number(35, 30);
+	}
+}
+
+void ScriptDR05::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptDR05::PlayerWalkedIn() {
+	if (!Game_Flag_Query(511) && !Game_Flag_Query(270) && Game_Flag_Query(272)) {
+		Item_Remove_From_World(122);
+	}
+	if (Game_Flag_Query(272)) {
+		Loop_Actor_Walk_To_XYZ(0, -10.0f, 0.3f, 133.0f, 0, 0, false, 0);
+		if (!Game_Flag_Query(511)) {
+			Game_Flag_Set(511);
+			if (Game_Flag_Query(48)) {
+				Actor_Voice_Over(730, 99);
+				Actor_Voice_Over(740, 99);
+				Actor_Voice_Over(750, 99);
+				Actor_Voice_Over(760, 99);
+				Actor_Clue_Acquire(0, 269, 1, -1);
+			} else {
+				Actor_Voice_Over(670, 99);
+				Actor_Voice_Over(680, 99);
+				Actor_Voice_Over(700, 99);
+				Actor_Voice_Over(710, 99);
+				Actor_Voice_Over(720, 99);
+				Actor_Clue_Acquire(0, 270, 1, -1);
+			}
+		}
+	} else {
+		Loop_Actor_Walk_To_XYZ(0, -10.0f, 0.3f, 133.0f, 0, 0, true, 0);
+	}
+	if (!Game_Flag_Query(274) && !Actor_Query_Goal_Number(35)) {
+		Actor_Face_Actor(0, 35, true);
+		Actor_Says(0, 1010, 13);
+		Actor_Face_Item(0, 78, true);
+		Player_Set_Combat_Mode(true);
+		Actor_Says(35, 60, 12);
+		Actor_Change_Animation_Mode(0, 0);
+		Game_Flag_Set(274);
+		//return true;
+	}
+	//return false;
+}
+
+void ScriptDR05::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+	if (Actor_Query_Goal_Number(35) == 10 || Actor_Query_Goal_Number(35) == 18 || Actor_Query_Goal_Number(35) == 19) {
+		Actor_Set_Goal_Number(35, 11);
+		//return true;
+	}
+	//return false;
+}
+
+void ScriptDR05::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/dr06.cpp b/engines/bladerunner/script/dr06.cpp
new file mode 100644
index 0000000..ebaa832
--- /dev/null
+++ b/engines/bladerunner/script/dr06.cpp
@@ -0,0 +1,225 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptDR06::InitializeScene() {
+	if (Game_Flag_Query(230)) {
+		Setup_Scene_Information(-733.57001f, 136.60001f, -968.64001f, 0);
+	} else {
+		Setup_Scene_Information(-707.57001f, 136.60001f, -1132.64f, 472);
+	}
+	Scene_Exit_Add_2D_Exit(0, 601, 11, 639, 479, 1);
+	if (Global_Variable_Query(1) > 3 && Game_Flag_Query(715)) {
+		Scene_Exit_Add_2D_Exit(1, 0, 272, 46, 477, 2);
+	}
+	Ambient_Sounds_Add_Looping_Sound(383, 25, 0, 1);
+	Ambient_Sounds_Add_Sound(73, 5, 60, 20, 20, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(74, 5, 60, 20, 20, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(268)) {
+		Overlay_Play("DR06over", 1, 1, 0, 0);
+		Ambient_Sounds_Add_Looping_Sound(300, 47, -75, 0);
+	} else {
+		Overlay_Play("DR06over", 0, 1, 0, 0);
+	}
+	if (Game_Flag_Query(548)) {
+		Overlay_Play("DR06ovr2", 0, 1, 0, 0);
+	}
+}
+
+void ScriptDR06::SceneLoaded() {
+	Obstacle_Object("X2_ASHTRAY", true);
+	Clickable_Object("X2_ASHTRAY");
+	Clickable_Object("X2KEYBRD02");
+	Clickable_Object("X2_MON01D01");
+	Clickable_Object("X2_MON01A04");
+	Clickable_Object("X2_TORSO04HIRES");
+	Clickable_Object("BOX16");
+	if (Actor_Clue_Query(0, 76)) {
+		Unclickable_Object("X2_TORSO04HIRES");
+	}
+}
+
+bool ScriptDR06::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptDR06::ClickedOn3DObject(const char *objectName, bool a2) {
+	if (Object_Query_Click("BOX16", objectName)) {
+		Loop_Actor_Walk_To_XYZ(0, -743.0f, 136.6f, -1091.0f, 0, 1, false, 0);
+		Actor_Face_Object(0, "BOX16", true);
+		if (!Game_Flag_Query(268)) {
+			Overlay_Play("DR06over", 1, 1, 1, 0);
+			Ambient_Sounds_Add_Looping_Sound(300, 47, -75, 0);
+			Game_Flag_Set(268);
+			return true;
+		}
+		Overlay_Play("DR06over", 0, 1, 1, 0);
+		Ambient_Sounds_Remove_Looping_Sound(300, false);
+		Game_Flag_Reset(268);
+		return true;
+	}
+	if (Object_Query_Click("X2_MON01A04", objectName)) {
+		if (Actor_Clue_Query(0, 71)) {
+			Actor_Face_Object(0, "X2_MON01A04", true);
+			Actor_Says(0, 8570, 13);
+		} else if (!Loop_Actor_Walk_To_XYZ(0, -684.94f, 136.6f, -1136.12f, 0, 1, false, 0)) {
+			Actor_Face_Object(0, "X2_MON01A04", true);
+			Actor_Says(39, 10, 3);
+			Actor_Says(39, 20, 3);
+			Actor_Says(39, 30, 3);
+			Actor_Says(0, 1025, 13);
+			Actor_Says(56, 0, 3);
+			Actor_Says(56, 10, 3);
+			Actor_Says(56, 20, 3);
+			Actor_Says(56, 30, 3);
+			Actor_Says(56, 40, 3);
+			Actor_Says(56, 50, 3);
+			Actor_Says(39, 40, 3);
+			Actor_Says(0, 1030, 13);
+			Actor_Says(39, 50, 3);
+			Actor_Clue_Acquire(0, 71, 1, 39);
+		}
+		return true;
+	}
+	if (Object_Query_Click("X2_MON01D01", objectName)) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -645.34f, 136.6f, -1047.37f, 0, 1, false, 0)) {
+			Actor_Face_Heading(0, 329, false);
+			if (Actor_Clue_Query(0, 125) && Actor_Clue_Query(0, 126) && !Game_Flag_Query(670)) {
+				Actor_Set_Goal_Number(0, 350);
+				Game_Flag_Set(670);
+			} else if (Game_Flag_Query(280)) {
+				Actor_Says(0, 8570, 13);
+			} else {
+				Actor_Voice_Over(770, 99);
+				Actor_Voice_Over(780, 99);
+				Actor_Voice_Over(790, 99);
+				Actor_Voice_Over(800, 99);
+				Game_Flag_Set(280);
+			}
+		}
+		return true;
+	}
+	if (Object_Query_Click("X2_KEYBRD02", objectName) && !Game_Flag_Query(278)) {
+		Loop_Actor_Walk_To_XYZ(0, -655.57f, 136.6f, -1092.64f, 0, 1, false, 0);
+		Actor_Face_Object(0, "X2_KEYBRD02", true);
+		Actor_Voice_Over(830, 99);
+		Actor_Voice_Over(840, 99);
+		Game_Flag_Set(278);
+		return true;
+	}
+	if (Object_Query_Click("X2_TORSO04HIRES", objectName)) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -700.0f, 136.6f, -1133.0f, 4, 1, false, 0)) {
+			Actor_Face_Object(0, "x2_TORSO04HIRES", true);
+			if (Global_Variable_Query(39) > 12) {
+				return true;
+			}
+			if (Game_Flag_Query(548)) {
+				Overlay_Remove("DR06ovr2");
+				Game_Flag_Reset(548);
+				Sound_Play(161, 100, 0, 0, 50);
+			} else {
+				Overlay_Play("DR06ovr2", 0, 1, 0, 0);
+				Game_Flag_Set(548);
+				Sound_Play(160, 100, 0, 0, 50);
+				if (!Actor_Clue_Query(0, 76)) {
+					Actor_Voice_Over(850, 99);
+					Item_Pickup_Spin_Effect(944, 171, 280);
+					Actor_Voice_Over(860, 99);
+					Actor_Voice_Over(870, 99);
+					Actor_Voice_Over(880, 99);
+					Actor_Clue_Acquire(0, 76, 1, 13);
+					if (Query_Difficulty_Level()) {
+						Global_Variable_Increment(2, 200);
+					}
+				}
+			}
+			Global_Variable_Increment(39, 1);
+			if (Global_Variable_Query(39) > 12) {
+				Sound_Play(204, 100, 0, 0, 50);
+				Unclickable_Object("X2_TORSO04HIRES");
+			}
+		}
+		return true;
+	}
+	Actor_Face_Object(0, "X2_MON01D01", true);
+	Actor_Says(0, 8525, 13);
+	return true;
+}
+
+bool ScriptDR06::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptDR06::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptDR06::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -733.0f, 136.6f, -980.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(231);
+			Set_Enter(7, 28);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -707.57f, 136.6f, -1132.64f, 0, 1, false, 0)) {
+			Game_Flag_Set(552);
+			Set_Enter(19, 100);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptDR06::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptDR06::SceneFrameAdvanced(int frame) {
+
+}
+
+void ScriptDR06::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptDR06::PlayerWalkedIn() {
+	if (Game_Flag_Query(230)) {
+		Loop_Actor_Walk_To_XYZ(0, -729.57f, 136.6f, -1016.0f, 0, 0, false, 0);
+	}
+	Game_Flag_Reset(230);
+	Game_Flag_Reset(551);
+}
+
+void ScriptDR06::PlayerWalkedOut() {
+	Overlay_Remove("DR06over");
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(0);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptDR06::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/esper.cpp b/engines/bladerunner/script/esper.cpp
new file mode 100644
index 0000000..778542f
--- /dev/null
+++ b/engines/bladerunner/script/esper.cpp
@@ -0,0 +1,385 @@
+/* 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 "bladerunner/script/esper.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+void ScriptESPER::SCRIPT_ESPER_DLL_Initialize() {
+	int v0 = 0;
+	if (Actor_Clue_Query(0, 12)) {
+		if (!Actor_Clue_Query(0, 28)) {
+			Actor_Says(39, 160, 3);
+			Actor_Says(39, 180, 3);
+			Actor_Clue_Acquire(0, 28, 1, 15);
+			v0 = 1;
+		}
+		ESPER_Add_Photo("RC02_FA.IMG", 0, 0);
+		if (!Actor_Clue_Query(0, 29)) {
+			Actor_Clue_Acquire(0, 29, 1, 15);
+		}
+		ESPER_Add_Photo("RC02_FA.IMG", 1, 1);
+	}
+	if (Actor_Clue_Query(0, 89)) {
+		if (!Actor_Clue_Query(0, 245)) {
+			Actor_Says(39, 160, 3);
+			Actor_Says(39, 170, 3);
+			Actor_Clue_Acquire(0, 245, 1, -1);
+			v0 = 1;
+		}
+		ESPER_Add_Photo("NR060000.IMG", 2, 2);
+	}
+	if (Actor_Clue_Query(0, 88)) {
+		ESPER_Add_Photo("NR070000.IMG", 3, 3);
+	}
+	if (Actor_Clue_Query(0, 246)) {
+		ESPER_Add_Photo("HC01AR11.IMG", 4, 4);
+	}
+	if (Actor_Clue_Query(0, 247)) {
+		ESPER_Add_Photo("HC01AR12.IMG", 5, 5);
+	}
+	if (Actor_Clue_Query(0, 260)) {
+		ESPER_Add_Photo("HC02CB1.IMG", 6, 6);
+	}
+	if (Actor_Clue_Query(0, 257)) {
+		if (!Actor_Clue_Query(0, 78)) {
+			Actor_Says(39, 160, 3);
+			Actor_Says(39, 170, 3);
+			Actor_Clue_Acquire(0, 78, 1, 32);
+			v0 = 1;
+		}
+		ESPER_Add_Photo("HC02CB2.IMG", 7, 7);
+	}
+	if (Actor_Clue_Query(0, 45)) {
+		if (!Actor_Clue_Query(0, 259)) {
+			Actor_Says(39, 160, 3);
+			Actor_Says(39, 170, 3);
+			Actor_Clue_Acquire(0, 259, 1, 17);
+			v0 = 1;
+		}
+		ESPER_Add_Photo("TB060000.IMG", 8, 8);
+	}
+	if (Actor_Clue_Query(0, 86)) {
+		ESPER_Add_Photo("KP06.IMG", 9, 9);
+	}
+	if (v0) {
+		Actor_Says(39, 200, 3);
+	}
+}
+
+void ScriptESPER::SCRIPT_ESPER_DLL_Photo_Selected(int photo) {
+	switch (photo) {
+	case 9:
+		Actor_Says(39, 270, 3);
+		ESPER_Define_Special_Region(22, 1208, 330, 1218, 340, 1050, 160, 1279, 550, 956, 203, 1278, 497, "KP06ESP1");
+		ESPER_Define_Special_Region(23, 854, 371, 858, 375, 790, 320, 940, 560, 722, 220, 1000, 505, "KP06ESP2");
+		ESPER_Define_Special_Region(24, 615, 325, 648, 365, 440, 220, 820, 959, 326, 140, 948, 474, "KP06ESP3");
+		ESPER_Define_Special_Region(25, 373, 417, 382, 426, 310, 370, 480, 560, 228, 323, 493, 509, "KP06ESP4");
+		break;
+	case 8:
+		Actor_Says(39, 230, 3);
+		ESPER_Define_Special_Region(18, 166, 623, 177, 632, 38, 528, 320, 770, 26, 530, 313, 771, "TB06ESP1");
+		ESPER_Define_Special_Region(19, 156, 356, 164, 360, 60, 280, 250, 460, 14, 251, 257, 459, "TB06ESP2");
+		ESPER_Define_Special_Region(20, 395, 158, 410, 185, 270, 70, 760, 640, 125, 0, 560, 307, "TB06ESP3");
+		ESPER_Define_Special_Region(21, 343, 269, 352, 276, 290, 200, 410, 340, 157, 118, 565, 405, "TB06ESP4");
+		break;
+	case 7:
+		Actor_Says(39, 250, 3);
+		ESPER_Define_Special_Region(16, 1171, 457, 1184, 466, 1060, 370, 1279, 730, 910, 300, 1279, 678, "HC02ESP3");
+		ESPER_Define_Special_Region(17, 328, 398, 340, 413, 250, 350, 460, 640, 100, 236, 530, 612, "HC02ESP4");
+		break;
+	case 6:
+		Actor_Says(39, 250, 3);
+		ESPER_Define_Special_Region(14, 879, 221, 882, 225, 640, 0, 1000, 512, 265, 146, 1014, 813, "HC02ESP5");
+		ESPER_Define_Special_Region(15, 660, 550, 678, 572, 560, 480, 850, 910, 265, 146, 1014, 813, "HC02ESP2");
+		break;
+	case 5:
+		Actor_Says(39, 240, 3);
+		ESPER_Define_Special_Region(13, 720, 485, 728, 491, 640, 390, 780, 630, 257, 94, 1013, 804, "HC01ESP3");
+		break;
+	case 4:
+		Actor_Says(39, 240, 3);
+		ESPER_Define_Special_Region(11, 420, 436, 434, 450, 350, 380, 520, 680, 257, 94, 1013, 804, "HC01ESP1");
+		ESPER_Define_Special_Region(12, 407, 489, 410, 509, 370, 450, 500, 560, 257, 94, 1013, 804, "HC01ESP2");
+		break;
+	case 3:
+		Actor_Says(39, 260, 3);
+		ESPER_Define_Special_Region(10, 893, 298, 901, 306, 770, 230, 980, 500, 340, 216, 942, 747, "NR07ESP1");
+		ESPER_Define_Special_Region(9, 479, 381, 482, 385, 430, 320, 520, 470, 265, 200, 815, 720, "NR07ESP2");
+		break;
+	case 2:
+		Actor_Says(39, 260, 3);
+		ESPER_Define_Special_Region(7, 102, 809, 108, 861, 20, 720, 200, 930, 191, 95, 1085, 870, "NR06ESP1");
+		ESPER_Define_Special_Region(8, 661, 437, 664, 443, 530, 320, 720, 600, 330, 200, 945, 750, "NR06ESP2");
+		break;
+	case 1:
+		Actor_Says(39, 220, 3);
+		ESPER_Define_Special_Region(3, 560, 210, 580, 220, 450, 130, 680, 540, 0, 0, 1279, 959, "RC02ESP4");
+		ESPER_Define_Special_Region(4, 584, 482, 595, 493, 460, 400, 660, 540, 0, 0, 1279, 959, "RC02ESP5");
+		ESPER_Define_Special_Region(5, 669, 322, 675, 329, 620, 230, 740, 390, 0, 0, 1279, 959, "RC02ESP6");
+		ESPER_Define_Special_Region(6, 698, 236, 748, 274, 600, 160, 850, 420, 160, 0, 1279, 750, "RC02ESP7");
+		break;
+	case 0:
+		Actor_Says(39, 220, 3);
+		ESPER_Define_Special_Region(0, 490, 511, 496, 517, 400, 440, 580, 580, 380, 260, 900, 710, "RC02ESP1");
+		ESPER_Define_Special_Region(1, 473, 342, 479, 349, 400, 300, 580, 580, 350, 250, 900, 710, "RC02ESP2");
+		ESPER_Define_Special_Region(2, 444, 215, 461, 223, 380, 120, 570, 340, 354, 160, 577, 354, "RC02ESP3");
+		break;
+	default:
+		return;
+	}
+}
+
+bool ScriptESPER::SCRIPT_ESPER_DLL_Special_Region_Selected(int photo, int region) {
+	switch (photo) {
+	case 9:
+		switch (region) {
+		case 22:
+			Actor_Says(0, 8705, 3);
+			if (!Actor_Clue_Query(0, 274)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 274, 1, -1);
+			}
+			break;
+		case 23:
+			Actor_Voice_Over(4240, 99);
+			if (!Actor_Clue_Query(0, 275)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 275, 1, -1);
+			}
+			break;
+		case 24:
+			Actor_Voice_Over(4220, 99);
+			if (!Actor_Clue_Query(0, 276)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 276, 1, -1);
+			}
+			break;
+		case 25:
+			if (!Actor_Clue_Query(0, 277)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 277, 1, -1);
+			}
+			break;
+		}
+		return false;
+	case 8:
+		switch (region) {
+		case 18:
+			Actor_Says(0, 8775, 3);
+			if (!Actor_Clue_Query(0, 263)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 263, 1, -1);
+			}
+			break;
+		case 19:
+			Actor_Voice_Over(4160, 99);
+			if (!Actor_Clue_Query(0, 262)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 262, 1, -1);
+			}
+			break;
+		case 20:
+			Actor_Voice_Over(2140, 99);
+			Actor_Voice_Over(2150, 99);
+			Actor_Voice_Over(2160, 99);
+			if (!Actor_Clue_Query(0, 47)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 47, 1, -1);
+			}
+			break;
+		case 21:
+			Actor_Says(0, 8890, 3);
+			if (!Actor_Clue_Query(0, 261)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 261, 1, -1);
+			}
+			break;
+		}
+		return false;
+	case 7:
+		if (region == 16) {
+			Actor_Voice_Over(4080, 99);
+			if (!Actor_Clue_Query(0, 255)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 255, 1, -1);
+			}
+		} else if (region == 17) {
+			Actor_Voice_Over(4210, 99);
+			if (!Actor_Clue_Query(0, 256)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 256, 1, -1);
+			}
+		}
+		return false;
+	case 6:
+		if (region == 14) {
+			Actor_Says(0, 6975, 3);
+			if (!Actor_Clue_Query(0, 254)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 254, 1, -1);
+			}
+		} else if (region == 15) {
+			Actor_Voice_Over(4220, 99);
+			if (!Actor_Clue_Query(0, 77)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 77, 1, -1);
+			}
+		}
+		return false;
+	case 5:
+		if (region == 13) {
+			Actor_Says(0, 8830, 3);
+			if (!Actor_Clue_Query(0, 253)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 253, 1, -1);
+			}
+		}
+		return false;
+	case 4:
+		if (region == 11) {
+			Actor_Voice_Over(4090, 99);
+			if (!Actor_Clue_Query(0, 251)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 251, 1, -1);
+			}
+		} else if (region == 12) {
+			Actor_Voice_Over(4180, 99);
+			if (!Actor_Clue_Query(0, 252)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 252, 1, -1);
+			}
+		}
+		return false;
+	case 3:
+		if (region == 9) {
+			Actor_Voice_Over(4230, 99);
+			if (!Actor_Clue_Query(0, 249)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 249, 1, -1);
+			}
+			return true;
+		} else if (region == 10) {
+			Actor_Voice_Over(4040, 99);
+			if (!Actor_Clue_Query(0, 250)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 250, 1, -1);
+			}
+			return true;
+		}
+		return false;
+	case 2:
+		if (region == 8) {
+			Actor_Voice_Over(4260, 99);
+			if (!Actor_Clue_Query(0, 248)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 248, 1, -1);
+			}
+		} else if (region == 7) {
+			Actor_Voice_Over(4190, 99);
+			if (!Actor_Clue_Query(0, 258)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 258, 1, -1);
+			}
+		}
+		return true;
+	case 1:
+		if (region == 3) {
+			Actor_Voice_Over(4080, 99);
+			if (!Actor_Clue_Query(0, 243)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 243, 1, -1);
+			}
+		} else if (region == 4) {
+			Actor_Voice_Over(4110, 99);
+			if (!Actor_Clue_Query(0, 244)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 244, 1, -1);
+			}
+		} else if (region == 5) {
+			Actor_Voice_Over(4120, 99);
+			if (!Actor_Clue_Query(0, 31)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 31, 1, -1);
+			}
+		} else if (region == 6) {
+			Actor_Voice_Over(4070, 99);
+			if (!Actor_Clue_Query(0, 30)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 30, 1, -1);
+			}
+		}
+		return true;
+	case 0:
+		if (region == 0) {
+			Actor_Voice_Over(4050, 99);
+			if (!Actor_Clue_Query(0, 14)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 14, 1, -1);
+			}
+		} else if (region == 1) {
+			Actor_Voice_Over(4040, 99);
+			if (!Actor_Clue_Query(0, 13)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 13, 1, -1);
+			}
+		} else if (region == 2) {
+			Actor_Voice_Over(4060, 99);
+			if (!Actor_Clue_Query(0, 9)) {
+				Actor_Says(0, 6945, 3);
+				Sound_Play(417, 50, 0, 0, 50);
+				Actor_Clue_Acquire(0, 9, 1, -1);
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/esper.h b/engines/bladerunner/script/esper.h
new file mode 100644
index 0000000..9532e11
--- /dev/null
+++ b/engines/bladerunner/script/esper.h
@@ -0,0 +1,45 @@
+/* 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 BLADERUNNER_SCRIPT_ESPER_H
+#define BLADERUNNER_SCRIPT_ESPER_H
+
+#include "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class ScriptESPER : ScriptBase {
+public:
+	ScriptESPER(BladeRunnerEngine *vm)
+		: ScriptBase(vm) {
+	}
+
+	void SCRIPT_ESPER_DLL_Initialize();
+	void SCRIPT_ESPER_DLL_Photo_Selected(int photo);
+	bool SCRIPT_ESPER_DLL_Special_Region_Selected(int photo, int region);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/script/hc01.cpp b/engines/bladerunner/script/hc01.cpp
new file mode 100644
index 0000000..aac8b28
--- /dev/null
+++ b/engines/bladerunner/script/hc01.cpp
@@ -0,0 +1,433 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptHC01::InitializeScene() {
+	Music_Play(0, 31, 0, 2, -1, 1, 2);
+	if (Game_Flag_Query(385)) {
+		Setup_Scene_Information(64.0f, 0.14f, 83.0f, 266);
+	} else if (Game_Flag_Query(387)) {
+		Setup_Scene_Information(607.0f, 0.14f, 9.0f, 530);
+	} else {
+		Setup_Scene_Information(780.0f, 0.14f, 153.0f, 815);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 460, 639, 479, 2);
+	if (Game_Flag_Query(402)) {
+		Scene_Exit_Add_2D_Exit(1, 394, 229, 485, 371, 1);
+	}
+	Scene_Exit_Add_2D_Exit(2, 117, 0, 286, 319, 0);
+	Ambient_Sounds_Add_Looping_Sound(103, 50, 50, 0);
+	Ambient_Sounds_Add_Looping_Sound(241, 50, 50, 0);
+	Ambient_Sounds_Add_Sound(242, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(243, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(244, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(245, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(246, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(247, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(248, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(249, 3, 30, 16, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(181, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(183, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(190, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(193, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(194, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Scene_Loop_Set_Default(0);
+}
+
+void ScriptHC01::SceneLoaded() {
+	Obstacle_Object("PILLAR", true);
+	if (Game_Flag_Query(322)) {
+		Preload(19);
+		Preload(426);
+		Preload(430);
+		Preload(437);
+		Preload(427);
+		Preload(431);
+		Preload(433);
+		Preload(424);
+		Preload(428);
+		Preload(436);
+		Preload(429);
+		Preload(425);
+		Preload(432);
+	}
+}
+
+bool ScriptHC01::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptHC01::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptHC01::ClickedOnActor(int actorId) {
+	if (actorId == 7 && (Actor_Query_Goal_Number(7) == 150 || Actor_Query_Goal_Number(7) == 0)) {
+		AI_Movement_Track_Pause(7);
+		if (!Loop_Actor_Walk_To_XYZ(0, 624.43f, 0.14f, 83.0f, 0, 1, false, 0)) {
+			if (Game_Flag_Query(400)) {
+				Actor_Face_Actor(0, 7, true);
+				Actor_Face_Actor(7, 0, true);
+				sub_402384();
+			} else {
+				Actor_Face_Actor(7, 0, true);
+				Actor_Says_With_Pause(7, 10, 0.2f, 13);
+				Actor_Face_Actor(0, 7, true);
+				Actor_Says(7, 20, 17);
+				Actor_Says(0, 1035, 18);
+				Actor_Says_With_Pause(7, 30, 0.2f, 17);
+				Actor_Says_With_Pause(7, 40, 0.0f, 13);
+				Actor_Says(7, 50, 12);
+				Actor_Says_With_Pause(0, 1040, 1.2f, 13);
+				Actor_Says(7, 60, 16);
+				Actor_Says_With_Pause(7, 70, 1.0f, 13);
+				Actor_Says_With_Pause(0, 1045, 0.6f, 14);
+				Actor_Says(7, 80, 18);
+				Game_Flag_Set(400);
+			}
+		}
+		AI_Movement_Track_Unpause(7);
+	}
+	return false;
+}
+
+bool ScriptHC01::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 107) {
+		Item_Remove_From_World(107);
+		Item_Pickup_Spin_Effect(977, 361, 381);
+		Delay(1500);
+		Item_Pickup_Spin_Effect(984, 377, 397);
+		Delay(1500);
+		Item_Pickup_Spin_Effect(984, 330, 384);
+		if (Game_Flag_Query(374)) {
+			Actor_Clue_Acquire(0, 246, 1, 7);
+		} else {
+			Actor_Clue_Acquire(0, 247, 1, 7);
+		}
+		Actor_Clue_Acquire(0, 260, 1, 7);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC01::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 814.0f, 0.14f, 153.0f, 0, 1, false, 0)) {
+			Music_Adjust(12, 0, 2);
+			Game_Flag_Set(323);
+			Set_Enter(0, 0);
+			Game_Flag_Reset(479);
+			Game_Flag_Set(180);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 607.0f, 0.14f, 9.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(386);
+			Set_Enter(8, 33);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 105.0f, 0.14f, 103.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(384);
+			Async_Actor_Walk_To_XYZ(0, -57.0f, 0.14f, 83.0f, 0, false);
+			Set_Enter(8, 32);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC01::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptHC01::SceneFrameAdvanced(int frame) {
+	Set_Fade_Color(1.0f, 1.0f, 1.0f);
+	if (frame >= 61 && frame < 65) {
+		Set_Fade_Density((frame - 61) / 4.0f);
+	} else if (frame >= 65 && frame < 93) {
+		Set_Fade_Density(1.0f);
+	} else if (frame >= 93 && frame < 106) {
+		Set_Fade_Density((105 - frame) / 13.0f);
+	} else {
+		Set_Fade_Density(0.0f);
+	}
+	if (frame == 61) {
+		Ambient_Sounds_Play_Sound(312, 90, 0, 0, 0);
+	}
+	if (frame == 65) {
+		Ambient_Sounds_Play_Sound(315, 50, 0, 100, 0);
+	}
+	if (frame == 80) {
+		Ambient_Sounds_Play_Sound(316, 40, 100, 100, 0);
+		Item_Add_To_World(121, 931, 8, 582.0f, 27.0f, -41.0f, 0, 8, 8, true, true, false, true);
+	}
+}
+
+void ScriptHC01::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptHC01::PlayerWalkedIn() {
+	if (Game_Flag_Query(385)) {
+		Loop_Actor_Walk_To_XYZ(0, 105.0f, 0.14f, 103.0f, 0, 0, false, 0);
+		Game_Flag_Reset(385);
+	}
+	if (Game_Flag_Query(387)) {
+		Game_Flag_Reset(387);
+	}
+	if (Game_Flag_Query(322)) {
+		Game_Flag_Reset(322);
+	}
+}
+
+void ScriptHC01::PlayerWalkedOut() {
+	Set_Fade_Density(0.0f);
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptHC01::DialogueQueueFlushed(int a1) {
+}
+
+void ScriptHC01::sub_402384() {
+	if (!Game_Flag_Query(401)) {
+		Actor_Says(0, 1055, 13);
+		Actor_Says(7, 130, 13);
+		Actor_Says_With_Pause(0, 1060, 0.2f, 13);
+		Actor_Says(7, 140, 13);
+		Game_Flag_Set(401);
+	}
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 56) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1020, 6, 7, 3);
+	} else if (Actor_Clue_Query(0, 44) || Actor_Clue_Query(0, 47) || Actor_Clue_Query(0, 14)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1010, 6, 7, 3);
+	}
+	if (Actor_Clue_Query(0, 58) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1030, 1, 5, 7);
+	} else if (Actor_Clue_Query(0, 5) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1040, 4, 4, 6);
+	}
+	if (Actor_Clue_Query(0, 181) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1050, -1, 3, 8);
+	} else if (Actor_Clue_Query(0, 180) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(1060, -1, 3, 8);
+	}
+	if (!Dialogue_Menu_Query_List_Size()) {
+		Actor_Says_With_Pause(0, 1105, 1.2f, 13);
+		if (Actor_Query_Friendliness_To_Other(7, 0) < 50) {
+			Actor_Says(7, 550, 15);
+		} else {
+			Actor_Says(7, 250, 13);
+			Actor_Modify_Friendliness_To_Other(7, 0, -1);
+			if (Actor_Query_Friendliness_To_Other(7, 0) < 47 && !Query_Difficulty_Level()) {
+				sub_40346C();
+			}
+		}
+		return;
+	}
+	Dialogue_Menu_Add_DONE_To_List(100);
+	bool end = false;
+	do {
+		Dialogue_Menu_Appear(320, 240);
+		int answer = Dialogue_Menu_Query_Input();
+		Dialogue_Menu_Disappear();
+		if (answer == 1020) {
+			Dialogue_Menu_Remove_From_List(1020);
+			Actor_Says(0, 1065, 15);
+			Actor_Says(7, 160, 3);
+			Actor_Says(0, 1110, 16);
+			Actor_Says(7, 170, 3);
+			Actor_Says(7, 180, 3);
+			Actor_Says(7, 190, 12);
+			if (Query_Difficulty_Level() < 2) {
+				Actor_Modify_Friendliness_To_Other(7, 0, -2);
+			}
+		}
+		if (answer == 1010) {
+			Dialogue_Menu_Remove_From_List(1010);
+			Actor_Clue_Acquire(0, 60, 0, 7);
+			Actor_Says(0, 1070, 13);
+			Actor_Says(7, 200, 17);
+			Actor_Says(7, 210, 12);
+			Actor_Says(0, 1115, 12);
+			Actor_Says(7, 220, 16);
+			Actor_Says(7, 230, 3);
+			Actor_Says(7, 240, 15);
+			if (Query_Difficulty_Level() < 2) {
+				Actor_Modify_Friendliness_To_Other(7, 0, -1);
+			}
+		}
+		if (answer == 1010 || answer == 1020) {
+			Actor_Says_With_Pause(0, 1120, 0.9f, 17);
+			Actor_Says(7, 250, 13);
+			Actor_Says(0, 1125, 14);
+			if (Actor_Query_Friendliness_To_Other(7, 0) < 47) {
+				Actor_Set_Goal_Number(7, 1);
+				Player_Loses_Control();
+				Actor_Says(7, 90, 3);
+				Actor_Face_Actor(7, 0, true);
+				Actor_Says(7, 100, 3);
+				Actor_Says(7, 110, 3);
+				Actor_Says_With_Pause(0, 1050, 0.2f, 3);
+				Actor_Says(7, 120, 3);
+				Actor_Set_Goal_Number(7, 2);
+			}
+			end = true;
+		}
+		if (answer == 1030) {
+			Dialogue_Menu_Remove_From_List(1030);
+			Actor_Says(0, 1075, 18);
+			Actor_Says(7, 260, 12);
+			Actor_Says(7, 270, 16);
+			Actor_Says(0, 1130, 14);
+			Actor_Says(7, 280, 17);
+			Actor_Says(0, 1135, 15);
+			Actor_Says(7, 290, 15);
+			Actor_Says(7, 300, 12);
+			Actor_Says(7, 310, 17);
+			Actor_Says(0, 1140, 3);
+			if (Query_Difficulty_Level() < 2) {
+				Actor_Modify_Friendliness_To_Other(7, 0, -2);
+			}
+			if (Actor_Query_Friendliness_To_Other(7, 0) < 47) {
+				Actor_Set_Goal_Number(7, 1);
+				Player_Loses_Control();
+				Actor_Says(7, 90, 3);
+				Actor_Face_Actor(7, 0, true);
+				Actor_Says(7, 100, 3);
+				Actor_Says(7, 110, 3);
+				Actor_Says_With_Pause(0, 1050, 0.2f, 3);
+				Actor_Says(7, 120, 3);
+				Actor_Set_Goal_Number(7, 2);
+			}
+			end = true;
+		}
+		if (answer == 1040) {
+			Dialogue_Menu_Remove_From_List(1040);
+			Actor_Says(0, 1080, 15);
+			Actor_Says(0, 1085, 17);
+			Actor_Says(7, 320, 17);
+			Actor_Says(0, 1145, 13);
+			Actor_Says(7, 330, 17);
+			Actor_Says(7, 340, 13);
+			Actor_Says(7, 350, 12);
+			end = true;
+		}
+		if (answer == 1050) {
+			Dialogue_Menu_Remove_From_List(1050);
+			Actor_Says(0, 1090, 18);
+			Actor_Says(7, 360, 14);
+			Actor_Says(0, 1150, 17);
+			Actor_Says(7, 370, 13);
+			Actor_Says(0, 1155, 15);
+			Actor_Says(7, 380, 12);
+			Actor_Says(0, 1160, 14);
+			Actor_Says(0, 1165, 18);
+			Actor_Says(7, 390, 16);
+			Actor_Says(0, 1170, 12);
+			Actor_Says(7, 400, 13);
+			Actor_Says(0, 1180, 14);
+			Actor_Says(7, 410, 12);
+			Actor_Says(7, 420, 16);
+			Actor_Says(7, 430, 17);
+			Actor_Says(7, 440, 13);
+			Actor_Modify_Friendliness_To_Other(7, 0, -4);
+			if (Actor_Query_Friendliness_To_Other(7, 0) < 47) {
+				Actor_Set_Goal_Number(7, 1);
+				Player_Loses_Control();
+				Actor_Says(7, 90, 3);
+				Actor_Face_Actor(7, 0, true);
+				Actor_Says(7, 100, 3);
+				Actor_Says(7, 110, 3);
+				Actor_Says_With_Pause(0, 1050, 0.2f, 3);
+				Actor_Says(7, 120, 3);
+				Actor_Set_Goal_Number(7, 2);
+			}
+			end = true;
+		}
+		if (answer == 1060) {
+			Dialogue_Menu_Remove_From_List(1060);
+			Actor_Says(0, 1095, 15);
+			Actor_Says_With_Pause(0, 1100, 1.2f, 18);
+			Actor_Says(7, 450, 12);
+			Actor_Says(7, 460, 13);
+			Actor_Says(0, 1185, 18);
+			Actor_Says(7, 470, 14);
+			Actor_Says(0, 1190, 14);
+			Actor_Says(7, 480, 13);
+			Actor_Says(0, 1195, 16);
+			Actor_Says(0, 1200, 18);
+			Actor_Says(7, 490, 12);
+			Actor_Says(0, 1205, 14);
+			Actor_Says(7, 500, 14);
+			Actor_Says(7, 510, 17);
+			Actor_Says(7, 520, 16);
+			Actor_Says(7, 530, 15);
+			Actor_Says(0, 1210, 16);
+			Actor_Modify_Friendliness_To_Other(7, 0, -4);
+			if (Actor_Query_Friendliness_To_Other(7, 0) < 47) {
+				Actor_Set_Goal_Number(7, 1);
+				Player_Loses_Control();
+				Actor_Says(7, 90, 3);
+				Actor_Face_Actor(7, 0, true);
+				Actor_Says(7, 100, 3);
+				Actor_Says(7, 110, 3);
+				Actor_Says_With_Pause(0, 1050, 0.2f, 3);
+				Actor_Says(7, 120, 3);
+				Actor_Set_Goal_Number(7, 2);
+			}
+			end = true;
+		}
+		if (answer == 100) {
+			end = true;
+		}
+	} while (!end);
+}
+
+void ScriptHC01::sub_40346C() {
+	Actor_Set_Goal_Number(7, 1);
+	Player_Loses_Control();
+	Actor_Says(7, 90, 3);
+	Actor_Face_Actor(7, 0, true);
+	Actor_Says(7, 100, 3);
+	Actor_Says(7, 110, 3);
+	Actor_Says_With_Pause(0, 1050, 0.2f, 3);
+	Actor_Says(7, 120, 3);
+	Actor_Set_Goal_Number(7, 2);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/hc02.cpp b/engines/bladerunner/script/hc02.cpp
new file mode 100644
index 0000000..908b992
--- /dev/null
+++ b/engines/bladerunner/script/hc02.cpp
@@ -0,0 +1,216 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptHC02::InitializeScene() {
+	Music_Play(4, 45, -60, 1, -1, 1, 3);
+	if (Game_Flag_Query(109)) {
+		Setup_Scene_Information(-88.0f, 0.14f, -463.0f, 540);
+	} else {
+		Setup_Scene_Information(-57.0f, 0.14f, 83.0f, 746);
+	}
+	Scene_Exit_Add_2D_Exit(0, 589, 255, 639, 479, 1);
+	Scene_Exit_Add_2D_Exit(1, 505, 0, 639, 170, 0);
+	Ambient_Sounds_Add_Looping_Sound(103, 50, 50, 0);
+	Ambient_Sounds_Add_Looping_Sound(280, 50, 50, 0);
+	Ambient_Sounds_Add_Sound(252, 3, 60, 33, 33, -60, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(254, 3, 60, 33, 33, -60, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(255, 3, 60, 33, 33, -60, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(256, 3, 60, 33, 33, -60, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(257, 3, 60, 33, 33, -60, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(258, 3, 60, 33, 33, -60, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(259, 3, 60, 33, 33, -100, 20, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(260, 3, 60, 33, 33, -100, 20, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(261, 3, 60, 33, 33, -100, 20, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(262, 3, 60, 33, 33, -100, 20, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(242, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(243, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(244, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(245, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(246, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(247, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(248, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(249, 3, 30, 14, 14, 30, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(238, 3, 50, 20, 20, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(240, 3, 50, 25, 25, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(384)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+		Game_Flag_Reset(384);
+	} else {
+		Scene_Loop_Set_Default(1);
+	}
+}
+
+void ScriptHC02::SceneLoaded() {
+	Obstacle_Object("BARSTOOL01", true);
+}
+
+bool ScriptHC02::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptHC02::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptHC02::ClickedOnActor(int actorId) {
+	if (actorId == 32) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -150.51f, 0.14f, 62.74f, 0, 1, false, 0)) {
+			Actor_Face_Actor(0, 32, true);
+			if (!Game_Flag_Query(404)) {
+				Actor_Says(0, 1225, 13);
+				Actor_Says_With_Pause(32, 0, 0.0f, 13);
+				Actor_Says(32, 10, 16);
+				Actor_Set_Goal_Number(32, 1);
+				Actor_Change_Animation_Mode(0, 23);
+				Delay(1500);
+				Actor_Change_Animation_Mode(0, 75);
+				Delay(1500);
+				Global_Variable_Increment(42, 1);
+				Game_Flag_Set(404);
+			} else if (Actor_Clue_Query(0, 254) && !Actor_Clue_Query(0, 257)) {
+				Actor_Says(0, 4545, 11);
+				Actor_Says(32, 120, 12);
+				Actor_Says(32, 180, 13);
+				Actor_Clue_Acquire(0, 257, 1, 32);
+				Item_Pickup_Spin_Effect(975, 229, 215);
+			} else if (Actor_Clue_Query(0, 122) && !Actor_Clue_Query(0, 131) && Global_Variable_Query(2) > 20 || Query_Difficulty_Level() == 0) {
+				Actor_Clue_Acquire(0, 131, 1, 32);
+				Actor_Says(0, 1230, 13);
+				Actor_Says(32, 20, 12);
+				Actor_Says(0, 1235, 13);
+				Actor_Says(32, 30, 15);
+				Actor_Says(0, 1240, 13);
+				Actor_Says(32, 40, 14);
+				Item_Pickup_Spin_Effect(945, 229, 215);
+				Actor_Set_Goal_Number(32, 2);
+				Actor_Change_Animation_Mode(0, 23);
+				Delay(1500);
+				Actor_Says_With_Pause(32, 50, 1.6f, 17);
+				if (Query_Difficulty_Level()) {
+					Global_Variable_Decrement(2, 20);
+				}
+				Actor_Says(0, 1245, 13);
+			} else {
+				if (Actor_Clue_Query(0, 75)  && !Game_Flag_Query(405)) {
+					Actor_Says(32, 80, 16);
+					Actor_Says(0, 1265, 13);
+					Actor_Says(32, 90, 13);
+					Game_Flag_Set(405);
+				}
+				if (Global_Variable_Query(2) > 5 || Query_Difficulty_Level() == 0) {
+					if (Query_Difficulty_Level()) {
+						Global_Variable_Decrement(2, 5);
+					}
+					Global_Variable_Increment(42, 1);
+					Actor_Says(0, 1250, 13);
+					Actor_Says_With_Pause(32, 60, 0.8f, 14);
+					Actor_Says(0, 1255, 13);
+					Actor_Set_Goal_Number(32, 1);
+					Actor_Change_Animation_Mode(0, 23);
+					Delay(1500);
+					Actor_Change_Animation_Mode(0, 75);
+					Delay(1500);
+				} else {
+					Actor_Says_With_Pause(0, 1260, 0.3f, 13);
+					Actor_Says(32, 70, 14);
+				}
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC02::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptHC02::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 7.0f, 0.14f, 79.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(385);
+			Set_Enter(8, 31);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -76.0f, 0.14f, -339.0f, 0, 1, false, 0)) {
+			Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+			Ambient_Sounds_Remove_All_Looping_Sounds(1);
+			Game_Flag_Set(110);
+			Async_Actor_Walk_To_XYZ(0, -88.0f, 0.14f, -463.0f, 0, false);
+			Set_Enter(8, 106);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC02::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptHC02::SceneFrameAdvanced(int frame) {
+	if (frame == 70) {
+		Sound_Play(73, 11, 50, -90, 50);
+	}
+	if (frame == 58) {
+		Sound_Play(73, 11, 50, -90, 50);
+	}
+	if (frame == 69 || frame == 77 || frame == 86 || frame == 95 || frame == 104 || frame == 113 || frame == 119) {
+		Sound_Play(60, Random_Query(6, 7), -20, 20, 50);
+	}
+}
+
+void ScriptHC02::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptHC02::PlayerWalkedIn() {
+	if (Game_Flag_Query(109)) {
+		Loop_Actor_Walk_To_XYZ(0, -76.0f, 0.14f, -339.0f, 0, 0, false, 0);
+		Game_Flag_Reset(109);
+	}
+}
+
+void ScriptHC02::PlayerWalkedOut() {
+}
+
+void ScriptHC02::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/hc03.cpp b/engines/bladerunner/script/hc03.cpp
new file mode 100644
index 0000000..58a822c
--- /dev/null
+++ b/engines/bladerunner/script/hc03.cpp
@@ -0,0 +1,188 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptHC03::InitializeScene() {
+	if (Game_Flag_Query(318)) {
+		Setup_Scene_Information(656.0f, 1.61f, -95.0f, 497);
+		Game_Flag_Set(388);
+		Game_Flag_Reset(318);
+	} else {
+		Setup_Scene_Information(607.0f, 0.14f, 13.0f, 57);
+		Game_Flag_Reset(386);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 0, 30, 479, 3);
+	if (Game_Flag_Query(403) || Global_Variable_Query(1) > 3) {
+		Item_Remove_From_World(121);
+		Game_Flag_Set(403);
+		Scene_Exit_Add_2D_Exit(1, 400, 275, 515, 375, 2);
+	}
+	Ambient_Sounds_Add_Looping_Sound(103, 50, 50, 0);
+	Ambient_Sounds_Add_Looping_Sound(241, 50, 50, 0);
+	Ambient_Sounds_Add_Sound(242, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(243, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(244, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(245, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(246, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(247, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(248, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(249, 3, 30, 16, 16, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(238, 3, 50, 25, 25, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(240, 3, 50, 33, 33, -100, -70, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(181, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(183, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(190, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(193, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(194, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	if (Game_Flag_Query(388)) {
+		Scene_Loop_Set_Default(6);
+	} else if (Game_Flag_Query(403) || Global_Variable_Query(1) > 3) {
+		Scene_Loop_Set_Default(3);
+	} else {
+		Scene_Loop_Set_Default(0);
+	}
+}
+
+void ScriptHC03::SceneLoaded() {
+	Obstacle_Object("GUITAR01", true);
+	if (Game_Flag_Query(403) || Game_Flag_Query(388) || Global_Variable_Query(1) > 3) {
+		Unobstacle_Object("GPscisGate", true);
+	} else {
+		Obstacle_Object("GPscisGate", true);
+	}
+	Unclickable_Object("GUITAR01");
+}
+
+bool ScriptHC03::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptHC03::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptHC03::ClickedOnActor(int actorId) {
+	return false;
+}
+
+bool ScriptHC03::ClickedOnItem(int itemId, bool a2) {
+	if (itemId == 121) {
+		if (a2) {
+			Scene_Loop_Set_Default(3);
+			Scene_Loop_Start_Special(2, 2, 1);
+			Game_Flag_Set(403);
+			Item_Remove_From_World(121);
+			Unobstacle_Object("GPscisGate", true);
+		} else {
+			Actor_Says(0, 8522, 12);
+		}
+		return true;
+	}
+	if (itemId == 107) {
+		Item_Remove_From_World(107);
+		Item_Pickup_Spin_Effect(977, 68, 435);
+		Delay(1500);
+		Item_Pickup_Spin_Effect(984, 78, 435);
+		Delay(1500);
+		Item_Pickup_Spin_Effect(984, 58, 435);
+		if (Game_Flag_Query(374)) {
+			Actor_Clue_Acquire(0, 246, 1, 7);
+		} else {
+			Actor_Clue_Acquire(0, 247, 1, 7);
+		}
+		Actor_Clue_Acquire(0, 260, 1, 7);
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC03::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 607.0f, 0.14f, 9.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(387);
+			Set_Enter(8, 31);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 628.0f, 2.04f, -123.0f, 0, 1, false, 0)) {
+			if (Game_Flag_Query(388)) {
+				Game_Flag_Set(319);
+				Game_Flag_Reset(479);
+				Game_Flag_Set(259);
+				Game_Flag_Set(388);
+				Music_Stop(2);
+				Set_Enter(75, 87);
+			} else {
+				Scene_Loop_Set_Default(6);
+				Scene_Loop_Start_Special(2, 5, 1);
+				Game_Flag_Set(388);
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC03::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptHC03::SceneFrameAdvanced(int frame) {
+	if (frame == 10 || frame == 19 || frame == 29 || frame == 39 || frame == 49 || frame == 59 || frame == 71 || frame == 82 || frame == 91 || frame == 101 || frame == 111 || frame == 121 || frame == 131) {
+		Sound_Play(281, Random_Query(33, 50), 50, 50, 50);
+	}
+	if (!Game_Flag_Query(521) && frame == 66) {
+		Ambient_Sounds_Play_Sound(328, 90, 0, -40, 99);
+		Sound_Play(201, Random_Query(47, 47), 0, -40, 50);
+		Scene_Exit_Add_2D_Exit(1, 400, 275, 515, 375, 2);
+		Game_Flag_Set(521);
+	}
+}
+
+void ScriptHC03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptHC03::PlayerWalkedIn() {
+}
+
+void ScriptHC03::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptHC03::DialogueQueueFlushed(int a1) {
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/hc04.cpp b/engines/bladerunner/script/hc04.cpp
new file mode 100644
index 0000000..5582a21
--- /dev/null
+++ b/engines/bladerunner/script/hc04.cpp
@@ -0,0 +1,242 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptHC04::InitializeScene() {
+	if (Game_Flag_Query(108)) {
+		Setup_Scene_Information(-112.0f, 0.14f, -655.0f, 460);
+		Game_Flag_Reset(108);
+	} else {
+		Setup_Scene_Information(-88.0f, 0.14f, -463.0f, 1013);
+	}
+	Music_Play(4, 14, -90, 1, -1, 1, 2);
+	Actor_Put_In_Set(59, 8);
+	Actor_Set_At_XYZ(59, -210.0f, 0.0f, -445.0f, 250);
+	Scene_Exit_Add_2D_Exit(0, 539, 51, 639, 309, 0);
+	Scene_Exit_Add_2D_Exit(1, 0, 456, 639, 479, 2);
+	Ambient_Sounds_Add_Looping_Sound(103, 50, 50, 0);
+	Ambient_Sounds_Add_Looping_Sound(329, 16, 16, 0);
+	Ambient_Sounds_Add_Looping_Sound(330, 40, 40, 0);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 14, 16, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(252, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(252, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(254, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(255, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(256, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(257, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(258, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(259, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(260, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(261, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(262, 3, 60, 16, 16, -100, -100, -101, -101, 0, 0);
+	if (Game_Flag_Query(110)) {
+		Scene_Loop_Start_Special(0, 0, 0);
+		Scene_Loop_Set_Default(1);
+		Game_Flag_Reset(110);
+	} else {
+		Scene_Loop_Set_Default(1);
+	}
+}
+
+void ScriptHC04::SceneLoaded() {
+	Obstacle_Object("CAN FIRE", true);
+	Unobstacle_Object("ASIANMALE01", true);
+	Clickable_Object("CAN FIRE");
+}
+
+bool ScriptHC04::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptHC04::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptHC04::ClickedOnActor(int actorId) {
+	if (actorId == 59) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -155.0f, 0.0f, -475.0f, 12, 1, false, 0)) {
+			Actor_Face_Actor(0, 59, true);
+			Actor_Face_Actor(59, 0, true);
+			if (Game_Flag_Query(106)) {
+				sub_401B90();
+				return true;
+			} else {
+				Actor_Says(59, 0, 3);
+				Actor_Says(0, 1280, 3);
+				Actor_Says(59, 20, 3);
+				Game_Flag_Set(106);
+				return true;
+			}
+		}
+	}
+	return false;
+}
+
+bool ScriptHC04::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptHC04::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -108.0f, 0.14f, -639.0f, 0, 1, false, 0)) {
+			Music_Stop(2);
+			Game_Flag_Set(107);
+			Game_Flag_Reset(479);
+			Game_Flag_Set(182);
+			Set_Enter(70, 80);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -72.0f, 0.14f, -399.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(109);
+			Set_Enter(8, 32);
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHC04::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptHC04::SceneFrameAdvanced(int frame) {
+}
+
+void ScriptHC04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptHC04::PlayerWalkedIn() {
+}
+
+void ScriptHC04::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+}
+
+void ScriptHC04::DialogueQueueFlushed(int a1) {
+}
+
+void ScriptHC04::sub_401B90() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 263) || Actor_Clue_Query(0, 53)) {
+		if (Actor_Clue_Query(0, 47)) {
+			DM_Add_To_List_Never_Repeat_Once_Selected(340, 5, 6, 5);
+		} else if (Actor_Clue_Query(0, 259)) {
+			DM_Add_To_List_Never_Repeat_Once_Selected(350, 5, 6, 5);
+		}
+		DM_Add_To_List_Never_Repeat_Once_Selected(360, 6, 4, 3);
+	}
+	if (Actor_Clue_Query(0, 87) && !Actor_Clue_Query(0, 101)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(370, 3, 4, 7);
+	}
+	if (Actor_Clue_Query(0, 101)) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(380, -1, 5, 8);
+	}
+	DM_Add_To_List_Never_Repeat_Once_Selected(390, 7, 5, -1);
+	Dialogue_Menu_Add_DONE_To_List(400);
+	Dialogue_Menu_Appear(320, 240);
+	int answer = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answer) {
+	case 340:
+		Actor_Says(0, 1285, 3);
+		Actor_Says(59, 50, 3);
+		Actor_Says(0, 1330, 3);
+		Actor_Says(59, 60, 3);
+		break;
+	case 350:
+		Actor_Says(0, 1290, 3);
+		Actor_Says(59, 70, 3);
+		Actor_Says(0, 1335, 3);
+		Actor_Says(59, 80, 3);
+		Actor_Says(0, 1340, 3);
+		Actor_Says(59, 90, 3);
+		Actor_Says(0, 1345, 3);
+		break;
+	case 360:
+		Actor_Says(0, 1295, 3);
+		Actor_Says(59, 100, 3);
+		Actor_Says(0, 1350, 3);
+		Actor_Says(59, 110, 3);
+		Actor_Says(0, 1355, 3);
+		Actor_Says(59, 130, 3);
+		Actor_Says(0, 1360, 3);
+		break;
+	case 370:
+		Actor_Says(0, 1300, 3);
+		Actor_Says(59, 140, 3);
+		Actor_Says(0, 1365, 3);
+		Actor_Says(59, 150, 3);
+		break;
+	case 380:
+		Actor_Says(0, 1305, 3);
+		Actor_Modify_Friendliness_To_Other(59, 0, -2);
+		Actor_Says(59, 160, 3);
+		Actor_Says(0, 1370, 3);
+		Actor_Says(59, 170, 3);
+		Actor_Says(0, 1375, 3);
+		Actor_Says(59, 180, 3);
+		Actor_Says(0, 1380, 3);
+		Actor_Says(59, 190, 3);
+		Actor_Says(59, 210, 3);
+		Actor_Says(59, 240, 3);
+		Actor_Says(0, 1385, 3);
+		Actor_Says(59, 260, 3);
+		Actor_Says(0, 1390, 3);
+		Actor_Says(59, 300, 3);
+		Actor_Says(59, 310, 3);
+		Actor_Says(59, 320, 3);
+		Actor_Says(0, 1395, 3);
+		Actor_Says(59, 330, 3);
+		Actor_Clue_Acquire(0, 102, 0, 59);
+		break;
+	case 390:
+		Actor_Says(0, 1310, 3);
+		Actor_Modify_Friendliness_To_Other(59, 0, 2);
+		Actor_Says(59, 340, 3);
+		break;
+	case 400:
+		Actor_Says(0, 1315, 3);
+		break;
+	default:
+		Actor_Says(0, 1320, 3);
+		Actor_Says(59, 30, 3);
+		Actor_Says(0, 1325, 3);
+		Actor_Says(0, 1345, 3);
+		break;
+	}
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/hf01.cpp b/engines/bladerunner/script/hf01.cpp
new file mode 100644
index 0000000..509f472
--- /dev/null
+++ b/engines/bladerunner/script/hf01.cpp
@@ -0,0 +1,475 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptHF01::InitializeScene() {
+	if (Game_Flag_Query(617)) {
+		Setup_Scene_Information(243.94f, 8.0f, -341.9f, 342);
+	} else if (Game_Flag_Query(313)) {
+		Setup_Scene_Information(-202.0f, 0.0f, -619.0f, 407);
+	} else if (Game_Flag_Query(311)) {
+		Setup_Scene_Information(124.0f, 8.0f, -880.0f, 455);
+	} else if (Game_Flag_Query(309)) {
+		Setup_Scene_Information(406.0f, 8.0f, -813.0f, 455);
+	} else {
+		Setup_Scene_Information(100.0f, 0.0f, -260.0f, 0);
+	}
+	Scene_Exit_Add_2D_Exit(0, 81, 226, 169, 321, 0);
+	if (!Game_Flag_Query(663)) {
+		Scene_Exit_Add_2D_Exit(1, 304, 239, 492, 339, 0);
+		Scene_Exit_Add_2D_Exit(2, 560, 231, 639, 360, 0);
+		if (Game_Flag_Query(256)) {
+			Scene_Exit_Add_2D_Exit(3, 0, 311, 66, 417, 2);
+		}
+	}
+	Ambient_Sounds_Add_Looping_Sound(54, 50, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(340, 25, 0, 1);
+	Ambient_Sounds_Add_Looping_Sound(81, 60, 100, 1);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(68, 10, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(69, 10, 180, 16, 25, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(375, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(376, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(377, 10, 180, 50, 100, 0, 0, -101, -101, 0, 0);
+	if (Game_Flag_Query(256)) {
+		if (!Game_Flag_Query(309) && !Game_Flag_Query(311) && !Game_Flag_Query(313)) {
+			Scene_Loop_Start_Special(0, 0, 0);
+		}
+		Scene_Loop_Set_Default(1);
+	} else if (Game_Flag_Query(663)) {
+		Scene_Loop_Set_Default(1);
+	} else {
+		Scene_Loop_Set_Default(5);
+	}
+}
+
+void ScriptHF01::SceneLoaded() {
+	Obstacle_Object("LOFT41", true);
+	if (!Game_Flag_Query(256)) {
+		Unobstacle_Object("OBSTACLE BOX15", true);
+	}
+}
+
+bool ScriptHF01::MouseClick(int x, int y) {
+	return false;
+}
+
+bool ScriptHF01::ClickedOn3DObject(const char *objectName, bool a2) {
+	return false;
+}
+
+bool ScriptHF01::ClickedOnActor(int actorId) {
+	int v1;
+	if (Global_Variable_Query(45) == 2) {
+		v1 = 3;
+	} else if (Global_Variable_Query(45) == 3) {
+		v1 = 6;
+	} else {
+		v1 = -1;
+	}
+	if (actorId == 22 || actorId == 31) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 504.04f, 8.0f, -242.17f, 12, 1, false, 0)) {
+			ADQ_Flush();
+			Actor_Face_Actor(0, 31, true);
+			if (Game_Flag_Query(382)) {
+				sub_4026B4();
+			} else {
+				Actor_Says(0, 1455, 15);
+				Actor_Says(31, 40, 13);
+				Actor_Says(0, 1460, 13);
+				Actor_Says(31, 50, 12);
+				Item_Pickup_Spin_Effect(951, 396, 359);
+				Actor_Face_Heading(31, 271, false);
+				Actor_Says(31, 60, 12);
+				Actor_Says(0, 1465, 15);
+				Actor_Face_Actor(31, 0, true);
+				Actor_Says(31, 70, 13);
+				Actor_Says(0, 1470, 14);
+				Actor_Says(22, 30, 3);
+				Actor_Says(31, 80, 15);
+				Actor_Says(22, 50, 3);
+				Actor_Says(31, 110, 14);
+				Game_Flag_Set(382);
+			}
+			return true;
+		}
+		return false;
+	}
+	if (actorId == v1) {
+		if (!Loop_Actor_Walk_To_Actor(0, actorId, 28, 1, false)) {
+			if (Actor_Query_Goal_Number(v1) == 599) {
+				Actor_Says(0, 8630, 13);
+				return true;
+			}
+			if (Global_Variable_Query(1) == 5 && (Actor_Clue_Query(0, 139) || Actor_Clue_Query(0, 141)) && !Game_Flag_Query(165) && Actor_Query_Goal_Number(9) != 2 && Game_Flag_Query(653) && !Game_Flag_Query(662)) {
+				Game_Flag_Set(662);
+				Actor_Face_Actor(0, v1, true);
+				Actor_Face_Actor(v1, 0, true);
+				if (v1 == 3) {
+					sub_4032DC();
+				} else if (v1 == 6) {
+					sub_403484();
+				}
+				Async_Actor_Walk_To_XYZ(v1, -175.0f, 8.0f, -617.0f, 0, false);
+				Loop_Actor_Walk_To_XYZ(0, -137.0f, 8.0f, -577.0f, 0, 0, false, 1);
+				Game_Flag_Set(312);
+				Set_Enter(41, 38);
+			}
+		}
+	}
+	return false;
+}
+
+bool ScriptHF01::ClickedOnItem(int itemId, bool a2) {
+	return false;
+}
+
+bool ScriptHF01::ClickedOnExit(int exitId) {
+	if (exitId == 0) {
+		if (!Loop_Actor_Walk_To_XYZ(0, -202.0f, 8.0f, -619.0f, 0, 1, false, 0)) {
+			Game_Flag_Set(312);
+			Set_Enter(41, 38);
+		}
+		return true;
+	}
+	if (exitId == 1) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 124.0f, 8.0f, -724.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 124.0f, 8.0f, -880.0f, 0, 0, false, 0);
+			Game_Flag_Set(310);
+			Set_Enter(39, 36);
+		}
+		return true;
+	}
+	if (exitId == 2) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 406.0f, 8.0f, -717.0f, 0, 1, false, 0)) {
+			Loop_Actor_Walk_To_XYZ(0, 406.0f, 8.0f, -813.0f, 0, 0, false, 0);
+			Game_Flag_Set(308);
+			Set_Enter(38, 35);
+		}
+		return true;
+	}
+	if (exitId == 3) {
+		if (!Loop_Actor_Walk_To_XYZ(0, 100.0f, 0.0f, -260.0f, 0, 1, false, 0)) {
+			Game_Flag_Reset(176);
+			Game_Flag_Reset(182);
+			Game_Flag_Reset(179);
+			Game_Flag_Reset(178);
+			Game_Flag_Reset(258);
+			Game_Flag_Reset(257);
+			int spinnerDest = Spinner_Interface_Choose_Dest(3, 0);
+			switch (spinnerDest) {
+			case 0:
+				Game_Flag_Set(178);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(251);
+				Set_Enter(61, 65);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 1:
+				Game_Flag_Set(179);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(250);
+				Set_Enter(49, 48);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 2:
+				Game_Flag_Set(182);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(249);
+				Set_Enter(69, 78);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 3:
+				Game_Flag_Set(176);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(248);
+				Set_Enter(4, 13);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 5:
+				Game_Flag_Set(261);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(307);
+				Set_Enter(17, 82);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 4:
+				Game_Flag_Set(180);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(252);
+				Set_Enter(0, 0);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 7:
+				Game_Flag_Set(258);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(254);
+				Set_Enter(20, 2);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 6:
+				Game_Flag_Set(177);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(253);
+				Set_Enter(7, 25);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			case 8:
+				Game_Flag_Set(181);
+				Game_Flag_Reset(256);
+				Game_Flag_Set(255);
+				Set_Enter(54, 54);
+				Scene_Loop_Start_Special(1, 4, 1);
+				break;
+			default:
+				Game_Flag_Set(257);
+				Loop_Actor_Walk_To_XYZ(0, 100.0f, 0.0f, -300.0f, 0, 1, false, 0);
+				break;
+			}
+		}
+		return true;
+	}
+	return false;
+}
+
+bool ScriptHF01::ClickedOn2DRegion(int region) {
+	return false;
+}
+
+void ScriptHF01::SceneFrameAdvanced(int frame) {
+	if (frame == 10) {
+		Sound_Play(118, 40, 0, 0, 50);
+	}
+	if (frame == 72 || frame == 193) {
+		Sound_Play(116, 100, -50, -50, 50);
+	}
+	if (frame == 88 || frame == 214) {
+		Sound_Play(119, 100, -50, -50, 50);
+	}
+	if (frame == 242) {
+		Sound_Play(117, 40, -50, 80, 50);
+	}
+	if (Actor_Query_Goal_Number(31) == 1) {
+		Actor_Set_Goal_Number(31, 0);
+	}
+}
+
+void ScriptHF01::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
+}
+
+void ScriptHF01::PlayerWalkedIn() {
+	if (Game_Flag_Query(663)) {
+		ADQ_Flush();
+		ADQ_Add(24, 280, 3);
+		Actor_Put_In_Set(23, 37);
+		Actor_Set_At_XYZ(23, 8.2f, 8.0f, -346.67f, 1021);
+		Actor_Put_In_Set(24, 37);
+		Actor_Set_At_XYZ(24, 51.21f, 8.0f, -540.78f, 796);
+		Non_Player_Actor_Combat_Mode_On(23, 3, 1, 0, 4, 4, 7, 8, 0, 0, 0, 100, 300, 0);
+		Non_Player_Actor_Combat_Mode_On(24, 3, 1, 0, 4, 4, 7, 8, 0, 0, 0, 100, 300, 0);
+	}
+	if (!Game_Flag_Query(165) && Actor_Query_Goal_Number(9) != 2) {
+		if (Actor_Clue_Query(0, 141) && Global_Variable_Query(45) == 3 && Actor_Query_Goal_Number(6) != 599) {
+			Actor_Put_In_Set(6, 37);
+			Actor_Set_At_XYZ(6, -5.0f, 8.0f, -622.0f, 419);
+			Actor_Set_Targetable(6, true);
+		} else if (Actor_Clue_Query(0, 139) && Global_Variable_Query(45) == 2 && Actor_Query_Goal_Number(3) != 599) {
+			Actor_Put_In_Set(3, 37);
+			Actor_Set_At_XYZ(3, -5.0f, 8.0f, -622.0f, 419);
+			Actor_Set_Targetable(3, true);
+		}
+	}
+	if (Game_Flag_Query(617)) {
+		Actor_Set_Goal_Number(1, 280);
+		Game_Flag_Reset(617);
+		//return true;
+		return;
+	}
+	if (Game_Flag_Query(652)) {
+		Game_Flag_Reset(652);
+		Actor_Voice_Over(950, 99);
+		Actor_Voice_Over(960, 99);
+		Actor_Voice_Over(970, 99);
+		Actor_Voice_Over(980, 99);
+	} else if (!Game_Flag_Query(377) && Global_Variable_Query(1) < 4) {
+		ADQ_Flush();
+		ADQ_Add(31, 0, 14);
+		ADQ_Add(31, 10, 3);
+		ADQ_Add(22, 0, 3);
+		Actor_Face_Actor(31, 22, true);
+		ADQ_Add(31, 20, 13);
+		ADQ_Add(22, 10, 3);
+		ADQ_Add(31, 30, 3);
+		ADQ_Add(22, 20, 3);
+		Actor_Face_Heading(31, 271, false);
+		Game_Flag_Set(377);
+	}
+	if (Game_Flag_Query(311)) {
+		Loop_Actor_Walk_To_XYZ(0, 124.0f, 8.0f, -724.0f, 0, 1, false, 0);
+	} else if (Game_Flag_Query(309)) {
+		Loop_Actor_Walk_To_XYZ(0, 406.0f, 8.0f, -717.0f, 0, 1, false, 0);
+	} else if (!Game_Flag_Query(313)) {
+		Loop_Actor_Walk_To_XYZ(0, 100.0f, 0.0f, -300.0f, 0, 1, false, 0);
+	}
+	Game_Flag_Reset(311);
+	Game_Flag_Reset(309);
+	Game_Flag_Reset(313);
+	//return false;
+}
+
+void ScriptHF01::PlayerWalkedOut() {
+	Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+	Ambient_Sounds_Remove_All_Looping_Sounds(1);
+	if (!Game_Flag_Query(312) && !Game_Flag_Query(308) && !Game_Flag_Query(310) && !Game_Flag_Query(722)) {
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Outtake_Play(35, 1, -1);
+		Outtake_Play(38, 1, -1);
+	}
+	Game_Flag_Reset(722);
+	if (Actor_Query_Goal_Number(6) == 450) {
+		Actor_Put_In_Set(6, 97);
+		Actor_Set_At_Waypoint(6, 39, 0);
+		Actor_Set_Goal_Number(6, 599);
+	}
+	if (Actor_Query_Goal_Number(3) == 450) {
+		Actor_Put_In_Set(3, 97);
+		Actor_Set_At_Waypoint(3, 39, 0);
+		Actor_Set_Goal_Number(3, 599);
+	}
+}
+
+void ScriptHF01::DialogueQueueFlushed(int a1) {
+}
+
+void ScriptHF01::sub_4026B4() {
+	Dialogue_Menu_Clear_List();
+	if (Actor_Clue_Query(0, 13) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(440, 8, 6, 3);
+	}
+	if (!Actor_Clue_Query(0, 13) && Actor_Clue_Query(0, 22) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(450, 7, 6, 3);
+	}
+	if (Actor_Clue_Query(0, 87) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(460, 3, 5, 6);
+	}
+	if (Actor_Clue_Query(0, 118) == 1) {
+		DM_Add_To_List_Never_Repeat_Once_Selected(470, -1, 3, 8);
+	}
+	Dialogue_Menu_Add_DONE_To_List(480);
+	Dialogue_Menu_Appear(320, 240);
+	int answer = Dialogue_Menu_Query_Input();
+	Dialogue_Menu_Disappear();
+	switch (answer) {
+	case 440:
+		Actor_Says(0, 1480, 15);
+		Actor_Says(22, 70, 3);
+		Actor_Says(31, 120, 3);
+		Actor_Says(0, 1505, 14);
+		Actor_Says(22, 80, 3);
+		Actor_Says(31, 130, 3);
+		Actor_Says(22, 90, 3);
+		Actor_Says(0, 1510, 12);
+		break;
+	case 450:
+		Actor_Says(0, 1485, 16);
+		Actor_Says(22, 100, 3);
+		Actor_Says(31, 140, 12);
+		Actor_Says(22, 110, 3);
+		Actor_Says(22, 120, 3);
+		Actor_Says(31, 150, 14);
+		break;
+	case 460:
+		Actor_Says(0, 1490, 13);
+		Actor_Says(31, 160, 15);
+		Actor_Says(22, 130, 13);
+		Actor_Says(31, 170, 12);
+		Actor_Says(31, 180, 13);
+		Actor_Says(31, 190, 14);
+		Actor_Says(0, 1515, 15);
+		Actor_Says(31, 200, 3);
+		Actor_Says(0, 1520, 15);
+		Actor_Says(31, 210, 13);
+		Actor_Says(31, 220, 13);
+		Actor_Says(22, 140, 12);
+		Actor_Says(31, 230, 13);
+		Actor_Clue_Acquire(0, 101, 0, 31);
+		break;
+	case 470:
+		Actor_Says(0, 1495, 14);
+		Actor_Face_Actor(31, 0, true);
+		Actor_Says(31, 240, 13);
+		Actor_Face_Actor(31, 22, true);
+		break;
+	case 480:
+		Actor_Says(0, 1500, 16);
+		break;
+	}
+}
+
+void ScriptHF01::sub_4032DC() {
+	Actor_Says(3, 0, 3);
+	Actor_Says(0, 1400, 3);
+	Actor_Says(3, 10, 3);
+	Actor_Says(0, 1405, 3);
+	Actor_Says(3, 20, 3);
+	Actor_Says(0, 1410, 3);
+	Actor_Says(3, 30, 3);
+	Actor_Says(0, 1415, 3);
+	Actor_Says(3, 40, 3);
+	Actor_Says(3, 50, 3);
+	Actor_Says(3, 60, 3);
+	Actor_Says(3, 70, 3);
+	Actor_Says(0, 1420, 3);
+	Actor_Says(3, 80, 3);
+}
+
+void ScriptHF01::sub_403484() {
+	Actor_Says(6, 0, 3);
+	Actor_Says(0, 1425, 3);
+	Actor_Says(6, 10, 3);
+	Actor_Says(6, 20, 3);
+	Actor_Says(0, 1430, 3);
+	Actor_Says(6, 30, 3);
+	Actor_Says(0, 1435, 3);
+	Actor_Says(6, 40, 3);
+	Actor_Says(6, 50, 3);
+	Actor_Says(0, 1440, 3);
+	Actor_Says(6, 60, 3);
+	Actor_Says(6, 70, 3);
+	Actor_Says(0, 1445, 3);
+	Actor_Says(6, 80, 3);
+	Actor_Says(6, 3030, 3);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/hf02.cpp b/engines/bladerunner/script/hf02.cpp
new file mode 100644
index 0000000..8c6e24d
--- /dev/null
+++ b/engines/bladerunner/script/hf02.cpp
@@ -0,0 +1,145 @@
+/* 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 "bladerunner/script/script.h"
+
+namespace BladeRunner {
+
+void ScriptHF02::InitializeScene() {
+	if (Game_Flag_Query(567)) {
+		Setup_Scene_Information(874.0f, 47.76f, -252.0f, 775);
+		Game_Flag_Reset(567);
+	} else if (Game_Flag_Query(528)) {
+		Setup_Scene_Information(470.0f, 47.76f, -500.0f, 560);
+	} else {
+		Setup_Scene_Information(-18.0f, 47.76f, -288.0f, 275);
+	}
+	Scene_Exit_Add_2D_Exit(0, 0, 0, 30, 479, 3);
+	Scene_Exit_Add_2D_Exit(1, 207, 66, 272, 207, 3);
+	Ambient_Sounds_Add_Looping_Sound(340, 28, -100, 1);
+	Ambient_Sounds_Add_Looping_Sound(341, 33, 0, 1);
+	Ambient_Sounds_Add_Sound(181, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(182, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(183, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(184, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(185, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(186, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(188, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(189, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(190, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(191, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(192, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(193, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(194, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+	Ambient_Sounds_Add_Sound(195, 5, 70, 12, 12, -100, 100, -101, -101, 0, 0);
+}
+
+void ScriptHF02::SceneLoaded() {
+	Obstacle_Object("BARD_NEON", true);


Commit: c6011c1349364fcd9ffd29e3b44ce58bc681d3db
    https://github.com/scummvm/scummvm/commit/c6011c1349364fcd9ffd29e3b44ce58bc681d3db
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:41+02:00

Commit Message:
BLADERUNNER: mccoy script completed, walking is now animated

Changed paths:
    engines/bladerunner/script/ai_00_mccoy.cpp
    engines/bladerunner/script/ai_00_mccoy.h
    engines/bladerunner/script/aiscript_officer_leroy.cpp
    engines/bladerunner/script/aiscript_officer_leroy.h
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/script/ai_00_mccoy.cpp b/engines/bladerunner/script/ai_00_mccoy.cpp
index 2d722f1..fa37efb 100644
--- a/engines/bladerunner/script/ai_00_mccoy.cpp
+++ b/engines/bladerunner/script/ai_00_mccoy.cpp
@@ -25,150 +25,1828 @@
 namespace BladeRunner {
 
 AIScript_McCoy::AIScript_McCoy(BladeRunnerEngine *vm)
-	: AIScriptBase(vm)
-{}
+	: AIScriptBase(vm) {
+}
 
-void AIScript_McCoy::Initialize()
-{
+void AIScript_McCoy::Initialize() {
 	dword_45A0D0_animation_state = 0;
-	dword_45A0D4 = 0;
+	dword_45A0D4_animation_frame = 0;
 	dword_45A0D8 = 0;
 	dword_45A0DC = 30;
 	dword_45A0E0 = 1;
 	dword_45A0E4 = 0;
+	off_45A0EC = 0;
 	dword_45A0E8 = 3;
+	dword_45A0F0 = 3;
+	dword_45A0F4 = 20;
+	dword_45A0F8 = -1;
+	dword_45A0FC = 0;
+	off_45A100 = 0;
+	Actor_Set_Goal_Number(0, 0);
 }
 
-void AIScript_McCoy::UpdateAnimation(int *animation, int *frame)
-{
-	*animation = *frame = 0;
-	switch (dword_45A0D0_animation_state)
-	{
-		case 0:
+bool AIScript_McCoy::Update() {
+	if (dword_45A0F8 != -1) {
+		Sound_Play(dword_45A0F8, 100, 0, 0, 50);
+		dword_45A0F8 = -1;
+	}
+	switch (Actor_Query_Goal_Number(0)) {
+	case 101:
+		Actor_Set_Goal_Number(0, 102);
+		return true;
+	case 102:
+		if (Actor_Query_Inch_Distance_From_Waypoint(0, 316) < 36 && !Game_Flag_Query(375)) {
+			Actor_Change_Animation_Mode(0, 21);
+			Game_Flag_Set(375);
+		}
+		if (Actor_Query_Inch_Distance_From_Waypoint(0, 316) < 4) {
+			Actor_Set_Goal_Number(0, 103);
+		}
+		return true;
+	case 201:
+		Actor_Set_Goal_Number(0, 0);
+		if (Player_Query_Current_Set() == 55) {
+			Loop_Actor_Walk_To_XYZ(0, -166.0f, -70.19f, -501.0f, 0, 0, false, 0);
+			Actor_Face_Heading(0, 300, false);
+		} else {
+			Loop_Actor_Walk_To_XYZ(0, -461.0f, 0.0f, -373.0f, 0, 0, false, 0);
+		}
+		Player_Gains_Control();
+		return true;
+	case 212:
+		if (Global_Variable_Query(47) >= 13) {
+			Global_Variable_Set(47, 500);
+		} else if (Global_Variable_Query(47) > 0) {
+			Global_Variable_Decrement(47, 1);
+		}
+		break;
+	case 221:
+		Actor_Set_Goal_Number(0, 0);
+		Actor_Set_Goal_Number(18, 212);
+		return true;
+	case 309:
+		sub_4053E0();
+		break;
+	case 391:
+		Actor_Retired_Here(0, 12, 48, 1, -1);
+		Actor_Set_Goal_Number(0, 599);
+		break;
+	case 231:
+		sub_4053E0();
+		break;
+	}
+	return false;
+}
+
+void AIScript_McCoy::TimerExpired(int timer) {
+}
+
+void AIScript_McCoy::CompletedMovementTrack() {
+}
+
+void AIScript_McCoy::ReceivedClue(int clueId, int fromActorId) {
+	switch (clueId) {
+	case 8:
+	case 9:
+		Spinner_Set_Selectable_Destination_Flag(3, 1);
+		break;
+	case 44:
+	case 47:
+		Spinner_Set_Selectable_Destination_Flag(4, 1);
+		break;
+	case 53:
+	case 263:
+		if (Query_Difficulty_Level() == 0) {
+			Spinner_Set_Selectable_Destination_Flag(4, 1);
+		}
+		break;
+	case 90:
+		Spinner_Set_Selectable_Destination_Flag(8, 1);
+		break;
+	case 84:
+	case 113:
+	case 114:
+	case 115:
+	case 118:
+		Spinner_Set_Selectable_Destination_Flag(9, 1);
+		Spinner_Set_Selectable_Destination_Flag(8, 1);
+		break;
+	case 66:
+	case 80:
+	case 82:
+	case 83:
+		Global_Variable_Increment(49, 1);
+		break;
+	case 125:
+		Global_Variable_Increment(49, 5);
+		break;
+	case 124:
+	case 128:
+		Global_Variable_Increment(49, 3);
+		break;
+	case 120:
+	case 121:
+		Global_Variable_Increment(49, 2);
+		break;
+	case 147:
+	case 148:
+	case 149:
+	case 150:
+	case 151:
+	case 152:
+		Global_Variable_Increment(48, 1);
+		break;
+	}
+	if (Global_Variable_Query(49) > 6 && Global_Variable_Query(1) > 3 && !Actor_Clue_Query(0, 126)) {
+		Delay(500);
+		Actor_Voice_Over(3320, 99);
+		switch (clueId) {
+		case 66:
+		case 80:
+		case 82:
+		case 83:
+		case 121:
+		case 128:
+			Actor_Voice_Over(3340, 99);
+			Actor_Voice_Over(3350, 99);
+			Actor_Voice_Over(3360, 99);
+			Actor_Voice_Over(3370, 99);
+			Actor_Voice_Over(3380, 99);
+			break;
+		case 124:
+			Actor_Voice_Over(3330, 99);
+			break;
+		case 120:
+			Actor_Voice_Over(3390, 99);
+			Actor_Voice_Over(3400, 99);
+			Actor_Voice_Over(3420, 99);
+			break;
+		}
+		Actor_Clue_Acquire(0, 126, 1, -1);
+		if (clueId == 125) {
+			Actor_Voice_Over(2780, 99);
+			Actor_Voice_Over(2800, 99);
+			Actor_Voice_Over(2810, 99);
+		} else if (Actor_Clue_Query(0, 125)) {
+			Actor_Voice_Over(3430, 99);
+			Actor_Voice_Over(3440, 99);
+			Actor_Voice_Over(3450, 99);
+			Actor_Voice_Over(3460, 99);
+			Actor_Voice_Over(3470, 99);
+			Actor_Voice_Over(3480, 99);
+			Actor_Voice_Over(3490, 99);
+			Actor_Voice_Over(3500, 99);
+		} else {
+			Actor_Voice_Over(3510, 99);
+			Actor_Voice_Over(3520, 99);
+			Actor_Voice_Over(3530, 99);
+			Actor_Voice_Over(3540, 99);
+		}
+	}
+}
+
+void AIScript_McCoy::ClickedByPlayer() {
+}
+
+void AIScript_McCoy::EnteredScene(int sceneId) {
+}
+
+void AIScript_McCoy::OtherAgentEnteredThisScene() {
+}
+
+void AIScript_McCoy::OtherAgentExitedThisScene() {
+}
+
+void AIScript_McCoy::OtherAgentEnteredCombatMode() {
+}
+
+void AIScript_McCoy::ShotAtAndMissed() {
+}
+
+void AIScript_McCoy::ShotAtAndHit() {
+}
+
+void AIScript_McCoy::Retired(int byActorId) {
+	if (byActorId == 1 && Actor_Query_In_Set(1, 42)) {
+		if (Actor_Query_In_Set(3, 42) && Actor_Query_Goal_Number(3) != 599) {
+			Non_Player_Actor_Combat_Mode_On(1, 3, 1, 3, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+		} else if (Actor_Query_In_Set(6, 42) && Actor_Query_Goal_Number(6) != 599) {
+			Non_Player_Actor_Combat_Mode_On(1, 3, 1, 6, 15, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+		}
+	}
+	if (Actor_Query_In_Set(0, 41) && Actor_Query_In_Set(23, 41) && Actor_Query_In_Set(3, 41) && Actor_Query_Goal_Number(3) != 599) {
+		Non_Player_Actor_Combat_Mode_On(23, 3, 1, 3, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+	}
+	if (Actor_Query_In_Set(0, 41) && Actor_Query_In_Set(24, 41) && Actor_Query_In_Set(3, 41) && Actor_Query_Goal_Number(3) != 599) {
+		Non_Player_Actor_Combat_Mode_On(24, 3, 1, 3, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+	}
+	if (Actor_Query_In_Set(0, 41) && Actor_Query_In_Set(23, 41) && Actor_Query_In_Set(6, 41) && Actor_Query_Goal_Number(6) != 599) {
+		Non_Player_Actor_Combat_Mode_On(23, 3, 1, 6, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+	}
+	if (Actor_Query_In_Set(0, 41) && Actor_Query_In_Set(24, 41) && Actor_Query_In_Set(6, 41) && Actor_Query_Goal_Number(6) != 599) {
+		Non_Player_Actor_Combat_Mode_On(24, 3, 1, 6, 4, 4, 7, 8, 0, 0, 100, 25, 300, 0);
+	}
+}
+
+void AIScript_McCoy::GetFriendlinessModifierIfGetsClue() {
+}
+
+bool AIScript_McCoy::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	unsigned int v5;
+	unsigned int v7;
+
+	switch (newGoalNumber) {
+	case 0:
+		return true;
+	case 1:
+		sub_4058B0();
+		return true;
+	case 2:
+		sub_405920();
+		return true;
+	case 100:
+		Actor_Set_At_Waypoint(0, 315, 263);
+		dword_45A0D0_animation_state = 53;
+		dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+		Actor_Set_Invisible(0, false);
+		return true;
+	case 102:
+		Async_Actor_Walk_To_Waypoint(0, 316, 0, 1);
+		return true;
+	case 103:
+		Actor_Face_Actor(0, 8, true);
+		return true;
+	case 231:
+		Player_Set_Combat_Mode(false);
+		Preload(18);
+		Set_Enter(59, 63);
+		Player_Loses_Control();
+		Actor_Force_Stop_Walking(0);
+		Actor_Put_In_Set(0, 59);
+		Actor_Set_At_XYZ(0, 14.0f, 110.84f, -300.0f, 926);
+		Actor_Change_Animation_Mode(0, 48);
+		dword_45A0D0_animation_state = 27;
+		dword_45A0D4_animation_frame = 0;
+		flt_462714 = 2.84f;
+		flt_462710 = 110.84f;
+		off_45A100 = -6.0f;
+		return true;
+	case 230:
+		dword_45A0FC = Actor_Query_Goal_Number(1) == 215;
+		Actor_Change_Animation_Mode(0, 6);
+		return true;
+	case 220:
+		Actor_Change_Animation_Mode(0, 75);
+		return true;
+	case 212:
+		Global_Variable_Set(47, 0);
+		Player_Set_Combat_Mode_Access(false);
+		Player_Gains_Control();
+		Scene_Exits_Disable();
+		dword_45A0D0_animation_state = 68;
+		dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+		return true;
+	case 211:
+		Actor_Face_Heading(0, 512, false);
+		Actor_Face_Heading(0, 768, true);
+		if (Random_Query(0, 1)) {
+			Actor_Change_Animation_Mode(0, 18);
+		} else {
+			Actor_Change_Animation_Mode(0, 16);
+		}
+		Delay(150);
+		Actor_Change_Animation_Mode(0, 0);
+		Actor_Set_Goal_Number(0, 0);
+		Player_Gains_Control();
+		return true;
+	case 210:
+		Actor_Put_In_Set(0, 54);
+		Actor_Set_At_XYZ(0, -204.0, 24.0, -817.0, 256);
+		Actor_Set_Invisible(0, false);
+		if (Game_Flag_Query(627)) {
+			Actor_Set_Goal_Number(0, 212);
+		} else {
+			dword_45A0D0_animation_state = 53;
+			dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+			Actor_Set_Invisible(0, false);
+		}
+		return true;
+	case 200:
+		Player_Loses_Control();
+		Actor_Change_Animation_Mode(0, 0);
+		return true;
+	case 301:
+		dword_45A0D0_animation_state = 62;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 302:
+		dword_45A0D0_animation_state = 64;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 303:
+		dword_45A0D0_animation_state = 65;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 350:
+		Sound_Play(123, 50, 0, 0, 50);
+		Delay(1000);
+		Sound_Play(403, 30, 0, 0, 50);
+		Delay(1000);
+		Sound_Play(123, 50, 0, 0, 50);
+		Actor_Says(4, 1380, 3);
+		Actor_Says(0, 6610, 13);
+		Actor_Says(4, 1390, 3);
+		Actor_Says(0, 6615, 18);
+		Actor_Says(4, 1420, 3);
+		Actor_Says(0, 6625, 11);
+		Actor_Says(4, 1430, 3);
+		Actor_Says(0, 6630, 12);
+		Actor_Says(0, 6635, 17);
+		Actor_Says(0, 6640, 13);
+		Actor_Says(0, 6645, 19);
+		Actor_Says(0, 6650, 18);
+		Actor_Says(0, 6655, 11);
+		Actor_Says(4, 1440, 3);
+		Actor_Says(0, 6660, 17);
+		Actor_Says(0, 6665, 13);
+		Delay(1000);
+		Actor_Says(4, 1450, 3);
+		Actor_Says(0, 6670, 14);
+		Actor_Says(0, 6675, 11);
+		Actor_Says(4, 1460, 3);
+		Actor_Says(0, 6680, 12);
+		Actor_Says(4, 1470, 3);
+		Actor_Says(0, 6685, 13);
+		Delay(500);
+		Actor_Says(0, 6695, 16);
+		Actor_Says(0, 6700, 17);
+		Actor_Says(4, 1480, 3);
+		Actor_Says(0, 6705, 11);
+		Sound_Play(123, 50, 0, 0, 50);
+		return true;
+	case 390:
+		Actor_Force_Stop_Walking(0);
+		Player_Loses_Control();
+		flt_462710 = 48.07f;
+		off_45A100 = -4.0f;
+		flt_462714 = -20.0f;
+		if (dword_45A0D0_animation_state != 27 && dword_45A0D0_animation_state != 50) {
+			dword_45A0D0_animation_state = 50;
+			dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+		}
+		return true;
+	case 400:
+		Actor_Set_Health(0, 50, 50);
+		Game_Flag_Set(373);
+		v5 = Global_Variable_Query(45);
+		if (v5 == 1) {
+			Actor_Modify_Friendliness_To_Other(1, 0, 3);
+		} else if (v5 == 2) {
+			Actor_Modify_Friendliness_To_Other(1, 0, -5);
+			Actor_Modify_Friendliness_To_Other(5, 0, 3);
+		} else if (v5 == 3) {
+			Actor_Modify_Friendliness_To_Other(1, 0, -5);
+			Actor_Modify_Friendliness_To_Other(5, 0, 5);
+		}
+		if (Game_Flag_Query(666)) {
+			Actor_Modify_Friendliness_To_Other(1, 0, 3);
+		}
+		if (Actor_Query_Friendliness_To_Other(1, 0) < Actor_Query_Friendliness_To_Other(5, 0)) {
+			Game_Flag_Set(653);
+		}
+		v7 = Global_Variable_Query(45);
+		if (v7 == 1) {
+			if (Game_Flag_Query(653)) {
+				Global_Variable_Set(45, 0);
+			}
+		} else if (v7 == 2 || v7 == 3) {
+			if (!Game_Flag_Query(653)) {
+				Global_Variable_Set(45, 0);
+			}
+		}
+		if (!Game_Flag_Query(653)) {
+			Game_Flag_Set(461);
+		}
+		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
+		Ambient_Sounds_Remove_All_Looping_Sounds(1);
+		Global_Variable_Set(1, 5);
+		Outtake_Play(10, 0, -1);
+		if (Game_Flag_Query(666)) {
+			Chapter_Enter(5, 53, 53);
+		} else {
+			Game_Flag_Set(34);
+			Chapter_Enter(5, 10, 49);
+		}
+		return true;
+	case 500:
+		Music_Stop(3);
+		Player_Set_Combat_Mode(false);
+		Actor_Change_Animation_Mode(0, 0);
+		dword_45A0D0_animation_state = 0;
+		dword_45A0D4_animation_frame = 0;
+		Game_Flag_Set(465);
+		Set_Enter(67, 72);
+		return true;
+	}
+	return false;
+}
+
+bool AIScript_McCoy::UpdateAnimation(int *animation, int *frame) {
+	int v7, v18, v19, v46;
+	switch (dword_45A0D0_animation_state) {
+	case 71:
+		*animation = 52;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(52)) {
+			Actor_Change_Animation_Mode(0, 0);
 			*animation = 19;
-			if (dword_45A0D8 < dword_45A0DC)
-			{
-				*frame = dword_45A0E8;
-				dword_45A0D4 += dword_45A0E0;
-				if (dword_45A0D4 > dword_45A0E8)
-				{
-					dword_45A0D4 = dword_45A0E8;
-					dword_45A0E0 = -1;
-				}
-				else
-				{
-					*frame = dword_45A0D4;
-					if (dword_45A0D4 < dword_45A0E4)
-					{
-						dword_45A0D4 = dword_45A0E4;
-						dword_45A0E0 = 1;
-						*frame = dword_45A0E4;
-					}
-				}
-				dword_45A0D8++;
-			}
-			else
-			{
-				dword_45A0D4 += dword_45A0E0;
-				dword_45A0DC = 0;
-				if (dword_45A0D4 == 18 && Random_Query(0, 2))
-				{
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+			Player_Gains_Control();
+		}
+		break;
+	case 70:
+		*animation = 51;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(51)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		break;
+	case 69:
+		*animation = 50;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(50)) {
+			Actor_Change_Animation_Mode(0, 53);
+			*animation = 51;
+		}
+		break;
+	case 68:
+		*animation = 18;
+		v7 = Slice_Animation_Query_Number_Of_Frames(*animation) - 1 - Global_Variable_Query(47);
+		if (dword_45A0D4_animation_frame < v7) {
+			dword_45A0D4_animation_frame++;
+		} else if (dword_45A0D4_animation_frame > v7) {
+			dword_45A0D4_animation_frame--;
+		}
+		if (dword_45A0D4_animation_frame <= 0) {
+			Actor_Change_Animation_Mode(0, 0);
+			*animation = 19;
+			dword_45A0D0_animation_state = 0;
+			dword_45A0D4_animation_frame = 0;
+			Game_Flag_Reset(627);
+			Scene_Exits_Enable();
+			Player_Set_Combat_Mode_Access(true);
+			Actor_Set_Goal_Number(0, 0);
+		}
+		break;
+	case 67:
+		*animation = 53;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(53)) {
+			Actor_Change_Animation_Mode(0, 0);
+			*animation = 19;
+			dword_45A0D0_animation_state = 0;
+			dword_45A0D4_animation_frame = 0;
+			if (Actor_Query_Goal_Number(0) == 220) {
+				Actor_Change_Animation_Mode(0, 48);
+			}
+		}
+		break;
+	case 66:
+		*animation = 40;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(40)) {
+			Actor_Change_Animation_Mode(0, 0);
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+		}
+		break;
+	case 65:
+		*animation = 45;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(45)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 14;
+			*animation = 0;
+			Actor_Set_Goal_Number(0, 0);
+		}
+		break;
+	case 64:
+		*animation = 44;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(44)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 63;
+			*animation = 43;
+		}
+		break;
+	case 63:
+		*animation = 43;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(43)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		break;
+	case 62:
+		*animation = 42;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(42)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 63;
+			*animation = 43;
+		}
+		break;
+	case 61:
+		*animation = 41;
+		dword_45A0D4_animation_frame--;
+		if (dword_45A0D4_animation_frame <= 0) {
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+			if (Actor_Query_Goal_Number(0) == 200) {
+				Actor_Set_Goal_Number(0, 201);
+			}
+		}
+		break;
+	case 60:
+		*animation = 41;
+		if (dword_45A0D4_animation_frame < Slice_Animation_Query_Number_Of_Frames(41) - 1) {
+			dword_45A0D4_animation_frame++;
+		}
+		return true;
+	case 59:
+		*animation = 48;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(48)) {
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0DC = 0;
+			dword_45A0D0_animation_state = 0;
+			Player_Gains_Control();
+			Item_Add_To_World(109, 982, 6, -110.0, 0.0, -192.0, 0, 48, 32, false, true, false, false);
+		}
+		break;
+	case 58:
+		*animation = 47;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame == 6) {
+			v18 = Random_Query(0, 2);
+			v19 = 0;
+			if (v18 == 0) {
+				v19 = 595;
+			} else if (v18 == 1) {
+				v19 = 594;
+			} else if (v18 == 2) {
+				v19 = 593;
+			}
+			Ambient_Sounds_Play_Sound(v19, 39, 0, 0, 99);
+		}
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(*animation) - 1) { //why -1? 
+			dword_45A0D4_animation_frame = 0;
+		}
+		break;
+	case 57:
+		*animation = 46;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(46)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		if (!Game_Flag_Query(550)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 59;
+			*animation = 48;
+		}
+		break;
+	case 56:
+		*animation = 49;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(49)) {
+			dword_45A0D4_animation_frame = 0;
+			if (Actor_Query_Which_Set_In(0) == 87) {
+				dword_45A0D0_animation_state = 27;
+			} else {
+				*animation = 19;
+				dword_45A0D0_animation_state = 0;
+				Actor_Change_Animation_Mode(0, 0);
+			}
+		}
+		break;
+	case 55:
+		*animation = 32;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame == 7) {
+			Actor_Change_Animation_Mode(66, 52);
+		}
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			*animation = 19;
+			dword_45A0D0_animation_state = 0;
+		}
+		break;
+	case 53:
+		*animation = 18;
+		dword_45A0D4_animation_frame--;
+		if (dword_45A0D4_animation_frame <= 0) {
+			Actor_Change_Animation_Mode(0, 0);
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+			if (Actor_Query_Goal_Number(0) == 100) {
+				Actor_Set_Goal_Number(0, 101);
+			}
+			if (Actor_Query_Goal_Number(0) == 210) {
+				Actor_Set_Goal_Number(0, 211);
+			}
+		}
+		break;
+	case 52:
+		*animation = 31;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(31)) {
+			dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(31) - 1;
+			dword_45A0D0_animation_state = 50;
+		}
+		break;
+	case 51:
+		*animation = 28;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(28)) {
+			Player_Set_Combat_Mode(true);
+			sub_405800();
+			Actor_Set_Goal_Number(0, 0);
+			dword_45A0D4_animation_frame = 0;
+			Player_Gains_Control();
+		}
+		break;
+	case 50:
+		*animation = 18;
+		dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+		break;
+	case 49:
+		*animation = 34;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(34)) {
+			Actor_Set_Goal_Number(0, 0);
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			sub_405660();
+		}
+		break;
+	case 48:
+		*animation = 33;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(33)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 49;
+			*animation = 34;
+		}
+		break;
+	case 47:
+		*animation = 29;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(29)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 48;
+			*animation = 33;
+		}
+		break;
+	case 46:
+		Actor_Set_Invisible(0, false);
+		*animation = 36;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(36)) {
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			Player_Gains_Control();
+			sub_405660();
+			Actor_Face_Heading(0, (Actor_Query_Facing_1024(0) + 512) & 1023, false);
+		}
+		break;
+	case 45:
+		*animation = 35;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(35)) {
+			Actor_Set_Invisible(0, true);
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			sub_405660();
+		}
+		break;
+	case 44:
+		*animation = 30;
+		if (dword_45A0D4_animation_frame++ == 127) {
+			Game_Flag_Set(325);
+		}
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(30)) {
+			*animation = 19;
+			sub_405660();
+			Actor_Set_At_XYZ(0, -203.41f, -621.3f, 724.57f, 538);
+			Player_Gains_Control();
+		}
+		break;
+	case 43:
+		*animation = 38;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(38) - 1) { //why -1? 
+			dword_45A0D4_animation_frame = 0;
+		}
+		switch (dword_45A0D4_animation_frame) {
+		case 9:
+			Sound_Left_Footstep_Walk(0);
+			break;
+		case 4:
+			Sound_Right_Footstep_Walk(0);
+			break;
+		case 1:
+			Sound_Right_Footstep_Walk(0);
+			break;
+		}
+		break;
+	case 42:
+		*animation = 37;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(37) - 1) { //why -1? 
+			dword_45A0D4_animation_frame = 0;
+		}
+		switch (dword_45A0D4_animation_frame) {
+		case 9:
+			Sound_Left_Footstep_Walk(0);
+			break;
+		case 4:
+			Sound_Right_Footstep_Walk(0);
+			break;
+		case 1:
+			Sound_Right_Footstep_Walk(0);
+			break;
+		}
+		break;
+	case 41:
+		*animation = 7;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(7)) {
+			dword_45A0D4_animation_frame = 0;
+			++off_45A0EC;
+		}
+		if (dword_45A0D4_animation_frame == 9) {
+			Sound_Left_Footstep_Walk(0);
+		} else if (dword_45A0D4_animation_frame == 4) {
+			Sound_Right_Footstep_Walk(0);
+		}
+		if (Game_Flag_Query(359)) {
+			sub_4059D0(-0.2f);
+		}
+		break;
+	case 40:
+		*animation = 6;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(6)) {
+			dword_45A0D4_animation_frame = 0;
+			++off_45A0EC;
+		}
+		if (dword_45A0D4_animation_frame == 8) {
+			Sound_Left_Footstep_Walk(0);
+		} else if (dword_45A0D4_animation_frame == 3) {
+			Sound_Right_Footstep_Walk(0);
+		}
+		if (Game_Flag_Query(358)) {
+			sub_405940(0.5f);
+		}
+		break;
+	case 39:
+		*animation = 16;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(16)) {
+			dword_45A0D4_animation_frame = 0;
+			++off_45A0EC;
+		}
+		if (dword_45A0D4_animation_frame == 8) {
+			Sound_Left_Footstep_Walk(0);
+		} else if (dword_45A0D4_animation_frame == 3) {
+			Sound_Right_Footstep_Walk(0);
+		}
+		if (Game_Flag_Query(359)) {
+			sub_4059D0(-0.2f);
+		}
+		break;
+	case 38:
+		*animation = 15;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(15)) {
+			dword_45A0D4_animation_frame = 0;
+			++off_45A0EC;
+		}
+		if (dword_45A0D4_animation_frame == 9) {
+			Sound_Left_Footstep_Walk(0);
+		} else if (dword_45A0D4_animation_frame == 4) {
+			Sound_Right_Footstep_Walk(0);
+		}
+		if (Game_Flag_Query(358)) {
+			sub_405940(0.5f);
+		}
+		break;
+	case 37:
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(4)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		*animation = 4;
+		if (dword_45A0D4_animation_frame == 6) {
+			Sound_Left_Footstep_Run(0);
+		}
+		if (dword_45A0D4_animation_frame == 0) {
+			Sound_Right_Footstep_Run(0);
+		}
+		break;
+	case 36:
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(3)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		*animation = 3;
+		if (dword_45A0D4_animation_frame == 15) {
+			Sound_Left_Footstep_Walk(0);
+		}
+		if (dword_45A0D4_animation_frame == 6) {
+			Sound_Right_Footstep_Walk(0);
+		}
+		break;
+	case 32:
+		dword_45A0D4_animation_frame = 1;
+		dword_45A0D0_animation_state = 30;
+		*animation = 13;
+		break;
+	case 31:
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(14)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		*animation = 14;
+		if (dword_45A0D4_animation_frame == 5) {
+			Sound_Left_Footstep_Run(0);
+		} else if (dword_45A0D4_animation_frame == 12) {
+			Sound_Right_Footstep_Run(0);
+		}
+		break;
+	case 30:
+		*animation = 13;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(13)) {
+			dword_45A0D4_animation_frame = 0;
+		}
+		if (dword_45A0D4_animation_frame == 2) {
+			Sound_Right_Footstep_Walk(0);
+		} else if (dword_45A0D4_animation_frame == 10) {
+			Sound_Left_Footstep_Walk(0);
+		}
+		break;
+	case 29:
+		v46 = dword_45A0D4_animation_frame + dword_45A0E0;
+		*animation = 18;
+		dword_45A0D4_animation_frame = v46;
+		if (v46 < 14) {
+			dword_45A0E0 = 1;
+		}
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(*animation)) {
+			Actor_Change_Animation_Mode(0, 48);
+			*animation = 18;
+			dword_45A0D0_animation_state = 27;
+			dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+		}
+		break;
+	case 28:
+		*animation = 5;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(5)) {
+			dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(*animation) - 1;
+			dword_45A0D0_animation_state = 50;
+			sub_4054F0();
+		}
+		break;
+	case 27:
+		*animation = 18;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(18)) {
+			dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(*animation) - 1;
+			dword_45A0D0_animation_state = 50;
+			sub_4054F0();
+			if (Actor_Query_Goal_Number(0) == 220) {
+				Actor_Set_Goal_Number(0, 221);
+			}
+		}
+		break;
+	case 26:
+		*animation = 17;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(17)) {
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+			Actor_Change_Animation_Mode(0, 0);
+		}
+		break;
+	case 25:
+		*animation = 17;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(17)) {
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+			Actor_Change_Animation_Mode(0, 0);
+		}
+		break;
+	case 24:
+		*animation = 1;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(1)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 14;
+			*animation = 0;
+			Actor_Change_Animation_Mode(0, 4);
+		}
+		break;
+	case 23:
+		*animation = 1;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(1)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 14;
+			*animation = 0;
+			Actor_Change_Animation_Mode(0, 4);
+		}
+		break;
+	case 22:
+		dword_45A0D4_animation_frame = 0;
+		dword_45A0D0_animation_state = 17;
+		*animation = 12;
+		break;
+	case 21:
+		*animation = 12;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame == 1 && Actor_Query_Goal_Number(0) == 230 && dword_45A0FC == 1) {
+			dword_45A0F8 = 27;
+		}
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(12)) {
+			dword_45A0D0_animation_state = 17;
+			dword_45A0D4_animation_frame = 0;
+			*animation = 12;
+			if (Actor_Query_Goal_Number(0) == 230) {
+				dword_45A0D4_animation_frame = 0;
+				dword_45A0D0_animation_state = 21;
+				dword_45A0FC = 1;
+				*animation = 12;
+			}
+		}
+		break;
+	case 19:
+		*animation = 11;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= 12) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 14;
+			*animation = 0;
+		}
+		break;
+	case 18:
+		*animation = 10;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(10)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 17;
+			*animation = 12;
+		}
+		break;
+	case 17:
+		*animation = 12;
+		dword_45A0D4_animation_frame = 0;
+		// weird, but thats in game code
+		if (Slice_Animation_Query_Number_Of_Frames(12) <= 0) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 17;
+		}
+		break;
+	case 16:
+		*animation = 9;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(9)) {
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+		}
+		break;
+	case 15:
+		*animation = 8;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(8)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 14;
+			*animation = 0;
+		}
+		break;
+	case 14:
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(0)) {
+			dword_45A0D0_animation_state = 14;
+			dword_45A0D4_animation_frame = 0;
+		}
+		*animation = 0;
+		break;
+	case 13:
+		*animation = 19;
+		if (dword_45A0D4_animation_frame < Slice_Animation_Query_Number_Of_Frames(19) / 2) {
+			dword_45A0D4_animation_frame -= 3;
+			if (dword_45A0D4_animation_frame <= 0) {
+				dword_45A0D4_animation_frame = 0;
+				*animation = dword_46271C;
+				dword_45A0D0_animation_state = dword_462718;
+			}
+		} else {
+			dword_45A0D4_animation_frame += 3;
+			if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(19)) {
+				dword_45A0D4_animation_frame = 0;
+				*animation = dword_46271C;
+				dword_45A0D0_animation_state = dword_462718;
+			}
+		}
+		break;
+	case 12:
+		*animation = 27;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(27)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 11:
+		*animation = 26;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(26)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 10:
+		*animation = 25;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(25)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 9:
+		*animation = 24;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(24)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 8:
+		*animation = 23;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(23)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 7:
+		*animation = 22;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(22)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 6:
+		*animation = 27;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(27)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 5:
+		*animation = 21;
+		dword_45A0D4_animation_frame++;
+		if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(21)) {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 3;
+			*animation = 20;
+		}
+		break;
+	case 3:
+	case 4:
+		if (dword_45A0D4_animation_frame == 0 && !Game_Flag_Query(236)) {
+			dword_45A0D4_animation_frame = 1;
+			dword_45A0D0_animation_state = dword_45A0F0;
+			*animation = dword_45A0F4;
+			dword_45A0F0 = 4;
+			dword_45A0F4 = 20;
+		} else if (dword_45A0D4_animation_frame <= 4 && Game_Flag_Query(236)) {
+			Game_Flag_Reset(236);
+			*animation = 19;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 0;
+		} else {
+			*animation = 20;
+			dword_45A0D4_animation_frame++;
+			if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(20)) {
+				dword_45A0D4_animation_frame = 0;
+			}
+		}
+		break;
+	case 0:
+		*animation = 19;
+		if (dword_45A0D8 < dword_45A0DC) {
+			//*frame = dword_45A0E8;
+			dword_45A0D4_animation_frame += dword_45A0E0;
+			if (dword_45A0D4_animation_frame > dword_45A0E8) {
+				dword_45A0D4_animation_frame = dword_45A0E8;
+				dword_45A0E0 = -1;
+			} else if (dword_45A0D4_animation_frame < dword_45A0E4) {
+				dword_45A0D4_animation_frame = dword_45A0E4;
+				dword_45A0E0 = 1;
+			}
+			dword_45A0D8++;
+		} else {
+			dword_45A0D4_animation_frame += dword_45A0E0;
+			dword_45A0DC = 0;
+			if (dword_45A0D4_animation_frame == 18 && Random_Query(0, 2)) {
+				dword_45A0E0 = -1;
+				dword_45A0D8 = 0;
+				dword_45A0E4 = 14;
+				dword_45A0E8 = 18;
+				dword_45A0DC = Random_Query(0, 30);
+			}
+			if (dword_45A0D4_animation_frame == 26) {
+				if (Random_Query(0, 2)) {
 					dword_45A0E0 = -1;
 					dword_45A0D8 = 0;
-					dword_45A0E4 = 14;
-					dword_45A0E8 = 18;
+					dword_45A0E4 = 23;
+					dword_45A0E8 = 26;
 					dword_45A0DC = Random_Query(0, 30);
 				}
-				if (dword_45A0D4 == 26)
-				{
-					if (Random_Query(0, 2))
-					{
-						dword_45A0E0 = -1;
-						dword_45A0D8 = 0;
-						dword_45A0E4 = 23;
-						dword_45A0E8 = 26;
-						dword_45A0DC = Random_Query(0, 30);
-						}
-				}
-				if (dword_45A0D4 >= Slice_Animation_Query_Number_Of_Frames(19))
-				{
-					dword_45A0D4 = 0;
-					if (Random_Query(0, 2))
-					{
-						dword_45A0D8 = 0;
-						dword_45A0E4 = 0;
-						dword_45A0E8 = 3;
-						dword_45A0DC = Random_Query(0, 45);
-					}
-				}
-				*frame = dword_45A0D4;
-				if (dword_45A0D4 < 0)
-				{
-					*frame = Slice_Animation_Query_Number_Of_Frames(19) - 1;
-					dword_45A0D4 = *frame;
+			}
+			if (dword_45A0D4_animation_frame >= Slice_Animation_Query_Number_Of_Frames(19)) {
+				dword_45A0D4_animation_frame = 0;
+				if (Random_Query(0, 2)) {
+					dword_45A0D8 = 0;
+					dword_45A0E4 = 0;
+					dword_45A0E8 = 3;
+					dword_45A0DC = Random_Query(0, 45);
 				}
 			}
+			if (dword_45A0D4_animation_frame < 0) {
+				dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(19) - 1;
+			}
+		}
+		break;
+	}
+	*frame = dword_45A0D4_animation_frame;
+	return true;
+}
+
+bool AIScript_McCoy::ChangeAnimationMode(int mode) {
+	int v2;
+	switch (mode) {
+	case 85:
+		dword_45A0D4_animation_frame = 0;
+		dword_45A0D0_animation_state = 69;
+		return true;
+	case 75:
+		dword_45A0D0_animation_state = 67;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 68:
+		dword_45A0D0_animation_state = 29;
+		dword_45A0D4_animation_frame = Slice_Animation_Query_Number_Of_Frames(18) - 1;
+		dword_45A0E0 = -1;
+		return true;
+	case 65:
+	case 67:
+		dword_45A0D0_animation_state = 43;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 64:
+	case 66:
+		dword_45A0D0_animation_state = 42;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 53:
+		if (dword_45A0D0_animation_state != 60 && (Player_Query_Current_Set() == 55 || Player_Query_Current_Set() == 13)) {
+			dword_45A0D0_animation_state = 60;
+			dword_45A0D4_animation_frame = 0;
+		} else {
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0D0_animation_state = 70;
+		}
+		return true;
+	case 52:
+		dword_45A0D0_animation_state = 55;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 51:
+		dword_45A0D0_animation_state = 27;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 49:
+		dword_45A0D0_animation_state = 28;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 48:
+		switch (dword_45A0D0_animation_state) {
+		case 14:
+			dword_45A0D0_animation_state = 28;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 13:
+			dword_45A0D0_animation_state = 22;
+			dword_45A0D4_animation_frame = 0;
+			return true;
+		case 10:
+			dword_45A0D0_animation_state = 18;
+			dword_45A0D4_animation_frame = 8 * (13 - dword_45A0D4_animation_frame) / 13;
+			return true;
+		case 8:
+		case 9:
+		case 12:
+			return true;
+		case 11:
+			dword_45A0D0_animation_state = 18;
+			dword_45A0D4_animation_frame = 0;
 			break;
+		case 7:
+			dword_45A0D0_animation_state = 14;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 0:
+		case 1:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+			dword_45A0D0_animation_state = 15;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		default:
+			if (dword_45A0D0_animation_state != 50) {
+				dword_45A0D0_animation_state = 27;
+				dword_45A0D4_animation_frame = 0;
+			}
+			break;
+		}
+		return true;
+	case 47:
+		dword_45A0D0_animation_state = 41;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 46:
+		dword_45A0D0_animation_state = 40;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 45:
+		dword_45A0D0_animation_state = 39;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 44:
+		dword_45A0D0_animation_state = 38;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 42:
+		dword_45A0D0_animation_state = 46;
+		dword_45A0D4_animation_frame = 0;
+		Player_Loses_Control();
+		return true;
+	case 41:
+		dword_45A0D0_animation_state = 45;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 40:
+		dword_45A0D0_animation_state = 44;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 39:
+		dword_45A0D4_animation_frame = 0;
+		dword_45A0D0_animation_state = 52;
+		if (Player_Query_Current_Set() == 27) {
+			dword_45A0D4_animation_frame = 23;
+		}
+		return true;
+	case 38:
+		dword_45A0D0_animation_state = 47;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 29:
+		Player_Loses_Control();
+		dword_45A0D4_animation_frame = 0;
+		dword_45A0D0_animation_state = 71;
+		return true;
+	case 23:
+		dword_45A0D0_animation_state = 66;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 22:
+		if (Random_Query(0, 1)) {
+			dword_45A0D0_animation_state = 23;
+		} else {
+			dword_45A0D0_animation_state = 24;
+		}
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 21:
+		switch (dword_45A0D0_animation_state) {
+		case 0:
+		case 2:
+		case 3:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+			dword_45A0D0_animation_state = 28;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 1:
+		case 8:
+			dword_45A0D0_animation_state = 27;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		default:
 
-		// Continue walking (follows state 32)
-		case 30:
-			*animation = 13;
-			if (++dword_45A0D4 >= Slice_Animation_Query_Number_Of_Frames(13))
-				dword_45A0D4 = 0;
-			*frame = dword_45A0D4;
+			if (Random_Query(0, 1)) {
+				dword_45A0D0_animation_state = 26;
+			} else {
+				dword_45A0D0_animation_state = 25;
+			}
+			dword_45A0D4_animation_frame = 0;
+			break;
+		}
+		return true;
+	case 20:
+		v2 = Actor_Query_Which_Set_In(0);
+		if (v2 == 27) {
+			dword_45A0D0_animation_state = 51;
+			dword_45A0D4_animation_frame = 0;
+			Player_Loses_Control();
+			Game_Flag_Set(210);
+		} else if (v2 == 70 || v2 == 87) {
+			dword_45A0D0_animation_state = 56;
+			dword_45A0D4_animation_frame = 0;
+		}
+		return true;
+	case 19:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 12;
+			dword_46271C = 27;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 12;
+			dword_45A0F4 = 27;
+		}
+		return true;
+	case 18:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 11;
+			dword_46271C = 26;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 11;
+			dword_45A0F4 = 26;
+		}
+		return true;
+	case 17:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 10;
+			dword_46271C = 25;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 10;
+			dword_45A0F4 = 25;
+		}
+		return true;
+	case 16:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 9;
+			dword_46271C = 24;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 9;
+			dword_45A0F4 = 24;
+		}
+		return true;
+	case 15:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 8;
+			dword_46271C = 23;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 8;
+			dword_45A0F4 = 23;
+		}
+		return true;
+	case 11:
+	case 14:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 7;
+			dword_46271C = 22;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 7;
+			dword_45A0F4 = 22;
+		}
+		return true;
+	case 10:
+	case 13:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 6;
+			dword_46271C = 27;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 6;
+			dword_45A0F4 = 27;
+		}
+		return true;
+	case 9:
+	case 12:
+		if (dword_45A0D0_animation_state < 3 || dword_45A0D0_animation_state > 12) {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 5;
+			dword_46271C = 21;
+		} else {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 5;
+			dword_45A0F4 = 21;
+		}
+		return true;
+	case 8:
+		if (dword_45A0D0_animation_state != 27 && dword_45A0D0_animation_state != 50) {
+			dword_45A0D0_animation_state = 37;
+			dword_45A0D4_animation_frame = 0;
+		}
+		return true;
+	case 7:
+		if (dword_45A0D0_animation_state != 27 && dword_45A0D0_animation_state != 50) {
+			dword_45A0D0_animation_state = 36;
+			dword_45A0D4_animation_frame = 0;
+		}
+		return true;
+	case 6:
+		dword_45A0D0_animation_state = 21;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 5:
+		switch (dword_45A0D0_animation_state) {
+		case 1:
+		case 2:
+		case 5:
+			dword_45A0D0_animation_state = 14;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 0:
+		case 3:
+		case 4:
+			dword_45A0D0_animation_state = 15;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		default:
+			dword_45A0D0_animation_state = 18;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		}
+		return true;
+	case 4:
+		switch (dword_45A0D0_animation_state) {
+		case 22:
+			dword_45A0D0_animation_state = 19;
+			dword_45A0D4_animation_frame = 41;
+			break;
+		case 18:
+			dword_45A0D0_animation_state = 19;
+			dword_45A0D4_animation_frame = 13 * ((8 - dword_45A0D4_animation_frame) / 8);
+			break;
+		case 17:
+		case 20:
+			dword_45A0D0_animation_state = 19;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 16:
+			dword_45A0D0_animation_state = 15;
+			dword_45A0D4_animation_frame = 12 - 12 * dword_45A0D4_animation_frame / 16;
+			break;
+		case 14:
+		case 15:
+		case 19:
+		case 21:
+		case 2:
+		case 3:
+			return true;
+		default:
+			dword_45A0D0_animation_state = 15;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 13:
+			dword_45A0D0_animation_state = 16;
+			dword_45A0D4_animation_frame = 0;
+			break;
+		case 0:
+		case 1:
+		case 4:
+		case 5:
+		case 6:
+		case 7:
+		case 8:
+		case 9:
+		case 10:
+		case 11:
+		case 12:
+			dword_45A0D0_animation_state = 0;
+			dword_45A0D4_animation_frame = 0;
+			dword_45A0DC = 0;
+			break;
+		}
+		return true;
+	case 3:
+		if (dword_45A0D0_animation_state >= 3 && dword_45A0D0_animation_state <= 12) {
+			Game_Flag_Reset(236);
+			dword_45A0F0 = 4;
+			dword_45A0F4 = 20;
+		} else {
+			dword_45A0D0_animation_state = 13;
+			dword_462718 = 3;
+			dword_46271C = 20;
+		}
+		return true;
+	case 2:
+		if (dword_45A0D0_animation_state == 27 || dword_45A0D0_animation_state == 50) {
+			return true;
+		}
+		if (!Game_Flag_Query(550)) {
+			dword_45A0D0_animation_state = 31;
+			dword_45A0D4_animation_frame = 0;
+			return true;
+		}
+		dword_45A0D0_animation_state = 58;
+		dword_45A0D4_animation_frame = 4;
+		return true;
+	case 1:
+		if (dword_45A0D0_animation_state == 27 || dword_45A0D0_animation_state == 50) {
+			return true;
+		}
+		if (!Game_Flag_Query(550)) {
+			dword_45A0D0_animation_state = 32;
+			dword_45A0D4_animation_frame = 0;
+			return true;
+		}
+		dword_45A0D0_animation_state = 58;
+		dword_45A0D4_animation_frame = 0;
+		return true;
+	case 0:
+		if (Game_Flag_Query(550)) {
+			if (dword_45A0D4_animation_frame > 6) {
+				dword_45A0D0_animation_state = 57;
+				dword_45A0D4_animation_frame = 0;
+				return true;
+			}
+			int v3 = Random_Query(0, 2);
+			int v4 = 0;
+			if (v3 == 0) {
+				v4 = 595;
+			} else if (v3 == 1) {
+				v4 = 594;
+			} else if (v3 == 2) {
+				v4 = 593;
+			}
+			Ambient_Sounds_Play_Sound(v4, 39, 0, 0, 99);
+			dword_45A0D0_animation_state = 57;
+			dword_45A0D4_animation_frame = 0;
+			return true;
+		}
+		if (dword_45A0D0_animation_state == 60) {
+			dword_45A0D0_animation_state = 61;
+			return true;
+		}
+		dword_45A0D0_animation_state = 0;
+		dword_45A0D4_animation_frame = 0;
+		dword_45A0DC = 0;
+		return true;
+	}
+	return true;
+}
 
-			if (dword_45A0D4 == 2)
-				; //Sound_Right_Footstep_Walk(0);
-			else if (dword_45A0D4 == 10)
-				; //Sound_Left_Footstep_Walk(0);
+void AIScript_McCoy::QueryAnimationState(int *animationState, int *a2, int *a3, int *a4) {
+	*animationState = dword_45A0D0_animation_state;
+	*a2 = dword_45A0D4_animation_frame;
+	*a3 = dword_462718;
+	*a4 = dword_46271C;
+}
 
-			break;
+void AIScript_McCoy::SetAnimationState(int animationState, int a2, int a3, int a4) {
+	dword_45A0D0_animation_state = animationState;
+	dword_45A0D4_animation_frame = a2;
+	dword_462718 = a3;
+	dword_46271C = a4;
+}
 
-		// Start walking
-		case 32:
-			dword_45A0D4 = 1;
-			dword_45A0D0_animation_state = 30;
-			*animation = 13;
-			*frame = 1;
-			break;
+bool AIScript_McCoy::ReachedMovementTrackWaypoint() {
+	return true;
+}
 
-		case 58:
-			*animation = 47;
-			if (dword_45A0D4++ == 5) {
-				int stepSound;
-				switch (Random_Query(0, 2)) {
-				case 0:
-					stepSound = 595;
-					break;
-				case 1:
-					stepSound = 594;
-					break;
-				default:
-					stepSound = 593;
-				}
-				(void)stepSound;
-				// Ambient_Sounds_Play_Sound(stepSound, 39, 0, 0, 99);
+void AIScript_McCoy::sub_4053E0() {
+	float x, y, z;
+	Actor_Query_XYZ(0, &x, &y, &z);
+	flt_462710 = flt_462710 + off_45A100;
+	if (flt_462714 < flt_462710) {
+		off_45A100 = off_45A100 - 0.2f;
+	} else {
+		flt_462710 = flt_462714;
+		Actor_Set_Goal_Number(0, 0);
+		Actor_Retired_Here(0, 12, 48, 1, -1);
+	}
+	return Actor_Set_At_XYZ(0, x, flt_462710, z, Actor_Query_Facing_1024(0));
+}
+
+void AIScript_McCoy::sub_4054F0() {
+	if (Actor_Query_Which_Set_In(0) == 87 && Actor_Query_Goal_Number(0) != 390 && !Game_Flag_Query(682)) {
+		float x, y, z;
+		Actor_Query_XYZ(0, &x, &y, &z);
+		if ((z < 220.0f) && (-210.0f < x) && (-70.0f > x)) {
+			Game_Flag_Set(682);
+			Scene_Loop_Set_Default(3);
+			Scene_Loop_Start_Special(2, 2, 1);
+			Actor_Set_Goal_Number(0, 390);
+			Actor_Query_XYZ(64, &x, &y, &z);
+			if (-200.0 < x && -62.0f > x) {
+				Actor_Set_Goal_Number(64, 309);
 			}
-			if (dword_45A0D4 > Slice_Animation_Query_Number_Of_Frames(*animation) - 2)
-				dword_45A0D4 = 0;
-			*frame = dword_45A0D4;
-			break;
+		} else {
+			Actor_Set_Goal_Number(0, 391);
+		}
 	}
 }
 
-void AIScript_McCoy::ChangeAnimationMode(int mode)
-{
-	switch (mode)
-	{
-		case 0:
-			dword_45A0D0_animation_state = 0;
-			dword_45A0D4 = 0;
-			break;
+void AIScript_McCoy::sub_405660() {
+	if (Game_Flag_Query(550)) {
+		if (dword_45A0D4_animation_frame <= 6) {
+			int v1 = Random_Query(0, 2);
+			int v2 = 0;
+			if (v1 == 0) {
+				v2 = 595;
+			} else if (v1 == 1) {
+				v2 = 594;
+			} else if (v1 == 2) {
+				v2 = 593;
+			}
+			Ambient_Sounds_Play_Sound(v2, 39, 0, 0, 99);
+		}
+		dword_45A0D0_animation_state = 57;
+		dword_45A0D4_animation_frame = 0;
+		return;
+	}
+	switch (dword_45A0D0_animation_state) {
+	case 17:
+	case 20:
+	case 21:
+	case 36:
+		dword_45A0D0_animation_state = 16;
+		dword_45A0D4_animation_frame = 0;
+		break;
+	case 16:
+	case 25:
+	case 26:
+		break;
+	case 15:
+		dword_45A0D0_animation_state = 16;
+		dword_45A0D4_animation_frame = 16 - 16 * dword_45A0D4_animation_frame / 12;
+		break;
+	case 14:
+		dword_45A0D0_animation_state = 16;
+		dword_45A0D4_animation_frame = 0;
+		break;
+	case 3:
+	case 4:
+	case 5:
+	case 6:
+	case 7:
+	case 8:
+	case 9:
+	case 10:
+	case 11:
+	case 12:
+		Game_Flag_Set(236);
+		dword_45A0D8 = 0;
+		dword_45A0DC = 30;
+		dword_45A0E4 = 0;
+		dword_45A0E0 = 1;
+		dword_45A0E8 = 3;
+		break;
+	case 60:
+		dword_45A0D0_animation_state = 61;
+		break;
+	default:
+		dword_45A0D0_animation_state = 0;
+		dword_45A0D4_animation_frame = 0;
+		dword_45A0DC = 0;
+	}
+}
 
-		case 1:
-			dword_45A0D0_animation_state = 32;
-			break;
+void AIScript_McCoy::sub_405800() {
+	switch (dword_45A0D0_animation_state) {
+	case 36:
+	case 37:
+	case 40:
+	case 41:
+	case 51:
+		dword_45A0D0_animation_state = 14;
+		dword_45A0D4_animation_frame = 0;
+		break;
+	case 22:
+		dword_45A0D0_animation_state = 19;
+		dword_45A0D4_animation_frame = 41;
+		break;
+	case 18:
+		dword_45A0D0_animation_state = 19;
+		dword_45A0D4_animation_frame = 13 * ((8 - dword_45A0D4_animation_frame) / 8);
+		break;
+	case 17:
+	case 20:
+		dword_45A0D0_animation_state = 19;
+		dword_45A0D4_animation_frame = 0;
+		break;
+	case 16:
+		dword_45A0D4_animation_frame = 12 - 12 * dword_45A0D4_animation_frame / 16;
+		dword_45A0D0_animation_state = 15;
+		break;
+	case 14:
+	case 15:
+	case 19:
+	case 21:
+		break;
+	default:
+		dword_45A0D0_animation_state = 15;
+		dword_45A0D4_animation_frame = 0;
+		break;
+	}
+}
+
+void AIScript_McCoy::sub_4058B0() {
+	int v0 = Actor_Query_Which_Set_In(0);
+	if (v0 == 27) {
+		dword_45A0D0_animation_state = 51;
+		dword_45A0D4_animation_frame = 0;
+		Player_Loses_Control();
+		Game_Flag_Set(210);
+	} else if (v0 == 70 || v0 == 87) {
+		dword_45A0D0_animation_state = 56;
+		dword_45A0D4_animation_frame = 0;
+	}
+}
+
+void AIScript_McCoy::sub_405920() {
+	dword_45A0D4_animation_frame = 0;
+	dword_45A0D0_animation_state = 47;
+}
+
+void AIScript_McCoy::sub_405940(float a1) {
+	float x, y, z;
+	int currentAngle = Actor_Query_Facing_1024(0);
+	Actor_Query_XYZ(0, &x, &y, &z);
+	int angle = currentAngle - 12;
+	y = y + a1;
+	if (angle < 0) {
+		angle = currentAngle + 1012;
+	}
+	if (angle > 1023) {
+		angle -= 1024;
+	}
+	Actor_Set_At_XYZ(0, x, y, z, angle);
+}
+
+void AIScript_McCoy::sub_4059D0(float a1) {
+	float x, y, z;
+	int currentAngle = Actor_Query_Facing_1024(0);
+	Actor_Query_XYZ(0, &x, &y, &z);
+	int angle = currentAngle + 15;
+	y = y + a1;
+	if (angle < 0) {
+		angle = currentAngle + 1039;
+	}
+	if (angle > 1023) {
+		angle -= 1024;
 	}
+	return Actor_Set_At_XYZ(0, x, y, z, angle);
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/ai_00_mccoy.h b/engines/bladerunner/script/ai_00_mccoy.h
index 11c9f1d..eedae2f 100644
--- a/engines/bladerunner/script/ai_00_mccoy.h
+++ b/engines/bladerunner/script/ai_00_mccoy.h
@@ -25,21 +25,58 @@
 #include "bladerunner/bladerunner.h"
 
 namespace BladeRunner {
-
 class AIScript_McCoy : public AIScriptBase {
 	int dword_45A0D0_animation_state;
-	int dword_45A0D4;
+	int dword_45A0D4_animation_frame;
 	int dword_45A0D8;
 	int dword_45A0DC;
 	int dword_45A0E0;
 	int dword_45A0E4;
+	float off_45A0EC;
 	int dword_45A0E8;
+	int dword_45A0F0;
+	int dword_45A0F4;
+	int dword_45A0F8;
+	int dword_45A0FC;
+	int dword_462718;
+	int dword_46271C;
+	float off_45A100;
+	float flt_462710;
+	float flt_462714;
+
 public:
 	AIScript_McCoy(BladeRunnerEngine *vm);
 
 	void Initialize();
-	void UpdateAnimation(int *animation, int *frame);
-	void ChangeAnimationMode(int mode);
-};
+	bool Update();
+	void TimerExpired(int timer);
+	void CompletedMovementTrack();
+	void ReceivedClue(int clueId, int fromActorId);
+	void ClickedByPlayer();
+	void EnteredScene(int sceneId);
+	void OtherAgentEnteredThisScene();
+	void OtherAgentExitedThisScene();
+	void OtherAgentEnteredCombatMode();
+	void ShotAtAndMissed();
+	void ShotAtAndHit();
+	void Retired(int byActorId);
+	void GetFriendlinessModifierIfGetsClue();
+	bool GoalChanged(int currentGoalNumber, int newGoalNumber);
+	bool UpdateAnimation(int *animation, int *frame);
+	bool ChangeAnimationMode(int mode);
+	void QueryAnimationState(int *animationState, int *a2, int *a3, int *a4);
+	void SetAnimationState(int animationState, int a2, int a3, int a4);
+	bool ReachedMovementTrackWaypoint();
 
+private:
+	void sub_4053E0();
+	void sub_4054F0();
+	void sub_405660();
+	void sub_405800();
+	void sub_4058B0();
+	void sub_405920();
+	void sub_405940(float a1);
+	void sub_4059D0(float a1);
+	
+};
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/aiscript_officer_leroy.cpp b/engines/bladerunner/script/aiscript_officer_leroy.cpp
index 1acb096..f388ede 100644
--- a/engines/bladerunner/script/aiscript_officer_leroy.cpp
+++ b/engines/bladerunner/script/aiscript_officer_leroy.cpp
@@ -40,7 +40,51 @@ void AIScript_Officer_Leroy::Initialize()
 	// Actor_Set_Frame_Rate_FPS(23, 8);
 }
 
-void AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
+bool AIScript_Officer_Leroy::Update() {
+	return false;
+}
+
+void AIScript_Officer_Leroy::TimerExpired(int timer) {
+}
+
+void AIScript_Officer_Leroy::CompletedMovementTrack() {
+}
+
+void AIScript_Officer_Leroy::ReceivedClue(int clueId, int fromActorId) {
+}
+
+void AIScript_Officer_Leroy::ClickedByPlayer() {
+}
+
+void AIScript_Officer_Leroy::EnteredScene(int sceneId) {
+}
+
+void AIScript_Officer_Leroy::OtherAgentEnteredThisScene() {
+}
+
+void AIScript_Officer_Leroy::OtherAgentExitedThisScene() {
+}
+
+void AIScript_Officer_Leroy::OtherAgentEnteredCombatMode() {
+}
+
+void AIScript_Officer_Leroy::ShotAtAndMissed() {
+}
+
+void AIScript_Officer_Leroy::ShotAtAndHit() {
+}
+
+void AIScript_Officer_Leroy::Retired(int byActorId) {
+}
+
+void AIScript_Officer_Leroy::GetFriendlinessModifierIfGetsClue() {
+}
+
+bool AIScript_Officer_Leroy::GoalChanged(int currentGoalNumber, int newGoalNumber) {
+	return false;
+}
+
+bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
 {
 	if (var_45D5B8 == 0) {
 		*animation = 589;
@@ -70,11 +114,11 @@ void AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
 			var_45D5B8 = Random_Query(0, 2);
 		}
 	}
-
 	*frame = var_45D5B4_frame;
+	return true;
 }
 
-void AIScript_Officer_Leroy::ChangeAnimationMode(int mode)
+bool AIScript_Officer_Leroy::ChangeAnimationMode(int mode)
 {
 	switch (mode)
 	{
@@ -82,6 +126,16 @@ void AIScript_Officer_Leroy::ChangeAnimationMode(int mode)
 			var_45D5B0_animation_state = 32;
 			break;
 	}
+	return true;
+}
+
+void AIScript_Officer_Leroy::QueryAnimationState(int *animationState, int *a2, int *a3, int *a4) {
+}
+
+void AIScript_Officer_Leroy::SetAnimationState(int animationState, int a2, int a3, int a4) {
 }
 
+bool AIScript_Officer_Leroy::ReachedMovementTrackWaypoint() {
+	return false;
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/aiscript_officer_leroy.h b/engines/bladerunner/script/aiscript_officer_leroy.h
index 7d81b62..152ba83 100644
--- a/engines/bladerunner/script/aiscript_officer_leroy.h
+++ b/engines/bladerunner/script/aiscript_officer_leroy.h
@@ -34,8 +34,25 @@ public:
 	AIScript_Officer_Leroy(BladeRunnerEngine *vm);
 
 	void Initialize();
-	void UpdateAnimation(int *animation, int *frame);
-	void ChangeAnimationMode(int mode);
+	bool Update();
+	void TimerExpired(int timer);
+	void CompletedMovementTrack();
+	void ReceivedClue(int clueId, int fromActorId);
+	void ClickedByPlayer();
+	void EnteredScene(int sceneId);
+	void OtherAgentEnteredThisScene();
+	void OtherAgentExitedThisScene();
+	void OtherAgentEnteredCombatMode();
+	void ShotAtAndMissed();
+	void ShotAtAndHit();
+	void Retired(int byActorId);
+	void GetFriendlinessModifierIfGetsClue();
+	bool GoalChanged(int currentGoalNumber, int newGoalNumber);
+	bool UpdateAnimation(int *animation, int *frame);
+	bool ChangeAnimationMode(int mode);
+	void QueryAnimationState(int *animationState, int *a2, int *a3, int *a4);
+	void SetAnimationState(int animationState, int a2, int a3, int a4);
+	bool ReachedMovementTrackWaypoint();
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index e9f9b60..4ecec287 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -146,7 +146,9 @@ void Script::SceneFrameAdvanced(int frame) {
 
 void Script::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
 	_inScriptCounter++;
-	_currentScript->ActorChangedGoal(actorId, newGoal, oldGoal, currentSet);
+	//TODO remove this check
+	if(_currentScript)
+		_currentScript->ActorChangedGoal(actorId, newGoal, oldGoal, currentSet);
 	_inScriptCounter--;
 }
 
@@ -788,10 +790,27 @@ void ScriptBase::Sound_Play_Speech_Line(int actorId, int speechId, int a3, int a
 	//TODO
 	warning("Sound_Play_Speech_Line(%d, %d, %d, %d, %d)", actorId, speechId, a3, a4, a5);
 }
-// ScriptBase::Sound_Left_Footstep_Walk
-// ScriptBase::Sound_Right_Footstep_Walk
-// ScriptBase::Sound_Left_Footstep_Run
-// ScriptBase::Sound_Right_Footstep_Run
+
+void ScriptBase::Sound_Left_Footstep_Walk(int actorId) {
+	//TODO
+	warning("Sound_Left_Footstep_Walk(%d)", actorId);
+}
+
+void ScriptBase::Sound_Right_Footstep_Walk(int actorId) {
+	//TODO
+	warning("Sound_Right_Footstep_Walk(%d)", actorId);
+}
+
+void ScriptBase::Sound_Left_Footstep_Run(int actorId) {
+	//TODO
+	warning("Sound_Left_Footstep_Run(%d)", actorId);
+}
+
+void ScriptBase::Sound_Right_Footstep_Run(int actorId) {
+	//TODO
+	warning("Sound_Right_Footstep_Run(%d)", actorId);
+}
+
 // ScriptBase::Sound_Walk_Shuffle_Stop
 
 void ScriptBase::Footstep_Sounds_Set(int walkboxId, int stepSound) {
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 20ed845..a4c8ad0 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -154,10 +154,10 @@ protected:
 	int Random_Query(int min, int max);
 	void Sound_Play(int id, int volume, int panFrom, int panTo, int priority);
 	void Sound_Play_Speech_Line(int actorId, int speechId, int a3, int a4, int a5);
-	// Sound_Left_Footstep_Walk
-	// Sound_Right_Footstep_Walk
-	// Sound_Left_Footstep_Run
-	// Sound_Right_Footstep_Run
+	void Sound_Left_Footstep_Walk(int actorId);
+	void Sound_Right_Footstep_Walk(int actorId);
+	void Sound_Left_Footstep_Run(int actorId);
+	void Sound_Right_Footstep_Run(int actorId);
 	// Sound_Walk_Shuffle_Stop
 	void Footstep_Sounds_Set(int index, int value);
 	void Footstep_Sound_Override_On(int footstepSoundOverride);
@@ -822,8 +822,25 @@ public:
 	{}
 
 	virtual void Initialize() = 0;
-	virtual void UpdateAnimation(int *animation, int *frame) = 0;
-	virtual void ChangeAnimationMode(int mode) = 0;
+	virtual bool Update() = 0;
+	virtual void TimerExpired(int timer) = 0;
+	virtual void CompletedMovementTrack() = 0;
+	virtual void ReceivedClue(int clueId, int fromActorId) = 0;
+	virtual void ClickedByPlayer() = 0;
+	virtual void EnteredScene(int sceneId) = 0;
+	virtual void OtherAgentEnteredThisScene() = 0;
+	virtual void OtherAgentExitedThisScene() = 0;
+	virtual void OtherAgentEnteredCombatMode() = 0;
+	virtual void ShotAtAndMissed() = 0;
+	virtual void ShotAtAndHit() = 0;
+	virtual void Retired(int byActorId) = 0;
+	virtual void GetFriendlinessModifierIfGetsClue() = 0;
+	virtual bool GoalChanged(int currentGoalNumber, int newGoalNumber) = 0;
+	virtual bool UpdateAnimation(int *animation, int *frame) = 0;
+	virtual bool ChangeAnimationMode(int mode) = 0;
+	virtual void QueryAnimationState(int *animationState, int *a2, int *a3, int *a4) = 0;
+	virtual void SetAnimationState(int animationState, int a2, int a3, int a4) = 0;
+	virtual bool ReachedMovementTrackWaypoint() = 0;
 };
 
 class AIScripts {


Commit: ae03eda3d131017d630139ae63972ebcf75e3fa7
    https://github.com/scummvm/scummvm/commit/ae03eda3d131017d630139ae63972ebcf75e3fa7
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:41+02:00

Commit Message:
BLADERUNNER: add more logic to actor::tick, added support for looking up scene objects

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 4b893c6..c112c72 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -47,30 +47,30 @@ Actor::Actor(BladeRunnerEngine *vm, int actorId) {
 	_vm = vm;
 	_id = actorId;
 
-	_walkInfo      = new ActorWalk(vm);
+	_walkInfo = new ActorWalk(vm);
 	_movementTrack = new MovementTrack();
-	_clues         = new ActorClues(vm, (actorId && actorId != 99) ? 2 : 4);
-	_bbox          = new BoundingBox();
-	_combatInfo    = new ActorCombat(vm);
+	_clues = new ActorClues(vm, (actorId && actorId != 99) ? 2 : 4);
+	_bbox = new BoundingBox();
+	_combatInfo = new ActorCombat(vm);
 
 	_friendlinessToOther = new int[_vm->_gameInfo->getActorCount()];
 }
 
 Actor::~Actor() {
 	delete[] _friendlinessToOther;
-	delete   _combatInfo;
-	delete   _bbox;
-	delete   _clues;
-	delete   _movementTrack;
-	delete   _walkInfo;
+	delete _combatInfo;
+	delete _bbox;
+	delete _clues;
+	delete _movementTrack;
+	delete _walkInfo;
 }
 
 void Actor::setup(int actorId) {
-	_id  = actorId;
+	_id = actorId;
 	_setId = -1;
 
-	_position  = Vector3(0.0, 0.0, 0.0);
-	_facing    = 512;
+	_position = Vector3(0.0, 0.0, 0.0);
+	_facing = 512;
 	_targetFacing = -1;
 	_walkboxId = -1;
 
@@ -79,32 +79,32 @@ void Actor::setup(int actorId) {
 	_fps = 15;
 	_frame_ms = 1000 / _fps;
 
-	_isTargetable        = false;
-	_isInvisible         = false;
+	_isTargetable = false;
+	_isInvisible = false;
 	_isImmuneToObstacles = false;
 
-	_isRetired           = false;
+	_isRetired = false;
 
-	_width         = 0;
-	_height        = 0;
-	_retiredWidth  = 0;
+	_width = 0;
+	_height = 0;
+	_retiredWidth = 0;
 	_retiredHeight = 0;
 
 	for (int i = 0; i != 7; ++i) {
 		_timersRemain[i] = 0;
-		_timersStart[i]  = _vm->getTotalPlayTime();
+		_timersStart[i] = _vm->getTotalPlayTime();
 	}
 
 	_scale = 1.0;
 
-	_honesty              = 50;
-	_intelligence         = 50;
+	_honesty = 50;
+	_intelligence = 50;
 	_combatAggressiveness = 50;
-	_stability            = 50;
+	_stability = 50;
 
-	_currentHP            = 50;
-	_maxHP                = 50;
-	_goalNumber           = -1;
+	_currentHP = 50;
+	_maxHP = 50;
+	_goalNumber = -1;
 
 	_timersRemain[4] = 60000;
 	_animationMode = -1;
@@ -125,8 +125,7 @@ void Actor::setup(int actorId) {
 	_actorSpeed = Vector3();
 }
 
-void Actor::changeAnimationMode(int animationMode, bool force)
-{
+void Actor::changeAnimationMode(int animationMode, bool force) {
 	if (force)
 		_animationMode = -1;
 
@@ -136,31 +135,48 @@ void Actor::changeAnimationMode(int animationMode, bool force)
 	}
 }
 
-void Actor::setFPS(int fps)
-{
+void Actor::setFPS(int fps) {
 	_fps = fps;
 
-	if (fps == 0)
-	{
+	if (fps == 0) {
 		_frame_ms = 0;
-	}
-	else if (fps == -1)
-	{
+	} else if (fps == -1) {
 		_frame_ms = -1000;
-	}
-	else if (fps == -2)
-	{
+	} else if (fps == -2) {
 		_fps = _vm->_sliceAnimations->getFPS(_animationId);
 		_frame_ms = 1000 / _fps;
-	}
-	else
-	{
+	} else {
 		_frame_ms = 1000 / fps;
 	}
 }
 
-void Actor::setAtXYZ(Vector3 pos, int facing, bool snapFacing, bool moving, bool retired)
-{
+void Actor::processMovement() {
+	/*if (movementTrack::is_paused(this->movementTrack) != 1 && this->id)
+	{
+		if (this->walkingWaypointId >= 0 && this->timeoutWalkingWaypoint >= 0)
+		{
+			worldWaypoints::get_sceneId(WorldWaypoints, this->walkingWaypointId);
+			if (!this->timeoutWalkingWaypoint)
+			{
+				this->timeoutWalkingWaypoint = 1;
+			}
+			if (actorScript::call_ReachedMovementTrackWaypoint(ActorScript, this->id, this->walkingWaypointId) == 1)
+			{
+				seconds = this->timeoutWalkingWaypoint;
+				if (seconds > 1)
+				{
+					actor::changeAnimationMode(this, 0, 0);
+					seconds = this->timeoutWalkingWaypoint;
+				}
+				actor::startTimer(this, 3, seconds);
+			}
+		}
+		this->walkingWaypointId = -1;
+		this->timeoutWalkingWaypoint = 0;
+	}*/
+}
+
+void Actor::setAtXYZ(Vector3 pos, int facing, bool snapFacing, bool moving, bool retired) {
 	_position = pos;
 	setFacing(facing, snapFacing);
 
@@ -174,13 +190,12 @@ void Actor::setAtXYZ(Vector3 pos, int facing, bool snapFacing, bool moving, bool
 
 	_vm->_sceneObjects->remove(_id);
 
-	if(_vm->_scene->getSetId() == _setId) {
+	if (_vm->_scene->getSetId() == _setId) {
 		_vm->_sceneObjects->addActor(_id, _bbox, &_screenRectangle, 1, moving, _isTargetable, retired);
 	}
 }
 
-void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired)
-{
+void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired) {
 	Vector3 waypointPosition;
 	_vm->_waypoints->getXYZ(waypointId, &waypointPosition.x, &waypointPosition.y, &waypointPosition.z);
 	setAtXYZ(waypointPosition, angle, true, moving, retired);
@@ -190,13 +205,11 @@ void Actor::loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int
 	this->loopWalkToXYZ(Vector3(x, y, z));
 }
 
-void Actor::loopWalkToXYZ(Vector3 destination)
-{
+void Actor::loopWalkToXYZ(Vector3 destination) {
 	int unk1;
 	_walkInfo->setup(_id, false, _position, destination, 0, &unk1);
 
-	for (;;)
-	{
+	for (;;) {
 		_vm->gameTick();
 		if (!_walkInfo->isWalking() && !_walkInfo->isRunning())
 			break;
@@ -208,8 +221,7 @@ void Actor::loopWalkToXYZ(Vector3 destination)
 float distance(float, float, float, float);
 float distance(Vector3 &v1, Vector3 &v2);
 
-void Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset)
-{
+void Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset) {
 	int sceneObject = _vm->_scene->_set->findObject(objectName);
 	if (sceneObject < 0)
 		return;
@@ -261,66 +273,132 @@ void Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset)
 	loopWalkToXYZ(destination);
 }
 
-bool Actor::tick(bool forceDraw)
-{
+bool Actor::tick(bool forceDraw) {
 	int remain = 0;
 	bool needsUpdate = false;
-	if (_fps > 0)
-	{
+	if (_fps > 0) {
 		countdownTimerUpdate(5);
 		remain = countdownTimerGetRemainingTime(5);
 		needsUpdate = remain <= 0;
-	}
-	else if (forceDraw)
-	{
+	} else if (forceDraw) {
 		needsUpdate = true;
 		remain = 0;
 	}
 
-	if (needsUpdate)
-	{
+	if (needsUpdate) {
 		int newAnimation = 0, newFrame = 0;
 		_vm->_aiScripts->UpdateAnimation(_id, &newAnimation, &newFrame);
 
 		if (_animationId != newAnimation) {
-			_animationId = newAnimation;
-			setFPS(-2);
+			if (_fps != 0 && _fps != -1) {
+				_animationId = newAnimation;
+				setFPS(-2);
+			}
 		}
+		_animationId = newAnimation;
 		_animationFrame = newFrame;
 
-		if (isWalking())
-		{
-			float stepDistance = 3.0;
-			if (stepDistance <= 0.0) {
-				stepDistance = 4.0;
-			}
-			if (_walkInfo->tick(_id, stepDistance, false)) {
-				_vm->_actors[_id]->changeAnimationMode(0);
+		Vector3 positionChange = _vm->_sliceAnimations->getPositionChange(_animationId);
+		float facingChange = _vm->_sliceAnimations->getFacingChange(_animationId);
+
+		if (_id == 47) {
+			positionChange.x = 0.0f;
+			positionChange.y = 0.0f;
+			positionChange.z = 0.0f;
+		}
+
+		if (isWalking()) {
+			if (0.0f <= positionChange.y) {
+				positionChange.y = -4.0f;
 			}
 
-			Vector3 pos; int facing;
+			this->_targetFacing = -1;
+
+			bool walked = _walkInfo->tick(_id, -positionChange.y, false);
+			Vector3 pos;
+			int facing;
 			_walkInfo->getCurrentPosition(_id, &pos, &facing);
 
-			setAtXYZ(pos, facing);
+			setAtXYZ(pos, facing, false, this->_isMoving, false);
+			if (walked) {
+				_vm->_actors[_id]->changeAnimationMode(0);
+
+				this->processMovement();
+				if (this->inCombat()) {
+					this->changeAnimationMode(this->_combatAnimationMode, false);
+				} else {
+					this->changeAnimationMode(0, false);
+				}
+			}
+		} else {
+			if (facingChange != 0.0f) {
+				int v27 = (512.0f / M_PI) * facingChange;
+				if (v27 != 0) {
+					this->_facing = this->_facing - v27;
+					if (this->_facing < 0) {
+						this->_facing += 1024;
+					}
+
+					if (this->_facing >= 1024) {
+						this->_facing = this->_facing - 1024;
+					}
+				}
+			}
+
+			if (0.0f != positionChange.x || 0.0f != positionChange.y || 0.0f != positionChange.z) {
+				if (this->_actorSpeed.x != 0.0f) {
+					positionChange.x = positionChange.x * this->_actorSpeed.x;
+				}
+				if (this->_actorSpeed.y != 0.0f) {
+					positionChange.y = positionChange.y * this->_actorSpeed.y;
+				}
+				if (this->_actorSpeed.z != 0.0f) {
+					positionChange.z = positionChange.z * this->_actorSpeed.z;
+				}
+
+				float facing = (_facing / 512.0f) * M_PI;
+				float sinx = sin(facing);
+				float cosx = cos(facing);
+
+				float originalX = this->_position.x;
+				float originalY = this->_position.y;
+				float originalZ = this->_position.z;
+
+				this->_position.x = this->_position.x + positionChange.x * cosx - positionChange.y * sinx;
+				this->_position.z = this->_position.z - positionChange.x * sinx - positionChange.y * cosx; //why minus?
+				this->_position.y = this->_position.y + positionChange.z;
+
+				if (_vm->_sceneObjects->existsOnXZ(this->_id, this->_position.x, this->_position.z, false, false) == 1 && !this->_isImmuneToObstacles) {
+					this->_position.x = originalX;
+					this->_position.y = originalY;
+					this->_position.z = originalZ;
+				}
+				setAtXYZ(this->_position, this->_facing, true, this->_isMoving, this->_isRetired);
+			}
 		}
 	}
 
 	draw();
 
-	if (needsUpdate)
-	{
+	if (needsUpdate) {
 		int nextFrameTime = remain + _frame_ms;
 		if (nextFrameTime <= 0)
 			nextFrameTime = 1;
 		countdownTimerStart(5, nextFrameTime);
 	}
-
+	if (this->_targetFacing >= 0) {
+		if (this->_targetFacing == this->_facing) {
+			this->_targetFacing = -1;
+		} else {
+			this->setFacing(this->_targetFacing, false);
+		}
+	}
 	return false;
 }
 
 void Actor::draw() {
 	Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0);
-	float   draw_facing = M_PI - _facing * M_PI / 512.0;
+	float draw_facing = M_PI - _facing * M_PI / 512.0;
 	// float   draw_scale  = _scale;
 
 	// TODO: Handle SHORTY mode
@@ -340,7 +418,7 @@ void Actor::setSetId(int setId) {
 
 	int i;
 
-	if(_setId > 0) {
+	if (_setId > 0) {
 		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
 				// TODO: actorScript->OtherAgentExitedThisScene( i, _id);
@@ -497,8 +575,7 @@ void Actor::faceHeading(int heading, bool animate) {
 	if (heading != _facing) {
 		if (animate) {
 			_targetFacing = heading;
-		}
-		else {
+		} else {
 			setFacing(heading, true);
 		}
 	}
@@ -644,7 +721,7 @@ float Actor::getZ() {
 	return _position.z;
 }
 
-void Actor::getXYZ(float* x, float* y, float* z) {
+void Actor::getXYZ(float *x, float *y, float *z) {
 	*x = _position.x;
 	*y = _position.y;
 	*z = _position.z;
@@ -726,27 +803,23 @@ void Actor::copyClues(int actorId) {
 	}
 }
 
-void Actor::countdownTimerStart(int timerId, int interval)
-{
+void Actor::countdownTimerStart(int timerId, int interval) {
 	assert(timerId >= 0 && timerId < 7);
 	_timersRemain[timerId] = interval;
 	_timersStart[timerId] = _vm->getTotalPlayTime();
 }
 
-void Actor::countdownTimerReset(int timerId)
-{
+void Actor::countdownTimerReset(int timerId) {
 	assert(timerId >= 0 && timerId < 7);
 	_timersRemain[timerId] = 0;
 }
 
-int Actor::countdownTimerGetRemainingTime(int timerId)
-{
+int Actor::countdownTimerGetRemainingTime(int timerId) {
 	assert(timerId >= 0 && timerId < 7);
 	return _timersRemain[timerId];
 }
 
-void Actor::countdownTimerUpdate(int timerId)
-{
+void Actor::countdownTimerUpdate(int timerId) {
 	if (_timersRemain[timerId] == 0)
 		return;
 
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 7827141..e098411 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -120,6 +120,8 @@ public:
 	void changeAnimationMode(int animationMode, bool force = false);
 	void setFPS(int fps);
 
+	void processMovement();
+
 	void loopWalkToXYZ(Vector3 destination);
 	void loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7);
 	void loopWalkToSceneObject(const char *objectName, int destinationOffset = 0);
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index bf9077f..13889ba 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -558,9 +558,12 @@ void BladeRunnerEngine::gameTick() {
 			_sliceRenderer->setView(*_view);
 
 			// Tick and draw all actors in current set
+			int setId = _scene->_setId;
 			for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
-				if (i == 0 || i == 23) // Currently limited to McCoy and Officer Leroy
+				//if (_actors[i]->getSetId() == setId) {
+					if (i == 0 || i == 23){ // Currently limited to McCoy and Officer Leroy
 					_actors[i]->tick(backgroundChanged);
+				}
 			}
 
 			// TODO: Draw items
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index ba09edf..4c038fa 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -63,21 +63,20 @@ void SceneObjects::clear() {
 	}
 }
 
-bool SceneObjects::addActor(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isTarget, uint8 isRetired) {
+bool SceneObjects::addActor(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, uint8 isClickable, uint8 isMoving, uint8 isTarget, uint8 isRetired) {
 	return addSceneObject(sceneObjectId, SceneObjectTypeActor, boundingBox, screenRectangle, isClickable, 0, 0, isTarget, isMoving, isRetired);
 }
 
-bool SceneObjects::addObject(int sceneObjectId, BoundingBox* boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget) {
+bool SceneObjects::addObject(int sceneObjectId, BoundingBox *boundingBox, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget) {
 	Common::Rect rect(-1, -1, -1, -1);
 	return addSceneObject(sceneObjectId, SceneObjectTypeObject, boundingBox, &rect, isClickable, isObstacle, unknown1, isTarget, 0, 0);
 }
 
-bool SceneObjects::addItem(int sceneObjectId, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isTarget, uint8 isObstacle) {
+bool SceneObjects::addItem(int sceneObjectId, BoundingBox *boundingBox, Common::Rect *screenRectangle, uint8 isTarget, uint8 isObstacle) {
 	return addSceneObject(sceneObjectId, SceneObjectTypeItem, boundingBox, screenRectangle, isObstacle, 0, 0, isTarget, 0, 0);
 }
 
-bool SceneObjects::remove(int sceneObjectId)
-{
+bool SceneObjects::remove(int sceneObjectId) {
 	int i = findById(sceneObjectId);
 	if (i == -1) {
 		return false;
@@ -99,8 +98,8 @@ bool SceneObjects::remove(int sceneObjectId)
 
 int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isTarget, float x, float y, float z, int findClickables, int findObstacles, int findTargets) {
 	*isClickable = 0;
-	*isObstacle  = 0;
-	*isTarget    = 0;
+	*isObstacle = 0;
+	*isTarget = 0;
 
 	for (int i = 0; i < _count; ++i) {
 		assert(_sceneObjectsSortedByDistance[i] < _count);
@@ -108,9 +107,8 @@ int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isTarget, fl
 		SceneObject &sceneObject = _sceneObjects[_sceneObjectsSortedByDistance[i]];
 
 		if ((findClickables && sceneObject._isClickable) ||
-		    (findObstacles  && sceneObject._isObstacle)  ||
-		    (findTargets    && sceneObject._isTarget))
-		{
+			(findObstacles  && sceneObject._isObstacle) ||
+			(findTargets    && sceneObject._isTarget)) {
 			BoundingBox boundingBox = sceneObject._boundingBox;
 
 			if (sceneObject._sceneObjectType == SceneObjectTypeObject || sceneObject._sceneObjectType == SceneObjectTypeItem) {
@@ -119,8 +117,8 @@ int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isTarget, fl
 
 			if (boundingBox.inside(x, y, z)) {
 				*isClickable = sceneObject._isClickable;
-				*isObstacle  = sceneObject._isObstacle;
-				*isTarget    = sceneObject._isTarget;
+				*isObstacle = sceneObject._isObstacle;
+				*isTarget = sceneObject._isTarget;
 
 				return sceneObject._sceneObjectId;
 			}
@@ -130,8 +128,43 @@ int SceneObjects::findByXYZ(int *isClickable, int *isObstacle, int *isTarget, fl
 	return -1;
 }
 
-int SceneObjects::findById(int sceneObjectId)
-{
+bool SceneObjects::existsOnXZ(int exceptSceneObjectId, float x, float z, bool a5, bool a6) {
+	float xMin = x - 12.5f;
+	float xMax = x + 12.5f;
+	float zMin = z - 12.5f;
+	float zMax = z + 12.5f;
+
+	int count = this->_count;
+
+	if (count > 0) {
+		for (int i = 0; i < count; i++) {
+			SceneObject *sceneObject = &this->_sceneObjects[this->_sceneObjectsSortedByDistance[i]];
+			bool v13 = false;
+			if (sceneObject->_sceneObjectType == SceneObjectTypeActor) {
+				if (sceneObject->_isRetired) {
+					v13 = false;
+				} else if (sceneObject->_isMoving) {
+					v13 = a5 != 0;
+				} else {
+					v13 = a6 != 0;
+				}
+			} else {
+				v13 = sceneObject->_isObstacle;
+			}
+
+			if (v13 && sceneObject->_sceneObjectId != exceptSceneObjectId) {
+				float x1, y1, z1, x2, y2, z2;
+				sceneObject->_boundingBox.getXYZ(&x1, &y1, &z1, &x2, &y2, &z2);
+				if (z1 <= zMax && z2 >= zMin && x1 <= xMax && x2 >= xMin) {
+					return true;
+				}
+			}
+		}
+	}
+	return false;
+}
+
+int SceneObjects::findById(int sceneObjectId) {
 	for (int i = 0; i < _count; ++i) {
 		if (_sceneObjects[i]._present && _sceneObjects[i]._sceneObjectId == sceneObjectId) {
 			return i;
@@ -140,23 +173,23 @@ int SceneObjects::findById(int sceneObjectId)
 	return -1;
 }
 
-bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox* boundingBox, Common::Rect* screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget, uint isMoving, uint isRetired) {
+bool SceneObjects::addSceneObject(int sceneObjectId, SceneObjectType sceneObjectType, BoundingBox *boundingBox, Common::Rect *screenRectangle, uint8 isClickable, uint8 isObstacle, uint8 unknown1, uint8 isTarget, uint isMoving, uint isRetired) {
 	int index = findEmpty();
 	if (index == -1) {
 		return false;
 	}
 
-	_sceneObjects[index]._sceneObjectId   = sceneObjectId;
+	_sceneObjects[index]._sceneObjectId = sceneObjectId;
 	_sceneObjects[index]._sceneObjectType = sceneObjectType;
-	_sceneObjects[index]._present         = 1;
-	_sceneObjects[index]._boundingBox     = *boundingBox;
+	_sceneObjects[index]._present = 1;
+	_sceneObjects[index]._boundingBox = *boundingBox;
 	_sceneObjects[index]._screenRectangle = *screenRectangle;
-	_sceneObjects[index]._isClickable     = isClickable;
-	_sceneObjects[index]._isObstacle      = isObstacle;
-	_sceneObjects[index]._unknown1        = unknown1;
-	_sceneObjects[index]._isTarget        = isTarget;
-	_sceneObjects[index]._isMoving        = isMoving;
-	_sceneObjects[index]._isRetired       = isRetired;
+	_sceneObjects[index]._isClickable = isClickable;
+	_sceneObjects[index]._isObstacle = isObstacle;
+	_sceneObjects[index]._unknown1 = unknown1;
+	_sceneObjects[index]._isTarget = isTarget;
+	_sceneObjects[index]._isMoving = isMoving;
+	_sceneObjects[index]._isRetired = isRetired;
 
 	float centerZ = (_sceneObjects[index]._boundingBox.getZ0() + _sceneObjects[index]._boundingBox.getZ1()) / 2.0;
 
@@ -213,11 +246,11 @@ bool SceneObjects::isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x
 	_sceneObjects[i]._boundingBox.getXYZ(&objectX1, &objectY1, &objectZ1, &objectX2, &objectY2, &objectZ2);
 
 	//TODO
-//		if (!lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ1, objectX2, objectZ1, &intersectionX, &intersectionY, &v18)
-//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ1, objectX2, objectZ2, &intersectionX, &intersectionY, &v18)
-//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ2, objectX1, objectZ2, &intersectionX, &intersectionY, &v18)
-//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ2, objectX1, objectZ1, &intersectionX, &intersectionY, &v18))
-//			return false;
+	//		if (!lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ1, objectX2, objectZ1, &intersectionX, &intersectionY, &v18)
+	//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ1, objectX2, objectZ2, &intersectionX, &intersectionY, &v18)
+	//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX2, objectZ2, objectX1, objectZ2, &intersectionX, &intersectionY, &v18)
+	//			&& !lineIntersectection(sourceX, sourceZ, targetX, targetZ, objectX1, objectZ2, objectX1, objectZ1, &intersectionX, &intersectionY, &v18))
+	//			return false;
 	return true;
 }
 
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 047301d..6414c5d 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -79,6 +79,7 @@ public:
 	bool remove(int sceneObjectId);
 	void clear();
 	int findByXYZ(int *isClickable, int *isObstacle, int *isTarget, float x, float y, float z, int findClickables, int findObstacles, int findTargets);
+	bool existsOnXZ(int exceptSceneObjectId, float x, float z, bool a5, bool a6);
 	void setMoving(int sceneObjectId, bool isMoving);
 	void setRetired(int sceneObjectId, bool isRetired);
 	bool isBetweenTwoXZ(int sceneObjectId, float x1, float z1, float x2, float z2);
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index 8497620..aafd268 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -170,4 +170,12 @@ void *SliceAnimations::getFramePtr(uint32 animation, uint32 frame) {
 	return (byte*)_pages[page]._data + pageOffset;
 }
 
+Vector3 SliceAnimations::getPositionChange(int animation) {
+	return _animations[animation].positionChange;
+}
+
+float SliceAnimations::getFacingChange(int animation) {
+	return _animations[animation].facingChange;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index dc5c88f..1e35d6b 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -106,6 +106,9 @@ public:
 
 	float getFrameCount(int animation){ return _animations[animation].frameCount; }
 	float getFPS(int animation){ return _animations[animation].fps; }
+
+	Vector3 getPositionChange(int animation);
+	float getFacingChange(int animation);
 };
 
 } // End of namespace BladeRunner


Commit: 7e7cf4e748172f956fddb7c6f21f34bfef058242
    https://github.com/scummvm/scummvm/commit/7e7cf4e748172f956fddb7c6f21f34bfef058242
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-09-29T22:33:41+02:00

Commit Message:
BLADERUNNER: Fix compilation

Changed paths:
    engines/bladerunner/audio_player.cpp



diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index 1698bfb..dc6f195 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -166,7 +166,7 @@ void AudioPlayer::fadeAndStopTrack(Track *track, int time)
 int AudioPlayer::playAud(const Common::String &name, int volume, int panFrom, int panTo, int priority, byte flags) {
 	/* Find first available track or, alternatively, the lowest priority playing track */
 	Track *track = NULL;
-	int    lowestPriority = INT_MAX;
+	int    lowestPriority = 1000000;
 	Track *lowestPriorityTrack = NULL;
 
 	for (int i = 0; i != 6; ++i) {


Commit: cfc8ffed8af71714cc6378b412557d5fc03781d4
    https://github.com/scummvm/scummvm/commit/cfc8ffed8af71714cc6378b412557d5fc03781d4
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:41+02:00

Commit Message:
BLADERUNNER: fixed exit selection, added footstep sounds, added some debugging display (scene objects, regions, exits, walkboxes, lights?)

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/light.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/regions.h
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/set.cpp
    engines/bladerunner/set.h
    engines/bladerunner/view.cpp
    engines/bladerunner/view.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index c112c72..c0c042e 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -365,7 +365,7 @@ bool Actor::tick(bool forceDraw) {
 				float originalZ = this->_position.z;
 
 				this->_position.x = this->_position.x + positionChange.x * cosx - positionChange.y * sinx;
-				this->_position.z = this->_position.z - positionChange.x * sinx - positionChange.y * cosx; //why minus?
+				this->_position.z = this->_position.z + positionChange.x * sinx + positionChange.y * cosx;
 				this->_position.y = this->_position.y + positionChange.z;
 
 				if (_vm->_sceneObjects->existsOnXZ(this->_id, this->_position.x, this->_position.z, false, false) == 1 && !this->_isImmuneToObstacles) {
@@ -494,6 +494,12 @@ void Actor::setBoundingBox(Vector3 position, bool retired) {
 	}
 }
 
+float Actor::distanceFromView(View *view) {
+	float xDist = this->_position.x - view->_cameraPosition.x;
+	float zDist = this->_position.z - view->_cameraPosition.z;
+	return sqrt(xDist * xDist + zDist * zDist);
+}
+
 bool Actor::isWalking() {
 	return _walkInfo->isWalking();
 }
@@ -803,6 +809,16 @@ void Actor::copyClues(int actorId) {
 	}
 }
 
+int Actor::soundVolume() {
+	float dist = distanceFromView(_vm->_view);
+	return 255.0f * MAX(MIN(dist / 1200.0f, 1.0f), 0.0f);
+}
+
+int Actor::soundBalance() {
+	Vector2 screenPosition = _vm->_view->calculateScreenPosition(_position);
+	return 127.0f * (MAX(MIN(screenPosition.x / 640.0f, 1.0f), 0.0f) * 2.0f - 1.0f);
+}
+
 void Actor::countdownTimerStart(int timerId, int interval) {
 	assert(timerId >= 0 && timerId < 7);
 	_timersRemain[timerId] = interval;
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index e098411..5383adb 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -35,6 +35,7 @@ class ActorWalk;
 class BladeRunnerEngine;
 class BoundingBox;
 class MovementTrack;
+class View;
 
 class Actor {
 	friend class ScriptBase;
@@ -138,6 +139,7 @@ public:
 	void setSetId(int setId);
 	BoundingBox* getBoundingBox() { return _bbox; }
 	Common::Rect* getScreenRectangle() { return &_screenRectangle; }
+	int getWalkbox() { return _walkboxId; }
 	bool isRetired() { return _isRetired; }
 	bool isTargetable() { return _isTargetable; }
 	void setTargetable(bool targetable);
@@ -191,9 +193,13 @@ public:
 	void loseClue(int clueId);
 	bool hasClue(int clueId);
 	void copyClues(int actorId);
+
+	int soundVolume();
+	int soundBalance();
 private:
 	void setFacing(int facing, bool halfOrSet = true);
 	void setBoundingBox(Vector3 position, bool retired);
+	float distanceFromView(View* view);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 13889ba..45ffdd8 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -500,6 +500,36 @@ void BladeRunnerEngine::gameLoop() {
 	} while (_gameIsRunning);
 }
 
+#if _DEBUG
+
+void drawBBox(Vector3 start, Vector3 end, View* view, Graphics::Surface *surface, int color) {
+	Vector2 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z));
+	Vector2 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z));
+	Vector2 bbr = view->calculateScreenPosition(Vector3(end.x, end.y, start.z));
+	Vector2 bbl = view->calculateScreenPosition(Vector3(end.x, start.y, start.z));
+
+	Vector2 tfl = view->calculateScreenPosition(Vector3(start.x, start.y, end.z));
+	Vector2 tfr = view->calculateScreenPosition(Vector3(start.x, end.y, end.z));
+	Vector2 tbr = view->calculateScreenPosition(Vector3(end.x, end.y, end.z));
+	Vector2 tbl = view->calculateScreenPosition(Vector3(end.x, start.y, end.z));
+
+	surface->drawLine(bfl.x, bfl.y, bfr.x, bfr.y, color);
+	surface->drawLine(bfr.x, bfr.y, bbr.x, bbr.y, color);
+	surface->drawLine(bbr.x, bbr.y, bbl.x, bbl.y, color);
+	surface->drawLine(bbl.x, bbl.y, bfl.x, bfl.y, color);
+
+	surface->drawLine(tfl.x, tfl.y, tfr.x, tfr.y, color);
+	surface->drawLine(tfr.x, tfr.y, tbr.x, tbr.y, color);
+	surface->drawLine(tbr.x, tbr.y, tbl.x, tbl.y, color);
+	surface->drawLine(tbl.x, tbl.y, tfl.x, tfl.y, color);
+
+	surface->drawLine(bfl.x, bfl.y, tfl.x, tfl.y, color);
+	surface->drawLine(bfr.x, bfr.y, tfr.x, tfr.y, color);
+	surface->drawLine(bbr.x, bbr.y, tbr.x, tbr.y, color);
+	surface->drawLine(bbl.x, bbl.y, tbl.x, tbl.y, color);
+}
+#endif
+
 void BladeRunnerEngine::gameTick() {
 	handleEvents();
 
@@ -554,11 +584,10 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: Tick Actor AI and Timers
 
 		if (_settings->getNewScene() == -1 || _script->_inScriptCounter /* || in_ai */) {
-
 			_sliceRenderer->setView(*_view);
 
 			// Tick and draw all actors in current set
-			int setId = _scene->_setId;
+			//int setId = _scene->_setId;
 			for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
 				//if (_actors[i]->getSetId() == setId) {
 					if (i == 0 || i == 23){ // Currently limited to McCoy and Officer Leroy
@@ -577,6 +606,98 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Process AUD
 			// TODO: Footstep sound
 
+			if (_walkSoundId >= 0)
+			{
+				const char *name = _gameInfo->getSfxTrack(_walkSoundId);
+				_audioPlayer->playAud(name, _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0);
+				_walkSoundId = -1;
+			}
+
+#if _DEBUG
+			//draw scene objects
+			int count = _sceneObjects->_count;
+			if (count > 0) {
+				for (int i = 0; i < count; i++) {
+					SceneObject *sceneObject = &_sceneObjects->_sceneObjects[_sceneObjects->_sceneObjectsSortedByDistance[i]];
+
+					BoundingBox *bbox = &sceneObject->_boundingBox;
+					Vector3 a, b;
+					bbox->getXYZ(&a.x, &a.y, &a.z, &b.x, &b.y, &b.z);
+
+					int color = 0b111111111111111;
+					if (sceneObject->_sceneObjectType == SceneObjectTypeActor) {
+						color = 0b111110000000000;
+					}
+					if (sceneObject->_sceneObjectType == SceneObjectTypeObject) {
+						color = 0b011110111101111;
+						//if (sceneObject->_isObstacle)
+						//	color += 0b100000000000000;
+						if (sceneObject->_isClickable)
+							color = 0b000001111100000;
+						//if (sceneObject->_isTarget)
+						//	color += 0b000000000010000;
+					}
+
+					sceneObject->_sceneObjectId;
+					drawBBox(a, b, _view, &_surface2, color);
+				}
+			}
+			
+			//draw regions
+			for (int i = 0; i < 10; i++) {
+				Region* region  =  &_scene->_regions->_regions[i];
+				if (!region->_present) continue;
+				_surface2.frameRect(region->_rectangle, 0b000000000011111);
+			}
+
+			for (int i = 0; i < 10; i++) {
+				Region* region = &_scene->_exits->_regions[i];
+				if (!region->_present) continue;
+				_surface2.frameRect(region->_rectangle, 0b111111111111111);
+			}
+
+			for (int i = 0; i < _scene->_set->_walkboxCount; i++) {
+				Walkbox *walkbox = &_scene->_set->_walkboxes[i];
+				
+				for(int j = 0; j < walkbox->_vertexCount; j++) {
+					Vector2 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
+					Vector2 end = _view->calculateScreenPosition(walkbox->_vertices[(j+1) % walkbox->_vertexCount]);
+					//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
+					_surface2.drawLine(start.x, start.y, end.x, end.y, 0b111111111100000);
+				}
+				
+			}
+
+			for (Light* light = _lights->_lights; light != nullptr; light->_next) {
+
+				Matrix4x3 matrix = light->_matrix;
+
+				// this is all wrong
+
+//					matrix = matrix * rotationMatrixX(float(M_PI) / 2.0f);
+
+//					Matrix4x3 a(
+//						-1.0f, 0.0f, 0.0f, 0.0f,
+//						0.0f, -1.0f, 0.0f, 0.0f,
+//						0.0f, 0.0f, 1.0f, 0.0f);
+
+				//matrix = a * matrix;
+//					matrix = invertMatrix(matrix);
+
+				int colorR = (light->_color.r * 31.0f);
+				int colorG = (light->_color.g * 31.0f);
+				int colorB = (light->_color.b * 31.0f);
+				int color = (colorR << 10) + (colorG << 5) + colorB;
+				drawBBox(
+					Vector3(matrix(0, 3) - 5.0f, matrix(1, 3) - 5.0f, matrix(2, 3) - 5.0f),
+					Vector3(matrix(0, 3) + 5.0f, matrix(1, 3) + 5.0f, matrix(2, 3) + 5.0f),
+					_view, &_surface2, color
+				);
+				light = light->_next;
+
+			}
+#endif
+
 			_system->copyRectToScreen((const byte *)_surface2.getBasePtr(0, 0), _surface2.pitch, 0, 0, 640, 480);
 			_system->updateScreen();
 			_system->delayMillis(10);
@@ -614,7 +735,7 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 	int isTarget;
 
 	int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
-	int exitIndex     = _scene->_exits->getTypeAtXY(x, y);
+	int exitIndex     = _scene->_exits->getRegionAtXY(x, y);
 
 	debug("%d %d", sceneObjectId, exitIndex);
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 082617e..51c6855 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -120,6 +120,10 @@ public:
 	bool _gameIsLoading;
 	bool _sceneIsLoading;
 
+	int _walkSoundId = -1;
+	int _walkSoundVolume = 0;
+	int _walkSoundBalance = 0;
+
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index b075c91..a6ac21e 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -38,6 +38,9 @@ class Lights;
 
 class Light
 {
+#if _DEBUG
+	friend class BladeRunnerEngine;
+#endif
 	friend class Lights;
 
 	char _name[20];
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index 7a6be94..eb18958 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -10,7 +10,7 @@ Lights::Lights(BladeRunnerEngine *vm)
 	_ambientLightColor.g = 0.0;
 	_ambientLightColor.b = 0.0;
 
-	_lights = NULL;
+	_lights = nullptr;
 	_frame = 0;
 }
 
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index 0db7a07..37a7b17 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -32,6 +32,9 @@
 namespace BladeRunner {
 
 class Lights {
+#if _DEBUG
+	friend class BladeRunnerEngine;
+#endif
 	BladeRunnerEngine *_vm;
 
 	Color _ambientLightColor;
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
index 8a65aed..ebb2ef7 100644
--- a/engines/bladerunner/regions.h
+++ b/engines/bladerunner/regions.h
@@ -38,6 +38,10 @@ struct Region
 
 class Regions
 {
+#ifdef _DEBUG
+	friend class BladeRunnerEngine;
+#endif
+
 private:
 	Region* _regions;
 	bool _enabled;
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 6414c5d..b7342d6 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -62,6 +62,9 @@ struct SceneObject
 };
 
 class SceneObjects {
+#if _DEBUG
+	friend class BladeRunnerEngine;
+#endif
 	BladeRunnerEngine *_vm;
 
 private:
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 7b00b5f..9d88d2d 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -25,10 +25,14 @@
 namespace BladeRunner {
 
 void ScriptRC01::InitializeScene() {
+#if _DEBUG
 	//TODO: not part of game, remove
 	Game_Flag_Set(24); // force skip intro
 	// Game_Flag_Set(9); // Force flag 9 so McCoy will be in view
 
+	Footstep_Sound_Override_On(0);
+#endif
+
 	if (!Game_Flag_Query(24)) {
 		Ambient_Sounds_Remove_All_Non_Looping_Sounds(1);
 		Ambient_Sounds_Remove_All_Looping_Sounds(1);
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 4ecec287..50d56d5 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -52,7 +52,13 @@ namespace BladeRunner {
 bool Script::open(const Common::String &name) {
 	delete _currentScript;
 
+
 	if (name == "RC01") { _currentScript = new ScriptRC01(_vm); return true; }
+	if (name == "RC02") { _currentScript = new ScriptRC02(_vm); return true; }
+	if (name == "RC03") { _currentScript = new ScriptRC03(_vm); return true; }
+	if (name == "RC04") { _currentScript = new ScriptRC04(_vm); return true; }
+	if (name == "RC51") { _currentScript = new ScriptRC51(_vm); return true; }
+
 
 	return false;
 }
@@ -792,40 +798,61 @@ void ScriptBase::Sound_Play_Speech_Line(int actorId, int speechId, int a3, int a
 }
 
 void ScriptBase::Sound_Left_Footstep_Walk(int actorId) {
-	//TODO
-	warning("Sound_Left_Footstep_Walk(%d)", actorId);
+	int walkboxId = _vm->_actors[actorId]->getWalkbox();
+	if (walkboxId < 0) {
+		walkboxId = 0;
+	}
+
+	_vm->_walkSoundId = _vm->_scene->_set->getWalkboxSoundWalkLeft(walkboxId);
+	_vm->_walkSoundVolume = _vm->_actors[actorId]->soundVolume();
+	_vm->_walkSoundBalance = _vm->_actors[actorId]->soundBalance();
 }
 
 void ScriptBase::Sound_Right_Footstep_Walk(int actorId) {
-	//TODO
-	warning("Sound_Right_Footstep_Walk(%d)", actorId);
+	int walkboxId = _vm->_actors[actorId]->getWalkbox();
+	if (walkboxId < 0) {
+		walkboxId = 0;
+	}
+
+	_vm->_walkSoundId = _vm->_scene->_set->getWalkboxSoundWalkRight(walkboxId);
+	_vm->_walkSoundVolume = _vm->_actors[actorId]->soundVolume();
+	_vm->_walkSoundBalance = _vm->_actors[actorId]->soundBalance();
 }
 
 void ScriptBase::Sound_Left_Footstep_Run(int actorId) {
-	//TODO
-	warning("Sound_Left_Footstep_Run(%d)", actorId);
+	int walkboxId = _vm->_actors[actorId]->getWalkbox();
+	if (walkboxId < 0) {
+		walkboxId = 0;
+	}
+
+	_vm->_walkSoundId = _vm->_scene->_set->getWalkboxSoundRunLeft(walkboxId);
+	_vm->_walkSoundVolume = _vm->_actors[actorId]->soundVolume();
+	_vm->_walkSoundBalance = _vm->_actors[actorId]->soundBalance();
 }
 
 void ScriptBase::Sound_Right_Footstep_Run(int actorId) {
-	//TODO
-	warning("Sound_Right_Footstep_Run(%d)", actorId);
+	int walkboxId = _vm->_actors[actorId]->getWalkbox();
+	if (walkboxId < 0) {
+		walkboxId = 0;
+	}
+
+	_vm->_walkSoundId = _vm->_scene->_set->getWalkboxSoundRunRight(walkboxId);
+	_vm->_walkSoundVolume = _vm->_actors[actorId]->soundVolume();
+	_vm->_walkSoundBalance = _vm->_actors[actorId]->soundBalance();
 }
 
 // ScriptBase::Sound_Walk_Shuffle_Stop
 
 void ScriptBase::Footstep_Sounds_Set(int walkboxId, int stepSound) {
-	//TODO
-	warning("Footstep_Sounds_Set(%d, %d)", walkboxId, stepSound);
+	_vm->_scene->_set->setWalkboxStepSound(walkboxId, stepSound);
 }
 
 void ScriptBase::Footstep_Sound_Override_On(int footstepSoundOverride) {
-	//TODO
-	warning("Footstep_Sound_Override_On(%d)", footstepSoundOverride);
+	_vm->_scene->_set->setFoodstepSoundOverride(footstepSoundOverride);
 }
 
 void ScriptBase::Footstep_Sound_Override_Off() {
-	//TODO
-	warning("Footstep_Sound_Override_Off()");
+	_vm->_scene->_set->resetFoodstepSoundOverride();
 }
 
 bool ScriptBase::Music_Play(int a1, int a2, int a3, int a4, int a5, int a6, int a7) {
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index f7db1c2..12db84a 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -44,6 +44,7 @@ Set::Set(BladeRunnerEngine *vm) : _vm(vm) {
 	_walkboxes = new Walkbox[95];
 	_footstepSoundOverride = -1;
 	_effects = new SetEffects(vm);
+	_loaded = false;
 }
 
 Set::~Set() {
@@ -64,7 +65,7 @@ bool Set::open(const Common::String &name) {
 	_objectCount = s->readUint32LE();
 	assert(_objectCount <= 85);
 
-	for (uint32 i = 0; i != _objectCount; ++i) {
+	for (int i = 0; i < _objectCount; ++i) {
 		s->read(_objects[i]._name, 20);
 
 		float x0, y0, z0, x1, y1, z1;
@@ -89,7 +90,7 @@ bool Set::open(const Common::String &name) {
 	_walkboxCount = s->readUint32LE();
 	assert(_walkboxCount <= 95);
 
-	for (uint32 i = 0; i != _walkboxCount; ++i) {
+	for (int i = 0; i < _walkboxCount; ++i) {
 		float x, y, z;
 
 		s->read(_walkboxes[i]._name, 20);
@@ -98,7 +99,7 @@ bool Set::open(const Common::String &name) {
 
 		assert(_walkboxes[i]._vertexCount <= 8);
 
-		for (uint32 j = 0; j != _walkboxes[i]._vertexCount; ++j) {
+		for (int j = 0; j < _walkboxes[i]._vertexCount; ++j) {
 			x = s->readFloatLE();
 			z = s->readFloatLE();
 
@@ -115,13 +116,18 @@ bool Set::open(const Common::String &name) {
 	_effects->read(s.get(), framesCount);
 	_vm->_sliceRenderer->setSetEffects(_effects);
 
+	// _vm->_sliceRenderer->set_setColors(&this->colors);
+	_loaded = true;
+
+	for (int i = 0; i < _walkboxCount; ++i) {
+		this->setWalkboxStepSound(i, 0);
+	}
+
 	return true;
 }
 
-void Set::addObjectsToScene(SceneObjects* sceneObjects)
-{
-	uint32 i;
-	for (i = 0; i < _objectCount; i++) {
+void Set::addObjectsToScene(SceneObjects *sceneObjects) {
+	for (int i = 0; i < _objectCount; i++) {
 		sceneObjects->addObject(i + SCENE_OBJECTS_OBJECTS_OFFSET, &_objects[i]._bbox, _objects[i]._isClickable, _objects[i]._isObstacle, _objects[i]._unknown1, _objects[i]._isTarget);
 	}
 }
@@ -146,14 +152,12 @@ bool pointInWalkbox(float x, float z, const Walkbox &w)
 }
 */
 
-static
-bool isXZInWalkbox(float x, float z, const Walkbox &walkbox) {
+static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox) {
 	int found = 0;
-	int i;
 
 	float lastX = walkbox._vertices[walkbox._vertexCount - 1].x;
 	float lastZ = walkbox._vertices[walkbox._vertexCount - 1].z;
-	for (i = 0; i < (int)walkbox._vertexCount; i++) {
+	for (int i = 0; i < walkbox._vertexCount; i++) {
 		float currentX = walkbox._vertices[i].x;
 		float currentZ = walkbox._vertices[i].z;
 
@@ -171,7 +175,7 @@ float Set::getAltitudeAtXZ(float x, float z, bool *inWalkbox) {
 	float altitude = _walkboxes[0]._altitude;
 	*inWalkbox = false;
 
-	for (uint32 i = 0; i != _walkboxCount; ++i) {
+	for (int i = 0; i < _walkboxCount; ++i) {
 		const Walkbox &w = _walkboxes[i];
 
 		if (isXZInWalkbox(x, z, w)) {
@@ -188,7 +192,7 @@ float Set::getAltitudeAtXZ(float x, float z, bool *inWalkbox) {
 int Set::findWalkbox(float x, float z) {
 	int result = -1;
 
-	for (uint32 i = 0; i != _walkboxCount; ++i) {
+	for (int i = 0; i < _walkboxCount; ++i) {
 		const Walkbox &w = _walkboxes[i];
 
 		if (isXZInWalkbox(x, z, w)) {
@@ -215,7 +219,7 @@ int Set::findObject(const char *objectName) {
 }
 
 bool Set::objectSetHotMouse(int objectId) {
-	if(!_objects || objectId < 0 || objectId >= (int)_objectCount) {
+	if (!_objects || objectId < 0 || objectId >= (int)_objectCount) {
 		return false;
 	}
 
@@ -254,4 +258,71 @@ const char *Set::objectGetName(int objectId) {
 	return _objects[objectId]._name;
 }
 
+void Set::setWalkboxStepSound(int walkboxId, int stepSound) {
+	this->_walkboxStepSound[walkboxId] = stepSound;
+}
+
+void Set::setFoodstepSoundOverride(int soundId) {
+	_footstepSoundOverride = soundId;
+}
+
+void Set::resetFoodstepSoundOverride() {
+	_footstepSoundOverride = -1;
+}
+
+int Set::getWalkboxSoundWalkLeft(int walkboxId) {
+	int soundId;
+	if (this->_footstepSoundOverride >= 0) {
+		soundId = this->_footstepSoundOverride;
+	} else {
+		soundId = this->_walkboxStepSound[walkboxId];
+	}
+
+	if (soundId == 0) { //stone floor
+		return _vm->_rnd.getRandomNumberRng(160, 164);
+	}
+	if (soundId == 1) { //gravel floor
+		return _vm->_rnd.getRandomNumberRng(164, 170);
+	}
+	if (soundId == 2) { //wooden floor
+		return _vm->_rnd.getRandomNumberRng(476, 480);
+	}
+	if (soundId == 3) { //metal floor
+		return _vm->_rnd.getRandomNumberRng(466, 470);
+	}
+
+	return -1;
+}
+
+int Set::getWalkboxSoundWalkRight(int walkboxId) {
+	int soundId;
+	if (this->_footstepSoundOverride >= 0) {
+		soundId = this->_footstepSoundOverride;
+	} else {
+		soundId = this->_walkboxStepSound[walkboxId];
+	}
+
+	if (soundId == 0) { //stone floor
+		return _vm->_rnd.getRandomNumberRng(165, 169);
+	}
+	if (soundId == 1) { //gravel floor
+		return _vm->_rnd.getRandomNumberRng(169, 175);
+	}
+	if (soundId == 2) { //wooden floor
+		return _vm->_rnd.getRandomNumberRng(481, 485);
+	}
+	if (soundId == 3) { //metal floor
+		return _vm->_rnd.getRandomNumberRng(471, 475);
+	}
+
+	return -1;
+}
+
+int Set::getWalkboxSoundRunLeft(int walkboxId) {
+	return getWalkboxSoundWalkLeft(walkboxId);
+}
+
+int Set::getWalkboxSoundRunRight(int walkboxId) {
+	return getWalkboxSoundWalkRight(walkboxId);
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index 18fde76..8d9c97b 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -49,15 +49,20 @@ struct Object {
 struct Walkbox {
 	char    _name[20];
 	float   _altitude;
-	uint32  _vertexCount;
+	int     _vertexCount;
 	Vector3 _vertices[8];
 };
 
 class Set {
+#if _DEBUG
+	friend class BladeRunnerEngine;
+#endif
+
 	BladeRunnerEngine *_vm;
 
-	uint32      _objectCount;
-	uint32      _walkboxCount;
+	bool        _loaded;
+	int         _objectCount;
+	int         _walkboxCount;
 	Object     *_objects;
 	Walkbox    *_walkboxes;
 	int         _walkboxStepSound[85];
@@ -86,6 +91,15 @@ public:
 	void objectSetIsObstacle(int objectId, bool isObstacle);
 	void objectSetIsTarget(int objectId, bool isTarget);
 	const char *objectGetName(int objectId);
+
+	void setWalkboxStepSound(int walkboxId, int soundId);
+	void setFoodstepSoundOverride(int soundId);
+	void resetFoodstepSoundOverride();
+	int getWalkboxSoundWalkLeft(int walkboxId);
+	int getWalkboxSoundWalkRight(int walkboxId);
+	int getWalkboxSoundRunLeft(int walkboxId);
+	int getWalkboxSoundRunRight(int walkboxId);
+	
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index b3b6ad8..f8acb91 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -49,7 +49,7 @@ bool View::read(Common::ReadStream *stream) {
 void View::setFovX(float fovX) {
 	_fovX = fovX;
 
-	_viewportHalfWidth  = 320.0f;
+	_viewportHalfWidth = 320.0f;
 	_viewportHalfHeight = 240.0f;
 
 	_viewportDistance = 320.0f / tanf(_fovX / 2.0f);
@@ -60,17 +60,16 @@ void View::calculateSliceViewMatrix() {
 
 	m = m * rotationMatrixX(float(M_PI) / 2.0f);
 
-	Matrix4x3 a( -1.0f,  0.0f,  0.0f,  0.0f,
-	              0.0f, -1.0f,  0.0f,  0.0f,
-	              0.0f,  0.0f,  1.0f,  0.0f);
+	Matrix4x3 a(-1.0f, 0.0f, 0.0f, 0.0f,
+	            0.0f, -1.0f, 0.0f, 0.0f,
+	            0.0f, 0.0f, 1.0f, 0.0f);
 
 	m = a * m;
 
 	_sliceViewMatrix = m;
 }
 
-void View::calculateCameraPosition()
-{
+void View::calculateCameraPosition() {
 	Matrix4x3 invertedMatrix = invertMatrix(_sliceViewMatrix);
 
 	_cameraPosition.x = invertedMatrix(0, 3);
@@ -78,5 +77,12 @@ void View::calculateCameraPosition()
 	_cameraPosition.z = invertedMatrix(2, 3);
 }
 
+Vector2 View::calculateScreenPosition(Vector3 worldPosition) {
+	Vector3 viewPosition = _frameViewMatrix * worldPosition;
+	return Vector2(
+		this->_viewportHalfWidth - viewPosition.x / viewPosition.z * _viewportDistance,
+		this->_viewportHalfHeight - viewPosition.y / viewPosition.z * _viewportDistance
+	);
+}
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
index 511ea66..2ffb4a9 100644
--- a/engines/bladerunner/view.h
+++ b/engines/bladerunner/view.h
@@ -45,6 +45,7 @@ public:
 	float     _viewportDistance;
 
 	bool read(Common::ReadStream *stream);
+	Vector2 calculateScreenPosition(Vector3 worldPosition);
 
 private:
 	void setFovX(float fovX);


Commit: f1cb735ee07c11785f67080ea800a72dd551ae19
    https://github.com/scummvm/scummvm/commit/f1cb735ee07c11785f67080ea800a72dd551ae19
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:41+02:00

Commit Message:
BLADERUNNER: added rendering support for lighting and effects, but its not working correctly yet

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/color.h
    engines/bladerunner/fog.cpp
    engines/bladerunner/fog.h
    engines/bladerunner/light.cpp
    engines/bladerunner/light.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/set_effects.cpp
    engines/bladerunner/set_effects.h
    engines/bladerunner/slice_animations.cpp
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/vector.h
    engines/bladerunner/view.cpp



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index c0c042e..29c83e7 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -399,12 +399,11 @@ bool Actor::tick(bool forceDraw) {
 void Actor::draw() {
 	Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0);
 	float draw_facing = M_PI - _facing * M_PI / 512.0;
-	// float   draw_scale  = _scale;
+	float draw_scale  = _scale;
 
 	// TODO: Handle SHORTY mode
-
-	_vm->_sliceRenderer->setupFrame(_animationId, _animationFrame, draw_position, draw_facing);
-	_vm->_sliceRenderer->drawFrame(_vm->_surface2, _vm->_zBuffer2);
+	
+	_vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, draw_position, draw_facing, draw_scale, _vm->_surface2, _vm->_zBuffer2);
 }
 
 int Actor::getSetId() {
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 45ffdd8..41f1bb5 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -613,7 +613,7 @@ void BladeRunnerEngine::gameTick() {
 				_walkSoundId = -1;
 			}
 
-#if _DEBUG
+#if 0 //_DEBUG
 			//draw scene objects
 			int count = _sceneObjects->_count;
 			if (count > 0) {
@@ -667,35 +667,6 @@ void BladeRunnerEngine::gameTick() {
 				}
 				
 			}
-
-			for (Light* light = _lights->_lights; light != nullptr; light->_next) {
-
-				Matrix4x3 matrix = light->_matrix;
-
-				// this is all wrong
-
-//					matrix = matrix * rotationMatrixX(float(M_PI) / 2.0f);
-
-//					Matrix4x3 a(
-//						-1.0f, 0.0f, 0.0f, 0.0f,
-//						0.0f, -1.0f, 0.0f, 0.0f,
-//						0.0f, 0.0f, 1.0f, 0.0f);
-
-				//matrix = a * matrix;
-//					matrix = invertMatrix(matrix);
-
-				int colorR = (light->_color.r * 31.0f);
-				int colorG = (light->_color.g * 31.0f);
-				int colorB = (light->_color.b * 31.0f);
-				int color = (colorR << 10) + (colorG << 5) + colorB;
-				drawBBox(
-					Vector3(matrix(0, 3) - 5.0f, matrix(1, 3) - 5.0f, matrix(2, 3) - 5.0f),
-					Vector3(matrix(0, 3) + 5.0f, matrix(1, 3) + 5.0f, matrix(2, 3) + 5.0f),
-					_view, &_surface2, color
-				);
-				light = light->_next;
-
-			}
 #endif
 
 			_system->copyRectToScreen((const byte *)_surface2.getBasePtr(0, 0), _surface2.pitch, 0, 0, 640, 480);
@@ -751,6 +722,7 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 	}
 
 	if (sceneObjectId == -1) {
+		_actors[0]->loopWalkToXYZ(mousePosition);
 		debug("Clicked on nothing");
 		return;
 	} else if (sceneObjectId >= 0 && sceneObjectId <= 73) {
diff --git a/engines/bladerunner/color.h b/engines/bladerunner/color.h
index eebe2dc..10d3737 100644
--- a/engines/bladerunner/color.h
+++ b/engines/bladerunner/color.h
@@ -23,13 +23,27 @@
 #ifndef BLADERUNNER_COLOR_H
 #define BLADERUNNER_COLOR_H
 
+#include "common/system.h"
+
 namespace BladeRunner {
 
-struct Color
-{
+struct Color {
 	float r;
 	float g;
 	float b;
+
+
+	Color() {
+	}
+
+	Color(float r, float g, float b) : r(r), g(g), b(b) {
+	}
+};
+
+struct Color256 {
+	uint8 r;
+	uint8 g;
+	uint8 b;
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
index ead7c91..bca548c 100644
--- a/engines/bladerunner/fog.cpp
+++ b/engines/bladerunner/fog.cpp
@@ -4,16 +4,13 @@
 
 namespace BladeRunner {
 
-Fog::Fog()
-{
+Fog::Fog() {
 }
 
-Fog::~Fog()
-{
+Fog::~Fog() {
 }
 
-int Fog::readCommon(Common::ReadStream* stream)
-{
+int Fog::readCommon(Common::ReadStream *stream) {
 	int offset = stream->readUint32LE();
 	stream->read(_name, 20);
 	_fogColor.r = stream->readFloatLE();
@@ -23,8 +20,7 @@ int Fog::readCommon(Common::ReadStream* stream)
 	return offset;
 }
 
-void Fog::readAnimationData(Common::ReadStream* stream, int size)
-{
+void Fog::readAnimationData(Common::ReadStream *stream, int size) {
 	_animatedParameters = stream->readUint32LE();
 	_animationData = new float[size / sizeof(float)];
 	stream->read(_animationData, size);
@@ -45,12 +41,10 @@ void Fog::readAnimationData(Common::ReadStream* stream, int size)
 	setupFrame(0);
 }
 
-void Fog::reset()
-{
+void Fog::reset() {
 }
 
-void Fog::setupFrame(int frame)
-{
+void Fog::setupFrame(int frame) {
 	int offset = frame % _framesCount;
 	_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
 	_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
@@ -67,24 +61,181 @@ void Fog::setupFrame(int frame)
 	_inverted = invertMatrix(_matrix);
 }
 
-void FogCone::read(Common::ReadStream* stream, int framesCount)
-{
+void FogCone::read(Common::ReadStream *stream, int framesCount) {
 	_framesCount = framesCount;
 	int size = readCommon(stream);
 	_parameter1 = stream->readFloatLE();
 	readAnimationData(stream, size - 52);
 }
 
-void FogSphere::read(Common::ReadStream* stream, int framesCount)
-{
+void FogCone::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) {
+	*coeficient = 0.0f;
+
+	Vector3 positionT = this->_matrix * position;
+	Vector3 viewPositionT = this->_matrix * viewPosition;
+
+	Vector3 vectorT = (viewPositionT - positionT).normalize();
+
+	float v67 = - positionT.x * vectorT.x - positionT.y * vectorT.y - positionT.z * vectorT.z;
+	float v66 = - (positionT.z * positionT.z) - (positionT.y * positionT.y) - (positionT.x * positionT.x) + (v67 * v67) + (this->_parameter1 * this->_parameter1);
+
+	if (v66 >= 0.0f) {
+		float v24 = sqrt(v66);
+
+		Vector3 v29 = positionT + (v67 - v24) * vectorT;
+		Vector3 v36 = positionT + (v67 + v24) * vectorT;
+
+		Vector3 v39 = this->_inverted * v29;
+		Vector3 v42 = this->_inverted * v36;
+
+		float v74 = (v39 - position).length();
+		float v76 = (v42 - position).length();
+
+		Vector3 vector = viewPosition - position;
+
+		float vectorLength = vector.length();
+
+		if (v74 < 0.0f) {
+			v74 = 0.0f;
+		}
+		if (v76 > vectorLength) {
+			v76 = vectorLength;
+		}
+		if (v76 >= v74) {
+			*coeficient = v76 - v74;
+		}
+	}
+}
+
+void FogSphere::read(Common::ReadStream *stream, int framesCount) {
 	_framesCount = framesCount;
 	int size = readCommon(stream);
 	_parameter1 = stream->readFloatLE();
 	readAnimationData(stream, size - 52);
 }
 
-void FogBox::read(Common::ReadStream* stream, int framesCount)
-{
+void FogSphere::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) {
+	*coeficient = 0.0f;
+
+	Vector3 positionT = this->_matrix * position;
+	Vector3 viewPositionT = this->_matrix * viewPosition;
+
+	Vector3 v158 = Vector3::cross(positionT, viewPositionT);
+
+	if (v158.x != 0.0f || v158.y != 0.0f || v158.z != 0.0f) {
+		Vector3 v167 = v158.normalize();
+		if (v167.z < 0.0f) {
+			v167 = -1.0f * v167;
+		}
+
+		float v173 = sqrt(1.0f - v167.z * v167.z);
+		if (v173 > cos(this->_parameter1)) {
+			Vector3 v37 = Vector3(v167.y, -v167.x, 0.0f).normalize();
+
+			float v41 = 1.0f / v173 / v173 - 1.0f;
+			float v42 = sqrt(v41);
+			float v43 = tan(this->_parameter1);
+			float v44 = sqrt(v43 * v43 - v41);
+
+			Vector3 v45 = v44 * v37;
+
+			Vector3 v48 = Vector3(
+				-v37.y * v42,
+				v37.x * v42,
+				0.0f * v42);
+
+			Vector3 v51 = v48 + Vector3(0.0f, 0.0f, -1.0f);
+
+			Vector3 v186 = v51 - v45;
+			Vector3 v183 = v51 + v45;
+
+			Vector3 vector = viewPositionT - positionT;
+
+			Vector3 v177 = -1.0f * positionT;
+			Vector3 v174 = Vector3::cross(v186, vector);
+
+			float v189, v191;
+			if (fabs(v174.x) <= fabs(v174.y)) {
+				if (fabs(v174.y) <= fabs(v174.z)) {
+					v191 = v177.x * v186.y - v177.y * v186.x;
+					v189 = v186.y * vector.x - v186.x * vector.y;
+				} else {
+					v191 = v177.z * v186.x - v186.z * v177.x;
+					v189 = v186.x * vector.z - v186.z * vector.x;
+				}
+			} else {
+				if (fabs(v174.x) <= fabs(v174.z)) {
+					v191 = v177.x * v186.y - v177.y * v186.x;
+					v189 = v186.y * vector.x - v186.x * vector.y;
+				} else {
+					v191 = v186.z * v177.y - v186.y * v177.z;
+					v189 = v186.z * vector.y - v186.y * vector.z;
+				}
+			}
+
+			float v88;
+			if (v189 == 0.0f) {
+				v88 = 0.0f;
+			} else {
+				v88 = v191 / v189;
+			}
+
+			Vector3 v196 = -1.0f * positionT;
+			Vector3 v193 = Vector3::cross(v183, vector);
+
+			float v190, v192;
+			if (fabs(v193.x) <= fabs(v193.y)) {
+				if (fabs(v193.y) <= fabs(v193.z)) {
+					v192 = v196.x * v183.y - v196.y * v183.x;
+					v190 = v183.y * vector.x - v183.x * vector.y;
+				} else {
+					v192 = v196.z * v183.x - v183.z * v196.x;
+					v190 = v183.x * vector.z - v183.z * vector.x;
+				}
+			} else {
+				if (fabs(v193.x) <= fabs(v193.z)) {
+					v192 = v196.x * v183.y - v196.y * v183.x;
+					v190 = v183.y * vector.x - v183.x * vector.y;
+				} else {
+					v192 = v183.z * v196.y - v183.y * v196.z;
+					v190 = v183.z * vector.y - v183.y * vector.z;
+				}
+			}
+
+			float v114;
+			if (v190 == 0.0f) {
+				v114 = 0.0f;
+			} else {
+				v114 = v192 / v190;
+			}
+
+			if (v114 < v88) {
+				float temp = v88;
+				v88 = v114;
+				v114 = temp;
+			}
+
+			if (v88 <= 1.0f && v114 >= 0.0f) {
+				if (v88 < 0.0f) {
+					v88 = 0.0;
+				}
+				if (v114 > 1.0f) {
+					v114 = 1.0;
+				}
+
+				Vector3 v139 = positionT + (v88 * vector);
+				Vector3 v142 = this->_inverted * v139;
+
+				Vector3 v148 = positionT + (v114 * vector);
+				Vector3 v151 = this->_inverted * v148;
+
+				*coeficient = (v151 - v142).length();
+			}
+		}
+	}
+}
+
+void FogBox::read(Common::ReadStream *stream, int framesCount) {
 	_framesCount = framesCount;
 	int size = readCommon(stream);
 	_parameter1 = stream->readFloatLE();
@@ -93,4 +244,105 @@ void FogBox::read(Common::ReadStream* stream, int framesCount)
 	readAnimationData(stream, size - 60);
 }
 
+void FogBox::calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) {
+	Vector3 v159 = this->_matrix * position;
+	Vector3 v146 = v159;
+	Vector3 v156 = this->_matrix * viewPosition;
+	Vector3 v153 = v156;
+	Vector3 v150 = v156 - v159;
+
+	float v149 = this->_parameter1 * 0.5f;
+	if (v159.x < -v149) {
+		if (v156.x < -v149) {
+			return;
+		}
+		float v28 = (-v159.x - v149) / v150.x;
+		Vector3 v29 = v28 * v150;
+		v146 = v159 + v29;
+	} else {
+		if (v156.x < -v149) {
+			float v19 = (-v156.x - v149) / v150.x;
+			Vector3 v20 = v19 * v150;
+			v153 = v156 + v20;
+		}
+	}
+	if (v149 < v146.x) {
+		if (v149 < v153.x) {
+			return;
+		}
+		float v48 = (v149 - v146.x) / v150.x;
+		Vector3 v49 = v48 * v150;
+		v146 = v146 + v49;
+	} else {
+		if (v149 < v153.x) {
+			float v40 = (v149 - v153.x) / v150.x;
+			Vector3 v41 = v40 * v150;
+			v153 = v153 + v41;
+		}
+	}
+	float v162 = this->_parameter2 * 0.5f;
+	if (v146.y < -v162) {
+		if (v153.y < -v162) {
+			return;
+		}
+		float v71 = (-v146.y - v162) / v150.y;
+		Vector3 v72 = v71 * v150;
+		v146 = v146 + v72;
+	} else {
+		if (v153.y < -v162) {
+			float v62 = (-v153.y - v162) / v150.y;
+			Vector3 v63 = v62 * v150;
+			v153 = v153 + v63;
+		}
+	}
+	if (v162 < v146.y) {
+		if (v162 < v153.y) {
+			return;
+		}
+		float v91 = (v162 - v146.y) / v150.y;
+		Vector3 v92 = v91 * v150;
+		v146 = v146 + v92;
+	} else {
+		if (v162 < v153.y) {
+			float v83 = (v162 - v153.y) / v150.y;
+			Vector3 v84 = v83 * v150;
+			v153 = v153 + v84;
+		}
+	}
+
+	if (0.0f <= v146.z) {
+		if (0.0f > v153.z) {
+			float v103 = -v153.z / v150.z;
+			Vector3 v104 = v103 * v150;
+			v153 = v153 + v104;
+		}
+	} else {
+		if (0.0f > v153.z) {
+			return;
+		}
+		float v111 = -v146.z / v150.z;
+		Vector3 v112 = v111 * v150;
+		v146 = v146 + v112;
+	}
+
+	if (v146.z <= this->_parameter3) {
+		if (v153.z > this->_parameter3) {
+			float v124 = (this->_parameter3 - v153.z) / v150.z;
+			Vector3 v125 = v124 * v150;
+			v153 = v153 + v125;
+		}
+	} else {
+		if (v153.z <= this->_parameter3) {
+			float v132 = (this->_parameter3 - v146.z) / v150.z;
+			Vector3 v133 = v132 * v150;
+			v146 = v146 + v133;
+		}
+	}
+
+	Vector3 v137 = this->_inverted * v146;
+	Vector3 v140 = this->_inverted * v153;
+	Vector3 v143 = v140 - v137;
+
+	*coeficient = v143.length();
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h
index db291e3..992ede5 100644
--- a/engines/bladerunner/fog.h
+++ b/engines/bladerunner/fog.h
@@ -71,7 +71,7 @@ public:
 	virtual ~Fog();
 
 	virtual void read(Common::ReadStream *stream, int framesCount) = 0;
-
+	virtual void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient) = 0;
 	void reset();
 
 	void setupFrame(int frame);
@@ -85,16 +85,19 @@ protected:
 class FogCone : public Fog
 {
 	void read(Common::ReadStream *stream, int framesCount);
+	void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient);
 };
 
 class FogSphere : public Fog
 {
 	void read(Common::ReadStream *stream, int framesCount);
+	void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient);
 };
 
 class FogBox : public Fog
 {
 	void read(Common::ReadStream *stream, int framesCount);
+	void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index d1d79b8..39dc3e3 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -1,17 +1,15 @@
 #include "bladerunner/light.h"
+#include "common/util.h"
 
 namespace BladeRunner {
 
-Light::Light()
-{
+Light::Light() {
 }
 
-Light::~Light()
-{
+Light::~Light() {
 }
 
-void Light::read(Common::ReadStream* stream, int framesCount, int frame, int animated)
-{
+void Light::read(Common::ReadStream *stream, int framesCount, int frame, int animated) {
 	_framesCount = framesCount;
 	_animated = animated;
 
@@ -48,8 +46,7 @@ void Light::read(Common::ReadStream* stream, int framesCount, int frame, int ani
 	setupFrame(frame);
 }
 
-void Light::readVqa(Common::ReadStream* stream, int framesCount, int frame, int animated)
-{
+void Light::readVqa(Common::ReadStream *stream, int framesCount, int frame, int animated) {
 	_framesCount = framesCount;
 	_animated = animated;
 
@@ -83,8 +80,7 @@ void Light::readVqa(Common::ReadStream* stream, int framesCount, int frame, int
 	setupFrame(frame);
 }
 
-void Light::setupFrame(int frame)
-{
+void Light::setupFrame(int frame) {
 	int offset = frame % _framesCount;
 	_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
 	_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
@@ -108,9 +104,185 @@ void Light::setupFrame(int frame)
 
 }
 
-float Light::attenuation(float min, float max, float distance)
-{
-	return 0.0;
+float Light::calculate(Vector3 start, Vector3 end) {
+	return calculateCoeficient(_matrix * start, _matrix * end, _field16, _field17);
+}
+
+void Light::calculateColor(Color *outColor, Vector3 position) {
+	Vector3 positionT = _matrix * position;
+	float att = attenuation(_field16, _field17, positionT.length());
+	outColor->r = _color.r * att;
+	outColor->g = _color.g * att;
+	outColor->b = _color.b * att;
+}
+
+float Light::calculateCoeficient(Vector3 start, Vector3 end, float a3, float a4) {
+	if (a4 == 0.0f) {
+		return 1.0e30f;
+	}
+
+	if (a3 >= start.length() && a3 >= end.length()) {
+		return 1.0e30f;
+	}
+
+	float v40 = (end - start).length();
+	float v31 = 0.0f;
+	if (v40 != 0.0f) {
+		Vector3 v27 = Vector3::cross(start, end);
+		v31 = v27.length() / v40;
+	}
+
+	if (v31 < a4) {
+		return 1.0f / (1.0f - (v31 / a4));
+	}
+	return 1.0e30f;
+}
+
+float Light::attenuation(float min, float max, float distance) {
+	if (max == 0.0f) {
+		return 1.0f;
+	}
+	if (min < max) {
+		distance = CLIP(distance, min, max);
+		float x = (max - distance) / (max - min);
+		return x * x * (3.0f - 2.0f * x);
+	}
+	if (min > distance) {
+		return 1.0f;
+	}
+	return 0.0f;
+}
+
+float Light1::calculate(Vector3 start, Vector3 end) {
+	start = _matrix * start;
+	end = _matrix * end;
+
+	float v40 = 0.0f;
+	if (_field17 != 0.0f) {
+		v40 = calculateCoeficient(start, end, _field16, _field17);
+	}
+
+	float v41 = atan2(start.length(), -start.z);
+	float v42 = atan2(end.length(), -end.z);
+
+	float v43;
+	if ((_field18 >= v41 && _field18 >= v42) || (_field19 <= v41 && _field19 <= v42)) {
+		v43 = 1.0e30f;
+	} else {
+		v43 = 2.0;
+	}
+	if (v43 < v40) {
+		return v40;
+	} else {
+		return v43;
+	}
+}
+
+void Light1::calculateColor(Color *outColor, Vector3 position) {
+	Vector3 positionT = _matrix * position;
+
+	outColor->r = 0.0f;
+	outColor->g = 0.0f;
+	outColor->b = 0.0f;
+
+	if (positionT.z < 0.0f) {
+		float v12 = attenuation(_field18, _field19, atan2(sqrt(positionT.x * positionT.x + positionT.y * positionT.y), -positionT.z));
+		float v13 = attenuation(_field16, _field17, positionT.length());
+
+		outColor->r = v12 * v13 * _color.r;
+		outColor->g = v12 * v13 * _color.g;
+		outColor->b = v12 * v13 * _color.b;
+	}
+}
+
+float Light2::calculate(Vector3 start, Vector3 end) {
+	start = _matrix * start;
+	end = _matrix * end;
+
+	float v54 = 0.0f;
+	if (_field17 != 0.0f) {
+		v54 = calculateCoeficient(start, end, _field16, _field17);
+	}
+
+	float v55 = atan2(fabs(start.x), -start.z);
+	float v58 = atan2(fabs(start.y), -start.z);
+	float v57 = atan2(fabs(end.x), -end.z);
+	float v56 = atan2(fabs(end.y), -end.z);
+
+	float v59;
+	if ((_field18 >= v55 && _field18 >= v57 && _field18 >= v58 && _field18 >= v56) || (_field19 <= v55 && _field19 <= v57 && _field19 <= v58 && _field19 <= v56)) {
+		v59 = 1.0e30f;
+	} else {
+		v59 = 2.0f;
+	}
+	if (v59 < v54) {
+		return v54;
+	} else {
+		return v59;
+	}
+}
+
+void Light2::calculateColor(Color *outColor, Vector3 position) {
+	Vector3 positionT = _matrix * position;
+
+	outColor->r = 0.0f;
+	outColor->g = 0.0f;
+	outColor->b = 0.0f;
+
+	if (positionT.z < 0.0f) {
+		float v11 = attenuation(_field18, _field19, atan2(fabs(positionT.y), -positionT.z));
+		float v12 = attenuation(_field18, _field19, atan2(fabs(positionT.x), -positionT.z));
+		float v13 = attenuation(_field16, _field17, positionT.length());
+
+		outColor->r = v11 * v12 * v13 * _color.r;
+		outColor->g = v11 * v12 * v13 * _color.g;
+		outColor->b = v11 * v12 * v13 * _color.b;
+	}
+}
+
+void Light3::calculateColor(Color *outColor, Vector3 position) {
+	Vector3 positionT = _matrix * position;
+
+	outColor->r = 0.0f;
+	outColor->g = 0.0f;
+	outColor->b = 0.0f;
+
+	if (positionT.z < 0.0f) {
+		float v12 = attenuation(_field18, _field19, sqrt(positionT.x * positionT.x + positionT.y * positionT.y));
+		float v13 = attenuation(_field16, _field17, positionT.length());
+
+		outColor->r = v12 * v13 * _color.r;
+		outColor->g = v12 * v13 * _color.g;
+		outColor->b = v12 * v13 * _color.b;
+	}
+}
+
+void Light4::calculateColor(Color *outColor, Vector3 position) {
+	Vector3 positionT = _matrix * position;
+
+	outColor->r = 0.0f;
+	outColor->g = 0.0f;
+	outColor->b = 0.0f;
+
+	if (positionT.z < 0.0f) {
+		float v11 = attenuation(_field18, _field19, fabs(positionT.y));
+		float v12 = attenuation(_field18, _field19, fabs(positionT.x));
+		float v13 = attenuation(_field16, _field17, positionT.length());
+
+		outColor->r = v11 * v12 * v13 * _color.r;
+		outColor->g = v11 * v12 * v13 * _color.g;
+		outColor->b = v11 * v12 * v13 * _color.b;
+	}
+}
+
+float Light5::calculate(Vector3 start, Vector3 end) {
+	return 1.0e30f;
+}
+
+void Light5::calculateColor(Color *outColor, Vector3 position) {
+	outColor->r = _color.r;
+	outColor->g = _color.g;
+	outColor->b = _color.b;
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index a6ac21e..9c2cdcb 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -42,7 +42,9 @@ class Light
 	friend class BladeRunnerEngine;
 #endif
 	friend class Lights;
+	friend class SliceRenderer;
 
+protected:
 	char _name[20];
 	int _framesCount;
 	int _animated;
@@ -77,35 +79,42 @@ class Light
 
 public:
 	Light();
-	~Light();
+	virtual ~Light();
 
 	void read(Common::ReadStream *stream, int framesCount, int frame, int animated);
 	void readVqa(Common::ReadStream *stream, int framesCount, int frame, int animated);
 
 	void setupFrame(int frame);
 
-private:
-	static float attenuation(float min, float max, float distance);
+	virtual float calculate(Vector3 start, Vector3 end);
+	virtual void calculateColor(Color *outColor, Vector3 position);
+
+protected:
+	float calculateCoeficient(Vector3 start, Vector3 end, float a3, float a4);
+	float attenuation(float min, float max, float distance);
 };
 
 class Light1 : public Light {
-
+	float calculate(Vector3 start, Vector3 end);
+	void calculateColor(Color *outColor, Vector3 position);
 };
 
 class Light2 : public Light {
-
+	float calculate(Vector3 start, Vector3 end);
+	void calculateColor(Color *outColor, Vector3 position);
 };
 
 class Light3 : public Light {
-
+	void calculateColor(Color *outColor, Vector3 position);
 };
 
 class Light4 : public Light {
-
+	void calculateColor(Color *outColor, Vector3 position);
 };
 
 class Light5 : public Light {
-
+	float calculate(Vector3 start, Vector3 end);
+	void calculateColor(Color *outColor, Vector3 position);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index eb18958..0d6a1be 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -2,8 +2,7 @@
 
 namespace BladeRunner {
 
-Lights::Lights(BladeRunnerEngine *vm)
-{
+Lights::Lights(BladeRunnerEngine *vm) {
 	_vm = vm;
 
 	_ambientLightColor.r = 1.0;
@@ -11,28 +10,25 @@ Lights::Lights(BladeRunnerEngine *vm)
 	_ambientLightColor.b = 0.0;
 
 	_lights = nullptr;
+	_lightsCount = 0;
 	_frame = 0;
 }
 
-Lights::~Lights()
-{
+Lights::~Lights() {
 	reset();
 }
 
-void Lights::read(Common::ReadStream *stream, int framesCount)
-{
+void Lights::read(Common::ReadStream *stream, int framesCount) {
 	_ambientLightColor.r = stream->readFloatLE();
 	_ambientLightColor.g = stream->readFloatLE();
 	_ambientLightColor.b = stream->readFloatLE();
 
 	_lightsCount = stream->readUint32LE();
 	int i;
-	for (i = 0; i < _lightsCount; i++)
-	{
+	for (i = 0; i < _lightsCount; i++) {
 		Light *light;
 		int type = stream->readUint32LE();
-		switch (type)
-		{
+		switch (type) {
 		case 1:
 			light = new Light1();
 			break;
@@ -58,24 +54,18 @@ void Lights::read(Common::ReadStream *stream, int framesCount)
 	}
 }
 
-void Lights::removeAnimated()
-{
+void Lights::removeAnimated() {
 	Light **nextLight;
-	Light *light; 
+	Light *light;
 
 	nextLight = &this->_lights;
 	light = this->_lights;
-	if (light)
-	{
-		do
-		{
-			if (light->_animated)
-			{
+	if (light) {
+		do {
+			if (light->_animated) {
 				*nextLight = light->_next;
 				delete light;
-			}
-			else
-			{
+			} else {
 				nextLight = &light->_next;
 			}
 			light = *nextLight;
@@ -83,8 +73,7 @@ void Lights::removeAnimated()
 	}
 }
 
-void Lights::readVqa(Common::ReadStream *stream)
-{
+void Lights::readVqa(Common::ReadStream *stream) {
 	removeAnimated();
 	if (stream->eos())
 		return;
@@ -93,26 +82,25 @@ void Lights::readVqa(Common::ReadStream *stream)
 	int count = stream->readUint32LE();
 	for (int i = 0; i < count; i++) {
 		int lightType = stream->readUint32LE();
-		Light* light;
-		switch(lightType)
-		{
-			case 5:
-				light = new Light5();
-				break;
-			case 4:
-				light = new Light4();
-				break;
-			case 3:
-				light = new Light3();
-				break;
-			case 2:
-				light = new Light2();
-				break;
-			case 1:
-				light = new Light1();
-				break;
-			default:
-				light = new Light();
+		Light *light;
+		switch (lightType) {
+		case 5:
+			light = new Light5();
+			break;
+		case 4:
+			light = new Light4();
+			break;
+		case 3:
+			light = new Light3();
+			break;
+		case 2:
+			light = new Light2();
+			break;
+		case 1:
+			light = new Light1();
+			break;
+		default:
+			light = new Light();
 		}
 		light->readVqa(stream, framesCount, _frame, 1);
 		light->_next = _lights;
@@ -120,8 +108,7 @@ void Lights::readVqa(Common::ReadStream *stream)
 	}
 }
 
-void Lights::setupFrame(int frame)
-{
+void Lights::setupFrame(int frame) {
 	Light *light;
 
 	if (frame == _frame)
@@ -130,22 +117,19 @@ void Lights::setupFrame(int frame)
 	if (!_lights)
 		return;
 
-	for (light = _lights; light; light = light->_next)
-	{
+	for (light = _lights; light; light = light->_next) {
 		light->setupFrame(frame);
 	}
 }
 
-void Lights::reset()
-{
+void Lights::reset() {
 	Light *light;
 	Light *nextLight;
 
 	if (!_lights)
 		return;
 
-	do
-	{
+	do {
 		light = _lights;
 		nextLight = light->_next;
 		delete light;
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index 37a7b17..2ba95b9 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -35,6 +35,8 @@ class Lights {
 #if _DEBUG
 	friend class BladeRunnerEngine;
 #endif
+	friend class SliceRenderer;
+
 	BladeRunnerEngine *_vm;
 
 	Color _ambientLightColor;
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
index bc10a0f..f4d2506 100644
--- a/engines/bladerunner/set_effects.cpp
+++ b/engines/bladerunner/set_effects.cpp
@@ -2,7 +2,7 @@
 
 namespace BladeRunner {
 
-SetEffects::SetEffects(BladeRunnerEngine* vm) {
+SetEffects::SetEffects(BladeRunnerEngine *vm) {
 	_vm = vm;
 
 	_distanceColor.r = 1.0f;
@@ -23,7 +23,7 @@ SetEffects::~SetEffects() {
 	reset();
 }
 
-void SetEffects::read(Common::ReadStream* stream, int framesCount) {
+void SetEffects::read(Common::ReadStream *stream, int framesCount) {
 	_distanceCoeficient = stream->readFloatLE();
 	_distanceColor.r = stream->readFloatLE();
 	_distanceColor.g = stream->readFloatLE();
@@ -33,9 +33,8 @@ void SetEffects::read(Common::ReadStream* stream, int framesCount) {
 	int i;
 	for (i = 0; i < _fogsCount; i++) {
 		int type = stream->readUint32LE();
-		Fog* fog = NULL;
-		switch (type)
-		{
+		Fog *fog = NULL;
+		switch (type) {
 		case 0:
 			fog = new FogCone();
 			break;
@@ -46,8 +45,7 @@ void SetEffects::read(Common::ReadStream* stream, int framesCount) {
 			fog = new FogBox();
 			break;
 		}
-		if (!fog)
-		{
+		if (!fog) {
 			//TODO exception, unknown fog type
 		}
 		fog->read(stream, framesCount);
@@ -57,7 +55,7 @@ void SetEffects::read(Common::ReadStream* stream, int framesCount) {
 }
 
 void SetEffects::reset() {
-	Fog* fog, *nextFog;
+	Fog *fog, *nextFog;
 
 	if (!_fogs)
 		return;
@@ -84,8 +82,8 @@ void SetEffects::setFadeDensity(float density) {
 	_fadeDensity = density;
 }
 
-void SetEffects::setFogColor(char* fogName, float r, float g, float b) {
-	Fog* fog = findFog(fogName);
+void SetEffects::setFogColor(char *fogName, float r, float g, float b) {
+	Fog *fog = findFog(fogName);
 	if (fog == nullptr)
 		return;
 
@@ -94,19 +92,46 @@ void SetEffects::setFogColor(char* fogName, float r, float g, float b) {
 	fog->_fogColor.b = b;
 }
 
-void SetEffects::setFogDensity(char* fogName, float density) {
-	Fog* fog = findFog(fogName);
+void SetEffects::setFogDensity(char *fogName, float density) {
+	Fog *fog = findFog(fogName);
 	if (fog == nullptr)
 		return;
 
 	fog->_fogDensity = density;
 }
 
-Fog* SetEffects::findFog(char* fogName) {
+void SetEffects::calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor) {
+	float distanceCoeficient = CLIP((position - viewPosition).length() * _distanceCoeficient, 0.0f, 1.0f);
+
+	*outCoeficient = 1.0f - distanceCoeficient;
+	outColor->r = _distanceColor.r * distanceCoeficient;
+	outColor->g = _distanceColor.g * distanceCoeficient;
+	outColor->b = _distanceColor.b * distanceCoeficient;
+
+	for (Fog *fog = this->_fogs; fog != nullptr; fog = fog->_next) {
+		float fogCoeficient = 0.0f;
+		fog->calculateCoeficient(position, viewPosition, &fogCoeficient);
+		if (fogCoeficient > 0.0f) {
+			fogCoeficient = CLIP(fog->_fogDensity * fogCoeficient, 0.0f, 1.0f);
+
+			*outCoeficient = *outCoeficient * (1.0f - fogCoeficient);
+			outColor->r = outColor->r * (1.0f - fogCoeficient) + fog->_fogColor.r * fogCoeficient;
+			outColor->g = outColor->g * (1.0f - fogCoeficient) + fog->_fogColor.g * fogCoeficient;
+			outColor->b = outColor->b * (1.0f - fogCoeficient) + fog->_fogColor.b * fogCoeficient;
+		}
+	}
+
+	*outCoeficient = *outCoeficient * (1.0f - this->_fadeDensity);
+	outColor->r = outColor->r * (1.0f - this->_fadeDensity) + this->_fadeColor.r * this->_fadeDensity;
+	outColor->g = outColor->g * (1.0f - this->_fadeDensity) + this->_fadeColor.g * this->_fadeDensity;
+	outColor->b = outColor->b * (1.0f - this->_fadeDensity) + this->_fadeColor.b * this->_fadeDensity;
+}
+
+Fog *SetEffects::findFog(char *fogName) {
 	if (!_fogs)
 		return nullptr;
 
-	Fog* fog = _fogs;
+	Fog *fog = _fogs;
 
 	while (fog != nullptr) {
 		if (strcmp(fogName, fog->_name) == 0) {
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
index 16317ed..233009d 100644
--- a/engines/bladerunner/set_effects.h
+++ b/engines/bladerunner/set_effects.h
@@ -57,6 +57,8 @@ public:
 	void setFadeDensity(float density);
 	void setFogColor(char* fogName, float r, float g, float b);
 	void setFogDensity(char* fogName, float density);
+
+	void calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor);
 private:
 
 	Fog* findFog(char* fogName);
diff --git a/engines/bladerunner/slice_animations.cpp b/engines/bladerunner/slice_animations.cpp
index aafd268..503193c 100644
--- a/engines/bladerunner/slice_animations.cpp
+++ b/engines/bladerunner/slice_animations.cpp
@@ -51,11 +51,15 @@ bool SliceAnimations::open(const Common::String &name) {
 			uint8 color_g = file.readByte();
 			uint8 color_b = file.readByte();
 
+			_palettes[i].color[j].r = color_r;
+			_palettes[i].color[j].g = color_g;
+			_palettes[i].color[j].b = color_b;
+
 			uint16 rgb555 = ((uint16)color_r << 10) |
 			                ((uint16)color_g <<  5) |
 			                 (uint16)color_b;
 
-			_palettes[i][j] = rgb555;
+			_palettes[i].color555[j] = rgb555;
 		}
 	}
 
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index 1e35d6b..0abdfb1 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -27,16 +27,20 @@
 #include "common/file.h"
 #include "common/str.h"
 #include "common/types.h"
-#include "vector.h"
+
+#include "bladerunner/color.h"
+#include "bladerunner/vector.h"
+
 
 namespace BladeRunner {
 
 class BladeRunnerEngine;
 
 struct SlicePalette {
-	uint16 color[256];
+	uint16 color555[256];
+	Color256 color[256];
 
-	uint16 &operator[](size_t i) { return color[i]; }
+//	uint16 &operator[](size_t i) { return color555[i]; }
 };
 
 class SliceAnimations {
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 6bce572..8dad519 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -55,6 +55,7 @@ void dump(const char *str, Matrix4x3 m) {
 
 SliceRenderer::SliceRenderer(BladeRunnerEngine* vm) {
 	_vm = vm;
+	_pixelFormat = createRGB555();
 	int i;
 
 	for (i = 0; i < 942; i++) { // yes, its going just to 942 and not 997
@@ -88,8 +89,8 @@ void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float
 
 	Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[_animation].frameSize);
 
-	_frameFront.x      = stream.readFloatLE();
-	_frameFront.y      = stream.readFloatLE();
+	_frameScale.x      = stream.readFloatLE();
+	_frameScale.y      = stream.readFloatLE();
 	_frameSliceHeight  = stream.readFloatLE();
 	_framePos.x        = stream.readFloatLE();
 	_framePos.y        = stream.readFloatLE();
@@ -144,31 +145,33 @@ void SliceRenderer::calculateBoundingRect() {
 	Matrix3x2 m4(_view._viewportDistance / bottom.z,  0.0f, 0.0f,
 	                                           0.0f, 25.5f, 0.0f);
 
-	Matrix3x2 m2(_frameFront.x,          0.0f, _framePos.x,
-	                      0.0f, _frameFront.y, _framePos.y);
+	Matrix3x2 m2(_frameScale.x,          0.0f, _framePos.x,
+	                      0.0f, _frameScale.y, _framePos.y);
 
 	_field_109E = m4 * (facingRotation * m2);
 
-	Vector4 B6(_view._viewportHalfWidth   + top.x / top.z * _view._viewportDistance,
+	Vector4 startScreenVector(
+	           _view._viewportHalfWidth   + top.x / top.z * _view._viewportDistance,
 	           _view._viewportHalfHeight  + top.y / top.z * _view._viewportDistance,
 	           1.0f / top.z,
 	           _frameSliceCount * (1.0f / top.z));
 
-	Vector4 C2(_view._viewportHalfWidth   + bottom.x / bottom.z * _view._viewportDistance,
+	Vector4 endScreenVector(
+	           _view._viewportHalfWidth   + bottom.x / bottom.z * _view._viewportDistance,
 	           _view._viewportHalfHeight  + bottom.y / bottom.z * _view._viewportDistance,
 	           1.0f / bottom.z,
 	           0.0f);
 
-	_field_10B6.x = B6.x;
-	_field_10B6.y = B6.y;
-	_field_10B6.z = B6.z;
-	_field_10C2.x = C2.x;
-	_field_10C2.y = C2.y;
-	_field_10C2.z = C2.z;
-	_field_10CE   = B6.w;
-	_field_10D2   = C2.w;
+	_startScreenVector.x = startScreenVector.x;
+	_startScreenVector.y = startScreenVector.y;
+	_startScreenVector.z = startScreenVector.z;
+	_endScreenVector.x   = endScreenVector.x;
+	_endScreenVector.y   = endScreenVector.y;
+	_endScreenVector.z   = endScreenVector.z;
+	_startSlice          = startScreenVector.w;
+	_endSlice            = endScreenVector.w;
 
-	Vector4 delta = C2 - B6;
+	Vector4 delta = endScreenVector - startScreenVector;
 
 	if (delta.y == 0.0f)
 		return;
@@ -180,37 +183,37 @@ void SliceRenderer::calculateBoundingRect() {
 	float screenMinY =   0.0f;
 	float screenMaxY = 479.0f;
 
-	if (B6.y < screenMinY) {
-		if (C2.y < screenMinY)
+	if (startScreenVector.y < screenMinY) {
+		if (endScreenVector.y < screenMinY)
 			return;
 
-		float f = (screenMinY - B6.y) / delta.y;
-		B6 = B6 + f * delta;
-	} else if (B6.y > screenMaxY) {
-		if (C2.y >= screenMaxY)
+		float f = (screenMinY - startScreenVector.y) / delta.y;
+		startScreenVector = startScreenVector + f * delta;
+	} else if (startScreenVector.y > screenMaxY) {
+		if (endScreenVector.y >= screenMaxY)
 			return;
 
-		float f = (screenMaxY - B6.y) / delta.y;
-		B6 = B6 + f * delta;
+		float f = (screenMaxY - startScreenVector.y) / delta.y;
+		startScreenVector = startScreenVector + f * delta;
 	}
 
-	if (C2.y < screenMinY) {
-		float f = (screenMinY - C2.y) / delta.y;
-		C2 = C2 + f * delta;
-	} else if (C2.y > screenMaxY) {
-		float f = (screenMaxY - C2.y) / delta.y;
-		C2 = C2 + f * delta;
+	if (endScreenVector.y < screenMinY) {
+		float f = (screenMinY - endScreenVector.y) / delta.y;
+		endScreenVector = endScreenVector + f * delta;
+	} else if (endScreenVector.y > screenMaxY) {
+		float f = (screenMaxY - endScreenVector.y) / delta.y;
+		endScreenVector = endScreenVector + f * delta;
 	}
 
-	int bbox_min_y = (int)MIN(B6.y, C2.y);
-	int bbox_max_y = (int)MAX(B6.y, C2.y) + 1;
+	int bbox_min_y = (int)MIN(startScreenVector.y, endScreenVector.y);
+	int bbox_max_y = (int)MAX(startScreenVector.y, endScreenVector.y) + 1;
 
 	/*
 	 * Calculate min and max X
 	 */
 
-	Matrix3x2 mB6 = _field_109E + Vector2(B6.x, 25.5f / B6.z);
-	Matrix3x2 mC2 = _field_109E + Vector2(C2.x, 25.5f / C2.z);
+	Matrix3x2 mB6 = _field_109E + Vector2(startScreenVector.x, 25.5f / startScreenVector.z);
+	Matrix3x2 mC2 = _field_109E + Vector2(endScreenVector.x,   25.5f / endScreenVector.z);
 
 	float min_x =  640.0f;
 	float max_x =    0.0f;
@@ -234,14 +237,14 @@ void SliceRenderer::calculateBoundingRect() {
 	int bbox_min_x = MIN(MAX((int)min_x,     0), 640);
 	int bbox_max_x = MIN(MAX((int)max_x + 1, 0), 640);
 
-	_field_10B6.x = B6.x;
-	_field_10B6.y = B6.y;
-	_field_10B6.z = B6.z;
-	_field_10C2.x = C2.x;
-	_field_10C2.y = C2.y;
-	_field_10C2.z = C2.z;
-	_field_10CE   = B6.w;
-	_field_10D2   = C2.w;
+	_startScreenVector.x = startScreenVector.x;
+	_startScreenVector.y = startScreenVector.y;
+	_startScreenVector.z = startScreenVector.z;
+	_endScreenVector.x   = endScreenVector.x;
+	_endScreenVector.y   = endScreenVector.y;
+	_endScreenVector.z   = endScreenVector.z;
+	_startSlice          = startScreenVector.w;
+	_endSlice            = endScreenVector.w;
 
 	_minX = bbox_min_x;
 	_minY = bbox_min_y;
@@ -250,72 +253,74 @@ void SliceRenderer::calculateBoundingRect() {
 }
 
 struct SliceLineIterator {
-	int _field_00[2][3];
-	int _field_18;
-	int _field_1C;
-
-	float _field_20;
-	float _field_24;
-	float _field_28;
-	float _field_2C;
-	float _field_30;
-	float _field_34;
+	int _sliceMatrix[2][3];
+	int _startY;
+	int _endY;
+
+	float _currentZ;
+	float _stepZ;
+	float _currentSlice;
+	float _stepSlice;
+	float _currentX;
+	float _stepX;
 	int   _field_38;
-	int   _field_3C;
+	int   _currentY;
 
-	void setup(float arg_1,  float arg_2,  float arg_3,
-	           float arg_4,  float arg_5,  float arg_6,
-	           float arg_7,  float arg_8,
-	           Matrix3x2 arg_9);
+	void setup(float endScreenX,   float endScreenY,   float endScreenZ,
+	           float startScreenX, float startScreenY, float startScreenZ,
+	           float endSlice,     float startSlice,
+	           Matrix3x2 m);
 	float line();
 	void advance();
 };
 
 void SliceLineIterator::setup(
-	float arg_1,  float arg_2,  float arg_3,
-	float arg_4,  float arg_5,  float arg_6,
-	float arg_7,  float arg_8,
-	Matrix3x2 arg_9)
+	float endScreenX,   float endScreenY,   float endScreenZ,
+	float startScreenX, float startScreenY, float startScreenZ,
+	float endSlice,     float startSlice,
+	Matrix3x2 m)
 {
-	_field_18 = (int)arg_5;
-	_field_1C = (int)arg_2;
+	_startY = (int)startScreenY;
+	_endY   = (int)endScreenY;
 
-	float var_3 = arg_2 - arg_5;
+	float size = endScreenY - startScreenY;
 
-	if (var_3 <= 0.0f || arg_6 <= 0.0f)
-		_field_3C = _field_1C + 1;
+	if (size <= 0.0f || startScreenZ <= 0.0f)
+		_currentY = _endY + 1;
 
-	_field_20 = arg_6;
-	_field_24 = (arg_3 - arg_6) / var_3;
-	_field_2C = (arg_7 - arg_8) / var_3;
-	_field_28 = arg_8 - (arg_5 - floor(arg_5) - 1.0f) * _field_2C;
+	_currentZ  = startScreenZ;
+	_stepZ     = (endScreenZ - startScreenZ) / size;
 
-	_field_30 = arg_4;
-	_field_34 = (arg_1 - arg_4) / var_3;
-	_field_38 = (int)((25.5f / var_3) * (1.0f / arg_3 - 1.0f / arg_6) * 64.0);
-	_field_3C = _field_18;
+	_stepSlice     = (endSlice - startSlice) / size;
+	_currentSlice  = startSlice - (startScreenY - floor(startScreenY) - 1.0f) * _stepSlice;
 
-	float var_54 =         _field_30;
-	float var_55 = 25.5f / _field_20;
+	_currentX = startScreenX;
+	_stepX    = (endScreenX - startScreenX) / size;
 
-	Matrix3x2 translate_matrix = Matrix3x2(1.0f, 0.0f, var_54,
-	                                       0.0f, 1.0f, var_55);
+	_field_38 = (int)((25.5f / size) * (1.0f / endScreenZ - 1.0f / startScreenZ) * 64.0);
+	_currentY = _startY;
+
+	float offsetX =         _currentX;
+	float offsetZ = 25.5f / _currentZ;
+
+	Matrix3x2 translate_matrix = Matrix3x2(1.0f, 0.0f, offsetX,
+	                                       0.0f, 1.0f, offsetZ);
 
 	Matrix3x2 scale_matrix = Matrix3x2(65536.0f,  0.0f, 0.0f,
 	                                       0.0f, 64.0f, 0.0f);
 
-	arg_9 = scale_matrix * (translate_matrix * arg_9);
+	m = scale_matrix * (translate_matrix * m);
 
 	for (int r = 0; r != 2; ++r)
 		for (int c = 0; c != 3; ++c)
-			_field_00[r][c] = arg_9(r, c);
+			_sliceMatrix[r][c] = m(r, c);
 }
 
 float SliceLineIterator::line() {
 	float var_0 = 0.0f;
 
-	if (_field_20 != 0.0f)
-		var_0 = _field_28 / _field_20;
+	if (_currentZ != 0.0f)
+		var_0 = _currentSlice / _currentZ;
 
 	if (var_0 < 0.0)
 		var_0 = 0.0f;
@@ -324,12 +329,12 @@ float SliceLineIterator::line() {
 }
 
 void SliceLineIterator::advance() {
-	_field_20 += _field_24;
-	_field_28 += _field_2C;
-	_field_30 += _field_34;
-	_field_3C += 1;
-	_field_00[0][2] += (int)(65536.0f * _field_34);
-	_field_00[1][2] += _field_38;
+	_currentZ          += _stepZ;
+	_currentSlice      += _stepSlice;
+	_currentX          += _stepX;
+	_currentY          += 1;
+	_sliceMatrix[0][2] += (int)(65536.0f * _stepX);
+	_sliceMatrix[1][2] += _field_38;
 }
 
 static
@@ -341,38 +346,87 @@ void setupLookupTable(int t[256], int inc) {
 	}
 }
 
-void SliceRenderer::drawFrame(Graphics::Surface &surface, uint16 *zbuffer) {
+void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer) {
 	assert(_sliceFramePtr);
 	assert(_lights);
 	assert(_setEffects);
 	//assert(_view);
 
+	_vm->_sliceRenderer->setupFrame(animationId, animationFrame, position, facing);
+
 	SliceLineIterator sliceLineIterator;
 	sliceLineIterator.setup(
-		_field_10C2.x, _field_10C2.y, _field_10C2.z,
-		_field_10B6.x, _field_10B6.y, _field_10B6.z,
-		_field_10D2, _field_10CE, // 2 floats
+		_endScreenVector.x,   _endScreenVector.y,   _endScreenVector.z,
+		_startScreenVector.x, _startScreenVector.y, _startScreenVector.z,
+		_endSlice,            _startSlice,
 		_field_109E              // 3x2 matrix
-		);
+	);
+
+	SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
 
 	_lights->setupFrame(_view._frame);
 	_setEffects->setupFrame(_view._frame);
 
-	setupLookupTable(_t1, sliceLineIterator._field_00[0][0]);
-	setupLookupTable(_t2, sliceLineIterator._field_00[0][1]);
-	setupLookupTable(_t4, sliceLineIterator._field_00[1][0]);
-	setupLookupTable(_t5, sliceLineIterator._field_00[1][1]);
+	float sliceLine = sliceLineIterator.line();
+
+	sliceRendererLights.calculateColorBase(
+		Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight),
+		Vector3(_position.x, _position.y, _position.z + _frameBottomZ),
+		sliceLineIterator._endY - sliceLineIterator._startY);
+	
+	float setEffectsColorCoeficient;
+	Color setEffectColor;
+	_setEffects->calculateColor(
+		_view._cameraPosition,
+		Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight),
+		&setEffectsColorCoeficient,
+		&setEffectColor);
+
+	_lightsColor.r = setEffectsColorCoeficient * sliceRendererLights._finalColor.r * 65536.0f;
+	_lightsColor.g = setEffectsColorCoeficient * sliceRendererLights._finalColor.g * 65536.0f;
+	_lightsColor.b = setEffectsColorCoeficient * sliceRendererLights._finalColor.b * 65536.0f;
+
+	_setEffectColor.r = setEffectColor.r * 31.0f * 65536.0f;
+	_setEffectColor.g = setEffectColor.g * 31.0f * 65536.0f;
+	_setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f;
+
+	setupLookupTable(_m11lookup, sliceLineIterator._sliceMatrix[0][0]);
+	setupLookupTable(_m12lookup, sliceLineIterator._sliceMatrix[0][1]);
+	setupLookupTable(_m21lookup, sliceLineIterator._sliceMatrix[1][0]);
+	setupLookupTable(_m22lookup, sliceLineIterator._sliceMatrix[1][1]);
+
+	if(_animationsShadowEnabled[_animation]) {
+		//TODO: draw shadows
+	}
 
-	int frameY = sliceLineIterator._field_18;
+	int frameY = sliceLineIterator._startY;
 
 	uint16 *frameLinePtr  = (uint16*)surface.getPixels() + 640 * frameY;
 	uint16 *zBufferLinePtr = zbuffer + 640 * frameY;
 
-	while (sliceLineIterator._field_3C <= sliceLineIterator._field_1C) {
-		_c3 = sliceLineIterator._field_00[0][2];
-		_c6 = sliceLineIterator._field_00[1][2];
+	while (sliceLineIterator._currentY <= sliceLineIterator._endY) {
+		_m13 = sliceLineIterator._sliceMatrix[0][2];
+		_m23 = sliceLineIterator._sliceMatrix[1][2];
+
+		sliceLine = sliceLineIterator.line();
+
+		sliceRendererLights.calculateColorSlice(Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight));
+
+		if (sliceLineIterator._currentY & 1) {
+			_setEffects->calculateColor(
+				_view._cameraPosition,
+				Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight),
+				&setEffectsColorCoeficient,
+				&setEffectColor);
+		}
 
-		float sliceLine = sliceLineIterator.line();
+		_lightsColor.r = setEffectsColorCoeficient * sliceRendererLights._finalColor.r * 65536.0f;
+		_lightsColor.g = setEffectsColorCoeficient * sliceRendererLights._finalColor.g * 65536.0f;
+		_lightsColor.b = setEffectsColorCoeficient * sliceRendererLights._finalColor.b * 65536.0f;
+
+		_setEffectColor.r = setEffectColor.r * 31.0f * 65536.0f;
+		_setEffectColor.g = setEffectColor.g * 31.0f * 65536.0f;
+		_setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f;
 
 		if (frameY >= 0 && frameY < 480)
 			drawSlice((int)sliceLine, frameLinePtr, zBufferLinePtr);
@@ -406,21 +460,30 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 			continue;
 
 		uint32 lastVertex = vertexCount - 1;
-		int lastVertexX = MAX((_t1[p[3*lastVertex]] + _t2[p[3*lastVertex+1]] + _c3) >> 16, 0);
+		int lastVertexX = MAX((_m11lookup[p[3*lastVertex]] + _m12lookup[p[3*lastVertex+1]] + _m13) >> 16, 0);
 
 		int previousVertexX = lastVertexX;
 
 		while (vertexCount--) {
-			int vertexX = CLIP((_t1[p[0]] + _t2[p[1]] + _c3) >> 16, 0, 640);
+			int vertexX = CLIP((_m11lookup[p[0]] + _m12lookup[p[1]] + _m13) >> 16, 0, 640);
 
 			if (vertexX > previousVertexX) {
-				int vertexZ = (_t4[p[0]] + _t5[p[1]] + _c6) >> 6;
+				int vertexZ = (_m21lookup[p[0]] + _m22lookup[p[1]] + _m23) >> 6;
 
 				if (vertexZ >= 0 && vertexZ < 65536) {
+					Color256 color = palette.color[p[2]];
+
+					float hackMul = 8.0f; //not part of game
+
+					color.r = (int)(_setEffectColor.r + hackMul * _lightsColor.r * color.r) >> 13; // >> 16,
+					color.g = (int)(_setEffectColor.g + hackMul * _lightsColor.g * color.g) >> 13;
+					color.b = (int)(_setEffectColor.b + hackMul * _lightsColor.b * color.b) >> 13;
+
+					int color555 = _pixelFormat.RGBToColor(color.r/* * 8*/, color.g/* * 8*/, color.b/* * 8*/);
+
 					for (int x = previousVertexX; x != vertexX; ++x) {
-						// debug("\t%04x < %04x", vertexZ, zbufLinePtr[x]);
 						if (vertexZ < zbufLinePtr[x]) {
-							frameLinePtr[x] = palette[p[2]];
+							frameLinePtr[x] = color555;
 							zbufLinePtr[x] = (uint16)vertexZ;
 						}
 					}
@@ -446,4 +509,102 @@ void SliceRenderer::disableShadows(int animationsIdsList[], int listSize) {
 	}
 }
 
+SliceRenderer::SliceRendererLights::SliceRendererLights(Lights *lights) {
+	_finalColor.r = 0.0f;
+	_finalColor.g = 0.0f;
+	_finalColor.b = 0.0f;
+
+	_lights = lights;
+
+	for(int i = 0; i < 20; i++) {
+		_colors[i].r = 0.0f;
+		_colors[i].g = 0.0f;
+		_colors[i].b = 0.0f;
+	}
+}
+
+
+void SliceRenderer::SliceRendererLights::calculateColorBase(Vector3 position1, Vector3 position2, float height) {
+	_finalColor.r = 0.0f;
+	_finalColor.g = 0.0f;
+	_finalColor.b = 0.0f;
+	_hmm3 = 0;
+	if (_lights) {
+		Light *light = _lights->_lights;
+		int i = 0;
+		if (light) {
+			do {
+				if (i < 20) {
+					float v8 = light->calculate(position1, position2/*, height*/);
+
+					this->_hmm2[i] = v8;
+					this->_hmm[i] = v8;
+					
+					Color v22;
+					light->calculateColor(&v22, position1);
+					_colors[i] = v22;
+					_finalColor.r += v22.r;
+					_finalColor.g += v22.g;
+					_finalColor.b += v22.b;
+				}
+				else
+				{
+					Color v23;
+					light->calculateColor(&v23, position1);
+					_finalColor.r += v23.r;
+					_finalColor.g += v23.g;
+					_finalColor.b += v23.b;
+				}
+				light = light->_next;
+				i++;
+			} while (light);
+		}
+
+		_finalColor.r += _lights->_ambientLightColor.r;
+		_finalColor.g += _lights->_ambientLightColor.g;
+		_finalColor.b += _lights->_ambientLightColor.b;
+	}
+}
+
+void SliceRenderer::SliceRendererLights::calculateColorSlice(Vector3 position) {
+	_finalColor.r = 0.0f;
+	_finalColor.g = 0.0f;
+	_finalColor.b = 0.0f;
+
+	if (_lights) {
+		Light *light = _lights->_lights;
+		int i = 0;
+		if (light) {
+			do {
+				if (i < 20) {
+					_hmm[i] = _hmm[i] - 1.0f;
+
+					if (_hmm[i] <= 0.0f) {
+						do {
+							_hmm[i] = _hmm[i] + _hmm2[i];
+						} while (_hmm[i] <= 0.0f);
+						light->calculateColor(&_colors[i], position);
+						_hmm3++;
+					} 
+					_finalColor.r += _colors[i].r;
+					_finalColor.g += _colors[i].g;
+					_finalColor.b += _colors[i].b;
+				} else {
+					Color color;
+					light->calculateColor(&color, position);
+					_hmm3++;
+					_finalColor.r += color.r;
+					_finalColor.g += color.g;
+					_finalColor.b += color.b;
+				}
+				light = light->_next;
+				i++;
+			} while (light);
+		}
+		_finalColor.r += _lights->_ambientLightColor.r;
+		_finalColor.g += _lights->_ambientLightColor.g;
+		_finalColor.b += _lights->_ambientLightColor.b;
+	}
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index 3dcd922..9cbd3ce 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -23,6 +23,7 @@
 #ifndef BLADERUNNER_SLICE_RENDERER_H
 #define BLADERUNNER_SLICE_RENDERER_H
 
+#include "bladerunner/color.h"
 #include "bladerunner/vector.h"
 #include "bladerunner/view.h"
 #include "bladerunner/matrix.h"
@@ -55,7 +56,7 @@ class SliceRenderer {
 	void       *_sliceFramePtr;
 
 	// Animation frame data
-	Vector2 _frameFront;
+	Vector2 _frameScale;
 	float   _frameBottomZ;
 	Vector2 _framePos;
 	float   _frameSliceHeight;
@@ -63,24 +64,29 @@ class SliceRenderer {
 	uint32  _frameSliceCount;
 
 	Matrix3x2 _field_109E;
-	Vector3   _field_10B6;
-	Vector3   _field_10C2;
-	float     _field_10CE;
-	float     _field_10D2;
+	Vector3   _startScreenVector;
+	Vector3   _endScreenVector;
+	float     _startSlice;
+	float     _endSlice;
 	int       _minX;
 	int       _maxX;
 	int       _minY;
 	int       _maxY;
 
-	int _t1[256];
-	int _t2[256];
-	int _c3;
-	int _t4[256];
-	int _t5[256];
-	int _c6;
+	int _m11lookup[256];
+	int _m12lookup[256];
+	int _m13;
+	int _m21lookup[256];
+	int _m22lookup[256];
+	int _m23;
 
 	bool _animationsShadowEnabled[997];
 
+	Color _setEffectColor;
+	Color _lightsColor;
+
+	Graphics::PixelFormat _pixelFormat;
+
 	Matrix3x2 calculateFacingRotationMatrix();
 	void drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr);
 
@@ -95,11 +101,29 @@ public:
 	void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f);
 	void calculateBoundingRect();
 
-	void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
+	//void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
+	void drawFrame(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
 
 	void preload(int animationId);
 
-	void disableShadows(int* animationsIdsList, int listSize);
+	void disableShadows(int *animationsIdsList, int listSize);
+
+private:
+	class SliceRendererLights {
+		Lights *_lights;
+		Color   _colors[20];
+		float   _hmm[20];
+		float   _hmm2[20];
+		int     _hmm3;
+	public: 
+		Color   _finalColor;
+
+	public:
+		SliceRendererLights(Lights *lights);
+
+		void calculateColorBase(Vector3 position1, Vector3 position2, float height);
+		void calculateColorSlice(Vector3 position);
+	};
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index 4f4bfed..80fd5f8 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -58,6 +58,20 @@ public:
 	{}
 
 	float length() { return sqrtf(x * x + y * y + z * z); }
+	Vector3 normalize() {
+		float len = length();
+		if (len == 0) {
+			return Vector3(0.0f, 0.0f, 0.0f);
+		}
+		return Vector3(x / len, y / len, z / len);
+	}
+
+	static Vector3 cross(Vector3 a, Vector3 b) {
+		return Vector3(
+			a.y * b.z - a.z * b.y,
+			a.z * b.x - a.x * b.z,
+			a.x * b.y - a.y * b.x);
+	}
 };
 
 inline
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index f8acb91..9356f04 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -60,9 +60,9 @@ void View::calculateSliceViewMatrix() {
 
 	m = m * rotationMatrixX(float(M_PI) / 2.0f);
 
-	Matrix4x3 a(-1.0f, 0.0f, 0.0f, 0.0f,
-	            0.0f, -1.0f, 0.0f, 0.0f,
-	            0.0f, 0.0f, 1.0f, 0.0f);
+	Matrix4x3 a(-1.0f,  0.0f, 0.0f, 0.0f,
+	             0.0f, -1.0f, 0.0f, 0.0f,
+	             0.0f,  0.0f, 1.0f, 0.0f);
 
 	m = a * m;
 


Commit: c7f7341f69b4f1b44c82b3693d7f51d9b570df46
    https://github.com/scummvm/scummvm/commit/c7f7341f69b4f1b44c82b3693d7f51d9b570df46
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:42+02:00

Commit Message:
BLADERUNNER: fixed lightning

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/light.cpp
    engines/bladerunner/light.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/slice_renderer.cpp



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 41f1bb5..88d441d 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -723,7 +723,7 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 
 	if (sceneObjectId == -1) {
 		_actors[0]->loopWalkToXYZ(mousePosition);
-		debug("Clicked on nothing");
+		debug("Clicked on nothing %f, %f, %f", mousePosition.x, mousePosition.y, mousePosition.z);
 		return;
 	} else if (sceneObjectId >= 0 && sceneObjectId <= 73) {
 		handleMouseClickActor(x, y, sceneObjectId);
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index 39dc3e3..562936f 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -1,5 +1,6 @@
 #include "bladerunner/light.h"
 #include "common/util.h"
+#include "common/debug.h"
 
 namespace BladeRunner {
 
@@ -23,25 +24,25 @@ void Light::read(Common::ReadStream *stream, int framesCount, int frame, int ani
 	_animationData = new float[size / sizeof(float)];
 	stream->read(_animationData, size);
 
-	_m11ptr = _animationData;
-	_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? framesCount : 1);
-	_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? framesCount : 1);
-	_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? framesCount : 1);
-	_m21ptr = _m14ptr + (_animatedParameters & 0x8 ? framesCount : 1);
-	_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? framesCount : 1);
-	_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? framesCount : 1);
-	_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? framesCount : 1);
-	_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? framesCount : 1);
-	_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? framesCount : 1);
-	_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? framesCount : 1);
-	_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? framesCount : 1);
-	_colorRPtr = _m34ptr + (_animatedParameters & 0x800 ? framesCount : 1);
-	_colorGPtr = _colorRPtr + (_animatedParameters & 0x1000 ? framesCount : 1);
-	_colorBPtr = _colorGPtr + (_animatedParameters & 0x2000 ? framesCount : 1);
-	_field16ptr = _colorGPtr + (_animatedParameters & 0x4000 ? framesCount : 1);
-	_field17ptr = _field16ptr + (_animatedParameters & 0x8000 ? framesCount : 1);
-	_field18ptr = _field17ptr + (_animatedParameters & 0x10000 ? framesCount : 1);
-	_field19ptr = _field18ptr + (_animatedParameters & 0x20000 ? framesCount : 1);
+	_m11ptr          = _animationData;
+	_m12ptr          = _m11ptr          + (_animatedParameters &     0x1 ? framesCount : 1);
+	_m13ptr          = _m12ptr          + (_animatedParameters &     0x2 ? framesCount : 1);
+	_m14ptr          = _m13ptr          + (_animatedParameters &     0x4 ? framesCount : 1);
+	_m21ptr          = _m14ptr          + (_animatedParameters &     0x8 ? framesCount : 1);
+	_m22ptr          = _m21ptr          + (_animatedParameters &    0x10 ? framesCount : 1);
+	_m23ptr          = _m22ptr          + (_animatedParameters &    0x20 ? framesCount : 1);
+	_m24ptr          = _m23ptr          + (_animatedParameters &    0x40 ? framesCount : 1);
+	_m31ptr          = _m24ptr          + (_animatedParameters &    0x80 ? framesCount : 1);
+	_m32ptr          = _m31ptr          + (_animatedParameters &   0x100 ? framesCount : 1);
+	_m33ptr          = _m32ptr          + (_animatedParameters &   0x200 ? framesCount : 1);
+	_m34ptr          = _m33ptr          + (_animatedParameters &   0x400 ? framesCount : 1);
+	_colorRPtr       = _m34ptr          + (_animatedParameters &   0x800 ? framesCount : 1);
+	_colorGPtr       = _colorRPtr       + (_animatedParameters &  0x1000 ? framesCount : 1);
+	_colorBPtr       = _colorGPtr       + (_animatedParameters &  0x2000 ? framesCount : 1);
+	_falloffStartPtr = _colorBPtr       + (_animatedParameters &  0x4000 ? framesCount : 1);
+	_falloffEndPtr   = _falloffStartPtr + (_animatedParameters &  0x8000 ? framesCount : 1);
+	_angleStartPtr   = _falloffEndPtr   + (_animatedParameters & 0x10000 ? framesCount : 1);
+	_angleEndPtr     = _angleStartPtr   + (_animatedParameters & 0x20000 ? framesCount : 1);
 
 	setupFrame(frame);
 }
@@ -57,83 +58,82 @@ void Light::readVqa(Common::ReadStream *stream, int framesCount, int frame, int
 	_animationData = new float[size / sizeof(float)];
 	stream->read(_animationData, size);
 
-	_m11ptr = _animationData;
-	_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? framesCount : 1);
-	_m13ptr = _m12ptr + (_animatedParameters & 0x2 ? framesCount : 1);
-	_m14ptr = _m13ptr + (_animatedParameters & 0x4 ? framesCount : 1);
-	_m21ptr = _m14ptr + (_animatedParameters & 0x8 ? framesCount : 1);
-	_m22ptr = _m21ptr + (_animatedParameters & 0x10 ? framesCount : 1);
-	_m23ptr = _m22ptr + (_animatedParameters & 0x20 ? framesCount : 1);
-	_m24ptr = _m23ptr + (_animatedParameters & 0x40 ? framesCount : 1);
-	_m31ptr = _m24ptr + (_animatedParameters & 0x80 ? framesCount : 1);
-	_m32ptr = _m31ptr + (_animatedParameters & 0x100 ? framesCount : 1);
-	_m33ptr = _m32ptr + (_animatedParameters & 0x200 ? framesCount : 1);
-	_m34ptr = _m33ptr + (_animatedParameters & 0x400 ? framesCount : 1);
-	_colorRPtr = _m34ptr + (_animatedParameters & 0x800 ? framesCount : 1);
-	_colorGPtr = _colorRPtr + (_animatedParameters & 0x1000 ? framesCount : 1);
-	_colorBPtr = _colorGPtr + (_animatedParameters & 0x2000 ? framesCount : 1);
-	_field16ptr = _colorGPtr + (_animatedParameters & 0x4000 ? framesCount : 1);
-	_field17ptr = _field16ptr + (_animatedParameters & 0x8000 ? framesCount : 1);
-	_field18ptr = _field17ptr + (_animatedParameters & 0x10000 ? framesCount : 1);
-	_field19ptr = _field18ptr + (_animatedParameters & 0x20000 ? framesCount : 1);
+	_m11ptr          = _animationData;
+	_m12ptr          = _m11ptr          + (_animatedParameters &     0x1 ? framesCount : 1);
+	_m13ptr          = _m12ptr          + (_animatedParameters &     0x2 ? framesCount : 1);
+	_m14ptr          = _m13ptr          + (_animatedParameters &     0x4 ? framesCount : 1);
+	_m21ptr          = _m14ptr          + (_animatedParameters &     0x8 ? framesCount : 1);
+	_m22ptr          = _m21ptr          + (_animatedParameters &    0x10 ? framesCount : 1);
+	_m23ptr          = _m22ptr          + (_animatedParameters &    0x20 ? framesCount : 1);
+	_m24ptr          = _m23ptr          + (_animatedParameters &    0x40 ? framesCount : 1);
+	_m31ptr          = _m24ptr          + (_animatedParameters &    0x80 ? framesCount : 1);
+	_m32ptr          = _m31ptr          + (_animatedParameters &   0x100 ? framesCount : 1);
+	_m33ptr          = _m32ptr          + (_animatedParameters &   0x200 ? framesCount : 1);
+	_m34ptr          = _m33ptr          + (_animatedParameters &   0x400 ? framesCount : 1);
+	_colorRPtr       = _m34ptr          + (_animatedParameters &   0x800 ? framesCount : 1);
+	_colorGPtr       = _colorRPtr       + (_animatedParameters &  0x1000 ? framesCount : 1);
+	_colorBPtr       = _colorGPtr       + (_animatedParameters &  0x2000 ? framesCount : 1);
+	_falloffStartPtr = _colorBPtr       + (_animatedParameters &  0x4000 ? framesCount : 1);
+	_falloffEndPtr   = _falloffStartPtr + (_animatedParameters &  0x8000 ? framesCount : 1);
+	_angleStartPtr   = _falloffEndPtr   + (_animatedParameters & 0x10000 ? framesCount : 1);
+	_angleEndPtr     = _angleStartPtr   + (_animatedParameters & 0x20000 ? framesCount : 1);
 
 	setupFrame(frame);
 }
 
 void Light::setupFrame(int frame) {
 	int offset = frame % _framesCount;
-	_matrix._m[0][0] = (_animatedParameters & 0x1 ? _m11ptr[offset] : *_m11ptr);
-	_matrix._m[0][1] = (_animatedParameters & 0x2 ? _m12ptr[offset] : *_m12ptr);
-	_matrix._m[0][2] = (_animatedParameters & 0x4 ? _m13ptr[offset] : *_m13ptr);
-	_matrix._m[0][3] = (_animatedParameters & 0x8 ? _m14ptr[offset] : *_m14ptr);
-	_matrix._m[1][0] = (_animatedParameters & 0x10 ? _m21ptr[offset] : *_m21ptr);
-	_matrix._m[1][1] = (_animatedParameters & 0x20 ? _m22ptr[offset] : *_m22ptr);
-	_matrix._m[1][2] = (_animatedParameters & 0x40 ? _m23ptr[offset] : *_m23ptr);
-	_matrix._m[1][3] = (_animatedParameters & 0x80 ? _m24ptr[offset] : *_m24ptr);
-	_matrix._m[2][0] = (_animatedParameters & 0x100 ? _m31ptr[offset] : *_m31ptr);
-	_matrix._m[2][1] = (_animatedParameters & 0x200 ? _m32ptr[offset] : *_m32ptr);
-	_matrix._m[2][2] = (_animatedParameters & 0x400 ? _m33ptr[offset] : *_m33ptr);
-	_matrix._m[2][3] = (_animatedParameters & 0x800 ? _m34ptr[offset] : *_m34ptr);
-	_color.r = (_animatedParameters & 0x1000 ? _colorRPtr[offset] : *_colorRPtr);
-	_color.g = (_animatedParameters & 0x2000 ? _colorGPtr[offset] : *_colorGPtr);
-	_color.b = (_animatedParameters & 0x4000 ? _colorBPtr[offset] : *_colorBPtr);
-	_field16 = (_animatedParameters & 0x8000 ? _field16ptr[offset] : *_field16ptr);
-	_field17 = (_animatedParameters & 0x10000 ? _field17ptr[offset] : *_field17ptr);
-	_field18 = (_animatedParameters & 0x20000 ? _field18ptr[offset] : *_field18ptr);
-	_field19 = (_animatedParameters & 0x40000 ? _field19ptr[offset] : *_field19ptr);
-
+	_matrix._m[0][0] = (_animatedParameters &     0x1 ? _m11ptr[offset]          : *_m11ptr);
+	_matrix._m[0][1] = (_animatedParameters &     0x2 ? _m12ptr[offset]          : *_m12ptr);
+	_matrix._m[0][2] = (_animatedParameters &     0x4 ? _m13ptr[offset]          : *_m13ptr);
+	_matrix._m[0][3] = (_animatedParameters &     0x8 ? _m14ptr[offset]          : *_m14ptr);
+	_matrix._m[1][0] = (_animatedParameters &    0x10 ? _m21ptr[offset]          : *_m21ptr);
+	_matrix._m[1][1] = (_animatedParameters &    0x20 ? _m22ptr[offset]          : *_m22ptr);
+	_matrix._m[1][2] = (_animatedParameters &    0x40 ? _m23ptr[offset]          : *_m23ptr);
+	_matrix._m[1][3] = (_animatedParameters &    0x80 ? _m24ptr[offset]          : *_m24ptr);
+	_matrix._m[2][0] = (_animatedParameters &   0x100 ? _m31ptr[offset]          : *_m31ptr);
+	_matrix._m[2][1] = (_animatedParameters &   0x200 ? _m32ptr[offset]          : *_m32ptr);
+	_matrix._m[2][2] = (_animatedParameters &   0x400 ? _m33ptr[offset]          : *_m33ptr);
+	_matrix._m[2][3] = (_animatedParameters &   0x800 ? _m34ptr[offset]          : *_m34ptr);
+	_color.r         = (_animatedParameters &  0x1000 ? _colorRPtr[offset]       : *_colorRPtr);
+	_color.g         = (_animatedParameters &  0x2000 ? _colorGPtr[offset]       : *_colorGPtr);
+	_color.b         = (_animatedParameters &  0x4000 ? _colorBPtr[offset]       : *_colorBPtr);
+	_falloffStart    = (_animatedParameters &  0x8000 ? _falloffStartPtr[offset] : *_falloffStartPtr);
+	_falloffEnd      = (_animatedParameters & 0x10000 ? _falloffEndPtr[offset]   : *_falloffEndPtr);
+	_angleStart      = (_animatedParameters & 0x20000 ? _angleStartPtr[offset]   : *_angleStartPtr);
+	_angleEnd        = (_animatedParameters & 0x40000 ? _angleEndPtr[offset]     : *_angleEndPtr);
 }
 
 float Light::calculate(Vector3 start, Vector3 end) {
-	return calculateCoeficient(_matrix * start, _matrix * end, _field16, _field17);
+	return calculateCoefficient(_matrix * start, _matrix * end, _falloffStart, _falloffEnd);
 }
 
 void Light::calculateColor(Color *outColor, Vector3 position) {
 	Vector3 positionT = _matrix * position;
-	float att = attenuation(_field16, _field17, positionT.length());
+	float att = attenuation(_falloffStart, _falloffEnd, positionT.length());
 	outColor->r = _color.r * att;
 	outColor->g = _color.g * att;
 	outColor->b = _color.b * att;
 }
 
-float Light::calculateCoeficient(Vector3 start, Vector3 end, float a3, float a4) {
-	if (a4 == 0.0f) {
+float Light::calculateCoefficient(Vector3 start, Vector3 end, float falloffStart, float falloffEnd) {
+	if (falloffEnd == 0.0f) {
 		return 1.0e30f;
 	}
 
-	if (a3 >= start.length() && a3 >= end.length()) {
+	if (falloffStart >= start.length() && falloffStart >= end.length()) {
 		return 1.0e30f;
 	}
 
 	float v40 = (end - start).length();
 	float v31 = 0.0f;
 	if (v40 != 0.0f) {
-		Vector3 v27 = Vector3::cross(start, end);
+		Vector3 v27 = Vector3::cross(start, (end - start));
 		v31 = v27.length() / v40;
 	}
 
-	if (v31 < a4) {
-		return 1.0f / (1.0f - (v31 / a4));
+	if (v31 < falloffEnd) {
+		return 1.0f / (1.0f - (v31 / falloffEnd));
 	}
 	return 1.0e30f;
 }
@@ -147,7 +147,7 @@ float Light::attenuation(float min, float max, float distance) {
 		float x = (max - distance) / (max - min);
 		return x * x * (3.0f - 2.0f * x);
 	}
-	if (min > distance) {
+	if (distance < min) {
 		return 1.0f;
 	}
 	return 0.0f;
@@ -158,15 +158,15 @@ float Light1::calculate(Vector3 start, Vector3 end) {
 	end = _matrix * end;
 
 	float v40 = 0.0f;
-	if (_field17 != 0.0f) {
-		v40 = calculateCoeficient(start, end, _field16, _field17);
+	if (_falloffEnd != 0.0f) {
+		v40 = calculateCoefficient(start, end, _falloffStart, _falloffEnd);
 	}
 
 	float v41 = atan2(start.length(), -start.z);
 	float v42 = atan2(end.length(), -end.z);
 
 	float v43;
-	if ((_field18 >= v41 && _field18 >= v42) || (_field19 <= v41 && _field19 <= v42)) {
+	if ((_angleStart >= v41 && _angleStart >= v42) || (_angleEnd <= v41 && _angleEnd <= v42)) {
 		v43 = 1.0e30f;
 	} else {
 		v43 = 2.0;
@@ -186,9 +186,9 @@ void Light1::calculateColor(Color *outColor, Vector3 position) {
 	outColor->b = 0.0f;
 
 	if (positionT.z < 0.0f) {
-		float v12 = attenuation(_field18, _field19, atan2(sqrt(positionT.x * positionT.x + positionT.y * positionT.y), -positionT.z));
-		float v13 = attenuation(_field16, _field17, positionT.length());
-
+		float v12 = attenuation(_angleStart, _angleEnd, atan2(sqrt(positionT.x * positionT.x + positionT.y * positionT.y), -positionT.z));
+		float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
+	
 		outColor->r = v12 * v13 * _color.r;
 		outColor->g = v12 * v13 * _color.g;
 		outColor->b = v12 * v13 * _color.b;
@@ -200,8 +200,8 @@ float Light2::calculate(Vector3 start, Vector3 end) {
 	end = _matrix * end;
 
 	float v54 = 0.0f;
-	if (_field17 != 0.0f) {
-		v54 = calculateCoeficient(start, end, _field16, _field17);
+	if (_falloffEnd != 0.0f) {
+		v54 = calculateCoefficient(start, end, _falloffStart, _falloffEnd);
 	}
 
 	float v55 = atan2(fabs(start.x), -start.z);
@@ -210,7 +210,7 @@ float Light2::calculate(Vector3 start, Vector3 end) {
 	float v56 = atan2(fabs(end.y), -end.z);
 
 	float v59;
-	if ((_field18 >= v55 && _field18 >= v57 && _field18 >= v58 && _field18 >= v56) || (_field19 <= v55 && _field19 <= v57 && _field19 <= v58 && _field19 <= v56)) {
+	if ((_angleStart >= v55 && _angleStart >= v57 && _angleStart >= v58 && _angleStart >= v56) || (_angleEnd <= v55 && _angleEnd <= v57 && _angleEnd <= v58 && _angleEnd <= v56)) {
 		v59 = 1.0e30f;
 	} else {
 		v59 = 2.0f;
@@ -230,9 +230,9 @@ void Light2::calculateColor(Color *outColor, Vector3 position) {
 	outColor->b = 0.0f;
 
 	if (positionT.z < 0.0f) {
-		float v11 = attenuation(_field18, _field19, atan2(fabs(positionT.y), -positionT.z));
-		float v12 = attenuation(_field18, _field19, atan2(fabs(positionT.x), -positionT.z));
-		float v13 = attenuation(_field16, _field17, positionT.length());
+		float v11 = attenuation(_angleStart, _angleEnd, atan2(fabs(positionT.y), -positionT.z));
+		float v12 = attenuation(_angleStart, _angleEnd, atan2(fabs(positionT.x), -positionT.z));
+		float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
 
 		outColor->r = v11 * v12 * v13 * _color.r;
 		outColor->g = v11 * v12 * v13 * _color.g;
@@ -248,8 +248,8 @@ void Light3::calculateColor(Color *outColor, Vector3 position) {
 	outColor->b = 0.0f;
 
 	if (positionT.z < 0.0f) {
-		float v12 = attenuation(_field18, _field19, sqrt(positionT.x * positionT.x + positionT.y * positionT.y));
-		float v13 = attenuation(_field16, _field17, positionT.length());
+		float v12 = attenuation(_angleStart, _angleEnd, sqrt(positionT.x * positionT.x + positionT.y * positionT.y));
+		float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
 
 		outColor->r = v12 * v13 * _color.r;
 		outColor->g = v12 * v13 * _color.g;
@@ -265,21 +265,21 @@ void Light4::calculateColor(Color *outColor, Vector3 position) {
 	outColor->b = 0.0f;
 
 	if (positionT.z < 0.0f) {
-		float v11 = attenuation(_field18, _field19, fabs(positionT.y));
-		float v12 = attenuation(_field18, _field19, fabs(positionT.x));
-		float v13 = attenuation(_field16, _field17, positionT.length());
-
+		float v11 = attenuation(_angleStart, _angleEnd, fabs(positionT.y));
+		float v12 = attenuation(_angleStart, _angleEnd, fabs(positionT.x));
+		float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
+		
 		outColor->r = v11 * v12 * v13 * _color.r;
 		outColor->g = v11 * v12 * v13 * _color.g;
 		outColor->b = v11 * v12 * v13 * _color.b;
 	}
 }
 
-float Light5::calculate(Vector3 start, Vector3 end) {
+float LightAmbient::calculate(Vector3 start, Vector3 end) {
 	return 1.0e30f;
 }
 
-void Light5::calculateColor(Color *outColor, Vector3 position) {
+void LightAmbient::calculateColor(Color *outColor, Vector3 position) {
 	outColor->r = _color.r;
 	outColor->g = _color.g;
 	outColor->b = _color.b;
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index 9c2cdcb..29e0dd7 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -51,10 +51,10 @@ protected:
 	int _animatedParameters;
 	Matrix4x3 _matrix;
 	Color _color;
-	float _field16;
-	float _field17;
-	float _field18;
-	float _field19;
+	float _falloffStart;
+	float _falloffEnd;
+	float _angleStart;
+	float _angleEnd;
 	float *_animationData;
 	float *_m11ptr;
 	float *_m12ptr;
@@ -71,11 +71,11 @@ protected:
 	float *_colorRPtr;
 	float *_colorGPtr;
 	float *_colorBPtr;
-	float *_field16ptr;
-	float *_field17ptr;
-	float *_field18ptr;
-	float *_field19ptr;
-	Light *_next;
+	float *_falloffStartPtr;
+	float *_falloffEndPtr;
+	float *_angleStartPtr;
+	float *_angleEndPtr;
+//	Light *_next;
 
 public:
 	Light();
@@ -90,7 +90,7 @@ public:
 	virtual void calculateColor(Color *outColor, Vector3 position);
 
 protected:
-	float calculateCoeficient(Vector3 start, Vector3 end, float a3, float a4);
+	float calculateCoefficient(Vector3 start, Vector3 end, float a3, float a4);
 	float attenuation(float min, float max, float distance);
 };
 
@@ -112,7 +112,7 @@ class Light4 : public Light {
 	void calculateColor(Color *outColor, Vector3 position);
 };
 
-class Light5 : public Light {
+class LightAmbient : public Light {
 	float calculate(Vector3 start, Vector3 end);
 	void calculateColor(Color *outColor, Vector3 position);
 };
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index 0d6a1be..e8660a2 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -8,9 +8,9 @@ Lights::Lights(BladeRunnerEngine *vm) {
 	_ambientLightColor.r = 1.0;
 	_ambientLightColor.g = 0.0;
 	_ambientLightColor.b = 0.0;
-
-	_lights = nullptr;
+	
 	_lightsCount = 0;
+	_lights.clear();
 	_frame = 0;
 }
 
@@ -42,34 +42,22 @@ void Lights::read(Common::ReadStream *stream, int framesCount) {
 			light = new Light4();
 			break;
 		case 5:
-			light = new Light5();
+			light = new LightAmbient();
 			break;
 		default:
 			light = new Light();
 		}
 
 		light->read(stream, framesCount, _frame, 0);
-		light->_next = _lights;
-		_lights = light;
+		_lights.push_back(light);
 	}
 }
 
 void Lights::removeAnimated() {
-	Light **nextLight;
-	Light *light;
-
-	nextLight = &this->_lights;
-	light = this->_lights;
-	if (light) {
-		do {
-			if (light->_animated) {
-				*nextLight = light->_next;
-				delete light;
-			} else {
-				nextLight = &light->_next;
-			}
-			light = *nextLight;
-		} while (*nextLight);
+	for (int i = (int)(_lights.size() - 1); i > 0; i--) {
+		if (_lights[i]->_animated) {
+			delete _lights.remove_at(i);
+		}
 	}
 }
 
@@ -85,7 +73,7 @@ void Lights::readVqa(Common::ReadStream *stream) {
 		Light *light;
 		switch (lightType) {
 		case 5:
-			light = new Light5();
+			light = new LightAmbient();
 			break;
 		case 4:
 			light = new Light4();
@@ -101,40 +89,27 @@ void Lights::readVqa(Common::ReadStream *stream) {
 			break;
 		default:
 			light = new Light();
-		}
+		}		
 		light->readVqa(stream, framesCount, _frame, 1);
-		light->_next = _lights;
-		_lights = light;
+		_lights.push_back(light);
 	}
 }
 
 void Lights::setupFrame(int frame) {
-	Light *light;
-
-	if (frame == _frame)
-		return;
-
-	if (!_lights)
+	if (frame == _frame) {
 		return;
+	}
 
-	for (light = _lights; light; light = light->_next) {
-		light->setupFrame(frame);
+	for (uint i = 0; i < _lights.size(); i++) {
+		_lights[i]->setupFrame(frame);
 	}
 }
 
 void Lights::reset() {
-	Light *light;
-	Light *nextLight;
-
-	if (!_lights)
-		return;
-
-	do {
-		light = _lights;
-		nextLight = light->_next;
-		delete light;
-		_lights = nextLight;
-	} while (nextLight);
+	for (int i = (int)(_lights.size() - 1); i > 0; i--) {
+		delete _lights.remove_at(i);
+	}
+	_lights.clear();
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index 2ba95b9..486e690 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -41,8 +41,8 @@ class Lights {
 
 	Color _ambientLightColor;
 
-	int _lightsCount;
-	Light *_lights;
+	int                   _lightsCount;
+	Common::Array<Light*> _lights;
 
 	int _frame;
 	//char gap[28];
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 8dad519..301f329 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -363,9 +363,9 @@ void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 posit
 	);
 
 	SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
-
-	_lights->setupFrame(_view._frame);
-	_setEffects->setupFrame(_view._frame);
+	
+	_lights->setupFrame(_frame);
+	_setEffects->setupFrame(_frame);
 
 	float sliceLine = sliceLineIterator.line();
 
@@ -460,7 +460,7 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 			continue;
 
 		uint32 lastVertex = vertexCount - 1;
-		int lastVertexX = MAX((_m11lookup[p[3*lastVertex]] + _m12lookup[p[3*lastVertex+1]] + _m13) >> 16, 0);
+		int lastVertexX = MAX((_m11lookup[p[3 * lastVertex]] + _m12lookup[p[3 * lastVertex + 1]] + _m13) >> 16, 0);
 
 		int previousVertexX = lastVertexX;
 
@@ -473,13 +473,13 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 				if (vertexZ >= 0 && vertexZ < 65536) {
 					Color256 color = palette.color[p[2]];
 
-					float hackMul = 8.0f; //not part of game
+					color.r = (int)(_setEffectColor.r + _lightsColor.r * color.r) >> 16;
+					color.g = (int)(_setEffectColor.g + _lightsColor.g * color.g) >> 16;
+					color.b = (int)(_setEffectColor.b + _lightsColor.b * color.b) >> 16;
 
-					color.r = (int)(_setEffectColor.r + hackMul * _lightsColor.r * color.r) >> 13; // >> 16,
-					color.g = (int)(_setEffectColor.g + hackMul * _lightsColor.g * color.g) >> 13;
-					color.b = (int)(_setEffectColor.b + hackMul * _lightsColor.b * color.b) >> 13;
+					int bladeToScummVmConstant = 256 / 32;
 
-					int color555 = _pixelFormat.RGBToColor(color.r/* * 8*/, color.g/* * 8*/, color.b/* * 8*/);
+					int color555 = _pixelFormat.RGBToColor(CLIP(color.r * bladeToScummVmConstant, 0, 255), CLIP(color.g * bladeToScummVmConstant, 0, 255), CLIP(color.b * bladeToScummVmConstant, 0, 255));
 
 					for (int x = previousVertexX; x != vertexX; ++x) {
 						if (vertexZ < zbufLinePtr[x]) {
@@ -530,34 +530,27 @@ void SliceRenderer::SliceRendererLights::calculateColorBase(Vector3 position1, V
 	_finalColor.b = 0.0f;
 	_hmm3 = 0;
 	if (_lights) {
-		Light *light = _lights->_lights;
-		int i = 0;
-		if (light) {
-			do {
-				if (i < 20) {
-					float v8 = light->calculate(position1, position2/*, height*/);
-
-					this->_hmm2[i] = v8;
-					this->_hmm[i] = v8;
-					
-					Color v22;
-					light->calculateColor(&v22, position1);
-					_colors[i] = v22;
-					_finalColor.r += v22.r;
-					_finalColor.g += v22.g;
-					_finalColor.b += v22.b;
-				}
-				else
-				{
-					Color v23;
-					light->calculateColor(&v23, position1);
-					_finalColor.r += v23.r;
-					_finalColor.g += v23.g;
-					_finalColor.b += v23.b;
-				}
-				light = light->_next;
-				i++;
-			} while (light);
+		for(uint i = 0; i < _lights->_lights.size(); i++) {
+			Light *light = _lights->_lights[i];
+			if (i < 20) {
+				float v8 = light->calculate(position1, position2/*, height*/);
+
+				this->_hmm2[i] = v8;
+				this->_hmm[i] = v8;
+
+				Color v22;
+				light->calculateColor(&v22, position1);
+				_colors[i] = v22;
+				_finalColor.r += v22.r;
+				_finalColor.g += v22.g;
+				_finalColor.b += v22.b;
+			} else {
+				Color v23;
+				light->calculateColor(&v23, position1);
+				_finalColor.r += v23.r;
+				_finalColor.g += v23.g;
+				_finalColor.b += v23.b;
+			}
 		}
 
 		_finalColor.r += _lights->_ambientLightColor.r;
@@ -572,34 +565,29 @@ void SliceRenderer::SliceRendererLights::calculateColorSlice(Vector3 position) {
 	_finalColor.b = 0.0f;
 
 	if (_lights) {
-		Light *light = _lights->_lights;
-		int i = 0;
-		if (light) {
-			do {
-				if (i < 20) {
-					_hmm[i] = _hmm[i] - 1.0f;
-
-					if (_hmm[i] <= 0.0f) {
-						do {
-							_hmm[i] = _hmm[i] + _hmm2[i];
-						} while (_hmm[i] <= 0.0f);
-						light->calculateColor(&_colors[i], position);
-						_hmm3++;
-					} 
-					_finalColor.r += _colors[i].r;
-					_finalColor.g += _colors[i].g;
-					_finalColor.b += _colors[i].b;
-				} else {
-					Color color;
-					light->calculateColor(&color, position);
+		for (uint i = 0; i < _lights->_lights.size(); i++) {
+			Light *light = _lights->_lights[i];
+			if (i < 20) {
+				_hmm[i] = _hmm[i] - 1.0f;
+
+				if (_hmm[i] <= 0.0f) {
+					do {
+						_hmm[i] = _hmm[i] + _hmm2[i];
+					} while (_hmm[i] <= 0.0f);
+					light->calculateColor(&_colors[i], position);
 					_hmm3++;
-					_finalColor.r += color.r;
-					_finalColor.g += color.g;
-					_finalColor.b += color.b;
 				}
-				light = light->_next;
-				i++;
-			} while (light);
+				_finalColor.r += _colors[i].r;
+				_finalColor.g += _colors[i].g;
+				_finalColor.b += _colors[i].b;
+			} else {
+				Color color;
+				light->calculateColor(&color, position);
+				_hmm3++;
+				_finalColor.r += color.r;
+				_finalColor.g += color.g;
+				_finalColor.b += color.b;
+			}
 		}
 		_finalColor.r += _lights->_ambientLightColor.r;
 		_finalColor.g += _lights->_ambientLightColor.g;


Commit: f5d5f3302f59d2073c15985f8ffb3058bad7d014
    https://github.com/scummvm/scummvm/commit/f5d5f3302f59d2073c15985f8ffb3058bad7d014
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:42+02:00

Commit Message:
BLADERUNNER: fixed current frame selection for lights

Changed paths:
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/view.cpp



diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 301f329..cf42f80 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -364,8 +364,8 @@ void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 posit
 
 	SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
 	
-	_lights->setupFrame(_frame);
-	_setEffects->setupFrame(_frame);
+	_lights->setupFrame(_view._frame);
+	_setEffects->setupFrame(_view._frame);
 
 	float sliceLine = sliceLineIterator.line();
 
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index 9356f04..b01273f 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -28,8 +28,7 @@
 namespace BladeRunner {
 
 bool View::read(Common::ReadStream *stream) {
-	uint32 frame;
-	frame = stream->readUint32LE();
+	_frame = stream->readUint32LE();
 
 	float d[12];
 	for (int i = 0; i != 12; ++i)


Commit: af70a90cbc239f820f6c33ac54c207829fd8847a
    https://github.com/scummvm/scummvm/commit/af70a90cbc239f820f6c33ac54c207829fd8847a
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-29T22:33:42+02:00

Commit Message:
BLADERUNNER: fixed loading of new set/scene, fixed memoryleak in lights

Changed paths:
    engines/bladerunner/aud_stream.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/gameinfo.cpp
    engines/bladerunner/gameinfo.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene.h
    engines/bladerunner/settings.cpp
    engines/bladerunner/vqa_player.cpp



diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
index 28f8531..97623f9 100644
--- a/engines/bladerunner/aud_stream.cpp
+++ b/engines/bladerunner/aud_stream.cpp
@@ -95,7 +95,8 @@ int AudStream::readBuffer(int16 *buffer, const int numSamples) {
 			samplesRead += 2 * bytesConsumed;
 		}
 	} else {
-		assert(0 && "readBuffer: Unimplemented");
+		//assert(0 && "readBuffer: Unimplemented");
+		warning("AudStream::readBuffer unknown compression type %d", _compressionType);
 	}
 
 	return samplesRead;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 88d441d..dee0c61 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -613,7 +613,7 @@ void BladeRunnerEngine::gameTick() {
 				_walkSoundId = -1;
 			}
 
-#if 0 //_DEBUG
+#if _DEBUG
 			//draw scene objects
 			int count = _sceneObjects->_count;
 			if (count > 0) {
@@ -667,6 +667,19 @@ void BladeRunnerEngine::gameTick() {
 				}
 				
 			}
+
+			for (int i = 0; i < (int)_lights->_lights.size(); i++) {
+				Light *light = _lights->_lights[i];
+				Matrix4x3 m = light->_matrix;
+				Vector3 pos = Vector3(m(0, 3), m(1, 3), m(2, 3));
+				Vector3 size = Vector3(5.0f, 5.0f, 5.0f);
+				int colorR = (light->_color.r * 31.0f);
+				int colorG = (light->_color.g * 31.0f);
+				int colorB = (light->_color.b * 31.0f);
+				int color = (colorR << 10) + (colorG << 5) + colorB;
+				drawBBox(pos-size, pos+size, _view, &_surface2, color);
+
+			}
 #endif
 
 			_system->copyRectToScreen((const byte *)_surface2.getBasePtr(0, 0), _surface2.pitch, 0, 0, 640, 480);
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index 19037c8..a5c01c1 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -32,14 +32,14 @@ namespace BladeRunner {
 GameInfo::GameInfo(BladeRunnerEngine *vm)
 	: _vm(vm)
 {
-	_set_names    = nullptr;
+	_scene_names    = nullptr;
 	_sfx_tracks   = nullptr;
 	_music_tracks = nullptr;
 	_outtakes     = nullptr;
 }
 
 GameInfo::~GameInfo() {
-	delete[] _set_names;
+	delete[] _scene_names;
 	delete[] _sfx_tracks;
 	delete[] _music_tracks;
 	delete[] _outtakes;
@@ -73,9 +73,9 @@ bool GameInfo::open(const Common::String &name) {
 
 	(void)unk;
 
-	_set_names = new char[_set_names_count][5];
+	_scene_names = new char[_set_names_count][5];
 	for (uint32 i = 0; i != _set_names_count; ++i)
-		s->read(_set_names[i], 5);
+		s->read(_scene_names[i], 5);
 
 	_sfx_tracks = new char[_sfx_track_count][13];
 	for (uint32 i = 0; i != _sfx_track_count; ++i)
@@ -97,7 +97,7 @@ bool GameInfo::open(const Common::String &name) {
 
 	if (false) {
 		for (uint32 i = 0; i != _set_names_count; ++i)
-			debug("%3d: %s", i, _set_names[i]);
+			debug("%3d: %s", i, _scene_names[i]);
 		for (uint32 i = 0; i != _sfx_track_count; ++i)
 			debug("%3d: %s", i, _sfx_tracks[i]);
 		for (uint32 i = 0; i != _music_track_count; ++i)
diff --git a/engines/bladerunner/gameinfo.h b/engines/bladerunner/gameinfo.h
index f907439..b77251d 100644
--- a/engines/bladerunner/gameinfo.h
+++ b/engines/bladerunner/gameinfo.h
@@ -49,7 +49,7 @@ class GameInfo {
 	uint32 _cover_waypoint_count;
 	uint32 _flee_waypoint_count;
 
-	char (*_set_names)[5];
+	char (*_scene_names)[5];
 	char (*_sfx_tracks)[13];
 	char (*_music_tracks)[13];
 	char (*_outtakes)[13];
@@ -75,7 +75,7 @@ public:
 	uint32 getCoverWaypointCount() { return _cover_waypoint_count; }
 	uint32 getFleeWaypointCount()  { return _flee_waypoint_count; }
 
-	const char *getSetName(int i)    { return _set_names[i]; }
+	const char *getSceneName(int i)  { return _scene_names[i]; }
 	const char *getSfxTrack(int i)   { return _sfx_tracks[i]; }
 	const char *getMusicTrack(int i) { return _music_tracks[i]; }
 	const char *getOuttake(int i)    { return _outtakes[i]; }
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index e8660a2..a996c28 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -9,7 +9,6 @@ Lights::Lights(BladeRunnerEngine *vm) {
 	_ambientLightColor.g = 0.0;
 	_ambientLightColor.b = 0.0;
 	
-	_lightsCount = 0;
 	_lights.clear();
 	_frame = 0;
 }
@@ -23,9 +22,8 @@ void Lights::read(Common::ReadStream *stream, int framesCount) {
 	_ambientLightColor.g = stream->readFloatLE();
 	_ambientLightColor.b = stream->readFloatLE();
 
-	_lightsCount = stream->readUint32LE();
-	int i;
-	for (i = 0; i < _lightsCount; i++) {
+	uint _lightsCount = stream->readUint32LE();
+	for (uint i = 0; i < _lightsCount; i++) {
 		Light *light;
 		int type = stream->readUint32LE();
 		switch (type) {
@@ -54,7 +52,7 @@ void Lights::read(Common::ReadStream *stream, int framesCount) {
 }
 
 void Lights::removeAnimated() {
-	for (int i = (int)(_lights.size() - 1); i > 0; i--) {
+	for (int i = (int)(_lights.size() - 1); i >= 0; i--) {
 		if (_lights[i]->_animated) {
 			delete _lights.remove_at(i);
 		}
@@ -106,7 +104,7 @@ void Lights::setupFrame(int frame) {
 }
 
 void Lights::reset() {
-	for (int i = (int)(_lights.size() - 1); i > 0; i--) {
+	for (int i = (int)(_lights.size() - 1); i >= 0; i--) {
 		delete _lights.remove_at(i);
 	}
 	_lights.clear();
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index 486e690..ca2e77b 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -39,12 +39,9 @@ class Lights {
 
 	BladeRunnerEngine *_vm;
 
-	Color _ambientLightColor;
-
-	int                   _lightsCount;
+	Color                 _ambientLightColor;
 	Common::Array<Light*> _lights;
-
-	int _frame;
+	int                   _frame;
 	//char gap[28];
 
 public:
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 29d73f3..65efe13 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -32,7 +32,6 @@
 #include "bladerunner/slice_renderer.h"
 
 #include "common/str.h"
-#include "common/stream.h"
 
 namespace BladeRunner {
 
@@ -44,7 +43,7 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	_setId = setId;
 	_sceneId = sceneId;
 
-	const Common::String setName = _vm->_gameInfo->getSetName(_sceneId);
+	const Common::String setName = _vm->_gameInfo->getSceneName(_sceneId);
 
 	if (isLoadingGame) {
 		// TODO: Set up overlays
@@ -70,10 +69,15 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		vqaName = Common::String::format("%s_%d.VQA", setName.c_str(), MIN(currentResourceId, 3));
 	}
 
-	if (!_vqaPlayer.open(vqaName))
+	if (_vqaPlayer != nullptr)
+		delete _vqaPlayer;
+
+	_vqaPlayer = new VQAPlayer(_vm);
+
+	if (!_vqaPlayer->open(vqaName))
 		return false;
 
-	Common::String sceneName = _vm->_gameInfo->getSetName(sceneId);
+	Common::String sceneName = _vm->_gameInfo->getSceneName(sceneId);
 	if (!_vm->_script->open(sceneName))
 		return false;
 
@@ -124,20 +128,44 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	// TODO: add all items to scene
 	// TODO: calculate walking obstacles??
 
-	// if (_playerWalkedIn) { // TODO: Not _playerWalkedIn
-	// 	_vm->_script->PlayerWalkedIn();
-	// }
+	 if (_specialLoopMode) {
+	 	_vm->_script->PlayerWalkedIn();
+	 }
 
 	return true;
 }
 
+bool Scene::close(bool isLoadingGame) {
+	bool result = true;
+	if (getSetId() == -1) {
+		return true;
+	}
+
+	//_vm->_policeMaze->clear(!isLoadingGame);
+	if (isLoadingGame) {
+		_vm->_script->PlayerWalkedOut();
+	}	
+//	if (SceneScript_isLoaded() && !SceneScript_unload()) {
+//		result = false;
+//	}
+	if (_vqaPlayer != nullptr) {
+		//_vqaPlayer->stop();
+		delete _vqaPlayer;
+		_vqaPlayer = nullptr;
+	}
+	_sceneId = -1;
+	_setId = -1;
+
+	return result;
+}
+
 int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
-	int frame = _vqaPlayer.update();
+	int frame = _vqaPlayer->update();
 	if (frame >= 0) {
-		surface.copyFrom(*_vqaPlayer.getSurface());
-		memcpy(zBuffer, _vqaPlayer.getZBuffer(), 640*480*2);
-		_vqaPlayer.updateView(_vm->_view);
-		_vqaPlayer.updateLights(_vm->_lights);
+		surface.copyFrom(*_vqaPlayer->getSurface());
+		memcpy(zBuffer, _vqaPlayer->getZBuffer(), 640*480*2);
+		_vqaPlayer->updateView(_vm->_view);
+		_vqaPlayer->updateLights(_vm->_lights);
 	}
 
 	if (frame < 0) {
@@ -145,12 +173,12 @@ int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	}
 	_frame = frame;
 
-	if (_specialLoopMode == 0 && frame == _vqaPlayer.getLoopEndFrame(_specialLoop)) {
+	if (_specialLoopMode == 0 && frame == _vqaPlayer->getLoopEndFrame(_specialLoop)) {
 		_playerWalkedIn = true;
 		_specialLoopMode = -1;
 	}
 	if (_specialLoopMode == 0 && !_defaultLoopSet) {
-		_vqaPlayer.setLoop(_defaultLoop + 1);
+		_vqaPlayer->setLoop(_defaultLoop + 1);
 		_defaultLoopSet = true;
 	}
 
diff --git a/engines/bladerunner/scene.h b/engines/bladerunner/scene.h
index e4a2406..6a34fcd 100644
--- a/engines/bladerunner/scene.h
+++ b/engines/bladerunner/scene.h
@@ -41,7 +41,7 @@ public:
 	Set        *_set;
 	int         _setId;
 	int         _sceneId;
-	VQAPlayer   _vqaPlayer;
+	VQAPlayer  *_vqaPlayer;
 
 	int         _defaultLoop;
 	int         _defaultLoopSet;
@@ -69,7 +69,7 @@ public:
 		  _set(new Set(vm)),
 		  _setId(-1),
 		  _sceneId(-1),
-		  _vqaPlayer(vm),
+		  _vqaPlayer(nullptr),
 		  _defaultLoop(0),
 		  _nextSetId(-1),
 		  _nextSceneId(-1),
@@ -83,9 +83,13 @@ public:
 		delete _set;
 		delete _regions;
 		delete _exits;
+		if (_vqaPlayer != nullptr) {
+			delete _vqaPlayer;
+		}
 	}
 
 	bool open(int setId, int sceneId, bool isLoadingGame);
+	bool close(bool isLoadingGame);
 	int  advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer);
 	void setActorStart(Vector3 position, int facing);
 
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index 0c3a774..daf876c 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -57,6 +57,9 @@ bool Settings::openNewScene() {
 
 	if (_startingGame) {
 		// Stop ambient audio and music
+//		ambient::removeAllNonLoopingSounds(Ambient, 1);
+//		ambient::removeAllLoopingSounds(Ambient, 1);
+//		music::stop(Music, 2);
 	}
 
 	int currentSet = _vm->_scene->_setId;
@@ -65,7 +68,9 @@ bool Settings::openNewScene() {
 
 	_newSet = -1;
 	_newScene = -1;
-
+	if (currentSet != -1) {
+		_vm->_scene->close(!_loadingGame && !_startingGame);
+	}
 	if (_chapterChanged) {
 		if (_vm->_chapters->hasOpenResources())
 			_vm->_chapters->closeResources();
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 2c40806..4d948fd 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -65,7 +65,6 @@ int VQAPlayer::update() {
 				queueAudioFrame(_decoder.decodeAudioFrame());
 			_surface = _decoder.decodeVideoFrame();
 			_zBuffer = _decoder.decodeZBuffer();
-			//_view = _decoder.getView();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);
@@ -89,7 +88,6 @@ int VQAPlayer::update() {
 		if (_curFrame >= 0) {
 			_surface = _decoder.decodeVideoFrame();
 			_zBuffer = _decoder.decodeZBuffer();
-			//_view = _decoder.getView();
 		}
 
 		_decodedFrame = calcNextFrame(_curFrame);


Commit: a6f8a39dd3de395fedd26cbe014b23584c8297a8
    https://github.com/scummvm/scummvm/commit/a6f8a39dd3de395fedd26cbe014b23584c8297a8
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-09-29T22:33:42+02:00

Commit Message:
BLADERUNNER: Fix warnings

Changed paths:
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/color.h
    engines/bladerunner/script/script.cpp



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index dee0c61..b683e35 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -73,6 +73,10 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_settings = new Settings(this);
 	_lights = new Lights(this);
 	_combat = new Combat(this);
+
+	_walkSoundId = -1;
+	_walkSoundVolume = 0;
+	_walkSoundBalance = 0;
 }
 
 BladeRunnerEngine::~BladeRunnerEngine() {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 51c6855..d736678 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -120,9 +120,9 @@ public:
 	bool _gameIsLoading;
 	bool _sceneIsLoading;
 
-	int _walkSoundId = -1;
-	int _walkSoundVolume = 0;
-	int _walkSoundBalance = 0;
+	int _walkSoundId;
+	int _walkSoundVolume;
+	int _walkSoundBalance;
 
 private:
 	static const int kArchiveCount = 10;
diff --git a/engines/bladerunner/color.h b/engines/bladerunner/color.h
index 10d3737..a93d79b 100644
--- a/engines/bladerunner/color.h
+++ b/engines/bladerunner/color.h
@@ -36,7 +36,7 @@ struct Color {
 	Color() {
 	}
 
-	Color(float r, float g, float b) : r(r), g(g), b(b) {
+	Color(float r_, float g_, float b_) : r(r_), g(g_), b(b_) {
 	}
 };
 
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 50d56d5..6cc4319 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -574,7 +574,7 @@ bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z,
 
 void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int running) {
 	//TODO
-	warning("Async_Actor_Walk_To_Waypoint(%d, %d, %d, %d)", actorId, a3, running);
+	warning("Async_Actor_Walk_To_Waypoint(%d, %d, %d, %d)", actorId, waypointId, a3, running);
 }
 
 void ScriptBase::Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool running) {
@@ -1075,7 +1075,7 @@ void ScriptBase::Combat_Flee_Waypoint_Set_Data(int combatFleeWaypointId, int a2,
 
 void ScriptBase::Police_Maze_Target_Track_Add(int itemId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, signed int data[], bool a10) {
 	//TODO
-	warning("Police_Maze_Target_Track_Add(%d, %f, %f, %f, %f, %f, %f, %d, %x, %d)", itemId,  startX,  startY,  startZ,  endX,  endY,  endZ,  steps,  data,  a10);
+	warning("Police_Maze_Target_Track_Add(%d, %f, %f, %f, %f, %f, %f, %d, %p, %d)", itemId,  startX,  startY,  startZ,  endX,  endY,  endZ,  steps,  (void *)data,  a10);
 	
 }
 


Commit: 0c7d323921baa36f0a6db4b81e906ff402509463
    https://github.com/scummvm/scummvm/commit/0c7d323921baa36f0a6db4b81e906ff402509463
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-30T22:42:40+02:00

Commit Message:
BLADERUNNER: add support for uncompressed audio, fixed wrong call to gamescript after loading scene

Changed paths:
    engines/bladerunner/aud_stream.cpp
    engines/bladerunner/scene.cpp



diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
index 97623f9..4eadb5b 100644
--- a/engines/bladerunner/aud_stream.cpp
+++ b/engines/bladerunner/aud_stream.cpp
@@ -62,9 +62,9 @@ AudStream::~AudStream() {
 int AudStream::readBuffer(int16 *buffer, const int numSamples) {
 	int samplesRead = 0;
 
-	assert(numSamples % 2 == 0);
-
 	if (_compressionType == 99) {
+		assert(numSamples % 2 == 0);
+
 		while (samplesRead < numSamples) {
 			if (_deafBlockRemain == 0) {
 				if (_end - _p == 0)
@@ -95,8 +95,10 @@ int AudStream::readBuffer(int16 *buffer, const int numSamples) {
 			samplesRead += 2 * bytesConsumed;
 		}
 	} else {
-		//assert(0 && "readBuffer: Unimplemented");
-		warning("AudStream::readBuffer unknown compression type %d", _compressionType);
+		int bytesToCopy = MIN(2 * numSamples, _end - _p);
+		memcpy(buffer, _p, bytesToCopy);
+		_p += bytesToCopy;
+		samplesRead = bytesToCopy / 2;
 	}
 
 	return samplesRead;
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 65efe13..0ced4d8 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -93,16 +93,15 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (isLoadingGame) {
 		// TODO: Advance VQA frame
 		if (sceneId >= 73 && sceneId <= 76)
-			_vm->_script->InitializeScene();
+			_vm->_script->SceneLoaded();
 		return true;
 	}
 
 	// TODO: set VQADecoder parameters
+	//_vm->_scene->advanceFrame(0, 0);
 
-	// TODO: Set actor position from scene info
 	_vm->_playerActor->setAtXYZ(_actorStartPosition, _actorStartFacing);
-
-	// TODO: Set actor set
+	//_vm->_playerActor->setSetId(setId);
 
 	_vm->_script->SceneLoaded();
 


Commit: 70c10f82430fcf9e8d523075563760b889c3bb83
    https://github.com/scummvm/scummvm/commit/70c10f82430fcf9e8d523075563760b889c3bb83
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-09-30T23:58:20+02:00

Commit Message:
BLADERUNNER: fixed compiler error in gcc and clang (was working in msvc14)

Changed paths:
    engines/bladerunner/aud_stream.cpp



diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
index 4eadb5b..e86f6d5 100644
--- a/engines/bladerunner/aud_stream.cpp
+++ b/engines/bladerunner/aud_stream.cpp
@@ -95,7 +95,7 @@ int AudStream::readBuffer(int16 *buffer, const int numSamples) {
 			samplesRead += 2 * bytesConsumed;
 		}
 	} else {
-		int bytesToCopy = MIN(2 * numSamples, _end - _p);
+		int bytesToCopy = MIN(2 * numSamples, (int)(_end - _p));
 		memcpy(buffer, _p, bytesToCopy);
 		_p += bytesToCopy;
 		samplesRead = bytesToCopy / 2;


Commit: fe2add5d5fb955724af9f0308d07c46c3110baad
    https://github.com/scummvm/scummvm/commit/fe2add5d5fb955724af9f0308d07c46c3110baad
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-01T03:20:03+02:00

Commit Message:
BLADERUNNER: fixed endian issue in uncompressed audio (thx madmoose), fixed some warnings, fixed some scene scripts

Changed paths:
    engines/bladerunner/aud_stream.cpp
    engines/bladerunner/script/ar02.cpp
    engines/bladerunner/script/ct01.cpp
    engines/bladerunner/script/ct04.cpp
    engines/bladerunner/script/dr06.cpp
    engines/bladerunner/script/hc01.cpp
    engines/bladerunner/script/hc02.cpp
    engines/bladerunner/script/hf05.cpp
    engines/bladerunner/script/kia.cpp
    engines/bladerunner/script/kp03.cpp
    engines/bladerunner/script/ma04.cpp
    engines/bladerunner/script/ma05.cpp
    engines/bladerunner/script/ma06.cpp
    engines/bladerunner/script/nr02.cpp
    engines/bladerunner/script/nr04.cpp
    engines/bladerunner/script/ps04.cpp
    engines/bladerunner/script/ps07.cpp
    engines/bladerunner/script/ps15.cpp
    engines/bladerunner/script/rc04.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/script/tb06.cpp
    engines/bladerunner/script/ug10.cpp
    engines/bladerunner/script/ug16.cpp
    engines/bladerunner/set_effects.cpp
    engines/bladerunner/set_effects.h



diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
index e86f6d5..8a17f6b 100644
--- a/engines/bladerunner/aud_stream.cpp
+++ b/engines/bladerunner/aud_stream.cpp
@@ -95,10 +95,10 @@ int AudStream::readBuffer(int16 *buffer, const int numSamples) {
 			samplesRead += 2 * bytesConsumed;
 		}
 	} else {
-		int bytesToCopy = MIN(2 * numSamples, (int)(_end - _p));
-		memcpy(buffer, _p, bytesToCopy);
-		_p += bytesToCopy;
-		samplesRead = bytesToCopy / 2;
+		samplesRead = MIN(numSamples, (int)(_end - _p) / 2);
+		for (int i = 0; i < samplesRead; i++, _p += 2) {
+			buffer[i] = READ_LE_UINT16(_p);
+		}
 	}
 
 	return samplesRead;
diff --git a/engines/bladerunner/script/ar02.cpp b/engines/bladerunner/script/ar02.cpp
index 5b6be5f..dc89758 100644
--- a/engines/bladerunner/script/ar02.cpp
+++ b/engines/bladerunner/script/ar02.cpp
@@ -300,7 +300,7 @@ void ScriptAR02::sub_402694() {
 
 void ScriptAR02::sub_402AE0() {
 	Dialogue_Menu_Clear_List();
-	if (Global_Variable_Query(2) >= 15 || !Query_Difficulty_Level()) {
+	if (Global_Variable_Query(2) >= 15 || Query_Difficulty_Level() == 0) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(530, 7, 5, 3);
 	}
 	DM_Add_To_List_Never_Repeat_Once_Selected(540, 3, 5, 7);
@@ -309,7 +309,7 @@ void ScriptAR02::sub_402AE0() {
 	Dialogue_Menu_Disappear();
 	if (answerValue == 530) {
 		Actor_Says(0, 120, 12);
-		if (Query_Difficulty_Level()) {
+		if (Query_Difficulty_Level() != 0) {
 			Global_Variable_Decrement(2, 15);
 		}
 		Actor_Clue_Acquire(0, 75, 1, 16);
diff --git a/engines/bladerunner/script/ct01.cpp b/engines/bladerunner/script/ct01.cpp
index 88e41fa..c5d633f 100644
--- a/engines/bladerunner/script/ct01.cpp
+++ b/engines/bladerunner/script/ct01.cpp
@@ -480,18 +480,18 @@ void ScriptCT01::sub_40269C() {
 		break;
 	case 70:
 		Actor_Says(0, 290, 13);
-		if (Actor_Query_Friendliness_To_Other(28, 0) <= 49 || Global_Variable_Query(2) <= 10 && Query_Difficulty_Level()) {
-			Actor_Says(28, 130, 15);
-		} else {
+		if (Actor_Query_Friendliness_To_Other(28, 0) > 49 && (Global_Variable_Query(2) > 10 || Query_Difficulty_Level() == 0)) {
 			Actor_Says(28, 50, 3);
 			Actor_Says(28, 60, 3);
 			Actor_Face_Actor(28, 0, true);
 			Actor_Says(28, 70, 16);
 			Actor_Says(0, 325, 13);
-			if (Query_Difficulty_Level()) {
+			if (Query_Difficulty_Level() != 0) {
 				Global_Variable_Decrement(2, 10);
 			}
 			Game_Flag_Set(192);
+		} else {
+			Actor_Says(28, 130, 15);
 		}
 		break;
 	case 80:
diff --git a/engines/bladerunner/script/ct04.cpp b/engines/bladerunner/script/ct04.cpp
index 795cf94..cad32df 100644
--- a/engines/bladerunner/script/ct04.cpp
+++ b/engines/bladerunner/script/ct04.cpp
@@ -126,7 +126,7 @@ bool ScriptCT04::ClickedOn3DObject(const char *objectName, bool a2) {
 
 void ScriptCT04::sub_401D4C() {
 	Dialogue_Menu_Clear_List();
-	if (Global_Variable_Query(2) > 10 || !Query_Difficulty_Level()) {
+	if (Global_Variable_Query(2) > 10 || Query_Difficulty_Level() == 0) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(410, 8, 4, -1);
 	}
 	DM_Add_To_List_Never_Repeat_Once_Selected(420, 2, 6, 8);
@@ -137,7 +137,7 @@ void ScriptCT04::sub_401D4C() {
 		Actor_Says(12, 10, 14);
 		Actor_Says(12, 20, 14);
 		Actor_Modify_Friendliness_To_Other(12, 0, 5);
-		if (Query_Difficulty_Level()) {
+		if (Query_Difficulty_Level() != 0) {
 			Global_Variable_Decrement(2, 10);
 		}
 	} else if (answer == 420) {
diff --git a/engines/bladerunner/script/dr06.cpp b/engines/bladerunner/script/dr06.cpp
index ebaa832..8556db7 100644
--- a/engines/bladerunner/script/dr06.cpp
+++ b/engines/bladerunner/script/dr06.cpp
@@ -150,7 +150,7 @@ bool ScriptDR06::ClickedOn3DObject(const char *objectName, bool a2) {
 					Actor_Voice_Over(870, 99);
 					Actor_Voice_Over(880, 99);
 					Actor_Clue_Acquire(0, 76, 1, 13);
-					if (Query_Difficulty_Level()) {
+					if (Query_Difficulty_Level() != 0) {
 						Global_Variable_Increment(2, 200);
 					}
 				}
diff --git a/engines/bladerunner/script/hc01.cpp b/engines/bladerunner/script/hc01.cpp
index aac8b28..c59eab6 100644
--- a/engines/bladerunner/script/hc01.cpp
+++ b/engines/bladerunner/script/hc01.cpp
@@ -253,7 +253,7 @@ void ScriptHC01::sub_402384() {
 		} else {
 			Actor_Says(7, 250, 13);
 			Actor_Modify_Friendliness_To_Other(7, 0, -1);
-			if (Actor_Query_Friendliness_To_Other(7, 0) < 47 && !Query_Difficulty_Level()) {
+			if (Actor_Query_Friendliness_To_Other(7, 0) < 47 && Query_Difficulty_Level() == 0) {
 				sub_40346C();
 			}
 		}
diff --git a/engines/bladerunner/script/hc02.cpp b/engines/bladerunner/script/hc02.cpp
index 908b992..c676938 100644
--- a/engines/bladerunner/script/hc02.cpp
+++ b/engines/bladerunner/script/hc02.cpp
@@ -106,7 +106,7 @@ bool ScriptHC02::ClickedOnActor(int actorId) {
 				Actor_Says(32, 180, 13);
 				Actor_Clue_Acquire(0, 257, 1, 32);
 				Item_Pickup_Spin_Effect(975, 229, 215);
-			} else if (Actor_Clue_Query(0, 122) && !Actor_Clue_Query(0, 131) && Global_Variable_Query(2) > 20 || Query_Difficulty_Level() == 0) {
+			} else if (Actor_Clue_Query(0, 122) && !Actor_Clue_Query(0, 131) && (Global_Variable_Query(2) > 20 || Query_Difficulty_Level() == 0)) {
 				Actor_Clue_Acquire(0, 131, 1, 32);
 				Actor_Says(0, 1230, 13);
 				Actor_Says(32, 20, 12);
@@ -119,7 +119,7 @@ bool ScriptHC02::ClickedOnActor(int actorId) {
 				Actor_Change_Animation_Mode(0, 23);
 				Delay(1500);
 				Actor_Says_With_Pause(32, 50, 1.6f, 17);
-				if (Query_Difficulty_Level()) {
+				if (Query_Difficulty_Level() != 0) {
 					Global_Variable_Decrement(2, 20);
 				}
 				Actor_Says(0, 1245, 13);
@@ -131,7 +131,7 @@ bool ScriptHC02::ClickedOnActor(int actorId) {
 					Game_Flag_Set(405);
 				}
 				if (Global_Variable_Query(2) > 5 || Query_Difficulty_Level() == 0) {
-					if (Query_Difficulty_Level()) {
+					if (Query_Difficulty_Level() != 0) {
 						Global_Variable_Decrement(2, 5);
 					}
 					Global_Variable_Increment(42, 1);
diff --git a/engines/bladerunner/script/hf05.cpp b/engines/bladerunner/script/hf05.cpp
index 94cfadb6..f569f48 100644
--- a/engines/bladerunner/script/hf05.cpp
+++ b/engines/bladerunner/script/hf05.cpp
@@ -329,7 +329,7 @@ void ScriptHF05::sub_402AE4() {
 	if (Actor_Clue_Query(0, 13) == 1 && Actor_Query_Goal_Number(6) != 599) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(1210, 4, 6, 2);
 	}
-	if (Actor_Clue_Query(0, 237) == 1 || Actor_Clue_Query(0, 99) == 1 && Global_Variable_Query(1) == 3) {
+	if (Actor_Clue_Query(0, 237) == 1 || (Actor_Clue_Query(0, 99) == 1 && Global_Variable_Query(1) == 3)) {
 		DM_Add_To_List_Never_Repeat_Once_Selected(1220, -1, 2, 8);
 	}
 	if (Actor_Clue_Query(0, 113) == 1 || Actor_Clue_Query(0, 115) == 1) {
diff --git a/engines/bladerunner/script/kia.cpp b/engines/bladerunner/script/kia.cpp
index c82e80c..587e25d 100644
--- a/engines/bladerunner/script/kia.cpp
+++ b/engines/bladerunner/script/kia.cpp
@@ -232,7 +232,7 @@ void ScriptKIA::SCRIPT_KIA_DLL_Play_Clue_Asset_Script(int a1, int clueId) {
 		break;
 	case 53:
 		KIA_Play_Slice_Model(955);
-		if (Query_Difficulty_Level() <= 0) {
+		if (Query_Difficulty_Level() == 0) {
 			KIA_Play_Actor_Dialogue(99, 4140);
 		} else {
 			KIA_Play_Actor_Dialogue(99, 4150);
@@ -869,7 +869,7 @@ void ScriptKIA::SCRIPT_KIA_DLL_Play_Clue_Asset_Script(int a1, int clueId) {
 		break;
 	case 263:
 		KIA_Play_Photograph(29);
-		if (Query_Difficulty_Level() <= 0) {
+		if (Query_Difficulty_Level() == 0) {
 			KIA_Play_Actor_Dialogue(99, 4140);
 		} else {
 			KIA_Play_Actor_Dialogue(99, 4150);
diff --git a/engines/bladerunner/script/kp03.cpp b/engines/bladerunner/script/kp03.cpp
index a037ff6..57a1eb5 100644
--- a/engines/bladerunner/script/kp03.cpp
+++ b/engines/bladerunner/script/kp03.cpp
@@ -46,7 +46,7 @@ void ScriptKP03::InitializeScene() {
 		Scene_Loop_Set_Default(2);
 		Game_Flag_Set(421);
 	}
-	if (Actor_Query_Goal_Number(1) != 599 && !Game_Flag_Query(422) && !Game_Flag_Query(484) && (Game_Flag_Query(653) && Game_Flag_Query(420) || !Game_Flag_Query(653) && Game_Flag_Query(417))) {
+	if ((Actor_Query_Goal_Number(1) != 599 && !Game_Flag_Query(422) && !Game_Flag_Query(484)) && ((Game_Flag_Query(653) && Game_Flag_Query(420)) || (!Game_Flag_Query(653) && Game_Flag_Query(417)))) {
 		Actor_Put_In_Set(1, 46);
 		Actor_Set_At_XYZ(1, -300.0f, -36.55f, 26.0f, 350);
 	}
@@ -162,17 +162,17 @@ void ScriptKP03::SceneFrameAdvanced(int frame) {
 		v1 = -1;
 		if (!Game_Flag_Query(422)) {
 			Actor_Query_XYZ(0, &x, &y, &z);
-			if (Game_Flag_Query(417) && -130.0f < x || Game_Flag_Query(420) && -130.0f > x) {
+			if ((Game_Flag_Query(417) && -130.0f < x) || (Game_Flag_Query(420) && -130.0f > x)) {
 				v1 = 0;
 			}
 		}
 		if (!Game_Flag_Query(422)) { //todo ? same condition as before
 			Actor_Query_XYZ(1, &x, &y, &z);
 			if (Game_Flag_Query(653) && Actor_Query_Which_Set_In(1) == 46) {
-				if (Game_Flag_Query(417) && -130.0f > x || Game_Flag_Query(420) && -130.0f < x) {
+				if ((Game_Flag_Query(417) && -130.0f > x) || (Game_Flag_Query(420) && -130.0f < x)) {
 					v1 = 1;
 				}
-			} else if (Game_Flag_Query(417) && -130.0f < x || Game_Flag_Query(420) && -130.0f > x) {
+			} else if ((Game_Flag_Query(417) && -130.0f < x) || (Game_Flag_Query(420) && -130.0f > x)) {
 				v1 = 1;
 			}
 		}
diff --git a/engines/bladerunner/script/ma04.cpp b/engines/bladerunner/script/ma04.cpp
index 3fb4c01..f31c732 100644
--- a/engines/bladerunner/script/ma04.cpp
+++ b/engines/bladerunner/script/ma04.cpp
@@ -280,7 +280,7 @@ void ScriptMA04::PlayerWalkedIn() {
 		//return false;
 		return;
 	}
-	if (Game_Flag_Query(40) || Game_Flag_Query(41) && !Game_Flag_Query(146)) {
+	if ((Game_Flag_Query(40) || Game_Flag_Query(41)) && !Game_Flag_Query(146)) {
 		Music_Play(2, 52, 0, 2, -1, 0, 0);
 		Player_Loses_Control();
 		Loop_Actor_Walk_To_XYZ(0, -7199.0f, 955.0f, 1677.0f, 0, 1, false, 0);
@@ -291,9 +291,7 @@ void ScriptMA04::PlayerWalkedIn() {
 		Game_Flag_Set(146);
 		Async_Actor_Walk_To_XYZ(0, -7204.0f, 956.17f, 1568.0f, 0, false);
 		Set_Enter(51, 51);
-		//return true;
 	}
-	//return false;
 }
 
 void ScriptMA04::PlayerWalkedOut() {
@@ -316,7 +314,7 @@ bool ScriptMA04::sub_402758() {
 }
 
 bool ScriptMA04::sub_402820() {
-	return Actor_Clue_Query(5, 222) && !Game_Flag_Query(649) || Actor_Clue_Query(6, 215) && !Game_Flag_Query(650);
+	return (Actor_Clue_Query(5, 222) && !Game_Flag_Query(649)) || (Actor_Clue_Query(6, 215) && !Game_Flag_Query(650));
 }
 
 bool ScriptMA04::sub_402888() {
@@ -552,7 +550,7 @@ void ScriptMA04::sub_403DA8() {
 			Game_Flag_Set(678);
 			Global_Variable_Set(1, 2);
 			Chapter_Enter(2, 10, 50);
-			if (Query_Difficulty_Level()) {
+			if (Query_Difficulty_Level() != 0) {
 				if (!Game_Flag_Query(723)) {
 					Global_Variable_Increment(2, 200);
 				}
diff --git a/engines/bladerunner/script/ma05.cpp b/engines/bladerunner/script/ma05.cpp
index 9861f90..839d913 100644
--- a/engines/bladerunner/script/ma05.cpp
+++ b/engines/bladerunner/script/ma05.cpp
@@ -105,7 +105,7 @@ void ScriptMA05::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool cu
 
 void ScriptMA05::PlayerWalkedIn() {
 	Music_Play(2, 52, 0, 2, -1, 0, 0);
-	if ((Random_Query(0, 4) == 1 || Game_Flag_Query(146) && !Game_Flag_Query(61)) && Global_Variable_Query(1) == 1) {
+	if ((Random_Query(0, 4) == 1 || (Game_Flag_Query(146) == 1 && !Game_Flag_Query(61))) && Global_Variable_Query(1) == 1) {
 		Scene_Loop_Set_Default(1);
 		Scene_Loop_Start_Special(2, 3, 1);
 		Sound_Play(69, 100, 0, 0, 50);
diff --git a/engines/bladerunner/script/ma06.cpp b/engines/bladerunner/script/ma06.cpp
index dfe9080..caea6cd 100644
--- a/engines/bladerunner/script/ma06.cpp
+++ b/engines/bladerunner/script/ma06.cpp
@@ -103,7 +103,7 @@ void ScriptMA06::DialogueQueueFlushed(int a1) {
 }
 
 bool ScriptMA06::sub_4012C0() {
-	return Game_Flag_Query(37) && !Game_Flag_Query(38) || Game_Flag_Query(33) && !Game_Flag_Query(34) || Game_Flag_Query(57) && !Game_Flag_Query(58);
+	return (Game_Flag_Query(37) && !Game_Flag_Query(38)) || (Game_Flag_Query(33) && !Game_Flag_Query(34)) || (Game_Flag_Query(57) && !Game_Flag_Query(58));
 }
 
 void ScriptMA06::sub_4014E4() {
diff --git a/engines/bladerunner/script/nr02.cpp b/engines/bladerunner/script/nr02.cpp
index 0622161..7290390 100644
--- a/engines/bladerunner/script/nr02.cpp
+++ b/engines/bladerunner/script/nr02.cpp
@@ -121,7 +121,7 @@ bool ScriptNR02::ClickedOnItem(int itemId, bool a2) {
 }
 
 bool ScriptNR02::ClickedOnExit(int exitId) {
-	if (!exitId == 0) {
+	if (exitId == 0) {
 		if (!Loop_Actor_Walk_To_XYZ(0, -283.0f, -24.0f, 326.0f, 0, 1, false, 0)) {
 			if (Actor_Query_Goal_Number(2) < 230 || Actor_Query_Goal_Number(2) > 250) {
 				Music_Stop(2);
diff --git a/engines/bladerunner/script/nr04.cpp b/engines/bladerunner/script/nr04.cpp
index dc1d40d..3af4257 100644
--- a/engines/bladerunner/script/nr04.cpp
+++ b/engines/bladerunner/script/nr04.cpp
@@ -145,7 +145,7 @@ bool ScriptNR04::ClickedOnExit(int exitId) {
 }
 
 bool ScriptNR04::ClickedOn2DRegion(int region) {
-	if (region == 0 || region == 1 || region == 2 && Actor_Query_Which_Set_In(18) != 12 && Actor_Query_Animation_Mode(0) != 53 && !Loop_Actor_Walk_To_Waypoint(0, 445, 0, 1, false)) {
+	if ((region == 0 || region == 1 || region == 2) && Actor_Query_Which_Set_In(18) != 12 && Actor_Query_Animation_Mode(0) != 53 && !Loop_Actor_Walk_To_Waypoint(0, 445, 0, 1, false)) {
 		Actor_Face_Heading(0, 49, false);
 		Actor_Change_Animation_Mode(0, 85);
 		Delay(2500);
diff --git a/engines/bladerunner/script/ps04.cpp b/engines/bladerunner/script/ps04.cpp
index 8ed76dc..3718c6d 100644
--- a/engines/bladerunner/script/ps04.cpp
+++ b/engines/bladerunner/script/ps04.cpp
@@ -183,7 +183,7 @@ void ScriptPS04::sub_4017E4() {
 			Actor_Says(4, 260, 33);
 			Actor_Says(4, 270, 32);
 			Game_Flag_Set(159);
-			if (Query_Difficulty_Level()) {
+			if (Query_Difficulty_Level() != 0) {
 				Global_Variable_Increment(2, 200);
 			}
 			Game_Flag_Set(723);
@@ -252,7 +252,7 @@ void ScriptPS04::sub_4017E4() {
 		Actor_Says(4, 550, 32);
 		Actor_Says(0, 4065, 18);
 		Actor_Says(4, 560, 34);
-		if (Query_Difficulty_Level()) {
+		if (Query_Difficulty_Level() != 0) {
 			Global_Variable_Increment(2, 100);
 		}
 		break;
diff --git a/engines/bladerunner/script/ps07.cpp b/engines/bladerunner/script/ps07.cpp
index 6708041..8d8ade5 100644
--- a/engines/bladerunner/script/ps07.cpp
+++ b/engines/bladerunner/script/ps07.cpp
@@ -71,7 +71,7 @@ bool ScriptPS07::ClickedOnActor(int actorId) {
 		if (!Game_Flag_Query(111)) {
 			Actor_Says(0, 4115, 13);
 		}
-		if (!Game_Flag_Query(111) && Game_Flag_Query(125) || Game_Flag_Query(126) || Game_Flag_Query(127) || Game_Flag_Query(128)) {
+		if (!Game_Flag_Query(111) && (Game_Flag_Query(125) || Game_Flag_Query(126) || Game_Flag_Query(127) || Game_Flag_Query(128))) {
 			Actor_Face_Actor(30, 0, true);
 			Actor_Says(30, 30, 12);
 			Game_Flag_Set(111);
diff --git a/engines/bladerunner/script/ps15.cpp b/engines/bladerunner/script/ps15.cpp
index 464efe9..3e8224a 100644
--- a/engines/bladerunner/script/ps15.cpp
+++ b/engines/bladerunner/script/ps15.cpp
@@ -57,7 +57,7 @@ bool ScriptPS15::ClickedOn3DObject(const char *objectName, bool a2) {
 
 bool ScriptPS15::ClickedOnActor(int actorId) {
 	if (actorId == 34) {
-		if (Actor_Clue_Query(0, 80) || Actor_Clue_Query(0, 83) && !Actor_Clue_Query(0, 81)) {
+		if ((Actor_Clue_Query(0, 80) || Actor_Clue_Query(0, 83)) && !Actor_Clue_Query(0, 81)) {
 			if (!Loop_Actor_Walk_To_XYZ(0, -256.0f, -113.43f, 43.51f, 0, 1, false, 0)) {
 				Actor_Face_Actor(0, 34, true);
 				Actor_Face_Actor(34, 0, true);
diff --git a/engines/bladerunner/script/rc04.cpp b/engines/bladerunner/script/rc04.cpp
index b0ac2f7..830b7f5 100644
--- a/engines/bladerunner/script/rc04.cpp
+++ b/engines/bladerunner/script/rc04.cpp
@@ -222,7 +222,7 @@ void ScriptRC04::sub_401DF4() {
 		Actor_Says(14, 2120, 31);
 		if (Global_Variable_Query(2) > 40 || Query_Difficulty_Level() == 0) {
 			Actor_Says(0, 4940, 13);
-			if (Query_Difficulty_Level()) {
+			if (Query_Difficulty_Level() != 0) {
 				Global_Variable_Decrement(2, 40);
 			}
 			Item_Pickup_Spin_Effect(995, 405, 192);
@@ -274,7 +274,7 @@ void ScriptRC04::sub_401DF4() {
 		Actor_Says(14, 880, 34);
 		Actor_Clue_Acquire(14, 110, 1, 0);
 		Actor_Modify_Friendliness_To_Other(14, 0, 8);
-		if (Query_Difficulty_Level()) {
+		if (Query_Difficulty_Level() != 0) {
 			Global_Variable_Increment(2, 60);
 		}
 		break;
@@ -330,7 +330,7 @@ bool ScriptRC04::ClickedOnActor(int actorId) {
 			Actor_Says(14, 2010, 35);
 			if (Global_Variable_Query(2) > 50 || Query_Difficulty_Level() == 0) {
 				Actor_Says(0, 8975, 16);
-				if (Query_Difficulty_Level()) {
+				if (Query_Difficulty_Level() != 0) {
 					Global_Variable_Decrement(2, 50);
 				}
 				Delay(3000);
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 6cc4319..dd6e293 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -1280,11 +1280,11 @@ void ScriptBase::Set_Fade_Density(float density) {
 	_vm->_scene->_set->_effects->setFadeDensity(density);
 }
 
-void ScriptBase::Set_Fog_Color(char* fogName, float r, float g, float b) {
+void ScriptBase::Set_Fog_Color(const char* fogName, float r, float g, float b) {
 	_vm->_scene->_set->_effects->setFogColor(fogName, r, g, b);
 }
 
-void ScriptBase::Set_Fog_Density(char* fogName, float density) {
+void ScriptBase::Set_Fog_Density(const char* fogName, float density) {
 	_vm->_scene->_set->_effects->setFogDensity(fogName, density);
 }
 
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index a4c8ad0..0ab9efa 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -250,8 +250,8 @@ protected:
 	void Un_Combat_Target_Object(const char *objectName);
 	void Set_Fade_Color(float r, float g, float b);
 	void Set_Fade_Density(float density);
-	void Set_Fog_Color(char* fogName, float r, float g, float b);
-	void Set_Fog_Density(char* fogName, float density);
+	void Set_Fog_Color(const char* fogName, float r, float g, float b);
+	void Set_Fog_Density(const char* fogName, float density);
 	void ADQ_Flush();
 	void ADQ_Add(int a1, int a2, int a3);
 	void ADQ_Add_Pause(int delay);
diff --git a/engines/bladerunner/script/tb06.cpp b/engines/bladerunner/script/tb06.cpp
index 81b35b6..d266e52 100644
--- a/engines/bladerunner/script/tb06.cpp
+++ b/engines/bladerunner/script/tb06.cpp
@@ -114,7 +114,7 @@ bool ScriptTB06::ClickedOnItem(int itemId, bool a2) {
 		Actor_Says(0, 5285, 3);
 		return true;
 	}
-	if (itemId == 103 || itemId == 104 || itemId == 105 && !Loop_Actor_Walk_To_Item(0, 103, 24, 1, false)) {
+	if ((itemId == 103 || itemId == 104 || itemId == 105) && !Loop_Actor_Walk_To_Item(0, 103, 24, 1, false)) {
 		Actor_Face_Item(0, 103, true);
 		Actor_Voice_Over(2380, 99);
 		Actor_Voice_Over(2390, 99);
diff --git a/engines/bladerunner/script/ug10.cpp b/engines/bladerunner/script/ug10.cpp
index 689dbdc..9879b6e 100644
--- a/engines/bladerunner/script/ug10.cpp
+++ b/engines/bladerunner/script/ug10.cpp
@@ -101,7 +101,7 @@ bool ScriptUG10::ClickedOnExit(int exitId) {
 	float x, y, z;
 	Actor_Query_XYZ(0, &x, &y, &z);
 	if (exitId == 0) {
-		if (!Game_Flag_Query(474) && x > 125.0f || Game_Flag_Query(474)) {
+		if ((!Game_Flag_Query(474) && x > 125.0f) || Game_Flag_Query(474)) {
 			if (!Loop_Actor_Walk_To_XYZ(0, 235.0f, 1.15f, 29.0f, 0, 1, false, 0)) {
 				Game_Flag_Set(317);
 				Set_Enter(74, 86);
@@ -111,7 +111,7 @@ bool ScriptUG10::ClickedOnExit(int exitId) {
 			Actor_Says(0, 8521, 3);
 		}
 	} else if (exitId == 1) {
-		if (!Game_Flag_Query(474) && x < 120.0f || Game_Flag_Query(474)) {
+		if ((!Game_Flag_Query(474) && x < 120.0f) || Game_Flag_Query(474)) {
 			if (!Loop_Actor_Walk_To_XYZ(0, -1.83f, 1.15f, -410.8f, 0, 1, false, 0)) {
 				Actor_Face_Heading(0, 0, false);
 				Loop_Actor_Travel_Stairs(0, 9, 1, 0);
@@ -124,7 +124,7 @@ bool ScriptUG10::ClickedOnExit(int exitId) {
 			Actor_Says(0, 6165, 3);
 		}
 	} else if (exitId == 2) {
-		if (!Game_Flag_Query(474) && x < 120.0f || Game_Flag_Query(474)) {
+		if ((!Game_Flag_Query(474) && x < 120.0f) || Game_Flag_Query(474)) {
 			if (!Loop_Actor_Walk_To_XYZ(0, -385.0f, 1.15f, 57.44f, 0, 1, false, 0)) {
 				Actor_Face_Heading(0, 1001, false);
 				Loop_Actor_Travel_Ladder(0, 1, 1, 0);
@@ -136,7 +136,7 @@ bool ScriptUG10::ClickedOnExit(int exitId) {
 			Actor_Says(0, 6165, 3);
 		}
 	} else if (exitId == 3) {
-		if (!Game_Flag_Query(474) && x < 120.0f || Game_Flag_Query(474)) {
+		if ((!Game_Flag_Query(474) && x < 120.0f) || Game_Flag_Query(474)) {
 			if (!Loop_Actor_Walk_To_XYZ(0, 2.5f, 1.15f, 405.0f, 0, 1, false, 0)) {
 				Game_Flag_Set(347);
 				Set_Enter(86, 98);
diff --git a/engines/bladerunner/script/ug16.cpp b/engines/bladerunner/script/ug16.cpp
index 379e0bb..2a4a028 100644
--- a/engines/bladerunner/script/ug16.cpp
+++ b/engines/bladerunner/script/ug16.cpp
@@ -98,19 +98,19 @@ bool ScriptUG16::ClickedOn3DObject(const char *objectName, bool a2) {
 	}
 	if (Object_Query_Click("SCREEN 01", objectName) && !Loop_Actor_Walk_To_XYZ(0, 194.0f, -35.0f, 160.8f, 0, 1, false, 0)) {
 		Actor_Face_Heading(0, 870, false);
-		if (Game_Flag_Query(595) || !Actor_Query_Is_In_Current_Set(10) && !Actor_Clue_Query(0, 151) && !Game_Flag_Query(568)) {
-			Delay(2000);
-			Actor_Face_Heading(0, 1016, false);
-			Delay(2000);
-			Actor_Says(0, 5725, 14);
-			Delay(1000);
-			Item_Pickup_Spin_Effect(941, 418, 305);
-			Actor_Clue_Acquire(0, 151, 1, -1);
-			return true;
+		if ((!Game_Flag_Query(595) && Actor_Query_Is_In_Current_Set(10)) || Actor_Clue_Query(0, 151) || Game_Flag_Query(568)) {
+			Actor_Says(0, 8525, 12);
+			Actor_Says(0, 8526, 12);
+			return false;
 		}
-		Actor_Says(0, 8525, 12);
-		Actor_Says(0, 8526, 12);
-		return false;
+		Delay(2000);
+		Actor_Face_Heading(0, 1016, false);
+		Delay(2000);
+		Actor_Says(0, 5725, 14);
+		Delay(1000);
+		Item_Pickup_Spin_Effect(941, 418, 305);
+		Actor_Clue_Acquire(0, 151, 1, -1);
+		return true;
 	}
 	return false;
 }
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
index f4d2506..318ad37 100644
--- a/engines/bladerunner/set_effects.cpp
+++ b/engines/bladerunner/set_effects.cpp
@@ -82,7 +82,7 @@ void SetEffects::setFadeDensity(float density) {
 	_fadeDensity = density;
 }
 
-void SetEffects::setFogColor(char *fogName, float r, float g, float b) {
+void SetEffects::setFogColor(const char *fogName, float r, float g, float b) {
 	Fog *fog = findFog(fogName);
 	if (fog == nullptr)
 		return;
@@ -92,7 +92,7 @@ void SetEffects::setFogColor(char *fogName, float r, float g, float b) {
 	fog->_fogColor.b = b;
 }
 
-void SetEffects::setFogDensity(char *fogName, float density) {
+void SetEffects::setFogDensity(const char *fogName, float density) {
 	Fog *fog = findFog(fogName);
 	if (fog == nullptr)
 		return;
@@ -127,7 +127,7 @@ void SetEffects::calculateColor(Vector3 viewPosition, Vector3 position, float *o
 	outColor->b = outColor->b * (1.0f - this->_fadeDensity) + this->_fadeColor.b * this->_fadeDensity;
 }
 
-Fog *SetEffects::findFog(char *fogName) {
+Fog *SetEffects::findFog(const char *fogName) {
 	if (!_fogs)
 		return nullptr;
 
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
index 233009d..199009f 100644
--- a/engines/bladerunner/set_effects.h
+++ b/engines/bladerunner/set_effects.h
@@ -55,13 +55,13 @@ public:
 
 	void setFadeColor(float r, float g, float b);
 	void setFadeDensity(float density);
-	void setFogColor(char* fogName, float r, float g, float b);
-	void setFogDensity(char* fogName, float density);
+	void setFogColor(const char* fogName, float r, float g, float b);
+	void setFogDensity(const char* fogName, float density);
 
 	void calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor);
 private:
 
-	Fog* findFog(char* fogName);
+	Fog* findFog(const char* fogName);
 
 };
 


Commit: 2c15b164d736d1339998f9dcf7a4a230984cdff5
    https://github.com/scummvm/scummvm/commit/2c15b164d736d1339998f9dcf7a4a230984cdff5
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-02T00:20:56+02:00

Commit Message:
BLADERUNNER: added support for rendering items in scenes

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor_combat.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/items.cpp
    engines/bladerunner/items.h
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/view.cpp
    engines/bladerunner/view.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 29c83e7..ba0beda 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -176,8 +176,8 @@ void Actor::processMovement() {
 	}*/
 }
 
-void Actor::setAtXYZ(Vector3 pos, int facing, bool snapFacing, bool moving, bool retired) {
-	_position = pos;
+void Actor::setAtXYZ(Vector3 position, int facing, bool snapFacing, bool moving, bool retired) {
+	_position = position;
 	setFacing(facing, snapFacing);
 
 	if (_vm->_scene->_setId == _setId) {
@@ -404,6 +404,7 @@ void Actor::draw() {
 	// TODO: Handle SHORTY mode
 	
 	_vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, draw_position, draw_facing, draw_scale, _vm->_surface2, _vm->_zBuffer2);
+	//todo udpate screenrect
 }
 
 int Actor::getSetId() {
@@ -814,7 +815,7 @@ int Actor::soundVolume() {
 }
 
 int Actor::soundBalance() {
-	Vector2 screenPosition = _vm->_view->calculateScreenPosition(_position);
+	Vector3 screenPosition = _vm->_view->calculateScreenPosition(_position);
 	return 127.0f * (MAX(MIN(screenPosition.x / 640.0f, 1.0f), 0.0f) * 2.0f - 1.0f);
 }
 
diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h
index 37fc577..df06e83 100644
--- a/engines/bladerunner/actor_combat.h
+++ b/engines/bladerunner/actor_combat.h
@@ -34,27 +34,27 @@ class ActorCombat
 	BladeRunnerEngine *_vm;
 
 private:
-	int _actorId;
-	int _combatOn;
-	int _field2;
-	int _field3;
-	int _otherActorId;
-	int _field5;
-	int _field6;
-	int _field7;
-	int _field8;
-	int _field9;
-	int _field10;
-	int _field11;
-	int _field12;
-	int _actorHp;
-	int _field14;
-	int _field15;
+//	int _actorId;
+//	int _combatOn;
+//	int _field2;
+//	int _field3;
+//	int _otherActorId;
+//	int _field5;
+//	int _field6;
+//	int _field7;
+//	int _field8;
+//	int _field9;
+//	int _field10;
+//	int _field11;
+//	int _field12;
+//	int _actorHp;
+//	int _field14;
+//	int _field15;
 	Vector3 actorPosition;
 	Vector3 otherActorPosition;
-	int _availableCoversCount;
-	int _availableFleeWaypointsCount;
-	int _field24;
+//	int _availableCoversCount;
+//	int _availableFleeWaypointsCount;
+//	int _field24;
 
 public:
 	ActorCombat(BladeRunnerEngine *vm);
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index b683e35..663d17d 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -507,15 +507,15 @@ void BladeRunnerEngine::gameLoop() {
 #if _DEBUG
 
 void drawBBox(Vector3 start, Vector3 end, View* view, Graphics::Surface *surface, int color) {
-	Vector2 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z));
-	Vector2 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z));
-	Vector2 bbr = view->calculateScreenPosition(Vector3(end.x, end.y, start.z));
-	Vector2 bbl = view->calculateScreenPosition(Vector3(end.x, start.y, start.z));
+	Vector3 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z));
+	Vector3 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z));
+	Vector3 bbr = view->calculateScreenPosition(Vector3(end.x, end.y, start.z));
+	Vector3 bbl = view->calculateScreenPosition(Vector3(end.x, start.y, start.z));
 
-	Vector2 tfl = view->calculateScreenPosition(Vector3(start.x, start.y, end.z));
-	Vector2 tfr = view->calculateScreenPosition(Vector3(start.x, end.y, end.z));
-	Vector2 tbr = view->calculateScreenPosition(Vector3(end.x, end.y, end.z));
-	Vector2 tbl = view->calculateScreenPosition(Vector3(end.x, start.y, end.z));
+	Vector3 tfl = view->calculateScreenPosition(Vector3(start.x, start.y, end.z));
+	Vector3 tfr = view->calculateScreenPosition(Vector3(start.x, end.y, end.z));
+	Vector3 tbr = view->calculateScreenPosition(Vector3(end.x, end.y, end.z));
+	Vector3 tbl = view->calculateScreenPosition(Vector3(end.x, start.y, end.z));
 
 	surface->drawLine(bfl.x, bfl.y, bfr.x, bfr.y, color);
 	surface->drawLine(bfr.x, bfr.y, bbr.x, bbr.y, color);
@@ -599,7 +599,8 @@ void BladeRunnerEngine::gameTick() {
 				}
 			}
 
-			// TODO: Draw items
+			_items->tick();
+			
 			// TODO: Draw item pickup
 			// TODO: Draw dialogue menu
 
@@ -664,8 +665,8 @@ void BladeRunnerEngine::gameTick() {
 				Walkbox *walkbox = &_scene->_set->_walkboxes[i];
 				
 				for(int j = 0; j < walkbox->_vertexCount; j++) {
-					Vector2 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
-					Vector2 end = _view->calculateScreenPosition(walkbox->_vertices[(j+1) % walkbox->_vertexCount]);
+					Vector3 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
+					Vector3 end = _view->calculateScreenPosition(walkbox->_vertices[(j+1) % walkbox->_vertexCount]);
 					//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
 					_surface2.drawLine(start.x, start.y, end.x, end.y, 0b111111111100000);
 				}
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index d736678..7c2e74d 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -28,7 +28,6 @@
 #include "common/array.h"
 #include "common/random.h"
 #include "common/stream.h"
-#include "common/types.h"
 
 #include "engines/engine.h"
 
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index 7017997..74ddf1a 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -1,11 +1,38 @@
 #include "bladerunner/item.h"
 
+#include "bladerunner/bladerunner.h"
+//#include "bladerunner/slice_animations.h"
+#include "bladerunner/slice_renderer.h"
+
 namespace BladeRunner {
 
-Item::Item() {
-	_animationId = -1;
+Item::Item(BladeRunnerEngine *vm) {
+	_vm = vm;
+
 	_itemId = -1;
 	_setId = -1;
+
+	_animationId = -1;
+	_position.x = 0;
+	_position.y = 0;
+	_position.z = 0;
+	_facing = 0;
+	_angle = 0.0f;
+	_width = 0;
+	_height = 0;
+	_boundingBox.setXYZ(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
+	_screenX = 0;
+	_screenY = 0;
+	_depth = 0.0f;
+	_isTargetable = false;
+	_isSpinning = false;
+	_facingChange = 0;
+	_isVisible = true;
+	_isPoliceMazeEnemy = true;
+	_screenRectangle.bottom = -1;
+	_screenRectangle.right = -1;
+	_screenRectangle.top = -1;
+	_screenRectangle.left = -1;
 }
 
 Item::~Item() {
@@ -17,4 +44,71 @@ void Item::getXYZ(float *x, float *y, float *z) {
 	*z = _position.z;
 }
 
+bool Item::isTargetable() {
+	return _isTargetable;
+}
+
+void Item::tick(bool special) {
+	if (_isVisible) {
+		Vector3 postition(_position.x, -_position.z, _position.y);
+		int animationId = _animationId + (special ? 1 : 0);
+		_vm->_sliceRenderer->drawFrame(animationId, 0, postition, M_PI - _angle, 1.0f, _vm->_surface2, _vm->_zBuffer2);
+		//todo udpate screenrect
+		if (_isSpinning) {
+			_facing += _facingChange;
+
+			if (_facing >= 1024) {
+				_facing -= 1024;
+			} else if (_facing < 0) {
+				_facing += 1024;
+			}
+			_angle = M_PI / 512.0f * _facing;
+
+			if (_facingChange > 0) {
+				_facingChange = _facingChange - 20;
+				if (_facingChange < 0) {
+					_facingChange = 0;
+					_isSpinning = false;
+				}
+			} else if (_facingChange < 0) {
+				_facingChange = _facingChange + 20;
+				if (_facingChange > 0) {
+					_facingChange = 0;
+					_isSpinning = false;
+				}
+			} else {
+				_isSpinning = false;
+			}
+		}
+	}
+}
+
+void Item::setXYZ(Vector3 position) {
+	_position = position;
+	int halfWidth = _width / 2;
+	_boundingBox.setXYZ(_position.x - halfWidth, _position.y,           _position.z - halfWidth,
+	                    _position.x + halfWidth, _position.y + _height, _position.z + halfWidth);
+	Vector3 screenPosition = _vm->_view->calculateScreenPosition(_position);
+	_screenX = screenPosition.x;
+	_screenY = screenPosition.y;
+	_depth = screenPosition.z * 25.5f;
+}
+
+void Item::init(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy) {
+	_itemId = itemId;
+	_setId = setId;
+	_animationId = animationId;
+	_facing = facing;
+	_angle = M_PI / 512.0f * facing;
+	_width = width;
+	_height = height;
+	_isTargetable = isTargetable;
+	_isVisible = isVisible;
+	_isPoliceMazeEnemy = isPoliceMazeEnemy;
+	setXYZ(position);
+	_screenRectangle.bottom = -1;
+	_screenRectangle.right = -1;
+	_screenRectangle.top = -1;
+	_screenRectangle.left = -1;
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index 5bb8e54..95500c3 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -23,44 +23,52 @@
 #ifndef BLADERUNNER_ITEM_H
 #define BLADERUNNER_ITEM_H
 
-#include "bladerunner/bladerunner.h"
 #include "bladerunner/boundingbox.h"
+#include "bladerunner/vector.h"
 
-#include "common/array.h"
 #include "common/rect.h"
 
 namespace BladeRunner {
-	class Items;
 
-	class Item {
-		friend class Items;
-	private:
-		int          _itemId;
-		int          _setId;
+class BladeRunnerEngine;
+class Items;
 
-		BoundingBox  _boundingBox;
-		Common::Rect _screenRectangle;
-		int          _animationId;
-		Vector3      _position;
-		int          _facing;
-		float        _angle;
-		int          _width;
-		int          _height;
-		//int field_1C8;
-		int          _target;
-		//float field_1D0;
-		int          _targetable;
-		int          _spinning;
-		int          _angleChange;
-		float        _cameraAngle;
-		int          _obstacle;
-		//int field_1E8;
-	public:
-		Item();
-		~Item();
+class Item {
+	BladeRunnerEngine *_vm;
 
-		void getXYZ(float *x, float *y, float *z);
-	};
+	friend class Items;
+
+private:
+	int          _itemId;
+	int          _setId;
+
+	BoundingBox  _boundingBox;
+	Common::Rect _screenRectangle;
+	int          _animationId;
+	Vector3      _position;
+	int          _facing;
+	float        _angle;
+	int          _width;
+	int          _height;
+	int          _screenX;
+	int          _screenY;
+	float        _depth;
+	bool         _isTargetable;
+	bool         _isSpinning;
+	int          _facingChange;
+	bool         _isVisible;
+	bool         _isPoliceMazeEnemy;
+
+public:
+	Item(BladeRunnerEngine* vm);
+	~Item();
+
+	void getXYZ(float *x, float *y, float *z);
+	bool isTargetable();
+	void tick(bool special);
+	void setXYZ(Vector3 position);
+	void init(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy);
+};
 
 }
 
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index da3e74c..46ea9e8 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -1,5 +1,8 @@
 #include "bladerunner/items.h"
 
+#include "bladerunner/scene.h"
+#include "bladerunner/scene_objects.h"
+
 namespace BladeRunner {
 
 Items::Items(BladeRunnerEngine *vm) {
@@ -7,18 +10,51 @@ Items::Items(BladeRunnerEngine *vm) {
 }
 
 Items::~Items() {
+	for(int i = _items.size() -1; i >= 0; i--) {
+		delete _items.remove_at(i);
+	}
 }
 
 void Items::getXYZ(int itemId, float* x, float* y, float* z) {
 	int itemIndex = findItem(itemId);
 	assert(itemIndex != -1);
 
-	_items[itemIndex].getXYZ(x, y, z);
+	_items[itemIndex]->getXYZ(x, y, z);
+}
+
+void Items::tick() {
+	int setId = _vm->_scene->getSetId();
+	for(int i = 0; i < (int)_items.size(); i++) {
+		if(_items[i]->_setId != setId) {
+			continue;
+		}
+		bool set14NotTarget = setId == 14 && !_items[i]->isTargetable();
+		_items[i]->tick(set14NotTarget);
+	}
+}
+
+bool Items::add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool addToSet) {
+	if (_items.size() >= 100) {
+		return false;
+	}
+	int i = findItem(itemId);
+	if(i == -1) {
+		i = _items.size();
+	}
+
+	Item *item = new Item(_vm);
+	item->init(itemId, setId, animationId, position, facing, height, width, isTargetable, isVisible, isPoliceMazeEnemy);
+	_items.push_back(item);
+
+	if(addToSet && setId == _vm->_scene->getSetId()) {
+		return _vm->_sceneObjects->addItem(itemId + SCENE_OBJECTS_ITEMS_OFFSET, &item->_boundingBox, &item->_screenRectangle, isTargetable, isVisible);
+	}
+	return true;
 }
 
 int Items::findItem(int itemId) {
 	for (int i = 0; i < (int)_items.size(); i++) {
-		if (_items[i]._itemId == itemId)
+		if (_items[i]->_itemId == itemId)
 			return i;
 	}
 	return -1;
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index 08d2a2b..aa6f41f 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -27,22 +27,21 @@
 #include "bladerunner/item.h"
 
 #include "common/array.h"
-#include "common/rect.h"
 
 namespace BladeRunner {
 
 class Items {
 	BladeRunnerEngine *_vm;
 
-private:
-	Common::Array<Item> _items;
+	Common::Array<Item*> _items;
 
 public:
 	Items(BladeRunnerEngine *vm);
 	~Items();
 
 	void getXYZ(int itemId, float *x, float *y, float *z);
-
+	void tick();
+	bool add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool b);
 private:
 	int findItem(int itemId);
 };
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index dd6e293..2b944f4 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -46,6 +46,7 @@
 
 #include "bladerunner/script/ai_00_mccoy.h"
 #include "bladerunner/script/aiscript_officer_leroy.h"
+#include "bladerunner/items.h"
 
 namespace BladeRunner {
 
@@ -631,9 +632,8 @@ void ScriptBase::Actor_Set_Immunity_To_Obstacles(int actorId, bool isImmune) {
 	_vm->_actors[actorId]->setImmunityToObstacles(isImmune);
 }
 
-void ScriptBase::Item_Add_To_World(int itemId, int animationId, int sceneIndex, float x, float y, float z, signed int angle, int height, int width, bool isTargetable, bool isObstacle, bool isPoliceMazeEnemy, bool updateOnly) {
-	//TODO
-	warning("Item_Add_To_World(%d, %d, %d, %f, %f, %f, %d, %d, %d, %d, %d, %d, %d)", itemId, animationId, sceneIndex, x, y, z, angle, height, width, isTargetable, isObstacle, isPoliceMazeEnemy, updateOnly);
+void ScriptBase::Item_Add_To_World(int itemId, int animationId, int setId, float x, float y, float z, signed int facing, int height, int width, bool isTargetable, bool isObstacle, bool isPoliceMazeEnemy, bool updateOnly) {
+	_vm->_items->add(itemId, animationId, setId, Vector3(x, y, z), facing, height, width, isTargetable, isObstacle, isPoliceMazeEnemy, updateOnly == 0);
 }
 
 void ScriptBase::Item_Remove_From_World(int itemId) {
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 0ab9efa..222cd4c 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -119,7 +119,7 @@ protected:
 	void Actor_Clues_Transfer_New_From_Mainframe(int actorId);
 	void Actor_Set_Invisible(int actorId, bool isInvisible);
 	void Actor_Set_Immunity_To_Obstacles(int actorId, bool isImmune);
-	void Item_Add_To_World(int itemId, int animationId, int sceneIndex, float x, float y, float z, signed int angle, int height, int width, bool isTargetable, bool isObstacle, bool isPoliceMazeEnemy, bool updateOnly);
+	void Item_Add_To_World(int itemId, int animationId, int setId, float x, float y, float z, signed int facing, int height, int width, bool isTargetable, bool isObstacle, bool isPoliceMazeEnemy, bool updateOnly);
 	void Item_Remove_From_World(int itemId);
 	void Item_Spin_In_World(int itemId);
 	void Item_Flag_As_Target(int itemId);
diff --git a/engines/bladerunner/view.cpp b/engines/bladerunner/view.cpp
index b01273f..ab9eb3e 100644
--- a/engines/bladerunner/view.cpp
+++ b/engines/bladerunner/view.cpp
@@ -76,11 +76,12 @@ void View::calculateCameraPosition() {
 	_cameraPosition.z = invertedMatrix(2, 3);
 }
 
-Vector2 View::calculateScreenPosition(Vector3 worldPosition) {
+Vector3 View::calculateScreenPosition(Vector3 worldPosition) {
 	Vector3 viewPosition = _frameViewMatrix * worldPosition;
-	return Vector2(
+	return Vector3(
 		this->_viewportHalfWidth - viewPosition.x / viewPosition.z * _viewportDistance,
-		this->_viewportHalfHeight - viewPosition.y / viewPosition.z * _viewportDistance
+		this->_viewportHalfHeight - viewPosition.y / viewPosition.z * _viewportDistance,
+		viewPosition.z
 	);
 }
 
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
index 2ffb4a9..bb92dc1 100644
--- a/engines/bladerunner/view.h
+++ b/engines/bladerunner/view.h
@@ -45,7 +45,7 @@ public:
 	float     _viewportDistance;
 
 	bool read(Common::ReadStream *stream);
-	Vector2 calculateScreenPosition(Vector3 worldPosition);
+	Vector3 calculateScreenPosition(Vector3 worldPosition);
 
 private:
 	void setFovX(float fovX);


Commit: 89d1805b37a6283d90a7dd5b4dbbdffd7950f5ab
    https://github.com/scummvm/scummvm/commit/89d1805b37a6283d90a7dd5b4dbbdffd7950f5ab
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-02T02:47:12+02:00

Commit Message:
BLADERUNNER: added ADQ, fixed some minor memory leaks

Changed paths:
  A engines/bladerunner/adq.cpp
  A engines/bladerunner/adq.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/items.cpp
    engines/bladerunner/items.h
    engines/bladerunner/module.mk
    engines/bladerunner/scene.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/adq.cpp b/engines/bladerunner/adq.cpp
new file mode 100644
index 0000000..7e77d64
--- /dev/null
+++ b/engines/bladerunner/adq.cpp
@@ -0,0 +1,151 @@
+#include "bladerunner/adq.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/actor.h"
+#include "bladerunner/audio_speech.h"
+#include "bladerunner/scene.h"
+
+#include "script/script.h"
+
+namespace BladeRunner {
+
+ADQ::ADQEntry::ADQEntry() {
+	this->_isNotPause = false;
+	this->_isPause = false;
+	this->_actorId = -1;
+	this->_delay = -1;
+	this->_sentenceId = -1;
+	this->_animationMode = -1;
+}
+
+ADQ::ADQ(BladeRunnerEngine *vm) {
+	_vm = vm;
+	clear();
+}
+
+ADQ::~ADQ() {
+}
+
+void ADQ::add(int actorId, int sentenceId, int animationMode) {
+	if (actorId == 0 || actorId == 99) {
+		animationMode = -1;
+	}
+	if (_entries.size() < 25) {
+		ADQEntry entry;
+		entry._isNotPause = true;
+		entry._isPause = false;
+		entry._actorId = actorId;
+		entry._sentenceId = sentenceId;
+		entry._animationMode = animationMode;
+		entry._delay = -1;
+
+		_entries.push_back(entry);
+	}
+}
+
+void ADQ::addPause(int delay) {
+	if (_entries.size() < 25) {
+		ADQEntry entry;
+		entry._isNotPause = false;
+		entry._isPause = true;
+		entry._actorId = -1;
+		entry._sentenceId = -1;
+		entry._animationMode = -1;
+		entry._delay = delay;
+
+		_entries.push_back(entry);
+	}
+}
+
+void ADQ::flush(int a1, bool callScript) {
+	if (_isNotPause && _vm->_audioSpeech->isPlaying()) {
+		_vm->_audioSpeech->stopSpeech();
+		if (_animationModePrevious >= 0) {
+			_vm->_actors[_actorId]->changeAnimationMode(_animationModePrevious, false);
+			_animationModePrevious = -1;
+		}
+		_isNotPause = false;
+		_actorId = -1;
+		_sentenceId = -1;
+		_animationMode = -1;
+	}
+	if (_isPause) {
+		_isPause = false;
+		_delay = 0;
+		_timeLast = 0;
+	}
+	clear();
+	if (callScript) {
+		_vm->_script->DialogueQueueFlushed(a1);
+	}
+}
+
+void ADQ::tick() {
+	if (!_vm->_audioSpeech->isPlaying()) {
+		if (_isPause) {
+			int time = _vm->getTotalPlayTime();
+			int timeDiff = time - _timeLast;
+			_timeLast = time;
+			_delay -= timeDiff;
+			if (_delay > 0) {
+				return;
+			}
+			_isPause = false;
+			_delay = 0;
+			_timeLast = 0;
+			if (_entries.empty()) {
+				flush(0, true);
+			}
+		}
+		if (_isNotPause) {
+			if (_animationModePrevious >= 0) {
+				_vm->_actors[_actorId]->changeAnimationMode(_animationModePrevious, false);
+				_animationModePrevious = -1;
+			}
+			_isNotPause = false;
+			_actorId = -1;
+			_sentenceId = -1;
+			_animationMode = -1;
+			if (_entries.empty()) {
+				flush(0, true);
+			}
+		}
+		if (!_entries.empty()) {
+			ADQEntry firstEntry = _entries.remove_at(0);
+			if (firstEntry._isNotPause) {
+				_animationMode = firstEntry._animationMode;
+				if (_vm->_actors[firstEntry._actorId]->getSetId() != _vm->_scene->getSetId()) {
+					_animationMode = -1;
+				}
+				_vm->_actors[firstEntry._actorId]->speechPlay(firstEntry._sentenceId, false);
+				_isNotPause = true;
+				_actorId = firstEntry._actorId;
+				_sentenceId = firstEntry._sentenceId;
+				if (_animationMode >= 0) {
+					_animationModePrevious = _vm->_actors[firstEntry._actorId]->getAnimationMode();
+					_vm->_actors[firstEntry._actorId]->changeAnimationMode(_animationMode, false);
+				} else {
+					_animationModePrevious = -1;
+				}
+			} else if (firstEntry._isPause) {
+				_isPause = true;
+				_delay = firstEntry._delay;
+				_timeLast = _vm->getTotalPlayTime();
+			}
+		}
+	}
+}
+
+void ADQ::clear() {
+	_entries.clear();
+	_isNotPause = false;
+	_actorId = -1;
+	_sentenceId = -1;
+	_animationMode = -1;
+	_animationModePrevious = -1;
+	_isPause = false;
+	_delay = 0;
+	_timeLast = 0;
+}
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/adq.h b/engines/bladerunner/adq.h
new file mode 100644
index 0000000..20a4c19
--- /dev/null
+++ b/engines/bladerunner/adq.h
@@ -0,0 +1,74 @@
+/* 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 BLADERUNNER_ADQ_H
+#define BLADERUNNER_ADQ_H
+#include "common/array.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+// actor dialogue queue??
+class ADQ { 
+	BladeRunnerEngine *_vm;
+
+	class ADQEntry {
+	public:
+		bool _isNotPause;
+		bool _isPause;
+		int _actorId;
+		int _sentenceId;
+		int _animationMode;
+		int _delay;
+
+		ADQEntry();
+	};
+
+	Common::Array<ADQEntry> _entries;
+
+	bool     _isNotPause;
+	int      _actorId;
+	int      _sentenceId;
+	int      _animationMode;
+	int      _animationModePrevious;
+	bool     _isPause;
+	int      _delay;
+	int      _timeLast;
+
+
+public:
+	ADQ(BladeRunnerEngine *vm);
+	~ADQ();
+
+	void add(int actorId, int speechId, int animationMode);
+	void addPause(int delay);
+	void flush(int a1, bool callScript);
+	void tick();
+
+private:
+	void clear();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 663d17d..5320f99 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -24,6 +24,7 @@
 #include "bladerunner/bladerunner.h"
 
 #include "bladerunner/actor.h"
+#include "bladerunner/adq.h"
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/audio_speech.h"
@@ -68,11 +69,12 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_gameIsRunning  = true;
 	_playerLosesControlCounter = 0;
 
-	_clues = NULL;
+	_clues = nullptr;
 	_script = new Script(this);
 	_settings = new Settings(this);
 	_lights = new Lights(this);
 	_combat = new Combat(this);
+	_adq = new ADQ(this);
 
 	_walkSoundId = -1;
 	_walkSoundVolume = 0;
@@ -99,7 +101,10 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
-
+	
+	delete _adq;
+	delete _combat;
+	delete _lights;
 	delete _settings;
 	delete _script;
 }
@@ -345,7 +350,7 @@ void BladeRunnerEngine::shutdown() {
 	// TODO: Shutdown Esper
 
 	delete _mouse;
-	_mouse = 0;
+	_mouse = nullptr;
 
 	for (uint i = 0; i != _shapes.size(); ++i) {
 		delete _shapes[i];
@@ -359,38 +364,38 @@ void BladeRunnerEngine::shutdown() {
 		if (_chapters->hasOpenResources())
 			_chapters->closeResources();
 		delete _chapters;
-		_chapters = 0;
+		_chapters = nullptr;
 	}
 
 	delete _clues;
-	_clues = 0;
+	_clues = nullptr;
 
 	delete _sliceRenderer;
-	_sliceRenderer = 0;
+	_sliceRenderer = nullptr;
 
 	delete _sliceAnimations;
-	_sliceAnimations = 0;
+	_sliceAnimations = nullptr;
 
 	delete _textActorNames;
-	_textActorNames = 0;
+	_textActorNames = nullptr;
 
 	delete _textCrimes;
-	_textCrimes = 0;
+	_textCrimes = nullptr;
 
 	delete _textCluetype;
-	_textCluetype = 0;
+	_textCluetype = nullptr;
 
 	delete _textKIA;
-	_textKIA = 0;
+	_textKIA = nullptr;
 
 	delete _textSpindest;
-	_textSpindest = 0;
+	_textSpindest = nullptr;
 
 	delete _textVK;
-	_textVK = 0;
+	_textVK = nullptr;
 
 	delete _textOptions;
-	_textOptions = 0;
+	_textOptions = nullptr;
 
 	// TODO: Delete dialogue menu
 
@@ -418,26 +423,26 @@ void BladeRunnerEngine::shutdown() {
 	// TODO: Delete KIA6PT.FON
 
 	delete _items;
-	_items = 0;
+	_items = nullptr;
 
 	delete _gameFlags;
-	_gameFlags = 0;
+	_gameFlags = nullptr;
 
 	delete _view;
-	_view = 0;
+	_view = nullptr;
 
 	delete _sceneObjects;
-	_sceneObjects = 0;
+	_sceneObjects = nullptr;
 
 	// TODO: Delete sine and cosine lookup tables
 
 	// TODO: Unload AI dll
 
 	delete[] _gameVars;
-	_gameVars = 0;
+	_gameVars = nullptr;
 
 	delete _waypoints;
-	_waypoints = 0;
+	_waypoints = nullptr;
 
 	// TODO: Delete Cover waypoints
 
@@ -459,13 +464,13 @@ void BladeRunnerEngine::shutdown() {
 
 	// TODO: Delete proper ZBuf class
 	delete[] _zBuffer1;
-	_zBuffer1 = 0;
+	_zBuffer1 = nullptr;
 
 	delete[] _zBuffer2;
-	_zBuffer2 = 0;
+	_zBuffer2 = nullptr;
 
 	delete _gameInfo;
-	_gameInfo = 0;
+	_gameInfo = nullptr;
 
 	// TODO: Delete graphics surfaces here
 	_surface1.free();
@@ -548,7 +553,8 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: VK
 		// TODO: Elevators
 		// TODO: Scores
-
+		
+		_adq->tick();
 		if (_scene->didPlayerWalkIn()) {
 			_script->PlayerWalkedIn();
 		}
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 7c2e74d..273449f 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -36,6 +36,7 @@
 namespace BladeRunner {
 
 class Actor;
+class ADQ;
 class AIScripts;
 class AmbientSounds;
 class AudioPlayer;
@@ -65,6 +66,7 @@ public:
 	bool      _windowIsActive;
 	int       _playerLosesControlCounter;
 
+	ADQ             *_adq;
 	AIScripts       *_aiScripts;
 	AmbientSounds   *_ambientSounds;
 	AudioPlayer     *_audioPlayer;
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index 74ddf1a..f59d6da 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -1,7 +1,7 @@
 #include "bladerunner/item.h"
 
 #include "bladerunner/bladerunner.h"
-//#include "bladerunner/slice_animations.h"
+
 #include "bladerunner/slice_renderer.h"
 
 namespace BladeRunner {
@@ -94,7 +94,7 @@ void Item::setXYZ(Vector3 position) {
 	_depth = screenPosition.z * 25.5f;
 }
 
-void Item::init(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy) {
+void Item::setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy) {
 	_itemId = itemId;
 	_setId = setId;
 	_animationId = animationId;
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index 95500c3..bdcaea7 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -67,7 +67,7 @@ public:
 	bool isTargetable();
 	void tick(bool special);
 	void setXYZ(Vector3 position);
-	void init(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy);
+	void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy);
 };
 
 }
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 46ea9e8..64d8bef 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -37,13 +37,13 @@ bool Items::add(int itemId, int animationId, int setId, Vector3 position, int fa
 	if (_items.size() >= 100) {
 		return false;
 	}
-	int i = findItem(itemId);
-	if(i == -1) {
-		i = _items.size();
+	int itemIndex = findItem(itemId);
+	if(itemIndex == -1) {
+		itemIndex = _items.size();
 	}
 
 	Item *item = new Item(_vm);
-	item->init(itemId, setId, animationId, position, facing, height, width, isTargetable, isVisible, isPoliceMazeEnemy);
+	item->setup(itemId, setId, animationId, position, facing, height, width, isTargetable, isVisible, isPoliceMazeEnemy);
 	_items.push_back(item);
 
 	if(addToSet && setId == _vm->_scene->getSetId()) {
@@ -52,6 +52,22 @@ bool Items::add(int itemId, int animationId, int setId, Vector3 position, int fa
 	return true;
 }
 
+bool Items::remove(int itemId) {
+	if (_items.size() == 0) {
+		return false;
+	}
+	int itemIndex = findItem(itemId);
+	if(itemIndex == -1) {
+		return false;
+	}
+
+	if (_items[itemIndex]->_setId == _vm->_scene->getSetId()) {
+		_vm->_sceneObjects->remove(itemId + SCENE_OBJECTS_ITEMS_OFFSET);
+	}
+	_items.remove_at(itemIndex);
+	return true;
+}
+
 int Items::findItem(int itemId) {
 	for (int i = 0; i < (int)_items.size(); i++) {
 		if (_items[i]->_itemId == itemId)
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index aa6f41f..e6e1cb2 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -42,6 +42,7 @@ public:
 	void getXYZ(int itemId, float *x, float *y, float *z);
 	void tick();
 	bool add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool b);
+	bool remove(int itemId);
 private:
 	int findItem(int itemId);
 };
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 60bea4a..3867331 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -1,6 +1,7 @@
 MODULE := engines/bladerunner
 
 MODULE_OBJS = \
+	adq.o \
 	actor.o \
 	actor_clues.o \
 	actor_combat.o \
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 0ced4d8..06563b7 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -25,6 +25,7 @@
 #include "bladerunner/bladerunner.h"
 
 #include "bladerunner/actor.h"
+#include "bladerunner/adq.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/scene_objects.h"
@@ -37,7 +38,7 @@ namespace BladeRunner {
 
 bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 	if (!isLoadingGame) {
-		// flush ADQ
+		_vm->_adq->flush(1, false);
 	}
 
 	_setId = setId;
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 2b944f4..9f4f539 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -26,6 +26,7 @@
 
 #include "bladerunner/actor.h"
 #include "bladerunner/actor_combat.h"
+#include "bladerunner/adq.h"
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/audio_speech.h"
@@ -351,14 +352,14 @@ void ScriptBase::Actor_Set_Targetable(int actorId, bool targetable) {
 
 void ScriptBase::Actor_Says(int actorId, int sentenceId, int animationMode){
 	_vm->loopActorSpeaking();
-	//_vm->ADQ->flush(1,1)
+	_vm->_adq->flush(1, true);
 	Actor_Says_With_Pause(actorId, sentenceId, 0.5f, animationMode);
 }
 
 void ScriptBase::Actor_Says_With_Pause(int actorId, int sentenceId, float pause, int animationMode) {
 	_vm->gameWaitForActive();
 	_vm->loopActorSpeaking();
-	//_vm->ADQ->flush(1,1)
+	_vm->_adq->flush(1, true);
 
 	Actor *actor = _vm->_actors[actorId];
 
@@ -432,8 +433,8 @@ void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
 void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
 	_vm->gameWaitForActive();
 	_vm->loopActorSpeaking();
-	//_vm->ADQ->flush(1,1)
-
+	_vm->_adq->flush(1, true);
+	
 	Actor *actor = _vm->_actors[actorId];
 
 	actor->speechPlay(sentenceId, true);
@@ -637,8 +638,7 @@ void ScriptBase::Item_Add_To_World(int itemId, int animationId, int setId, float
 }
 
 void ScriptBase::Item_Remove_From_World(int itemId) {
-	//TODO
-	warning("Item_Remove_From_World(%d)", itemId);
+	_vm->_items->remove(itemId);
 }
 
 void ScriptBase::Item_Spin_In_World(int itemId) {
@@ -930,6 +930,8 @@ int ScriptBase::Ambient_Sounds_Play_Sound(int a1, int a2, int a3, int a4, int a5
 // ScriptBase::Ambient_Sounds_Play_Speech_Sound
 
 void ScriptBase::Ambient_Sounds_Remove_All_Non_Looping_Sounds(int time) {
+	//TODO
+	warning("Ambient_Sounds_Remove_All_Non_Looping_Sounds(%d)", time);
 	// _vm->_ambientSounds->removeAllNonLoopingSounds(time);
 }
 
@@ -948,6 +950,8 @@ void ScriptBase::Ambient_Sounds_Remove_Looping_Sound(int id, bool a2){
 }
 
 void ScriptBase::Ambient_Sounds_Remove_All_Looping_Sounds(int time) {
+	//TODO
+	warning("Ambient_Sounds_Remove_All_Looping_Sounds(%d)", time);
 	// _vm->_ambientSounds->removeAllLoopingSounds(time);
 }
 
@@ -1289,18 +1293,15 @@ void ScriptBase::Set_Fog_Density(const char* fogName, float density) {
 }
 
 void ScriptBase::ADQ_Flush() {
-	//TODO
-	warning("ADQ_Flush()");
+	_vm->_adq->flush(0, true);
 }
 
-void ScriptBase::ADQ_Add(int a1, int a2, int a3) {
-	//TODO
-	warning("ADQ_Add(%d, %d, %d)", a1, a2, a3);
+void ScriptBase::ADQ_Add(int actorId, int sentenceId, int animationMode) {
+	_vm->_adq->add(actorId, sentenceId, animationMode);
 }
 
 void ScriptBase::ADQ_Add_Pause(int delay) {
-	//TODO
-	warning("ADQ_Add_Pause(%d)", delay);
+	_vm->_adq->addPause(delay);
 }
 
 bool ScriptBase::Game_Over() {
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 222cd4c..914462a 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -253,7 +253,7 @@ protected:
 	void Set_Fog_Color(const char* fogName, float r, float g, float b);
 	void Set_Fog_Density(const char* fogName, float density);
 	void ADQ_Flush();
-	void ADQ_Add(int a1, int a2, int a3);
+	void ADQ_Add(int actorId, int sentenceId, int animationMode);
 	void ADQ_Add_Pause(int delay);
 	bool Game_Over();
 	void Autosave_Game(int textId);


Commit: 77be430824ad0cafb0de9952ecb352ba4ad18571
    https://github.com/scummvm/scummvm/commit/77be430824ad0cafb0de9952ecb352ba4ad18571
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-03T11:24:13+02:00

Commit Message:
BLADERUNNER: Added missing copyright headers and normalized the rest

Changed paths:
    engines/bladerunner/actor_clues.cpp
    engines/bladerunner/actor_combat.cpp
    engines/bladerunner/actor_walk.h
    engines/bladerunner/adq.cpp
    engines/bladerunner/adq.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/combat.cpp
    engines/bladerunner/combat.h
    engines/bladerunner/fog.cpp
    engines/bladerunner/item.cpp
    engines/bladerunner/items.cpp
    engines/bladerunner/light.cpp
    engines/bladerunner/light.h
    engines/bladerunner/lights.cpp
    engines/bladerunner/lights.h
    engines/bladerunner/movement_track.cpp
    engines/bladerunner/movement_track.h
    engines/bladerunner/regions.cpp
    engines/bladerunner/regions.h
    engines/bladerunner/scene_objects.h
    engines/bladerunner/set_effects.cpp
    engines/bladerunner/waypoints.cpp
    engines/bladerunner/waypoints.h



diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
index 2f02ddf..c876829 100644
--- a/engines/bladerunner/actor_clues.cpp
+++ b/engines/bladerunner/actor_clues.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/actor_clues.h"
 
 #include "bladerunner/clues.h"
diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp
index aac9086..09d89df 100644
--- a/engines/bladerunner/actor_combat.cpp
+++ b/engines/bladerunner/actor_combat.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/actor_combat.h"
 
 namespace BladeRunner {
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index 8b343bb..3e03c79 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_ACTOR_WALK_H
 #define BLADERUNNER_ACTOR_WALK_H
diff --git a/engines/bladerunner/adq.cpp b/engines/bladerunner/adq.cpp
index 7e77d64..b8611ee 100644
--- a/engines/bladerunner/adq.cpp
+++ b/engines/bladerunner/adq.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/adq.h"
 
 #include "bladerunner/bladerunner.h"
diff --git a/engines/bladerunner/adq.h b/engines/bladerunner/adq.h
index 20a4c19..b0619c7 100644
--- a/engines/bladerunner/adq.h
+++ b/engines/bladerunner/adq.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_ADQ_H
 #define BLADERUNNER_ADQ_H
@@ -29,7 +29,7 @@ namespace BladeRunner {
 class BladeRunnerEngine;
 
 // actor dialogue queue??
-class ADQ { 
+class ADQ {
 	BladeRunnerEngine *_vm;
 
 	class ADQEntry {
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 5320f99..6b97a0b 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -1,4 +1,3 @@
-
 /* ScummVM - Graphic Adventure Engine
  *
  * ScummVM is the legal property of its developers, whose names
@@ -101,7 +100,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
-	
+
 	delete _adq;
 	delete _combat;
 	delete _lights;
@@ -553,7 +552,7 @@ void BladeRunnerEngine::gameTick() {
 		// TODO: VK
 		// TODO: Elevators
 		// TODO: Scores
-		
+
 		_adq->tick();
 		if (_scene->didPlayerWalkIn()) {
 			_script->PlayerWalkedIn();
@@ -606,7 +605,7 @@ void BladeRunnerEngine::gameTick() {
 			}
 
 			_items->tick();
-			
+
 			// TODO: Draw item pickup
 			// TODO: Draw dialogue menu
 
@@ -653,7 +652,7 @@ void BladeRunnerEngine::gameTick() {
 					drawBBox(a, b, _view, &_surface2, color);
 				}
 			}
-			
+
 			//draw regions
 			for (int i = 0; i < 10; i++) {
 				Region* region  =  &_scene->_regions->_regions[i];
@@ -669,14 +668,14 @@ void BladeRunnerEngine::gameTick() {
 
 			for (int i = 0; i < _scene->_set->_walkboxCount; i++) {
 				Walkbox *walkbox = &_scene->_set->_walkboxes[i];
-				
+
 				for(int j = 0; j < walkbox->_vertexCount; j++) {
 					Vector3 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
 					Vector3 end = _view->calculateScreenPosition(walkbox->_vertices[(j+1) % walkbox->_vertexCount]);
 					//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
 					_surface2.drawLine(start.x, start.y, end.x, end.y, 0b111111111100000);
 				}
-				
+
 			}
 
 			for (int i = 0; i < (int)_lights->_lights.size(); i++) {
@@ -788,7 +787,7 @@ void BladeRunnerEngine::handleMouseClickItem(int x, int y, int itemId)
 }
 
 void BladeRunnerEngine::handleMouseClickActor(int x, int y, int actorId)
-{	
+{
 	debug("Clicked on actor %d", actorId);
 	_script->ClickedOnActor(actorId);
 }
diff --git a/engines/bladerunner/combat.cpp b/engines/bladerunner/combat.cpp
index 1f61d7b..7564faa 100644
--- a/engines/bladerunner/combat.cpp
+++ b/engines/bladerunner/combat.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/combat.h"
 
 #include "bladerunner/bladerunner.h"
diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h
index 79de69d..f5deec5 100644
--- a/engines/bladerunner/combat.h
+++ b/engines/bladerunner/combat.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_COMBAT_H
 #define BLADERUNNER_COMBAT_H
diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
index bca548c..b51ec10 100644
--- a/engines/bladerunner/fog.cpp
+++ b/engines/bladerunner/fog.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/fog.h"
 
 #include "common/stream.h"
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index f59d6da..fd5c3e5 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/item.h"
 
 #include "bladerunner/bladerunner.h"
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 64d8bef..e9cb013 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/items.h"
 
 #include "bladerunner/scene.h"
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index 562936f..fbbf595 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/light.h"
 #include "common/util.h"
 #include "common/debug.h"
@@ -188,7 +210,7 @@ void Light1::calculateColor(Color *outColor, Vector3 position) {
 	if (positionT.z < 0.0f) {
 		float v12 = attenuation(_angleStart, _angleEnd, atan2(sqrt(positionT.x * positionT.x + positionT.y * positionT.y), -positionT.z));
 		float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
-	
+
 		outColor->r = v12 * v13 * _color.r;
 		outColor->g = v12 * v13 * _color.g;
 		outColor->b = v12 * v13 * _color.b;
@@ -268,7 +290,7 @@ void Light4::calculateColor(Color *outColor, Vector3 position) {
 		float v11 = attenuation(_angleStart, _angleEnd, fabs(positionT.y));
 		float v12 = attenuation(_angleStart, _angleEnd, fabs(positionT.x));
 		float v13 = attenuation(_falloffStart, _falloffEnd, positionT.length());
-		
+
 		outColor->r = v11 * v12 * v13 * _color.r;
 		outColor->g = v11 * v12 * v13 * _color.g;
 		outColor->b = v11 * v12 * v13 * _color.b;
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index 29e0dd7..cae5816 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_LIGHT_H
 #define BLADERUNNER_LIGHT_H
diff --git a/engines/bladerunner/lights.cpp b/engines/bladerunner/lights.cpp
index a996c28..811d72f 100644
--- a/engines/bladerunner/lights.cpp
+++ b/engines/bladerunner/lights.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/lights.h"
 
 namespace BladeRunner {
@@ -8,7 +30,7 @@ Lights::Lights(BladeRunnerEngine *vm) {
 	_ambientLightColor.r = 1.0;
 	_ambientLightColor.g = 0.0;
 	_ambientLightColor.b = 0.0;
-	
+
 	_lights.clear();
 	_frame = 0;
 }
@@ -87,7 +109,7 @@ void Lights::readVqa(Common::ReadStream *stream) {
 			break;
 		default:
 			light = new Light();
-		}		
+		}
 		light->readVqa(stream, framesCount, _frame, 1);
 		_lights.push_back(light);
 	}
diff --git a/engines/bladerunner/lights.h b/engines/bladerunner/lights.h
index ca2e77b..ed8edb5 100644
--- a/engines/bladerunner/lights.h
+++ b/engines/bladerunner/lights.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_LIGHTS_H
 #define BLADERUNNER_LIGHTS_H
@@ -54,7 +54,7 @@ public:
 	void reset();
 
 	void setupFrame(int frame);
-private: 
+private:
 	void removeAnimated();
 };
 
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
index 0913e77..b7d0adc 100644
--- a/engines/bladerunner/movement_track.cpp
+++ b/engines/bladerunner/movement_track.cpp
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 "bladerunner/movement_track.h"
 
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
index 30ac07e..976adc2 100644
--- a/engines/bladerunner/movement_track.h
+++ b/engines/bladerunner/movement_track.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_MOVEMENT_TRACK_H
 #define BLADERUNNER_MOVEMENT_TRACK_H
diff --git a/engines/bladerunner/regions.cpp b/engines/bladerunner/regions.cpp
index f75be0f..55a1aa1 100644
--- a/engines/bladerunner/regions.cpp
+++ b/engines/bladerunner/regions.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/regions.h"
 
 namespace BladeRunner {
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
index ebb2ef7..0b722c8 100644
--- a/engines/bladerunner/regions.h
+++ b/engines/bladerunner/regions.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_REGIONS_H
 #define BLADERUNNER_REGIONS_H
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index b7342d6..5f52d85 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_SCENE_OBJECTS_H
 #define BLADERUNNER_SCENE_OBJECTS_H
diff --git a/engines/bladerunner/set_effects.cpp b/engines/bladerunner/set_effects.cpp
index 318ad37..8954b6f 100644
--- a/engines/bladerunner/set_effects.cpp
+++ b/engines/bladerunner/set_effects.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/set_effects.h"
 
 namespace BladeRunner {
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
index 3229aaf..3530da7 100644
--- a/engines/bladerunner/waypoints.cpp
+++ b/engines/bladerunner/waypoints.cpp
@@ -1,3 +1,25 @@
+/* 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 "bladerunner/waypoints.h"
 namespace BladeRunner {
 
diff --git a/engines/bladerunner/waypoints.h b/engines/bladerunner/waypoints.h
index 6f58b63..c75cf00 100644
--- a/engines/bladerunner/waypoints.h
+++ b/engines/bladerunner/waypoints.h
@@ -1,24 +1,24 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_WAYPOINTS_H
 #define BLADERUNNER_WAYPOINTS_H


Commit: 281c19ab036f387a99192594aa645e696009f40b
    https://github.com/scummvm/scummvm/commit/281c19ab036f387a99192594aa645e696009f40b
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-03T12:38:43+02:00

Commit Message:
BLADERUNNER: Code formatting fixes

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/actor_clues.cpp
    engines/bladerunner/actor_clues.h
    engines/bladerunner/actor_combat.cpp
    engines/bladerunner/actor_combat.h
    engines/bladerunner/actor_walk.cpp
    engines/bladerunner/actor_walk.h
    engines/bladerunner/adpcm_decoder.cpp
    engines/bladerunner/adpcm_decoder.h
    engines/bladerunner/ambient_sounds.cpp
    engines/bladerunner/archive.cpp
    engines/bladerunner/aud_stream.cpp
    engines/bladerunner/audio_player.cpp
    engines/bladerunner/audio_player.h
    engines/bladerunner/audio_speech.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/boundingbox.h
    engines/bladerunner/chapters.h
    engines/bladerunner/clues.cpp
    engines/bladerunner/decompress_lcw.cpp
    engines/bladerunner/decompress_lzo.cpp
    engines/bladerunner/fog.h
    engines/bladerunner/gameflags.cpp
    engines/bladerunner/gameinfo.cpp
    engines/bladerunner/image.cpp
    engines/bladerunner/image.h
    engines/bladerunner/item.cpp
    engines/bladerunner/light.h
    engines/bladerunner/matrix.cpp
    engines/bladerunner/matrix.h
    engines/bladerunner/mouse.cpp
    engines/bladerunner/movement_track.cpp
    engines/bladerunner/movement_track.h
    engines/bladerunner/outtake.h
    engines/bladerunner/regions.h
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/aiscript_officer_leroy.cpp
    engines/bladerunner/script/ar02.cpp
    engines/bladerunner/script/bb03.cpp
    engines/bladerunner/script/bb04.cpp
    engines/bladerunner/script/bb05.cpp
    engines/bladerunner/script/bb06.cpp
    engines/bladerunner/script/bb07.cpp
    engines/bladerunner/script/bb08.cpp
    engines/bladerunner/script/ct03.cpp
    engines/bladerunner/script/dr06.cpp
    engines/bladerunner/script/hf02.cpp
    engines/bladerunner/script/init.h
    engines/bladerunner/script/ps15.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/script/ug03.cpp
    engines/bladerunner/script/ug15.cpp
    engines/bladerunner/script/ug18.cpp
    engines/bladerunner/set_effects.h
    engines/bladerunner/settings.cpp
    engines/bladerunner/shape.cpp
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h
    engines/bladerunner/text_resource.cpp
    engines/bladerunner/vector.h
    engines/bladerunner/view.h
    engines/bladerunner/vqa_decoder.cpp
    engines/bladerunner/vqa_decoder.h
    engines/bladerunner/vqa_player.cpp
    engines/bladerunner/vqa_player.h
    engines/bladerunner/waypoints.cpp



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index ba0beda..1ea2b17 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -402,7 +402,7 @@ void Actor::draw() {
 	float draw_scale  = _scale;
 
 	// TODO: Handle SHORTY mode
-	
+
 	_vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, draw_position, draw_facing, draw_scale, _vm->_surface2, _vm->_zBuffer2);
 	//todo udpate screenrect
 }
@@ -798,8 +798,7 @@ bool Actor::hasClue(int clueId) {
 
 void Actor::copyClues(int actorId) {
 	Actor *otherActor = _vm->_actors[actorId];
-	int i;
-	for (i = 0; i < (int)_vm->_gameInfo->getClueCount(); i++) {
+	for (int i = 0; i < (int)_vm->_gameInfo->getClueCount(); i++) {
 		if (hasClue(i) && !_clues->isFlag4(i) && !otherActor->hasClue(i)) {
 			int fromActorId = _id;
 			if (_id == 99)
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 5383adb..1edbea4 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -137,8 +137,8 @@ public:
 
 	int getSetId();
 	void setSetId(int setId);
-	BoundingBox* getBoundingBox() { return _bbox; }
-	Common::Rect* getScreenRectangle() { return &_screenRectangle; }
+	BoundingBox *getBoundingBox() { return _bbox; }
+	Common::Rect *getScreenRectangle() { return &_screenRectangle; }
 	int getWalkbox() { return _walkboxId; }
 	bool isRetired() { return _isRetired; }
 	bool isTargetable() { return _isTargetable; }
diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
index c876829..9c0a61c 100644
--- a/engines/bladerunner/actor_clues.cpp
+++ b/engines/bladerunner/actor_clues.cpp
@@ -28,14 +28,12 @@
 
 namespace BladeRunner {
 
-ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType)
-{
+ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType) {
 	_vm = vm;
 	_count = 0;
 	_maxCount = 0;
 	_clues = 0;
-	switch (cluesType)
-	{
+	switch (cluesType) {
 	case 4:
 		_maxCount = _vm->_gameInfo->getClueCount();
 		break;
@@ -66,8 +64,7 @@ ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType)
 		_maxCount = 0;
 }
 
-ActorClues::~ActorClues()
-{
+ActorClues::~ActorClues() {
 	if (_clues)
 		delete[] _clues;
 
@@ -75,8 +72,7 @@ ActorClues::~ActorClues()
 	_count = 0;
 }
 
-void ActorClues::acquire(int clueId, char flag2, int fromActorId)
-{
+void ActorClues::acquire(int clueId, char flag2, int fromActorId) {
 	int clueIndex = findClueIndex(clueId);
 	_clues[clueIndex]._flags |= 0x01;
 	_clues[_count]._flags = (_clues[_count]._flags & ~0x02) | ((flag2 << 1) & 0x02);
@@ -85,14 +81,12 @@ void ActorClues::acquire(int clueId, char flag2, int fromActorId)
 	debug("Actor acquired clue: \"%s\" from %d", _vm->_clues->getClueText(clueId), fromActorId);
 }
 
-void ActorClues::lose(int clueId)
-{
+void ActorClues::lose(int clueId) {
 	int clueIndex = findClueIndex(clueId);
 	_clues[clueIndex]._flags = 0;
 }
 
-bool ActorClues::isAcquired(int clueId)
-{
+bool ActorClues::isAcquired(int clueId) {
 	int clueIndex = findClueIndex(clueId);
 	if (clueIndex == -1)
 		return 0;
@@ -100,8 +94,7 @@ bool ActorClues::isAcquired(int clueId)
 	return _clues[clueIndex]._flags & 0x01;
 }
 
-int ActorClues::getFromActorId(int clueId)
-{
+int ActorClues::getFromActorId(int clueId) {
 	int clueIndex = findClueIndex(clueId);
 	if (clueIndex == -1)
 		return  -1;
@@ -109,8 +102,7 @@ int ActorClues::getFromActorId(int clueId)
 	return _clues[clueIndex]._fromActorId;
 }
 
-bool ActorClues::isFlag2(int clueId)
-{
+bool ActorClues::isFlag2(int clueId) {
 	int clueIndex = findClueIndex(clueId);
 	if (clueIndex == -1)
 		return 0;
@@ -118,8 +110,7 @@ bool ActorClues::isFlag2(int clueId)
 	return (_clues[clueIndex]._flags & 0x02) >> 1;
 }
 
-bool ActorClues::isFlag3(int clueId)
-{
+bool ActorClues::isFlag3(int clueId) {
 	int clueIndex = findClueIndex(clueId);
 	if (clueIndex == -1)
 		return 0;
@@ -127,8 +118,7 @@ bool ActorClues::isFlag3(int clueId)
 	return (_clues[clueIndex]._flags & 0x04) >> 2;
 }
 
-bool ActorClues::isFlag4(int clueId)
-{
+bool ActorClues::isFlag4(int clueId) {
 	int clueIndex = findClueIndex(clueId);
 	if (clueIndex == -1)
 		return 0;
@@ -136,8 +126,7 @@ bool ActorClues::isFlag4(int clueId)
 	return (_clues[clueIndex]._flags & 0x08) >> 3;
 }
 
-int ActorClues::getField1(int clueId)
-{
+int ActorClues::getField1(int clueId) {
 	if (!_count)
 		return 0;
 
@@ -148,21 +137,18 @@ int ActorClues::getField1(int clueId)
 	return _clues[clueIndex]._field1;
 }
 
-int ActorClues::getCount()
-{
+int ActorClues::getCount() {
 	return _count;
 }
 
-void ActorClues::removeAll()
-{
+void ActorClues::removeAll() {
 	_count = 0;
 	for (int i = 0; i < _maxCount; ++i) {
 		remove(i);
 	}
 }
 
-int ActorClues::findClueIndex(int clueId)
-{
+int ActorClues::findClueIndex(int clueId) {
 	for (int i = 0; i < _count; i++) {
 		if (clueId == _clues[i]._clueId) {
 			return i;
@@ -171,8 +157,7 @@ int ActorClues::findClueIndex(int clueId)
 	return -1;
 }
 
-void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId)
-{
+void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId) {
 	assert(_count < _maxCount);
 
 	debug("Actor %d added clue: \"%s\" from %d", actorId, _vm->_clues->getClueText(clueId), fromActorId);
@@ -188,8 +173,7 @@ void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool u
 	++_count;
 }
 
-void ActorClues::remove(int index)
-{
+void ActorClues::remove(int index) {
 	if (_vm->_clues)
 		debug("Actor removed clue: \"%s\"", _vm->_clues->getClueText(_clues[index]._clueId));
 
@@ -206,8 +190,7 @@ void ActorClues::remove(int index)
 	_clues[index]._field8 = 0;
 }
 
-bool ActorClues::exists(int clueId)
-{
+bool ActorClues::exists(int clueId) {
 	return findClueIndex(clueId) != -1;
 }
 
diff --git a/engines/bladerunner/actor_clues.h b/engines/bladerunner/actor_clues.h
index 06ac815..26510ec 100644
--- a/engines/bladerunner/actor_clues.h
+++ b/engines/bladerunner/actor_clues.h
@@ -29,8 +29,7 @@
 
 namespace BladeRunner {
 
-struct ActorClue
-{
+struct ActorClue {
 	int _clueId;
 	int _field1;
 	int _fromActorId;
@@ -43,8 +42,7 @@ struct ActorClue
 	unsigned char _flags;
 };
 
-class ActorClues
-{
+class ActorClues {
 	BladeRunnerEngine *_vm;
 
 private:
diff --git a/engines/bladerunner/actor_combat.cpp b/engines/bladerunner/actor_combat.cpp
index 09d89df..4bd8d17 100644
--- a/engines/bladerunner/actor_combat.cpp
+++ b/engines/bladerunner/actor_combat.cpp
@@ -24,7 +24,7 @@
 
 namespace BladeRunner {
 
-ActorCombat::ActorCombat(BladeRunnerEngine* vm) {
+ActorCombat::ActorCombat(BladeRunnerEngine *vm) {
 	_vm = vm;
 }
 
diff --git a/engines/bladerunner/actor_combat.h b/engines/bladerunner/actor_combat.h
index df06e83..ee29bf4 100644
--- a/engines/bladerunner/actor_combat.h
+++ b/engines/bladerunner/actor_combat.h
@@ -29,8 +29,7 @@
 
 namespace BladeRunner {
 
-class ActorCombat
-{
+class ActorCombat {
 	BladeRunnerEngine *_vm;
 
 private:
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index 5b23736..ed55bd0 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -46,28 +46,23 @@ ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
 ActorWalk::~ActorWalk() {
 }
 
-int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2)
-{
+int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2) {
 	Vector3 next;
 
 	*unk2 = 0;
 	int r = nextOnPath(actorId, from, to, &next);
 
 	if (r == 0) {
-		if (actorId != 0)
-		{
+		if (actorId != 0) {
 			_current = from;
 			_destination = to;
 			stop(actorId, false);
-		}
-		else
-		{
+		} else {
 			stop(actorId, true);
 		}
 		return 0;
 	}
-	if (r == -1)
-	{
+	if (r == -1) {
 		stop(actorId, true);
 		*unk2 = 1;
 		return 0;
@@ -77,18 +72,14 @@ int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, i
 	// TODO: Update screen index
 	// Set actor field e8
 
-	if (_running)
-	{
+	if (_running) {
 		run = true;
 	}
 
 	int animationMode;
-	if (_vm->_actors[actorId]->inCombat())
-	{
+	if (_vm->_actors[actorId]->inCombat()) {
 		animationMode = run ? 8 : 7;
-	}
-	else
-	{
+	} else {
 		animationMode = run ? 2 : 1;
 	}
 
@@ -98,8 +89,7 @@ int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, i
 	_current = from;
 	_next = next;
 
-	if (next.x != _current.x || next.z != _current.z)
-	{
+	if (next.x != _current.x || next.z != _current.z) {
 		_facing = angle_1024(_current, next);
 		_walking = true;
 		_running = run;
@@ -112,26 +102,21 @@ int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, i
 	return 0;
 }
 
-bool ActorWalk::tick(int actorId, float stepDistance, bool flag)
-{
-	if (_status == 5)
-	{
-		if (flag)
-		{
+bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
+	if (_status == 5) {
+		if (flag) {
 			stop(actorId, true);
 			return true;
 		}
 
-		if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1)
-		{
+		if (actorId != 0 && _vm->_rnd.getRandomNumberRng(1, 15) != 1) {
 			return false;
 		}
 		_status = 3;
 	}
 	// TODO: Handle collisions?
 
-	if (stepDistance > distance(_current, _destination))
-	{
+	if (stepDistance > distance(_current, _destination)) {
 		stop(actorId, true);
 		_current = _destination;
 		// TODO: Update y from walkbox
@@ -149,14 +134,12 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag)
 	return false;
 }
 
-void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing)
-{
+void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) {
 	*pos    = _current;
 	*facing = _facing;
 }
 
-void ActorWalk::setRunning()
-{
+void ActorWalk::setRunning() {
 	_running = true;
 	// TODO: Set animation mode
 }
@@ -182,10 +165,8 @@ void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused)
 	}
 }
 
-int ActorWalk::nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next)
-{
-	if (distance(from, to) < 6.0)
-	{
+int ActorWalk::nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next) {
+	if (distance(from, to) < 6.0) {
 		return -1;
 	}
 
@@ -197,25 +178,20 @@ int ActorWalk::nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next)
 	error("TODO!");
 }
 
-static
-int angle_1024(float x1, float z1, float x2, float z2)
-{
+static int angle_1024(float x1, float z1, float x2, float z2) {
 	float angle_rad = atan2(x2 - x1, z1 - z2);
 	int a = int(512.0 * angle_rad / M_PI);
 	return (a + 1024) % 1024;
 }
 
-static
-int angle_1024(Vector3 &v1, Vector3 &v2)
-{
+static int angle_1024(Vector3 &v1, Vector3 &v2) {
 	return angle_1024(v1.x, v1.z, v2.x, v2.z);
 }
 
-float distance(float x1, float z1, float x2, float z2)
-{
+float distance(float x1, float z1, float x2, float z2) {
 	float dx = x1 - x2;
 	float dz = z1 - z2;
-	float d = sqrt(dx*dx + dz*dz);
+	float d = sqrt(dx * dx + dz * dz);
 
 	float int_part = (int)d;
 	float frac_part = d - int_part;
@@ -226,8 +202,7 @@ float distance(float x1, float z1, float x2, float z2)
 	return int_part + frac_part;
 }
 
-float distance(Vector3 &v1, Vector3 &v2)
-{
+float distance(Vector3 &v1, Vector3 &v2) {
 	return distance(v1.x, v1.z, v2.x, v2.z);
 }
 
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index 3e03c79..12da69b 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -29,14 +29,12 @@ namespace BladeRunner {
 
 class BladeRunnerEngine;
 
-struct ActorWalkEntry
-{
+struct ActorWalkEntry {
 	int _actorId;
 	int _present;
 };
 
-class ActorWalk
-{
+class ActorWalk {
 	BladeRunnerEngine *_vm;
 
 private:
diff --git a/engines/bladerunner/adpcm_decoder.cpp b/engines/bladerunner/adpcm_decoder.cpp
index e262da6..c93d4eb 100644
--- a/engines/bladerunner/adpcm_decoder.cpp
+++ b/engines/bladerunner/adpcm_decoder.cpp
@@ -30,8 +30,7 @@ static const
 int16 imaIndexTable[8] = { -1, -1, -1, -1, 2, 4, 6, 8 };
 
 static const
-uint16 imaStepTable[712] =
-{
+uint16 imaStepTable[712] = {
  0x0000,0x0001,0x0003,0x0004,0x0007,0x0008,0x000a,0x000b,
  0x0001,0x0003,0x0005,0x0007,0x0009,0x000b,0x000d,0x000f,
  0x0001,0x0003,0x0005,0x0007,0x000a,0x000c,0x000e,0x0010,
@@ -123,19 +122,16 @@ uint16 imaStepTable[712] =
  0x0fff,0x2ffe,0x4ffe,0x6ffd,0x8ffe,0xaffd,0xcffd,0xeffc
 };
 
-void ADPCMWestwoodDecoder::decode(uint8 *in, size_t size, int16 *out)
-{
+void ADPCMWestwoodDecoder::decode(uint8 *in, size_t size, int16 *out) {
 	uint8 *end = in + size;
 
 	int16 stepIndex = _stepIndex;
 	int32 predictor = _predictor;
 
-	while (in != end)
-	{
+	while (in != end) {
 		uint16 bl = *in++;
 
-		for (int n = 0; n != 2; ++n)
-		{
+		for (int n = 0; n != 2; ++n) {
 			uint8 nibble = (bl >> (4 * n)) & 0x0f;
 			uint8 code = nibble & 0x07;
 			uint8 sign = nibble & 0x08;
diff --git a/engines/bladerunner/adpcm_decoder.h b/engines/bladerunner/adpcm_decoder.h
index fd174ae..8f7a228 100644
--- a/engines/bladerunner/adpcm_decoder.h
+++ b/engines/bladerunner/adpcm_decoder.h
@@ -33,11 +33,10 @@ class ADPCMWestwoodDecoder {
 
 public:
 	ADPCMWestwoodDecoder()
-		: _stepIndex(0), _predictor(0)
-	{}
+		: _stepIndex(0), _predictor(0) {
+	}
 
-	void setParameters(int16 stepIndex, int32 predictor)
-	{
+	void setParameters(int16 stepIndex, int32 predictor) {
 		_stepIndex = stepIndex;
 		_predictor = predictor;
 	}
diff --git a/engines/bladerunner/ambient_sounds.cpp b/engines/bladerunner/ambient_sounds.cpp
index 77b8195..c33deef 100644
--- a/engines/bladerunner/ambient_sounds.cpp
+++ b/engines/bladerunner/ambient_sounds.cpp
@@ -34,9 +34,7 @@ namespace BladeRunner {
 #define NON_LOOPING_SOUNDS 25
 #define LOOPING_SOUNDS      3
 
-AmbientSounds::AmbientSounds(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+AmbientSounds::AmbientSounds(BladeRunnerEngine *vm) : _vm(vm) {
 	_nonLoopingSounds = new NonLoopingSound[NON_LOOPING_SOUNDS];
 	_loopingSounds = new LoopingSound[LOOPING_SOUNDS];
 	_ambientVolume = 65;
@@ -66,13 +64,12 @@ static inline void sort(int &a, int &b) {
 }
 
 void AmbientSounds::addSound(
-	int id,
-	int timeRangeBegin, int timeRangeEnd,
-	int volumeRangeBegin, int volumeRangeEnd,
-	int unk1RangeBegin, int unk1RangeEnd,
-	int unk2RangeBegin, int unk2RangeEnd,
-	int priority, int unk3)
-{
+		int id,
+		int timeRangeBegin, int timeRangeEnd,
+		int volumeRangeBegin, int volumeRangeEnd,
+		int unk1RangeBegin, int unk1RangeEnd,
+		int unk2RangeBegin, int unk2RangeEnd,
+		int priority, int unk3) {
 	const char *name = _vm->_gameInfo->getSfxTrack(id);
 
 	sort(volumeRangeBegin, volumeRangeEnd);
@@ -187,8 +184,7 @@ void AmbientSounds::addSoundByName(
 		int volumeRangeBegin, int volumeRangeEnd,
 		int pan1begin, int pan1end,
 		int pan2begin, int pan2end,
-		int priority, int unk3)
-{
+		int priority, int unk3) {
 	int i = findAvailableNonLoopingTrack();
 	if (i < 0)
 		return;
diff --git a/engines/bladerunner/archive.cpp b/engines/bladerunner/archive.cpp
index 464ca15..0051455 100644
--- a/engines/bladerunner/archive.cpp
+++ b/engines/bladerunner/archive.cpp
@@ -121,8 +121,7 @@ int32 tlk_id(const Common::String &name) {
 uint32 MIXArchive::indexForId(int32 id) const {
 	uint32 lo = 0, hi = _entry_count;
 
-	while (lo < hi)
-	{
+	while (lo < hi) {
 		uint32 mid = lo + (hi - lo) / 2;
 
 		if (id > _entries[mid].id)
diff --git a/engines/bladerunner/aud_stream.cpp b/engines/bladerunner/aud_stream.cpp
index 8a17f6b..b583531 100644
--- a/engines/bladerunner/aud_stream.cpp
+++ b/engines/bladerunner/aud_stream.cpp
@@ -28,22 +28,18 @@
 
 namespace BladeRunner {
 
-AudStream::AudStream(byte *data)
-	: _cache(nullptr)
-{
+AudStream::AudStream(byte *data) : _cache(nullptr) {
 	init(data);
 }
 
 AudStream::AudStream(AudioCache *cache, int32 hash)
-	: _cache(cache), _hash(hash)
-{
+		: _cache(cache), _hash(hash) {
 	_cache->incRef(_hash);
 
 	init(_cache->findByHash(_hash));
 }
 
-void AudStream::init(byte *data)
-{
+void AudStream::init(byte *data) {
 	_data = data;
 	_end = _data + READ_LE_UINT32(_data + 2) + 12;
 	assert(_end - _data >= 12);
diff --git a/engines/bladerunner/audio_player.cpp b/engines/bladerunner/audio_player.cpp
index dc6f195..0c2b747 100644
--- a/engines/bladerunner/audio_player.cpp
+++ b/engines/bladerunner/audio_player.cpp
@@ -126,9 +126,7 @@ void AudioCache::decRef(int32 hash) {
 	assert(0 && "AudioCache::decRef: hash not found");
 }
 
-AudioPlayer::AudioPlayer(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+AudioPlayer::AudioPlayer(BladeRunnerEngine *vm) : _vm(vm) {
 	_cache = new AudioCache();
 
 	for (int i = 0; i != 6; ++i) {
@@ -141,23 +139,20 @@ AudioPlayer::~AudioPlayer() {
 	delete _cache;
 }
 
-bool AudioPlayer::isTrackActive(Track *track)
-{
+bool AudioPlayer::isTrackActive(Track *track) {
 	if (!track->isMaybeActive)
 		return false;
 
 	return track->isMaybeActive = _vm->_mixer->isSoundHandleActive(track->soundHandle);
 }
 
-void AudioPlayer::stopAll()
-{
+void AudioPlayer::stopAll() {
 	for (int i = 0; i != TRACKS; ++i) {
 		_vm->_mixer->stopHandle(_tracks[i].soundHandle);
 	}
 }
 
-void AudioPlayer::fadeAndStopTrack(Track *track, int time)
-{
+void AudioPlayer::fadeAndStopTrack(Track *track, int time) {
 	(void)time;
 
 	_vm->_mixer->stopHandle(track->soundHandle);
diff --git a/engines/bladerunner/audio_player.h b/engines/bladerunner/audio_player.h
index eb4c75d..4260a7b 100644
--- a/engines/bladerunner/audio_player.h
+++ b/engines/bladerunner/audio_player.h
@@ -58,8 +58,8 @@ public:
 	AudioCache() :
 		_totalSize(0),
 		_maxSize(2457600),
-		_accessCounter(0)
-	{}
+		_accessCounter(0) {
+	}
 	~AudioCache();
 
 	bool  canAllocate(uint32 size);
@@ -82,9 +82,7 @@ class AudioPlayer {
 		int32              hash;
 		int                volume;
 
-		Track()
-			: isMaybeActive(false)
-		{}
+		Track() : isMaybeActive(false) {}
 	};
 
 	Track _tracks[TRACKS];
diff --git a/engines/bladerunner/audio_speech.cpp b/engines/bladerunner/audio_speech.cpp
index 7e7e4f0..2d06025 100644
--- a/engines/bladerunner/audio_speech.cpp
+++ b/engines/bladerunner/audio_speech.cpp
@@ -31,9 +31,7 @@ namespace BladeRunner {
 
 #define BUFFER_SIZE 200000
 
-AudioSpeech::AudioSpeech(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+AudioSpeech::AudioSpeech(BladeRunnerEngine *vm) : _vm(vm) {
 	_volume = 50;
 	_isMaybeActive = false;
 	_data = new byte[BUFFER_SIZE];
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 6b97a0b..3365bb1 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -61,9 +61,8 @@
 namespace BladeRunner {
 
 BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
-	: Engine(syst),
-	  _rnd("bladerunner")
-{
+		: Engine(syst),
+		  _rnd("bladerunner") {
 	_windowIsActive = true;
 	_gameIsRunning  = true;
 	_playerLosesControlCounter = 0;
@@ -616,8 +615,7 @@ void BladeRunnerEngine::gameTick() {
 			// TODO: Process AUD
 			// TODO: Footstep sound
 
-			if (_walkSoundId >= 0)
-			{
+			if (_walkSoundId >= 0) {
 				const char *name = _gameInfo->getSfxTrack(_walkSoundId);
 				_audioPlayer->playAud(name, _walkSoundVolume, _walkSoundBalance, _walkSoundBalance, 50, 0);
 				_walkSoundId = -1;
@@ -669,7 +667,7 @@ void BladeRunnerEngine::gameTick() {
 			for (int i = 0; i < _scene->_set->_walkboxCount; i++) {
 				Walkbox *walkbox = &_scene->_set->_walkboxes[i];
 
-				for(int j = 0; j < walkbox->_vertexCount; j++) {
+				for (int j = 0; j < walkbox->_vertexCount; j++) {
 					Vector3 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
 					Vector3 end = _view->calculateScreenPosition(walkbox->_vertices[(j+1) % walkbox->_vertexCount]);
 					//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
@@ -709,11 +707,11 @@ void BladeRunnerEngine::handleEvents() {
 	Common::EventManager *eventMan = _system->getEventManager();
 	while (eventMan->pollEvent(event)) {
 		switch (event.type) {
-			case Common::EVENT_LBUTTONDOWN:
-			case Common::EVENT_RBUTTONDOWN:
-				handleMouseClick(event.mouse.x, event.mouse.y);
-			default:
-				;
+		case Common::EVENT_LBUTTONDOWN:
+		case Common::EVENT_RBUTTONDOWN:
+			handleMouseClick(event.mouse.x, event.mouse.y);
+		default:
+			;
 		}
 	}
 }
@@ -760,34 +758,29 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 	}
 }
 
-void BladeRunnerEngine::handleMouseClickExit(int x, int y, int exitIndex)
-{
+void BladeRunnerEngine::handleMouseClickExit(int x, int y, int exitIndex) {
 	// clickedOnExit(exitType, x, y);
 	debug("clicked on exit %d %d %d", exitIndex, x, y);
 	_script->ClickedOnExit(exitIndex);
 }
 
-void BladeRunnerEngine::handleMouseClickRegion(int x, int y, int regionIndex)
-{
+void BladeRunnerEngine::handleMouseClickRegion(int x, int y, int regionIndex) {
 	debug("clicked on region %d %d %d", regionIndex, x, y);
 	_script->ClickedOn2DRegion(regionIndex);
 }
 
-void BladeRunnerEngine::handleMouseClick3DObject(int x, int y, int objectId, bool isClickable, bool isTarget)
-{
+void BladeRunnerEngine::handleMouseClick3DObject(int x, int y, int objectId, bool isClickable, bool isTarget) {
 	const char *objectName = _scene->objectGetName(objectId);
 	debug("Clicked on object %s", objectName);
 	_script->ClickedOn3DObject(objectName, false);
 }
 
-void BladeRunnerEngine::handleMouseClickItem(int x, int y, int itemId)
-{
+void BladeRunnerEngine::handleMouseClickItem(int x, int y, int itemId) {
 	debug("Clicked on item %d", itemId);
 	_script->ClickedOnItem(itemId, false);
 }
 
-void BladeRunnerEngine::handleMouseClickActor(int x, int y, int actorId)
-{
+void BladeRunnerEngine::handleMouseClickActor(int x, int y, int actorId) {
 	debug("Clicked on actor %d", actorId);
 	_script->ClickedOnActor(actorId);
 }
diff --git a/engines/bladerunner/boundingbox.h b/engines/bladerunner/boundingbox.h
index 5031ce5..da91489 100644
--- a/engines/bladerunner/boundingbox.h
+++ b/engines/bladerunner/boundingbox.h
@@ -38,7 +38,7 @@ public:
 	bool inside(float x, float y, float z);
 
 	void setXYZ(float x0, float y0, float z0, float x1, float y1, float z1);
-	void getXYZ(float* x0, float* y0, float* z0, float* x1, float* y1, float* z1);
+	void getXYZ(float* x0, float *y0, float* z0, float *x1, float* y1, float* z1);
 
 	float getZ0();
 	float getZ1();
diff --git a/engines/bladerunner/chapters.h b/engines/bladerunner/chapters.h
index 9778209..5d4da57 100644
--- a/engines/bladerunner/chapters.h
+++ b/engines/bladerunner/chapters.h
@@ -35,9 +35,7 @@ class Chapters {
 	bool _hasOpenResources;
 
 public:
-	Chapters(BladeRunnerEngine *vm)
-		: _vm(vm), _chapter(0)
-	{
+	Chapters(BladeRunnerEngine *vm) : _vm(vm), _chapter(0) {
 		_chapter = 0;
 
 		_resourceIds[0] = 1;
diff --git a/engines/bladerunner/clues.cpp b/engines/bladerunner/clues.cpp
index cbdf536..b87761b 100644
--- a/engines/bladerunner/clues.cpp
+++ b/engines/bladerunner/clues.cpp
@@ -28,9 +28,7 @@
 
 namespace BladeRunner {
 
-Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, int clueCount)
-	: _clueCount(clueCount)
-{
+Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, int clueCount) : _clueCount(clueCount) {
 	// reset();
 
 	_crimes     = new int[_clueCount];
diff --git a/engines/bladerunner/decompress_lcw.cpp b/engines/bladerunner/decompress_lcw.cpp
index 8d20e23..9fc4640 100644
--- a/engines/bladerunner/decompress_lcw.cpp
+++ b/engines/bladerunner/decompress_lcw.cpp
@@ -34,79 +34,61 @@ uint32 decompress_lcw(uint8 *inBuf, uint32 inLen, uint8 *outBuf, uint32 outLen)
 	uint8 *dst = outBuf;
 	uint8 *outEnd = dst + outLen;
 
-	if (src[0] == 0)
-	{
+	if (src[0] == 0) {
 		version = 2;
 		++src;
 	}
 
-	while (src < inBuf + inLen && dst < outEnd && src[0] != 0x80)
-	{
+	while (src < inBuf + inLen && dst < outEnd && src[0] != 0x80) {
 		out_remain = (int)(outEnd - dst);
 
-		if (src[0] == 0xff)      // 0b11111111
-		{
+		if (src[0] == 0xff) {     // 0b11111111
 			count = src[1] | (src[2] << 8);
 			pos   = src[3] | (src[4] << 8);
 			src += 5;
 			count = MIN(count, out_remain);
 
-			if (version == 1)
-			{
+			if (version == 1) {
 				for (i = 0; i < count; i++)
 					dst[i] = outBuf[i + pos];
-			}
-			else
-			{
+			} else {
 				for (i = 0; i < count; i++)
 					dst[i] = *(dst + i - pos);
 			}
-		}
-		else if (src[0] == 0xfe) // 0b11111110
-		{
+		} else if (src[0] == 0xfe) { // 0b11111110
 			count = src[1] | (src[2] << 8);
 			color = src[3];
 			src += 4;
 			count = MIN(count, out_remain);
 
 			memset(dst, color, count);
-		}
-		else if (src[0] >= 0xc0)  // 0b11??????
-		{
+		} else if (src[0] >= 0xc0) { // 0b11??????
 			count = (src[0] & 0x3f) + 3;
 			pos   = src[1] | (src[2] << 8);
 			src += 3;
 			count = MIN(count, out_remain);
 
-			if (version == 1)
-			{
+			if (version == 1) {
 				for (i = 0; i < count; i++)
 					dst[i] = outBuf[i + pos];
-			}
-			else
-			{
+			} else {
 				for (i = 0; i < count; i++)
 					dst[i] = *(dst + i - pos);
 			}
-		}
-		else if (src[0] >= 0x80)  // 0b10??????
-		{
+		} else if (src[0] >= 0x80) { // 0b10??????
 			count = src[0] & 0x3f;
 			++src;
 			count = MIN(count, out_remain);
 
 			memcpy(dst, src, count);
 			src += count;
-		}
-		else                     // 0b0???????
-		{
+		} else {                    // 0b0???????
 			count  = ((src[0] & 0x70) >> 4) + 3;
 			relpos = ((src[0] & 0x0f) << 8) | src[1];
 			src += 2;
 			count = MIN(count, out_remain);
 
-			for (i = 0; i < count; i++)
-			{
+			for (i = 0; i < count; i++) {
 				dst[i] = *(dst + i - relpos);
 			}
 		}
@@ -125,30 +107,20 @@ uint32 decompress_lcw_output_size(uint8 *inBuf, uint32 inLen) {
 	if (src[0] == 0)
 		++src;
 
-	while (src[0] != 0x80 && src < inBuf + inLen)
-	{
-		if (src[0] == 0xff)      // 0b11111111
-		{
+	while (src[0] != 0x80 && src < inBuf + inLen) {
+		if (src[0] == 0xff) {        // 0b11111111
 			count = src[1] | (src[2] << 8);
 			src += 5;
-		}
-		else if (src[0] == 0xfe) // 0b11111110
-		{
+		} else if (src[0] == 0xfe) { // 0b11111110
 			count = src[1] | (src[2] << 8);
 			src += 4;
-		}
-		else if (src[0] >= 0xc0)  // 0b11??????
-		{
+		} else if (src[0] >= 0xc0) { // 0b11??????
 			count = (src[0] & 0x3f) + 3;
 			src += 3;
-		}
-		else if (src[0] & 0x80)  // 0b10??????
-		{
+		} else if (src[0] & 0x80) {  // 0b10??????
 			count = src[0] & 0x3f;
 			src += count + 1;
-		}
-		else                     // 0b0???????
-		{
+		} else {                    // 0b0???????
 			count  = ((src[0] & 0x70) >> 4) + 3;
 			src += 2;
 		}
diff --git a/engines/bladerunner/decompress_lzo.cpp b/engines/bladerunner/decompress_lzo.cpp
index aa4ebc7..c2c9712 100644
--- a/engines/bladerunner/decompress_lzo.cpp
+++ b/engines/bladerunner/decompress_lzo.cpp
@@ -24,10 +24,9 @@
 
 namespace BladeRunner {
 
-static inline
-uint32 decode_count(const uint8 **pp) {
+static inline uint32 decode_count(const uint8 **pp) {
 	uint32 v = 0;
-	for (;!**pp;(*pp)++)
+	for (; !**pp; (*pp)++)
 		v += 255;
 
 	v += **pp;
@@ -36,8 +35,7 @@ uint32 decode_count(const uint8 **pp) {
 	return v;
 }
 
-static inline
-void copy(uint8 **dst, const uint8 **src, int count) {
+static inline void copy(uint8 **dst, const uint8 **src, int count) {
 	assert(count > 0);
 
 	uint8 *d = *dst;
@@ -87,22 +85,17 @@ first_literal_run:
 
 		for (;;) {
 match:
-			if (t >= 64)
-			{
+			if (t >= 64) {
 				m_pos = op - 1 - ((t >> 2) & 7) - (*ip++ << 3);
 				t = (t >> 5) - 1;
 				goto copy_match;
-			}
-			else if (t >= 32)
-			{
+			} else if (t >= 32) {
 				t &= 31;
 				if (t == 0)
 					t = 31 + decode_count(&ip);
 				m_pos = op - 1 - (ip[0] >> 2) - (ip[1] << 6);
 				ip += 2;
-			}
-			else if (t >= 16)
-			{
+			} else if (t >= 16) {
 				m_pos = op - ((t & 8) << 11);
 				t &= 7;
 				if (t == 0)
@@ -112,9 +105,7 @@ match:
 				if (m_pos == op)
 					goto eof_found;
 				m_pos -= 0x4000;
-			}
-			else
-			{
+			} else {
 				m_pos = op - 1 - (t >> 2) - (*ip++ << 2);
 				copy(&op, &m_pos, 2);
 				goto match_done;
diff --git a/engines/bladerunner/fog.h b/engines/bladerunner/fog.h
index 992ede5..445308d 100644
--- a/engines/bladerunner/fog.h
+++ b/engines/bladerunner/fog.h
@@ -34,8 +34,7 @@ namespace BladeRunner {
 
 class SetEffects;
 
-class Fog
-{
+class Fog {
 	friend class SetEffects;
 
 protected:
@@ -82,20 +81,17 @@ protected:
 
 };
 
-class FogCone : public Fog
-{
+class FogCone : public Fog {
 	void read(Common::ReadStream *stream, int framesCount);
 	void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient);
 };
 
-class FogSphere : public Fog
-{
+class FogSphere : public Fog {
 	void read(Common::ReadStream *stream, int framesCount);
 	void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient);
 };
 
-class FogBox : public Fog
-{
+class FogBox : public Fog {
 	void read(Common::ReadStream *stream, int framesCount);
 	void calculateCoeficient(Vector3 position, Vector3 viewPosition, float *coeficient);
 };
diff --git a/engines/bladerunner/gameflags.cpp b/engines/bladerunner/gameflags.cpp
index 087292e..db4271d 100644
--- a/engines/bladerunner/gameflags.cpp
+++ b/engines/bladerunner/gameflags.cpp
@@ -27,8 +27,7 @@
 namespace BladeRunner {
 
 GameFlags::GameFlags()
-	: flags(NULL), flagCount(0)
-{
+	: flags(NULL), flagCount(0) {
 }
 
 GameFlags::~GameFlags() {
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index a5c01c1..5f30e51 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -30,8 +30,7 @@
 namespace BladeRunner {
 
 GameInfo::GameInfo(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+		: _vm(vm) {
 	_scene_names    = nullptr;
 	_sfx_tracks   = nullptr;
 	_music_tracks = nullptr;
@@ -78,15 +77,13 @@ bool GameInfo::open(const Common::String &name) {
 		s->read(_scene_names[i], 5);
 
 	_sfx_tracks = new char[_sfx_track_count][13];
-	for (uint32 i = 0; i != _sfx_track_count; ++i)
-	{
+	for (uint32 i = 0; i != _sfx_track_count; ++i) {
 		s->read(_sfx_tracks[i], 9);
 		strcat(_sfx_tracks[i], ".AUD");
 	}
 
 	_music_tracks = new char[_music_track_count][13];
-	for (uint32 i = 0; i != _music_track_count; ++i)
-	{
+	for (uint32 i = 0; i != _music_track_count; ++i) {
 		s->read(_music_tracks[i], 9);
 		strcat(_music_tracks[i], ".AUD");
 	}
diff --git a/engines/bladerunner/image.cpp b/engines/bladerunner/image.cpp
index abdd6ff..1a23823 100644
--- a/engines/bladerunner/image.cpp
+++ b/engines/bladerunner/image.cpp
@@ -31,8 +31,7 @@
 namespace BladeRunner {
 
 Image::Image(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+	: _vm(vm) {
 }
 
 Image::~Image() {
diff --git a/engines/bladerunner/image.h b/engines/bladerunner/image.h
index 376f996..4e44ae9 100644
--- a/engines/bladerunner/image.h
+++ b/engines/bladerunner/image.h
@@ -36,6 +36,7 @@ class BladeRunnerEngine;
 class Image {
 	BladeRunnerEngine *_vm;
 	Graphics::Surface  _surface;
+
 public:
 	Image(BladeRunnerEngine *vm);
 	~Image();
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index fd5c3e5..11e75e9 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -133,4 +133,5 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f
 	_screenRectangle.top = -1;
 	_screenRectangle.left = -1;
 }
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/light.h b/engines/bladerunner/light.h
index cae5816..ce54171 100644
--- a/engines/bladerunner/light.h
+++ b/engines/bladerunner/light.h
@@ -36,8 +36,7 @@ namespace BladeRunner {
 
 class Lights;
 
-class Light
-{
+class Light {
 #if _DEBUG
 	friend class BladeRunnerEngine;
 #endif
diff --git a/engines/bladerunner/matrix.cpp b/engines/bladerunner/matrix.cpp
index db4d4d5..42e3f68 100644
--- a/engines/bladerunner/matrix.cpp
+++ b/engines/bladerunner/matrix.cpp
@@ -26,15 +26,13 @@
 
 namespace BladeRunner {
 
-Matrix3x2::Matrix3x2()
-{
+Matrix3x2::Matrix3x2() {
 	for (int r = 0; r != 2; ++r)
 		for (int c = 0; c != 3; ++c)
 			_m[r][c] = (r == c) ? 1.0f : 0.0f;
 }
 
-Matrix3x2::Matrix3x2(float d[6])
-{
+Matrix3x2::Matrix3x2(float d[6]) {
 	for (int r = 0; r != 2; ++r)
 		for (int c = 0; c != 3; ++c)
 			_m[r][c] = d[r*3+c];
@@ -42,8 +40,7 @@ Matrix3x2::Matrix3x2(float d[6])
 
 Matrix3x2::Matrix3x2(
 	float m00, float m01, float m02,
-	float m10, float m11, float m12)
-{
+	float m10, float m11, float m12) {
 	_m[0][0] = m00;
 	_m[0][1] = m01;
 	_m[0][2] = m02;
@@ -52,15 +49,13 @@ Matrix3x2::Matrix3x2(
 	_m[1][2] = m12;
 }
 
-Matrix4x3::Matrix4x3()
-{
+Matrix4x3::Matrix4x3() {
 	for (int r = 0; r != 3; ++r)
 		for (int c = 0; c != 4; ++c)
 			_m[r][c] = (r == c) ? 1.0f : 0.0f;
 }
 
-Matrix4x3::Matrix4x3(float d[12])
-{
+Matrix4x3::Matrix4x3(float d[12]) {
 	for (int r = 0; r != 3; ++r)
 		for (int c = 0; c != 4; ++c)
 			_m[r][c] = d[r*4+c];
@@ -69,8 +64,7 @@ Matrix4x3::Matrix4x3(float d[12])
 Matrix4x3::Matrix4x3(
 	float m00, float m01, float m02, float m03,
 	float m10, float m11, float m12, float m13,
-	float m20, float m21, float m22, float m23)
-{
+	float m20, float m21, float m22, float m23) {
 	_m[0][0] = m00;
 	_m[0][1] = m01;
 	_m[0][2] = m02;
@@ -85,8 +79,7 @@ Matrix4x3::Matrix4x3(
 	_m[2][3] = m23;
 }
 
-Matrix4x3 rotationMatrixX(float angle)
-{
+Matrix4x3 rotationMatrixX(float angle) {
 	float ca = cos(angle);
 	float sa = sin(angle);
 
@@ -95,33 +88,25 @@ Matrix4x3 rotationMatrixX(float angle)
 	                  0.0f,  -sa,   ca, 0.0f );
 }
 
-static inline
-void swapRows(double *r1, double *r2)
-{
-	for (int c = 0; c != 8; ++c)
-	{
+static inline void swapRows(double *r1, double *r2) {
+	for (int c = 0; c != 8; ++c) {
 		double t = r1[c];
 		r1[c] = r2[c];
 		r2[c] = t;
 	}
 }
 
-static inline
-void subtractRow(double *r1, double factor, double *r2)
-{
+static inline void subtractRow(double *r1, double factor, double *r2) {
 	for (int c = 0; c != 8; ++c)
 		r1[c] -= factor * r2[c];
 }
 
-static inline
-void divideRow(double *r1, double d)
-{
+static inline void divideRow(double *r1, double d) {
 	for (int c = 0; c != 8; ++c)
 		r1[c] /= d;
 }
 
-Matrix4x3 invertMatrix(const Matrix4x3 &m)
-{
+Matrix4x3 invertMatrix(const Matrix4x3 &m) {
 	double w[3][8];
 
 	for (int r = 0; r != 3; ++r) {
@@ -166,8 +151,7 @@ Matrix4x3 invertMatrix(const Matrix4x3 &m)
 	return result;
 }
 
-void Matrix4x3::unknown()
-{
+void Matrix4x3::unknown() {
 	Matrix4x3 t;
 
 	// Transpose the 3x3 top left submatrix
diff --git a/engines/bladerunner/matrix.h b/engines/bladerunner/matrix.h
index 4450306..5fe7fc2 100644
--- a/engines/bladerunner/matrix.h
+++ b/engines/bladerunner/matrix.h
@@ -27,8 +27,7 @@
 
 namespace BladeRunner {
 
-class Matrix3x2
-{
+class Matrix3x2 {
 public:
 	float _m[2][3];
 
@@ -42,9 +41,7 @@ public:
 	const float &operator()(int r, int c) const { assert(r >= 0 && r < 2); assert(c >= 0 && c < 3); return _m[r][c]; }
 };
 
-inline
-Matrix3x2 operator*(const Matrix3x2 &a, const Matrix3x2 &b)
-{
+inline Matrix3x2 operator*(const Matrix3x2 &a, const Matrix3x2 &b) {
 	Matrix3x2 t;
 
 	t(0,0) = a(0,0)*b(0,0) + a(0,1)*b(1,0);
@@ -57,9 +54,7 @@ Matrix3x2 operator*(const Matrix3x2 &a, const Matrix3x2 &b)
 	return t;
 }
 
-inline
-Matrix3x2 operator+(const Matrix3x2 &a, Vector2 b)
-{
+inline Matrix3x2 operator+(const Matrix3x2 &a, Vector2 b) {
 	Matrix3x2 t(a);
 
 	t(0,2) += b.x;
@@ -68,9 +63,7 @@ Matrix3x2 operator+(const Matrix3x2 &a, Vector2 b)
 	return t;
 }
 
-inline
-Vector2 operator*(const Matrix3x2 &a, Vector2 b)
-{
+inline Vector2 operator*(const Matrix3x2 &a, Vector2 b) {
 	Vector2 t;
 
 	t.x = a(0,0) * b.x + a(0,1) * b.y + a(0,2);
@@ -79,8 +72,7 @@ Vector2 operator*(const Matrix3x2 &a, Vector2 b)
 	return t;
 }
 
-class Matrix4x3
-{
+class Matrix4x3 {
 public:
 	float _m[3][4];
 
@@ -100,13 +92,10 @@ public:
 Matrix4x3 invertMatrix(const Matrix4x3 &m);
 Matrix4x3 rotationMatrixX(float angle);
 
-inline
-Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b)
-{
+inline Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b) {
 	Matrix4x3 t;
 
-	for (int i = 0; i !=3; ++i)
-	{
+	for (int i = 0; i !=3; ++i) {
 		// printf("t(%d,0) = %7.2f*%7.2f + %7.2f*%7.2f + %7.2f*%7.2f\n", i, a(i,0), b(0,0), a(i,0), b(1,0), a(i,0), b(2,0));
 		t(i,0) = a(i,0)*b(0,0) + a(i,1)*b(1,0) + a(i,2)*b(2,0);
 		t(i,1) = a(i,0)*b(0,1) + a(i,1)*b(1,1) + a(i,2)*b(2,1);
@@ -117,9 +106,7 @@ Matrix4x3 operator*(const Matrix4x3 &a, const Matrix4x3 &b)
 	return t;
 }
 
-inline
-Vector3 operator*(const Matrix4x3 &m, const Vector3 &v)
-{
+inline Vector3 operator*(const Matrix4x3 &m, const Vector3 &v) {
 	Vector3 r;
 
 	r.x = m(0, 0) * v.x + m(0, 1) * v.y + m(0, 2) * v.z + m(0, 3);
diff --git a/engines/bladerunner/mouse.cpp b/engines/bladerunner/mouse.cpp
index 14a2151..675e20c 100644
--- a/engines/bladerunner/mouse.cpp
+++ b/engines/bladerunner/mouse.cpp
@@ -31,9 +31,7 @@
 
 namespace BladeRunner {
 
-Mouse::Mouse(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+Mouse::Mouse(BladeRunnerEngine *vm) : _vm(vm) {
 	_cursor = 0;
 	_frame = 3;
 	_hotspotX = 0;
@@ -248,8 +246,7 @@ void Mouse::updateCursorFrame() {
 	}
 }
 
-void Mouse::tick(int x, int y)
-{
+void Mouse::tick(int x, int y) {
 	if (!_vm->playerHasControl() || isDisabled())
 		return;
 
@@ -288,8 +285,7 @@ void Mouse::tick(int x, int y)
 	if (true /* not in combat */) {
 		if (sceneObjectId == 0
 		 || (sceneObjectId >= 0 && isClickable)
-		 || _vm->_scene->_regions->getRegionAtXY(x, y) >= 0)
-		{
+		 || _vm->_scene->_regions->getRegionAtXY(x, y) >= 0) {
 			cursorId = 1;
 		}
 		setCursor(cursorId);
@@ -300,8 +296,7 @@ void Mouse::tick(int x, int y)
 }
 
 // TEST: RC01 after intro: [290, 216] -> [-204.589249 51.450668 7.659241]
-Vector3 Mouse::getXYZ(int x, int y)
-{
+Vector3 Mouse::getXYZ(int x, int y) {
 	if (_vm->_scene->getSetId() == -1)
 		return Vector3();
 
diff --git a/engines/bladerunner/movement_track.cpp b/engines/bladerunner/movement_track.cpp
index b7d0adc..60a190a 100644
--- a/engines/bladerunner/movement_track.cpp
+++ b/engines/bladerunner/movement_track.cpp
@@ -24,24 +24,20 @@
 
 namespace BladeRunner {
 
-MovementTrack::MovementTrack()
-{
+MovementTrack::MovementTrack() {
 	reset();
 }
 
-MovementTrack::~MovementTrack()
-{
+MovementTrack::~MovementTrack() {
 	reset();
 }
 
-void MovementTrack::reset()
-{
+void MovementTrack::reset() {
 	_currentIndex = -1;
 	_lastIndex = -1;
 	_hasNext = 0;
 	_paused = 0;
-	for (int i = 0; i < 100; i++)
-	{
+	for (int i = 0; i < 100; i++) {
 		_entries[i].waypointId = -1;
 		_entries[i].delay = -1;
 		_entries[i].angle = -1;
@@ -49,13 +45,11 @@ void MovementTrack::reset()
 	}
 }
 
-int MovementTrack::append(int waypointId, int delay, int running)
-{
+int MovementTrack::append(int waypointId, int delay, int running) {
 	return append(waypointId, delay, -1, running);
 }
 
-int MovementTrack::append(int waypointId, int delay, int angle, int running)
-{
+int MovementTrack::append(int waypointId, int delay, int angle, int running) {
 	if (_lastIndex > ARRAYSIZE(_entries))
 		return 0;
 
@@ -70,41 +64,34 @@ int MovementTrack::append(int waypointId, int delay, int angle, int running)
 	return 1;
 }
 
-void MovementTrack::flush()
-{
+void MovementTrack::flush() {
 	reset();
 }
 
-void MovementTrack::repeat()
-{
+void MovementTrack::repeat() {
 	_currentIndex = 0;
 	_hasNext = 1;
 }
 
-int MovementTrack::pause()
-{
+int MovementTrack::pause() {
 	_paused = 1;
 	return 1;
 }
 
-int MovementTrack::unpause()
-{
+int MovementTrack::unpause() {
 	_paused = 0;
 	return 1;
 }
 
-int MovementTrack::isPaused()
-{
+int MovementTrack::isPaused() {
 	return _paused;
 }
 
-int MovementTrack::hasNext()
-{
+int MovementTrack::hasNext() {
 	return _hasNext;
 }
 
-int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running)
-{
+int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running) {
 	if (_currentIndex < _lastIndex && this->_hasNext)
 	{
 		*waypointId = _entries[_currentIndex].waypointId;
@@ -112,9 +99,7 @@ int MovementTrack::next(int *waypointId, int *delay, int *angle, int *running)
 		*angle = _entries[_currentIndex].angle;
 		*running = _entries[_currentIndex++].running;
 		return 1;
-	}
-	else
-	{
+	} else {
 		*waypointId = -1;
 		*delay = -1;
 		*angle = -1;
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
index 976adc2..f5cb03f 100644
--- a/engines/bladerunner/movement_track.h
+++ b/engines/bladerunner/movement_track.h
@@ -30,8 +30,7 @@ namespace BladeRunner {
 class BladeRunnerEngine;
 class BoundingBox;
 
-struct MovementTrackEntry
-{
+struct MovementTrackEntry {
 	int waypointId;
 	int delay;
 	int angle;
diff --git a/engines/bladerunner/outtake.h b/engines/bladerunner/outtake.h
index 872656e..acbd00f 100644
--- a/engines/bladerunner/outtake.h
+++ b/engines/bladerunner/outtake.h
@@ -35,9 +35,7 @@ class OuttakePlayer {
 	BladeRunnerEngine *_vm;
 
 public:
-	OuttakePlayer(BladeRunnerEngine *vm) :
-		_vm(vm)
-	{}
+	OuttakePlayer(BladeRunnerEngine *vm) : _vm(vm) {}
 
 	void play(const Common::String &name, bool noLocalization, int container);
 };
diff --git a/engines/bladerunner/regions.h b/engines/bladerunner/regions.h
index 0b722c8..2dd6808 100644
--- a/engines/bladerunner/regions.h
+++ b/engines/bladerunner/regions.h
@@ -29,15 +29,13 @@
 
 namespace BladeRunner {
 
-struct Region
-{
+struct Region {
 	Common::Rect _rectangle;
 	int _type;
 	int _present;
 };
 
-class Regions
-{
+class Regions {
 #ifdef _DEBUG
 	friend class BladeRunnerEngine;
 #endif
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 5f52d85..947ee17 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -32,8 +32,7 @@ namespace BladeRunner {
 class BladeRunnerEngine;
 class View;
 
-enum SceneObjectType
-{
+enum SceneObjectType {
 	SceneObjectTypeUnknown = -1,
 	SceneObjectTypeActor = 0,
 	SceneObjectTypeObject = 1,
@@ -45,8 +44,7 @@ enum SceneObjectType
 #define SCENE_OBJECTS_ITEMS_OFFSET 74
 #define SCENE_OBJECTS_OBJECTS_OFFSET 198
 
-struct SceneObject
-{
+struct SceneObject {
 	int             _sceneObjectId;
 	SceneObjectType _sceneObjectType;
 	BoundingBox     _boundingBox;
diff --git a/engines/bladerunner/script/aiscript_officer_leroy.cpp b/engines/bladerunner/script/aiscript_officer_leroy.cpp
index f388ede..7881984 100644
--- a/engines/bladerunner/script/aiscript_officer_leroy.cpp
+++ b/engines/bladerunner/script/aiscript_officer_leroy.cpp
@@ -25,11 +25,10 @@
 namespace BladeRunner {
 
 AIScript_Officer_Leroy::AIScript_Officer_Leroy(BladeRunnerEngine *vm)
-	: AIScriptBase(vm)
-{}
+	: AIScriptBase(vm) {
+}
 
-void AIScript_Officer_Leroy::Initialize()
-{
+void AIScript_Officer_Leroy::Initialize() {
 	var_45D5B0_animation_state = 0;
 	var_45D5B4_frame = 0;
 	var_45D5B8 = 0;
@@ -84,14 +83,12 @@ bool AIScript_Officer_Leroy::GoalChanged(int currentGoalNumber, int newGoalNumbe
 	return false;
 }
 
-bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
-{
+bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame) {
 	if (var_45D5B8 == 0) {
 		*animation = 589;
 		var_45D5B4_frame++;
 
-		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(589))
-		{
+		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(589)) {
 			var_45D5B4_frame = 0;
 			var_45D5B8 = Random_Query(0, 2);
 		}
@@ -99,8 +96,7 @@ bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
 		*animation = 590;
 		var_45D5B4_frame++;
 
-		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(590))
-		{
+		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(590)) {
 			var_45D5B4_frame = 0;
 			var_45D5B8 = Random_Query(0, 2);
 		}
@@ -108,8 +104,7 @@ bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
 		*animation = 591;
 		var_45D5B4_frame++;
 
-		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(591))
-		{
+		if (var_45D5B4_frame >= Slice_Animation_Query_Number_Of_Frames(591)) {
 			var_45D5B4_frame = 0;
 			var_45D5B8 = Random_Query(0, 2);
 		}
@@ -118,13 +113,11 @@ bool AIScript_Officer_Leroy::UpdateAnimation(int *animation, int *frame)
 	return true;
 }
 
-bool AIScript_Officer_Leroy::ChangeAnimationMode(int mode)
-{
-	switch (mode)
-	{
-		case 1:
-			var_45D5B0_animation_state = 32;
-			break;
+bool AIScript_Officer_Leroy::ChangeAnimationMode(int mode) {
+	switch (mode) {
+	case 1:
+		var_45D5B0_animation_state = 32;
+		break;
 	}
 	return true;
 }
diff --git a/engines/bladerunner/script/ar02.cpp b/engines/bladerunner/script/ar02.cpp
index dc89758..2204027 100644
--- a/engines/bladerunner/script/ar02.cpp
+++ b/engines/bladerunner/script/ar02.cpp
@@ -224,7 +224,6 @@ bool ScriptAR02::ClickedOn2DRegion(int region) {
 }
 
 void ScriptAR02::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptAR02::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -386,5 +385,4 @@ void ScriptAR02::sub_402CE4() {
 	}
 }
 
-
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/bb03.cpp b/engines/bladerunner/script/bb03.cpp
index 24b4332..7307c5c 100644
--- a/engines/bladerunner/script/bb03.cpp
+++ b/engines/bladerunner/script/bb03.cpp
@@ -136,7 +136,6 @@ bool ScriptBB03::ClickedOn2DRegion(int region) {
 }
 
 void ScriptBB03::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptBB03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -154,7 +153,6 @@ void ScriptBB03::PlayerWalkedIn() {
 }
 
 void ScriptBB03::PlayerWalkedOut() {
-
 }
 
 void ScriptBB03::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/bb04.cpp b/engines/bladerunner/script/bb04.cpp
index ca96c11..b99ea50 100644
--- a/engines/bladerunner/script/bb04.cpp
+++ b/engines/bladerunner/script/bb04.cpp
@@ -108,7 +108,6 @@ bool ScriptBB04::ClickedOn2DRegion(int region) {
 }
 
 void ScriptBB04::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptBB04::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -123,7 +122,6 @@ void ScriptBB04::PlayerWalkedIn() {
 }
 
 void ScriptBB04::PlayerWalkedOut() {
-
 }
 
 void ScriptBB04::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/bb05.cpp b/engines/bladerunner/script/bb05.cpp
index 1f2b974..aff2f7b 100644
--- a/engines/bladerunner/script/bb05.cpp
+++ b/engines/bladerunner/script/bb05.cpp
@@ -140,7 +140,6 @@ bool ScriptBB05::ClickedOn2DRegion(int region) {
 }
 
 void ScriptBB05::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptBB05::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -206,7 +205,6 @@ void ScriptBB05::PlayerWalkedIn() {
 }
 
 void ScriptBB05::PlayerWalkedOut() {
-
 }
 
 void ScriptBB05::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/bb06.cpp b/engines/bladerunner/script/bb06.cpp
index d389fcc..66c9a85 100644
--- a/engines/bladerunner/script/bb06.cpp
+++ b/engines/bladerunner/script/bb06.cpp
@@ -169,7 +169,6 @@ void ScriptBB06::PlayerWalkedIn() {
 }
 
 void ScriptBB06::PlayerWalkedOut() {
-
 }
 
 void ScriptBB06::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/bb07.cpp b/engines/bladerunner/script/bb07.cpp
index 3284df8..7b9b4ae 100644
--- a/engines/bladerunner/script/bb07.cpp
+++ b/engines/bladerunner/script/bb07.cpp
@@ -159,7 +159,6 @@ bool ScriptBB07::ClickedOn2DRegion(int region) {
 }
 
 void ScriptBB07::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptBB07::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -177,7 +176,6 @@ void ScriptBB07::PlayerWalkedIn() {
 }
 
 void ScriptBB07::PlayerWalkedOut() {
-
 }
 
 void ScriptBB07::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/bb08.cpp b/engines/bladerunner/script/bb08.cpp
index cd05fe8..5464aab 100644
--- a/engines/bladerunner/script/bb08.cpp
+++ b/engines/bladerunner/script/bb08.cpp
@@ -109,7 +109,6 @@ bool ScriptBB08::ClickedOn2DRegion(int region) {
 }
 
 void ScriptBB08::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptBB08::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -129,7 +128,6 @@ void ScriptBB08::PlayerWalkedIn() {
 }
 
 void ScriptBB08::PlayerWalkedOut() {
-
 }
 
 void ScriptBB08::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/ct03.cpp b/engines/bladerunner/script/ct03.cpp
index 133c5d0..b7dcdd4 100644
--- a/engines/bladerunner/script/ct03.cpp
+++ b/engines/bladerunner/script/ct03.cpp
@@ -110,7 +110,6 @@ bool ScriptCT03::ClickedOn2DRegion(int region) {
 }
 
 void ScriptCT03::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptCT03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
diff --git a/engines/bladerunner/script/dr06.cpp b/engines/bladerunner/script/dr06.cpp
index 8556db7..f744d21 100644
--- a/engines/bladerunner/script/dr06.cpp
+++ b/engines/bladerunner/script/dr06.cpp
@@ -199,7 +199,6 @@ bool ScriptDR06::ClickedOn2DRegion(int region) {
 }
 
 void ScriptDR06::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptDR06::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
diff --git a/engines/bladerunner/script/hf02.cpp b/engines/bladerunner/script/hf02.cpp
index 8c6e24d..575e3f8 100644
--- a/engines/bladerunner/script/hf02.cpp
+++ b/engines/bladerunner/script/hf02.cpp
@@ -136,7 +136,6 @@ void ScriptHF02::PlayerWalkedIn() {
 }
 
 void ScriptHF02::PlayerWalkedOut() {
-
 }
 
 void ScriptHF02::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/init.h b/engines/bladerunner/script/init.h
index e7023fb..7b95008 100644
--- a/engines/bladerunner/script/init.h
+++ b/engines/bladerunner/script/init.h
@@ -32,8 +32,8 @@ class BladeRunnerEngine;
 class ScriptInit : ScriptBase {
 public:
 	ScriptInit(BladeRunnerEngine *vm)
-		: ScriptBase(vm)
-	{}
+		: ScriptBase(vm) {
+	}
 
 	void SCRIPT_Initialize_Game();
 
diff --git a/engines/bladerunner/script/ps15.cpp b/engines/bladerunner/script/ps15.cpp
index 3e8224a..5200d89 100644
--- a/engines/bladerunner/script/ps15.cpp
+++ b/engines/bladerunner/script/ps15.cpp
@@ -131,7 +131,6 @@ bool ScriptPS15::ClickedOn2DRegion(int region) {
 }
 
 void ScriptPS15::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptPS15::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -166,7 +165,6 @@ void ScriptPS15::PlayerWalkedIn() {
 }
 
 void ScriptPS15::PlayerWalkedOut() {
-
 }
 
 void ScriptPS15::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 9f4f539..216428c 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -84,7 +84,7 @@ void Script::SceneLoaded() {
 bool Script::MouseClick(int x, int y) {
 	if (_inScriptCounter > 0)
 		return true;
-	
+
 	_inScriptCounter++;
 	//MouseX = x;
 	//MouseY = y;
@@ -434,7 +434,7 @@ void ScriptBase::Actor_Voice_Over(int sentenceId, int actorId) {
 	_vm->gameWaitForActive();
 	_vm->loopActorSpeaking();
 	_vm->_adq->flush(1, true);
-	
+
 	Actor *actor = _vm->_actors[actorId];
 
 	actor->speechPlay(sentenceId, true);
@@ -1080,7 +1080,7 @@ void ScriptBase::Combat_Flee_Waypoint_Set_Data(int combatFleeWaypointId, int a2,
 void ScriptBase::Police_Maze_Target_Track_Add(int itemId, float startX, float startY, float startZ, float endX, float endY, float endZ, int steps, signed int data[], bool a10) {
 	//TODO
 	warning("Police_Maze_Target_Track_Add(%d, %f, %f, %f, %f, %f, %f, %d, %p, %d)", itemId,  startX,  startY,  startZ,  endX,  endY,  endZ,  steps,  (void *)data,  a10);
-	
+
 }
 
 // ScriptBase::Police_Maze_Query_Score
@@ -1184,7 +1184,7 @@ bool ScriptBase::Voight_Kampff_Activate(int a1, int a2){
 int ScriptBase::Elevator_Activate(int elevator) {
 	//TODO
 	warning("Elevator_Activate(%d)", elevator);
-	return 0;	
+	return 0;
 }
 
 void ScriptBase::View_Score_Board() {
@@ -1387,10 +1387,7 @@ void ScriptBase::ESPER_Define_Special_Region(int a1, int a2, int a3, int a4, int
 	warning("ESPER_Define_Special_Region(%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %s)",  a1,  a2,  a3,  a4,  a5,  a6,  a7,  a8,  a9,  a10,  a11,  a12,  a13, name);
 }
 
-AIScripts::AIScripts(BladeRunnerEngine *vm)
-	: _vm(vm),
-	  _inScriptCounter(0)
-{
+AIScripts::AIScripts(BladeRunnerEngine *vm) : _vm(vm), _inScriptCounter(0) {
 	for (int i = 0; i != 100; ++i)
 		_AIScripts[i] = 0;
 
@@ -1398,22 +1395,19 @@ AIScripts::AIScripts(BladeRunnerEngine *vm)
 	_AIScripts[23] = new AIScript_Officer_Leroy(_vm);
 }
 
-void AIScripts::Initialize(int actor)
-{
+void AIScripts::Initialize(int actor) {
 	if (_AIScripts[actor])
 		_AIScripts[actor]->Initialize();
 }
 
-void AIScripts::UpdateAnimation(int actor, int *animation, int *frame)
-{
+void AIScripts::UpdateAnimation(int actor, int *animation, int *frame) {
 	_inScriptCounter++;
 	if (_AIScripts[actor])
 		_AIScripts[actor]->UpdateAnimation(animation, frame);
 	_inScriptCounter--;
 }
 
-void AIScripts::ChangeAnimationMode(int actor, int mode)
-{
+void AIScripts::ChangeAnimationMode(int actor, int mode) {
 	_inScriptCounter++;
 	if (_AIScripts[actor])
 		_AIScripts[actor]->ChangeAnimationMode(mode);
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 914462a..0e4c0e9 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -34,11 +34,8 @@ protected:
 	BladeRunnerEngine *_vm;
 
 public:
-	ScriptBase(BladeRunnerEngine *vm)
-		: _vm(vm)
-	{}
-	virtual ~ScriptBase()
-	{}
+	ScriptBase(BladeRunnerEngine *vm) : _vm(vm) {}
+	virtual ~ScriptBase() {}
 
 protected:
 	void Preload(int animationId);
@@ -285,9 +282,7 @@ protected:
 
 class SceneScriptBase : public ScriptBase {
 public:
-	SceneScriptBase(BladeRunnerEngine *vm)
-		: ScriptBase(vm)
-	{}
+	SceneScriptBase(BladeRunnerEngine *vm) : ScriptBase(vm) {}
 
 	virtual void InitializeScene() = 0;
 	virtual void SceneLoaded() = 0;
@@ -317,8 +312,8 @@ public:
 	Script(BladeRunnerEngine *vm)
 		: _vm(vm),
 		  _inScriptCounter(0),
-		  _currentScript(nullptr)
-	{}
+		  _currentScript(nullptr) {
+	}
 	~Script();
 
 	bool open(const Common::String &name);
@@ -327,10 +322,10 @@ public:
 	void SceneLoaded();
 	bool MouseClick(int x, int y);
 	bool ClickedOn3DObject(const char *objectName, bool a2);
-	bool ClickedOnActor(int actorId); 
+	bool ClickedOnActor(int actorId);
 	bool ClickedOnItem(int itemId, bool a2);
-	bool ClickedOnExit(int exitId); 
-	bool ClickedOn2DRegion(int region); 
+	bool ClickedOnExit(int exitId);
+	bool ClickedOn2DRegion(int region);
 	void SceneFrameAdvanced(int frame);
 	void ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet);
 	void PlayerWalkedIn();
@@ -817,9 +812,7 @@ END_SCRIPT
 
 class AIScriptBase : public ScriptBase {
 public:
-	AIScriptBase(BladeRunnerEngine *vm)
-		: ScriptBase(vm)
-	{}
+	AIScriptBase(BladeRunnerEngine *vm) : ScriptBase(vm) {}
 
 	virtual void Initialize() = 0;
 	virtual bool Update() = 0;
diff --git a/engines/bladerunner/script/ug03.cpp b/engines/bladerunner/script/ug03.cpp
index fa41317..89c142d 100644
--- a/engines/bladerunner/script/ug03.cpp
+++ b/engines/bladerunner/script/ug03.cpp
@@ -128,7 +128,6 @@ bool ScriptUG03::ClickedOn2DRegion(int region) {
 }
 
 void ScriptUG03::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptUG03::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
diff --git a/engines/bladerunner/script/ug15.cpp b/engines/bladerunner/script/ug15.cpp
index c202e4f..c432882 100644
--- a/engines/bladerunner/script/ug15.cpp
+++ b/engines/bladerunner/script/ug15.cpp
@@ -195,7 +195,6 @@ void ScriptUG15::PlayerWalkedIn() {
 }
 
 void ScriptUG15::PlayerWalkedOut() {
-
 }
 
 void ScriptUG15::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/script/ug18.cpp b/engines/bladerunner/script/ug18.cpp
index 3ba8223..215d447 100644
--- a/engines/bladerunner/script/ug18.cpp
+++ b/engines/bladerunner/script/ug18.cpp
@@ -127,7 +127,6 @@ bool ScriptUG18::ClickedOn2DRegion(int region) {
 }
 
 void ScriptUG18::SceneFrameAdvanced(int frame) {
-
 }
 
 void ScriptUG18::ActorChangedGoal(int actorId, int newGoal, int oldGoal, bool currentSet) {
@@ -186,7 +185,6 @@ void ScriptUG18::PlayerWalkedIn() {
 }
 
 void ScriptUG18::PlayerWalkedOut() {
-
 }
 
 void ScriptUG18::DialogueQueueFlushed(int a1) {
diff --git a/engines/bladerunner/set_effects.h b/engines/bladerunner/set_effects.h
index 199009f..1e041ad 100644
--- a/engines/bladerunner/set_effects.h
+++ b/engines/bladerunner/set_effects.h
@@ -31,8 +31,7 @@
 
 namespace BladeRunner {
 
-class SetEffects
-{
+class SetEffects {
 	BladeRunnerEngine *_vm;
 
 private:
@@ -61,7 +60,7 @@ public:
 	void calculateColor(Vector3 viewPosition, Vector3 position, float *outCoeficient, Color *outColor);
 private:
 
-	Fog* findFog(const char* fogName);
+	Fog *findFog(const char* fogName);
 
 };
 
diff --git a/engines/bladerunner/settings.cpp b/engines/bladerunner/settings.cpp
index daf876c..679db51 100644
--- a/engines/bladerunner/settings.cpp
+++ b/engines/bladerunner/settings.cpp
@@ -30,9 +30,7 @@
 
 namespace BladeRunner {
 
-Settings::Settings(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+Settings::Settings(BladeRunnerEngine *vm) : _vm(vm) {
 	_chapter = 1;
 	_gamma = 1.0f;
 
diff --git a/engines/bladerunner/shape.cpp b/engines/bladerunner/shape.cpp
index 4f5a826..59fc103 100644
--- a/engines/bladerunner/shape.cpp
+++ b/engines/bladerunner/shape.cpp
@@ -33,8 +33,7 @@
 namespace BladeRunner {
 
 Shape::Shape(BladeRunnerEngine *vm)
-	: _vm(vm), _data(0)
-{
+	: _vm(vm), _data(0) {
 }
 
 Shape::~Shape() {
@@ -125,7 +124,7 @@ void Shape::draw(Graphics::Surface &surface, int x, int y) {
 		}
 
 		src_p += 2 * (_width - rect_w);
-		dst_p += surface.pitch - 2*rect_w;
+		dst_p += surface.pitch - 2 * rect_w;
 	}
 }
 
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index 0abdfb1..bed4271 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -46,8 +46,7 @@ struct SlicePalette {
 class SliceAnimations {
 	friend class SliceRenderer;
 
-	struct Animation
-	{
+	struct Animation {
 		uint32 frameCount;
 		uint32 frameSize;
 		float  fps;
@@ -60,9 +59,7 @@ class SliceAnimations {
 		void   *_data;
 		uint32 _lastAccess;
 
-		Page()
-			: _data(nullptr)
-		{}
+		Page() : _data(nullptr) {}
 	};
 
 	struct PageFile {
@@ -70,9 +67,7 @@ class SliceAnimations {
 		Common::File         _file;
 		Common::Array<int32> _pageOffsets;
 
-		PageFile(SliceAnimations *sliceAnimations)
-			: _sliceAnimations(sliceAnimations)
-		{}
+		PageFile(SliceAnimations *sliceAnimations) : _sliceAnimations(sliceAnimations) {}
 
 		bool  open(const Common::String &name);
 		void *loadPage(uint32 page);
@@ -96,8 +91,8 @@ public:
 	SliceAnimations(BladeRunnerEngine *vm)
 		: _vm(vm),
 		  _coreAnimPageFile(this),
-		  _framesPageFile(this)
-	{}
+		  _framesPageFile(this) {
+	}
 	~SliceAnimations();
 
 	bool open(const Common::String &name);
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index cf42f80..0972598 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -218,10 +218,8 @@ void SliceRenderer::calculateBoundingRect() {
 	float min_x =  640.0f;
 	float max_x =    0.0f;
 
-	for (float i = 0.0f; i <= 256.0f; i += 255.0f)
-	{
-		for (float j = 0.0f; j <= 256.0f; j += 255.0f)
-		{
+	for (float i = 0.0f; i <= 256.0f; i += 255.0f) {
+		for (float j = 0.0f; j <= 256.0f; j += 255.0f) {
 			Vector2 v1 = mB6 * Vector2(i, j);
 
 			min_x = MIN(min_x, v1.x);
@@ -275,11 +273,10 @@ struct SliceLineIterator {
 };
 
 void SliceLineIterator::setup(
-	float endScreenX,   float endScreenY,   float endScreenZ,
-	float startScreenX, float startScreenY, float startScreenZ,
-	float endSlice,     float startSlice,
-	Matrix3x2 m)
-{
+		float endScreenX,   float endScreenY,   float endScreenZ,
+		float startScreenX, float startScreenY, float startScreenZ,
+		float endSlice,     float startSlice,
+		Matrix3x2 m) {
 	_startY = (int)startScreenY;
 	_endY   = (int)endScreenY;
 
@@ -337,8 +334,7 @@ void SliceLineIterator::advance() {
 	_sliceMatrix[1][2] += _field_38;
 }
 
-static
-void setupLookupTable(int t[256], int inc) {
+static void setupLookupTable(int t[256], int inc) {
 	int v = 0;
 	for (int i = 0; i != 256; ++i) {
 		t[i] = v;
@@ -363,7 +359,7 @@ void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 posit
 	);
 
 	SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
-	
+
 	_lights->setupFrame(_view._frame);
 	_setEffects->setupFrame(_view._frame);
 
@@ -373,7 +369,7 @@ void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 posit
 		Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight),
 		Vector3(_position.x, _position.y, _position.z + _frameBottomZ),
 		sliceLineIterator._endY - sliceLineIterator._startY);
-	
+
 	float setEffectsColorCoeficient;
 	Color setEffectColor;
 	_setEffects->calculateColor(
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index 9cbd3ce..c1c0dc4 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -31,7 +31,7 @@
 #include "graphics/surface.h"
 
 namespace Common {
-	class MemoryReadStream;
+class MemoryReadStream;
 }
 
 namespace BladeRunner {
@@ -115,7 +115,8 @@ private:
 		float   _hmm[20];
 		float   _hmm2[20];
 		int     _hmm3;
-	public: 
+
+	public:
 		Color   _finalColor;
 
 	public:
diff --git a/engines/bladerunner/text_resource.cpp b/engines/bladerunner/text_resource.cpp
index 801808d..03460d0 100644
--- a/engines/bladerunner/text_resource.cpp
+++ b/engines/bladerunner/text_resource.cpp
@@ -30,9 +30,7 @@
 
 namespace BladeRunner {
 
-TextResource::TextResource(BladeRunnerEngine *vm)
-	: _vm(vm)
-{
+TextResource::TextResource(BladeRunnerEngine *vm) : _vm(vm) {
 	_count   = 0;
 	_ids     = nullptr;
 	_offsets = nullptr;
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index 80fd5f8..070ca86 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -27,35 +27,25 @@
 
 namespace BladeRunner {
 
-class Vector2
-{
+class Vector2 {
 public:
 	float x;
 	float y;
 
-	Vector2()
-		: x(0.0), y(0.0)
-	{}
+	Vector2() : x(0.0), y(0.0) {}
 
-	Vector2(float ax, float ay)
-		: x(ax), y(ay)
-	{}
+	Vector2(float ax, float ay) : x(ax), y(ay) {}
 };
 
-class Vector3
-{
+class Vector3 {
 public:
 	float x;
 	float y;
 	float z;
 
-	Vector3()
-		: x(0.0), y(0.0), z(0.0)
-	{}
+	Vector3() : x(0.0), y(0.0), z(0.0) {}
 
-	Vector3(float ax, float ay, float az)
-		: x(ax), y(ay), z(az)
-	{}
+	Vector3(float ax, float ay, float az) : x(ax), y(ay), z(az) {}
 
 	float length() { return sqrtf(x * x + y * y + z * z); }
 	Vector3 normalize() {
@@ -74,68 +64,47 @@ public:
 	}
 };
 
-inline
-Vector3 operator+(Vector3 a, Vector3 b)
-{
+inline Vector3 operator+(Vector3 a, Vector3 b) {
 	return Vector3(a.x + b.x, a.y + b.y, a.z + b.z);
 }
 
-inline
-Vector3 operator-(Vector3 a, Vector3 b)
-{
+inline Vector3 operator-(Vector3 a, Vector3 b) {
 	return Vector3(a.x - b.x, a.y - b.y, a.z - b.z);
 }
 
-inline
-Vector3 operator*(float f, Vector3 v)
-{
+inline Vector3 operator*(float f, Vector3 v) {
 	return Vector3(f * v.x, f * v.y, f * v.z);
 }
 
-class Vector4
-{
+class Vector4 {
 public:
 	float x;
 	float y;
 	float z;
 	float w;
 
-	Vector4()
-		: x(0.0), y(0.0), z(0.0), w(0.0)
-	{}
+	Vector4() : x(0.0), y(0.0), z(0.0), w(0.0) {}
 
-	Vector4(float ax, float ay, float az, float aw)
-		: x(ax), y(ay), z(az), w(aw)
-	{}
+	Vector4(float ax, float ay, float az, float aw) : x(ax), y(ay), z(az), w(aw) {}
 };
 
-inline
-Vector4 operator+(Vector4 a, Vector4 b)
-{
+inline Vector4 operator+(Vector4 a, Vector4 b) {
 	return Vector4(a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w);
 }
 
-inline
-Vector4 operator-(Vector4 a, Vector4 b)
-{
+inline Vector4 operator-(Vector4 a, Vector4 b) {
 	return Vector4(a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w);
 }
 
-inline
-Vector4 operator*(float f, Vector4 v)
-{
+inline Vector4 operator*(float f, Vector4 v) {
 	return Vector4(f * v.x, f * v.y, f * v.z, f * v.w);
 }
 
-inline
-Vector4 operator*(Vector4 v, float f)
-{
+inline Vector4 operator*(Vector4 v, float f) {
 	return Vector4(f * v.x, f * v.y, f * v.z, f * v.w);
 }
 
-inline
-Vector4 operator/(Vector4 a, Vector4 b)
-{
+inline Vector4 operator/(Vector4 a, Vector4 b) {
 	return Vector4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
 }
 
diff --git a/engines/bladerunner/view.h b/engines/bladerunner/view.h
index bb92dc1..eb68aa9 100644
--- a/engines/bladerunner/view.h
+++ b/engines/bladerunner/view.h
@@ -26,7 +26,7 @@
 #include "matrix.h"
 
 namespace Common {
-	class ReadStream;
+class ReadStream;
 }
 
 namespace BladeRunner {
diff --git a/engines/bladerunner/vqa_decoder.cpp b/engines/bladerunner/vqa_decoder.cpp
index df1b4f4..940f53e 100644
--- a/engines/bladerunner/vqa_decoder.cpp
+++ b/engines/bladerunner/vqa_decoder.cpp
@@ -81,8 +81,7 @@ int32 remain(Common::SeekableReadStream *s) {
 	return size - pos;
 }
 
-struct IFFChunkHeader
-{
+struct IFFChunkHeader {
 	IFFChunkHeader()
 		: id(0), size(0)
 	{}
@@ -91,9 +90,7 @@ struct IFFChunkHeader
 	uint32 size;
 };
 
-static
-bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
-{
+static bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts) {
 	if (remain(s) < 8)
 		return false;
 
@@ -103,13 +100,11 @@ bool readIFFChunkHeader(Common::SeekableReadStream *s, IFFChunkHeader *ts)
 	return true;
 }
 
-static inline uint32 roundup(uint32 v)
-{
+static inline uint32 roundup(uint32 v) {
 	return (v + 1) & ~1u;
 }
 
-const char *strTag(uint32 tag)
-{
+const char *strTag(uint32 tag) {
 	static char s[5];
 
 	sprintf(s, "%c%c%c%c",
@@ -121,15 +116,13 @@ const char *strTag(uint32 tag)
 	return s;
 }
 
-VQADecoder::VQADecoder()
-	: _s(nullptr),
+VQADecoder::VQADecoder() : _s(nullptr),
 	  _frameInfo(nullptr),
 	  _videoTrack(nullptr),
 	  _audioTrack(nullptr),
 	  _maxVIEWChunkSize(0),
 	  _maxZBUFChunkSize(0),
-	  _maxAESCChunkSize(0)
-{
+	  _maxAESCChunkSize(0) {
 }
 
 VQADecoder::~VQADecoder() {
@@ -160,20 +153,19 @@ bool VQADecoder::loadStream(Common::SeekableReadStream *s) {
 			return false;
 
 		rc = false;
-		switch (chd.id)
-		{
-			case kCINF: rc = readCINF(s, chd.size); break;
-			case kCLIP: rc = readCLIP(s, chd.size); break;
-			case kFINF: rc = readFINF(s, chd.size); break;
-			case kLINF: rc = readLINF(s, chd.size); break;
-			case kLNIN: rc = readLNIN(s, chd.size); break;
-			case kMFCI: rc = readMFCI(s, chd.size); break;
-			case kMSCI: rc = readMSCI(s, chd.size); break;
-			case kVQHD: rc = readVQHD(s, chd.size); break;
-			default:
-				warning("Unhandled chunk '%s'", strTag(chd.id));
-				s->skip(roundup(chd.size));
-				rc = true;
+		switch (chd.id) {
+		case kCINF: rc = readCINF(s, chd.size); break;
+		case kCLIP: rc = readCLIP(s, chd.size); break;
+		case kFINF: rc = readFINF(s, chd.size); break;
+		case kLINF: rc = readLINF(s, chd.size); break;
+		case kLNIN: rc = readLNIN(s, chd.size); break;
+		case kMFCI: rc = readMFCI(s, chd.size); break;
+		case kMSCI: rc = readMSCI(s, chd.size); break;
+		case kVQHD: rc = readVQHD(s, chd.size); break;
+		default:
+			warning("Unhandled chunk '%s'", strTag(chd.id));
+			s->skip(roundup(chd.size));
+			rc = true;
 		}
 
 		if (!rc) {
@@ -209,13 +201,11 @@ Audio::SeekableAudioStream *VQADecoder::decodeAudioFrame() {
 	return _audioTrack->decodeAudioFrame();
 }
 
-void VQADecoder::decodeView(View* view)
-{
+void VQADecoder::decodeView(View *view) {
 	_videoTrack->decodeView(view);
 }
 
-void VQADecoder::decodeLights(Lights *lights)
-{
+void VQADecoder::decodeLights(Lights *lights) {
 	_videoTrack->decodeLights(lights);
 }
 
@@ -235,20 +225,20 @@ void VQADecoder::readNextPacket() {
 
 		bool rc = false;
 		switch (chd.id) {
-			// Video track
-			case kAESC: rc = _videoTrack->readAESC(_s, chd.size); break;
-			case kLITE: rc = _videoTrack->readLITE(_s, chd.size); break;
-			case kVIEW: rc = _videoTrack->readVIEW(_s, chd.size); break;
-			case kVQFL: rc = _videoTrack->readVQFL(_s, chd.size); break;
-			case kVQFR: rc = _videoTrack->readVQFR(_s, chd.size); break;
-			case kZBUF: rc = _videoTrack->readZBUF(_s, chd.size); break;
-			// Sound track
-			case kSN2J: rc = _audioTrack->readSN2J(_s, chd.size); break;
-			case kSND2: rc = _audioTrack->readSND2(_s, chd.size); break;
+		// Video track
+		case kAESC: rc = _videoTrack->readAESC(_s, chd.size); break;
+		case kLITE: rc = _videoTrack->readLITE(_s, chd.size); break;
+		case kVIEW: rc = _videoTrack->readVIEW(_s, chd.size); break;
+		case kVQFL: rc = _videoTrack->readVQFL(_s, chd.size); break;
+		case kVQFR: rc = _videoTrack->readVQFR(_s, chd.size); break;
+		case kZBUF: rc = _videoTrack->readZBUF(_s, chd.size); break;
+		// Sound track
+		case kSN2J: rc = _audioTrack->readSN2J(_s, chd.size); break;
+		case kSND2: rc = _audioTrack->readSND2(_s, chd.size); break;
 
-			default:
-				_s->skip(roundup(chd.size));
-				rc = false;
+		default:
+			_s->skip(roundup(chd.size));
+			rc = false;
 		}
 
 		if (!rc) {
@@ -268,8 +258,7 @@ void VQADecoder::readPacket(int frame) {
 	readNextPacket();
 }
 
-bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size) {
 	if (size != 42)
 		return false;
 
@@ -295,14 +284,12 @@ bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 	_header.maxCBFZSize = s->readUint32LE();
 	_header.unk5        = s->readUint32LE();
 
-	if (_header.offsetX || _header.offsetY)
-	{
+	if (_header.offsetX || _header.offsetY) {
 		debug("_header.offsetX, _header.offsetY: %d %d", _header.offsetX, _header.offsetY);
 	}
 
 	// if (_header.unk3 || _header.unk4 != 4 || _header.unk5 || _header.flags != 0x0014)
-	if (false)
-	{
+	if (false) {
 		debug("_header.version      %d", _header.version);
 		debug("_header.flags        %04x", _header.flags);
 		debug("_header.numFrames    %d", _header.numFrames);
@@ -338,27 +325,23 @@ bool VQADecoder::readVQHD(Common::SeekableReadStream *s, uint32 size)
 	return true;
 }
 
-bool VQADecoder::VQAVideoTrack::readVQFR(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readVQFR(Common::SeekableReadStream *s, uint32 size) {
 	IFFChunkHeader chd;
 
-	while (size >= 8)
-	{
+	while (size >= 8) {
 		if (!readIFFChunkHeader(s, &chd))
 			return false;
 		size -= roundup(chd.size) + 8;
 
 		bool rc = false;
-		switch (chd.id)
-		{
+		switch (chd.id) {
 		case kCBFZ: rc = readCBFZ(s, chd.size); break;
 		case kVPTR: rc = readVPTR(s, chd.size); break;
 		default:
 			s->skip(roundup(chd.size));
 		}
 
-		if (!rc)
-		{
+		if (!rc) {
 			debug("VQFR: error handling chunk %s", strTag(chd.id));
 			return false;
 		}
@@ -367,8 +350,7 @@ bool VQADecoder::VQAVideoTrack::readVQFR(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size) {
 	IFFChunkHeader chd;
 	readIFFChunkHeader(_s, &chd);
 
@@ -384,14 +366,12 @@ bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
 	if (chd.id != kMSCT || chd.size != count * 0x10)
 		return false;
 
-	for (uint32 i = 0; i < count; ++i)
-	{
+	for (uint32 i = 0; i < count; ++i) {
 		uint32 tag, max_size;
 		tag  = s->readUint32BE();
 		max_size = s->readUint32LE();
 
-		switch (tag)
-		{
+		switch (tag) {
 		case kVIEW:
 			_maxVIEWChunkSize = max_size;
 			break;
@@ -413,8 +393,7 @@ bool VQADecoder::readMSCI(Common::SeekableReadStream *s, uint32 size)
 	return true;
 }
 
-bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size) {
 	IFFChunkHeader chd;
 	readIFFChunkHeader(_s, &chd);
 
@@ -432,8 +411,7 @@ bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size)
 		return false;
 
 	_loopInfo.loops = new Loop[_loopInfo.loopCount];
-	for (int i = 0; i != _loopInfo.loopCount; ++i)
-	{
+	for (int i = 0; i != _loopInfo.loopCount; ++i) {
 		_loopInfo.loops[i].begin = s->readUint16LE();
 		_loopInfo.loops[i].end   = s->readUint16LE();
 
@@ -443,8 +421,7 @@ bool VQADecoder::readLINF(Common::SeekableReadStream *s, uint32 size)
 	return true;
 }
 
-bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size) {
 	IFFChunkHeader chd;
 
 	readIFFChunkHeader(_s, &chd);
@@ -458,8 +435,7 @@ bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size)
 	if (chd.id != kCIND || chd.size != 6u * _clipInfo.clipCount)
 		return false;
 
-	for (int i = 0; i != _clipInfo.clipCount; ++i)
-	{
+	for (int i = 0; i != _clipInfo.clipCount; ++i) {
 		uint16 a;
 		uint32 b;
 		a = s->readUint16LE();
@@ -469,8 +445,7 @@ bool VQADecoder::readCINF(Common::SeekableReadStream *s, uint32 size)
 	return true;
 }
 
-bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size) {
 	if (size != 4u * _header.numFrames)
 		return false;
 
@@ -481,8 +456,7 @@ bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size)
 
 	if (false) {
 		uint32 last = 0;
-		for (uint32 i = 0; i != _header.numFrames; ++i)
-		{
+		for (uint32 i = 0; i != _header.numFrames; ++i) {
 			uint32 diff = _frameInfo[i] - last;
 			debug("_frameInfo[%4d] = 0x%08x   - %08x", i, _frameInfo[i], diff);
 			last = _frameInfo[i];
@@ -492,8 +466,7 @@ bool VQADecoder::readFINF(Common::SeekableReadStream *s, uint32 size)
 	return true;
 }
 
-bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::readLNIN(Common::SeekableReadStream *s, uint32 size) {
 	IFFChunkHeader chd;
 
 	readIFFChunkHeader(_s, &chd);
@@ -696,42 +669,34 @@ bool VQADecoder::VQAVideoTrack::readCBFZ(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-static
-int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
-{
+static int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen) {
 	uint32 dstSize = 640 * 480; // This is taken from global variables?
 	uint32 dstRemain = dstSize;
 
 	uint16 *curzp = curZBUF;
 	uint16 *inp = (uint16*)src;
 
-	while (dstRemain && (inp - (uint16*)src) < (std::ptrdiff_t)srcLen)
-	{
+	while (dstRemain && (inp - (uint16*)src) < (std::ptrdiff_t)srcLen) {
 		uint32 count = FROM_LE_16(*inp++);
 
-		if (count & 0x8000)
-		{
+		if (count & 0x8000) {
 			count = MIN(count & 0x7fff, dstRemain);
 			dstRemain -= count;
 
-			while (count--)
-			{
+			while (count--) {
 				uint16 value = FROM_LE_16(*inp++);
 				if (value)
 					*curzp = value;
 				++curzp;
 			}
-		}
-		else
-		{
+		} else {
 			count = MIN(count, dstRemain);
 			dstRemain -= count;
 			uint16 value = FROM_LE_16(*inp++);
 
-			if (!value)
+			if (!value) {
 				curzp += count;
-			else
-			{
+			} else {
 				while (count--)
 					*curzp++ = value;
 			}
@@ -740,8 +705,7 @@ int decodeZBUF_partial(uint8 *src, uint16 *curZBUF, uint32 srcLen)
 	return dstSize - dstRemain;
 }
 
-bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 size) {
 	if (size > _maxZBUFChunkSize) {
 		debug("VQA ERROR: ZBUF chunk size: %08x > %08x", size, _maxZBUFChunkSize);
 		s->skip(roundup(size));
@@ -756,8 +720,7 @@ bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 s
 
 	uint32 remain = size - 16;
 
-	if (_width != width || _height != height)
-	{
+	if (_width != width || _height != height) {
 		debug("%d, %d, %d, %d", width, height, complete, unk0);
 		s->skip(roundup(remain));
 		return false;
@@ -770,8 +733,7 @@ bool VQADecoder::VQAVideoTrack::readZBUF(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
-{
+const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer() {
 	if (_maxZBUFChunkSize == 0)
 		return nullptr;
 
@@ -788,8 +750,7 @@ const uint16 *VQADecoder::VQAVideoTrack::decodeZBuffer()
 	return _zbuffer;
 }
 
-bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 size) {
 	if (size != 56)
 		return false;
 
@@ -805,8 +766,7 @@ bool VQADecoder::VQAVideoTrack::readVIEW(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-void VQADecoder::VQAVideoTrack::decodeView(View* view)
-{
+void VQADecoder::VQAVideoTrack::decodeView(View *view) {
 	if (!view || !_viewData)
 		return;
 
@@ -817,16 +777,14 @@ void VQADecoder::VQAVideoTrack::decodeView(View* view)
 	_viewData = nullptr;
 }
 
-bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readAESC(Common::SeekableReadStream *s, uint32 size) {
 	debug("VQADecoder::readAESC(%d)", size);
 
 	s->skip(roundup(size));
 	return true;
 }
 
-bool VQADecoder::VQAVideoTrack::readLITE(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readLITE(Common::SeekableReadStream *s, uint32 size) {
 	if (_lightsData) {
 		delete[] _lightsData;
 		_lightsData = nullptr;
@@ -840,8 +798,7 @@ bool VQADecoder::VQAVideoTrack::readLITE(Common::SeekableReadStream *s, uint32 s
 }
 
 
-void VQADecoder::VQAVideoTrack::decodeLights(Lights *lights)
-{
+void VQADecoder::VQAVideoTrack::decodeLights(Lights *lights) {
 	if (!lights || !_lightsData)
 		return;
 
@@ -853,8 +810,7 @@ void VQADecoder::VQAVideoTrack::decodeLights(Lights *lights)
 }
 
 
-bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 size) {
 	if (size > _maxVPTRSize)
 		return false;
 
@@ -869,8 +825,7 @@ bool VQADecoder::VQAVideoTrack::readVPTR(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha)
-{
+void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBlock, unsigned int srcBlock, int count, bool alpha) {
 	uint16 frame_width  = _width;
 	uint32 frame_stride = 640;
 	uint16 block_width  = _blockW;
@@ -881,8 +836,7 @@ void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBl
 
 	int blocks_per_line = frame_width / block_width;
 
-	do
-	{
+	do {
 		uint32 frame_x = dstBlock % blocks_per_line * block_width  + _offsetX / 2;
 		uint32 frame_y = dstBlock / blocks_per_line * block_height + _offsetY;
 
@@ -892,11 +846,9 @@ void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBl
 		uint16      *__restrict dst = frame + dst_offset;
 
 		unsigned int block_y;
-		for (block_y = 0; block_y != block_height; ++block_y)
-		{
+		for (block_y = 0; block_y != block_height; ++block_y) {
 			unsigned int block_x;
-			for (block_x = 0; block_x != block_width; ++block_x)
-			{
+			for (block_x = 0; block_x != block_width; ++block_x) {
 				uint16 rgb555 = src[0] | (src[1] << 8);
 				src += 2;
 
@@ -908,12 +860,10 @@ void VQADecoder::VQAVideoTrack::VPTRWriteBlock(uint16 *frame, unsigned int dstBl
 		}
 
 		++dstBlock;
-	}
-	while (--count);
+	} while (--count);
 }
 
-bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
-{
+bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame) {
 	if (!_codebook || !_vpointer)
 		return false;
 
@@ -923,14 +873,12 @@ bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
 	uint16 count, srcBlock, dstBlock = 0;
 	(void)srcBlock;
 
-	while (end - src >= 2)
-	{
+	while (end - src >= 2) {
 		uint16 command = src[0] | (src[1] << 8);
 		uint8  prefix = command >> 13;
 		src += 2;
 
-		switch (prefix)
-		{
+		switch (prefix) {
 		case 0:
 			count = command & 0x1fff;
 			dstBlock += count;
@@ -949,8 +897,7 @@ bool VQADecoder::VQAVideoTrack::decodeFrame(uint16 *frame)
 			VPTRWriteBlock(frame, dstBlock, srcBlock, 1);
 			++dstBlock;
 
-			for (int i = 0; i < count; ++i)
-			{
+			for (int i = 0; i < count; ++i) {
 				srcBlock = *src++;
 				VPTRWriteBlock(frame, dstBlock, srcBlock, 1);
 				++dstBlock;
@@ -998,8 +945,7 @@ Audio::SeekableAudioStream *VQADecoder::VQAAudioTrack::decodeAudioFrame() {
 	return Audio::makeRawStream((byte*)audioFrame, 4 * 735, _frequency, flags, DisposeAfterUse::YES);
 }
 
-bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 size) {
 	if (size != 735) {
 		warning("audio frame size: %d", size);
 		return false;
@@ -1010,8 +956,7 @@ bool VQADecoder::VQAAudioTrack::readSND2(Common::SeekableReadStream *s, uint32 s
 	return true;
 }
 
-bool VQADecoder::VQAAudioTrack::readSN2J(Common::SeekableReadStream *s, uint32 size)
-{
+bool VQADecoder::VQAAudioTrack::readSN2J(Common::SeekableReadStream *s, uint32 size) {
 	if (size != 6)
 		return false;
 
diff --git a/engines/bladerunner/vqa_decoder.h b/engines/bladerunner/vqa_decoder.h
index eb486c8..7863afa 100644
--- a/engines/bladerunner/vqa_decoder.h
+++ b/engines/bladerunner/vqa_decoder.h
@@ -41,8 +41,7 @@ namespace BladeRunner {
 class Lights;
 class View;
 
-class VQADecoder
-{
+class VQADecoder {
 public:
 	VQADecoder();
 	~VQADecoder();
@@ -72,8 +71,7 @@ public:
 protected:
 
 private:
-	struct Header
-	{
+	struct Header {
 		uint16 version;     // 0x00
 		uint16 flags;       // 0x02
 		uint16 numFrames;   // 0x04
@@ -109,23 +107,18 @@ private:
 		{}
 	};
 
-	struct LoopInfo
-	{
+	struct LoopInfo {
 		uint16  loopCount;
 		uint32  flags;
 		Loop   *loops;
 
-		LoopInfo()
-			: loopCount(0),
-			  loops(nullptr)
-		{}
+		LoopInfo() : loopCount(0), loops(nullptr) {}
 		~LoopInfo() {
 			delete[] loops;
 		}
 	};
 
-	struct ClipInfo
-	{
+	struct ClipInfo {
 		uint16 clipCount;
 	};
 
diff --git a/engines/bladerunner/vqa_player.cpp b/engines/bladerunner/vqa_player.cpp
index 4d948fd..f875b84 100644
--- a/engines/bladerunner/vqa_player.cpp
+++ b/engines/bladerunner/vqa_player.cpp
@@ -113,13 +113,11 @@ const uint16 *VQAPlayer::getZBuffer() const {
 	return _zBuffer;
 }
 
-void VQAPlayer::updateView(View* view)
-{
+void VQAPlayer::updateView(View *view) {
 	_decoder.decodeView(view);
 }
 
-void VQAPlayer::updateLights(Lights* lights)
-{
+void VQAPlayer::updateLights(Lights *lights) {
 	_decoder.decodeLights(lights);
 }
 
diff --git a/engines/bladerunner/vqa_player.h b/engines/bladerunner/vqa_player.h
index 0acbb35..f576994 100644
--- a/engines/bladerunner/vqa_player.h
+++ b/engines/bladerunner/vqa_player.h
@@ -69,8 +69,8 @@ public:
 		  _loopEnd(-1),
 		  _nextFrameTime(0),
 		  _hasAudio(false),
-		  _audioStarted(false)
-	{}
+		  _audioStarted(false) {
+	}
 
 	~VQAPlayer() {
 		close();
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
index 3530da7..2d7fd19 100644
--- a/engines/bladerunner/waypoints.cpp
+++ b/engines/bladerunner/waypoints.cpp
@@ -23,7 +23,7 @@
 #include "bladerunner/waypoints.h"
 namespace BladeRunner {
 
-Waypoints::Waypoints(BladeRunnerEngine* vm, int count) {
+Waypoints::Waypoints(BladeRunnerEngine *vm, int count) {
 	_count = count;
 	_waypoints = new Waypoint[count];
 }


Commit: 6547c35e15252fd24f260ebd6b8f01d9edd01aa2
    https://github.com/scummvm/scummvm/commit/6547c35e15252fd24f260ebd6b8f01d9edd01aa2
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-04T18:15:57+02:00

Commit Message:
BLADERUNNER: trying to figure out walking, added structures for obstacles used for pathfinding, fixed bug in searching for walkboxes

Changed paths:
  A engines/bladerunner/obstacles.cpp
  A engines/bladerunner/obstacles.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor.h
    engines/bladerunner/actor_walk.cpp
    engines/bladerunner/actor_walk.h
    engines/bladerunner/adq.cpp
    engines/bladerunner/adq.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/items.cpp
    engines/bladerunner/items.h
    engines/bladerunner/module.mk
    engines/bladerunner/scene.cpp
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/scene_objects.h
    engines/bladerunner/script/nr03.cpp
    engines/bladerunner/script/nr05.cpp
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h
    engines/bladerunner/set.cpp
    engines/bladerunner/vector.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 1ea2b17..d1493b9 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -31,6 +31,7 @@
 #include "bladerunner/boundingbox.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/items.h"
+#include "bladerunner/mouse.h"
 #include "bladerunner/movement_track.h"
 #include "bladerunner/scene.h"
 #include "bladerunner/scene_objects.h"
@@ -39,8 +40,6 @@
 #include "bladerunner/slice_renderer.h"
 #include "bladerunner/waypoints.h"
 
-#include "common/system.h"
-
 namespace BladeRunner {
 
 Actor::Actor(BladeRunnerEngine *vm, int actorId) {
@@ -176,7 +175,21 @@ void Actor::processMovement() {
 	}*/
 }
 
-void Actor::setAtXYZ(Vector3 position, int facing, bool snapFacing, bool moving, bool retired) {
+bool Actor::loopWalkToActor(int otherActorId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) {
+	return loopWalk(_vm->_actors[otherActorId]->_position, destinationOffset, a3, run, _position, 24.0f, 24.0f, a5, isRunning, false);
+}
+
+bool Actor::loopWalkToItem(int itemId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) {
+	float x, y, z;
+	int width, height;
+	_vm->_items->getXYZ(itemId, &x, &y, &z);
+	_vm->_items->getWidthHeight(itemId, &width, &height);
+	Vector3 itemPosition(x, y, z);
+
+	return loopWalk(itemPosition, destinationOffset, a3, run, _position, width, 24.0f, a5, isRunning, false);
+}
+
+void Actor::setAtXYZ(const Vector3 &position, int facing, bool snapFacing, bool moving, bool retired) {
 	_position = position;
 	setFacing(facing, snapFacing);
 
@@ -201,76 +214,170 @@ void Actor::setAtWaypoint(int waypointId, int angle, int moving, bool retired) {
 	setAtXYZ(waypointPosition, angle, true, moving, retired);
 }
 
-void Actor::loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7) {
-	this->loopWalkToXYZ(Vector3(x, y, z));
-}
+bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool a3, bool run, const Vector3 &start, float targetWidth, float targetSize, bool a8, bool *isRunning, bool async) {
+	if (true) { // simple walking
+		*isRunning = false;
+		bool stopped;
+		_walkInfo->setup(_id, false, _position, destination, false, &stopped);
+
+		for (;;) {
+			_vm->gameTick();
+			if (!_walkInfo->isWalking() && !_walkInfo->isRunning())
+				break;
+			if (!_vm->_gameIsRunning)
+				break;
+		}
+		return false;
+	} else { 
+		//TODO:
+		// original code, not yet working
+		*isRunning = false;
+
+		if (destinationOffset > 0) {
+			float dist = distance(_position, destination);
+			if (dist - targetSize <= destinationOffset) {
+				return false;
+			}
+		}
+
+		if (a8 && !async && _id && destinationOffset <= 24) {
+			if (distance(_vm->_playerActor->_position, destination) <= 24.0f) {
+				_vm->_playerActor->walkToU(destination, 48.0f);
+			}
+		}
 
-void Actor::loopWalkToXYZ(Vector3 destination) {
-	int unk1;
-	_walkInfo->setup(_id, false, _position, destination, 0, &unk1);
+		if (_id) {
+			a3 = false;
+		}
 
-	for (;;) {
-		_vm->gameTick();
-		if (!_walkInfo->isWalking() && !_walkInfo->isRunning())
-			break;
-		if (!_vm->_gameIsRunning)
-			break;
+		Vector3 destinationX(destination);
+
+		if (destinationOffset > 0) {
+			walkFindU2(&destinationX, targetWidth, destinationOffset, targetSize, _position, destination);
+		}
+
+		bool walking = walkTo(run, destinationX, a8);
+
+		if (async) {
+			return false;
+		}
+
+		if (!walking && destinationOffset > 0) {
+			walking = walkTo(run, destination, a8);
+		}
+
+		if (!walking) {
+			return false;
+		}
+
+		if (async) {
+			return false;
+		}
+		if (_id) {
+			_vm->_mouse->disable();
+		}
+		if (a3) {
+			//			TODO:
+			//			dword_482990 = 1;
+			//			dword_482994 = 0;
+		} else {
+			_vm->playerLosesControl();
+		}
+
+		if (a8) {
+			_inWalkLoop = true;
+		}
+
+		bool v46 = false;
+		while (_walkInfo->isWalking() && _vm->_gameIsRunning) {
+			if (_walkInfo->isRunning()) {
+				*isRunning = true;
+			}
+			_vm->gameTick();
+			if (_id == 0 && a3 /*&& dword_482994*/) {
+				stopWalking(false);
+				v46 = true;
+			}
+		}
+		if (a8) {
+			_inWalkLoop = false;
+		}
+		if (a3) {
+			//			dword_482990 = 1;
+		} else {
+			_vm->playerGainsControl();
+		}
+		if (!v46 && destinationOffset == 0 /* && !PlayerActorIdle*/) {
+			setAtXYZ(destination, _facing, true, false, false);
+		}
+		if (_id) {
+			_vm->_mouse->enable();
+		}
+		return v46;
 	}
 }
 
-float distance(float, float, float, float);
-float distance(Vector3 &v1, Vector3 &v2);
+bool Actor::walkTo(bool run, const Vector3 &destination, bool a3) {
+	bool isRunning;
+
+	return _walkInfo->setup(_id, run, _position, destination, a3, &isRunning);
+}
+
+bool Actor::loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning) {
+	return loopWalk(destination, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false);
+}
 
-void Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset) {
+bool Actor::loopWalkToSceneObject(const char *objectName, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning) {
 	int sceneObject = _vm->_scene->_set->findObject(objectName);
-	if (sceneObject < 0)
-		return;
+	if (sceneObject < 0) {
+		return true;
+	}
 
 	BoundingBox bbox;
-	if (!_vm->_scene->_set->objectGetBoundingBox(sceneObject, &bbox))
-		return;
+	if (!_vm->_scene->_set->objectGetBoundingBox(sceneObject, &bbox)) {
+		return true;
+	}
 
 	float x0, y0, z0, x1, y1, z1;
 	bbox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
 
-	// debug("[%f %f] -> [%f %f %f, %f %f %f]", _position.x, _position.z, x0, y0, z0, x1, y1, z1);
-
-	float closest_distance = distance(_position.x, _position.z, x0, z0);
-	float closest_x = x0;
-	float closest_z = z0;
+	float closestDistance = distance(_position.x, _position.z, x0, z0);
+	float closestX = x0;
+	float closestZ = z0;
 
 	float d = distance(_position.x, _position.z, x1, z0);
-	// debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0);
-	if (d < closest_distance) {
-		closest_x = x1;
-		closest_z = z0;
-		closest_distance = d;
+	if (d < closestDistance) {
+		closestX = x1;
+		closestZ = z0;
+		closestDistance = d;
 	}
 
 	d = distance(_position.x, _position.z, x1, z1);
-	// debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0);
-	if (d < closest_distance) {
-		closest_x = x1;
-		closest_z = z1;
-		closest_distance = d;
+	if (d < closestDistance) {
+		closestX = x1;
+		closestZ = z1;
+		closestDistance = d;
 	}
 
 	d = distance(_position.x, _position.z, x0, z1);
-	// debug("%f - %f %f %f %f", d, _position.x, _position.z, x1, z0);
-	if (d < closest_distance) {
-		closest_x = x0;
-		closest_z = z1;
-		closest_distance = d;
+	if (d < closestDistance) {
+		closestX = x0;
+		closestZ = z1;
+		closestDistance = d;
 	}
+	bool inWalkbox;
+	float y = _vm->_scene->_set->getAltitudeAtXZ(closestX, closestZ, &inWalkbox);
+	Vector3 destination(closestX, y, closestZ);
 
-	// debug("%f = %f %f %f %f", closest_distance, _position.x, _position.z, closest_x, closest_z);
-
-	Vector3 destination(closest_x, _position.y, closest_z);
+	return loopWalk(destination, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false);
+}
 
-	// Vector3 properDestination(-124.2592, -0.3046913, 204.0923);
-	// debug("delta: %f\n", distance(destination, properDestination));
+bool Actor::loopWalkToWaypoint(int waypointId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning) {
+	float x, y, z;
+	_vm->_waypoints->getXYZ(waypointId, &x, &y, &z);
+	Vector3 waypointPosition(x, y, z);
 
-	loopWalkToXYZ(destination);
+	return loopWalk(waypointPosition, destinationOffset, a3, run, _position, 0.0f, 24.0f, a5, isRunning, false);
 }
 
 bool Actor::tick(bool forceDraw) {
@@ -299,7 +406,7 @@ bool Actor::tick(bool forceDraw) {
 		_animationFrame = newFrame;
 
 		Vector3 positionChange = _vm->_sliceAnimations->getPositionChange(_animationId);
-		float facingChange = _vm->_sliceAnimations->getFacingChange(_animationId);
+		float angleChange = _vm->_sliceAnimations->getFacingChange(_animationId);
 
 		if (_id == 47) {
 			positionChange.x = 0.0f;
@@ -331,10 +438,10 @@ bool Actor::tick(bool forceDraw) {
 				}
 			}
 		} else {
-			if (facingChange != 0.0f) {
-				int v27 = (512.0f / M_PI) * facingChange;
-				if (v27 != 0) {
-					this->_facing = this->_facing - v27;
+			if (angleChange != 0.0f) {
+				int facingChange = angleChange * (512.0f / M_PI);
+				if (facingChange != 0) {
+					this->_facing = this->_facing - facingChange;
 					if (this->_facing < 0) {
 						this->_facing += 1024;
 					}
@@ -356,9 +463,9 @@ bool Actor::tick(bool forceDraw) {
 					positionChange.z = positionChange.z * this->_actorSpeed.z;
 				}
 
-				float facing = (_facing / 512.0f) * M_PI;
-				float sinx = sin(facing);
-				float cosx = cos(facing);
+				float angle = _facing * (M_PI / 512.0f);
+				float sinx = sin(angle);
+				float cosx = cos(angle);
 
 				float originalX = this->_position.x;
 				float originalY = this->_position.y;
@@ -397,13 +504,13 @@ bool Actor::tick(bool forceDraw) {
 }
 
 void Actor::draw() {
-	Vector3 draw_position(_position.x, -_position.z, _position.y + 2.0);
-	float draw_facing = M_PI - _facing * M_PI / 512.0;
-	float draw_scale  = _scale;
+	Vector3 drawPosition(_position.x, -_position.z, _position.y + 2.0);
+	float drawAngle = M_PI - _facing * (M_PI / 512.0f);
+	float drawScale = _scale;
 
 	// TODO: Handle SHORTY mode
 
-	_vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, draw_position, draw_facing, draw_scale, _vm->_surface2, _vm->_zBuffer2);
+	_vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zBuffer2);
 	//todo udpate screenrect
 }
 
@@ -421,16 +528,16 @@ void Actor::setSetId(int setId) {
 	if (_setId > 0) {
 		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
-				// TODO: actorScript->OtherAgentExitedThisScene( i, _id);
+				// TODO: _vm->_aiScripts->OtherAgentExitedThisScene( i, _id);
 			}
 		}
 	}
 	_setId = setId;
-	// TODO: actorScript->EnteredScene(_id, set);
+	// TODO: _vm->_aiScripts->EnteredScene(_id, set);
 	if (_setId > 0) {
 		for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 			if (_vm->_actors[i]->_id != _id && _vm->_actors[i]->_setId == _setId) {
-				// TODO: actorScript->OtherAgentEnteredThisScene(i, _id);
+				// TODO: _vm->_aiScripts->OtherAgentEnteredThisScene(i, _id);
 			}
 		}
 	}
@@ -474,7 +581,7 @@ void Actor::setFacing(int facing, bool halfOrSet) {
 	_facing = (_facing + offset) % 1024;
 }
 
-void Actor::setBoundingBox(Vector3 position, bool retired) {
+void Actor::setBoundingBox(const Vector3 &position, bool retired) {
 	if (retired) {
 		_bbox->setXYZ(position.x - (_retiredWidth / 2.0f),
 		              position.y,
@@ -510,11 +617,11 @@ void Actor::stopWalking(bool value) {
 	}
 
 	if (isWalking()) {
-		_walkInfo->stop(_id, 1, _combatAnimationMode, 0);
+		_walkInfo->stop(_id, true, _combatAnimationMode, 0);
 	} else if (inCombat()) {
-		changeAnimationMode(_combatAnimationMode, 0);
+		changeAnimationMode(_combatAnimationMode, false);
 	} else {
-		changeAnimationMode(0, 0);
+		changeAnimationMode(0, false);
 	}
 }
 
@@ -563,13 +670,13 @@ void Actor::faceWaypoint(int waypointId, bool animate) {
 
 void Actor::faceXYZ(float x, float y, float z, bool animate) {
 	if (isWalking()) {
-		stopWalking(0);
+		stopWalking(false);
 	}
 	if (x == _position.x && z == _position.z) {
 		return;
 	}
 
-	int heading = int(512.0f * atan2f(_position.x - x, _position.z - z) / M_PI) % 1024;
+	int heading = angle_1024(_position.x, _position.z, x, z);
 	faceHeading(heading, animate);
 }
 
@@ -622,7 +729,7 @@ void Actor::setImmunityToObstacles(bool isImmune) {
 void Actor::modifyCurrentHP(signed int change) {
 	_currentHP = MIN(MAX(_currentHP + change, 0), 100);
 	if (_currentHP > 0)
-		retire(0, 0, 0, -1);
+		retire(false, 0, 0, -1);
 }
 
 void Actor::modifyMaxHP(signed int change) {
@@ -674,7 +781,7 @@ void Actor::setHealth(int hp, int maxHp) {
 	_currentHP = hp;
 	_maxHP = maxHp;
 	if (hp > 0) {
-		retire(0, 0, 0, -1);
+		retire(false, 0, 0, -1);
 	}
 }
 
@@ -685,8 +792,8 @@ void Actor::combatModeOn(int a2, int a3, int otherActorId, int a5, int combatAni
 	_inCombat = true;
 	if (_id > 0)
 		_combatInfo->combatOn(_id, a2, a3, otherActorId, a5, a9, a10, a11, ammoDamage, a13, a14);
-	stopWalking(0);
-	changeAnimationMode(_combatAnimationMode, 0);
+	stopWalking(false);
+	changeAnimationMode(_combatAnimationMode, false);
 	int i;
 	for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 		Actor *otherActor = _vm->_actors[i];
@@ -700,8 +807,8 @@ void Actor::combatModeOff() {
 	if (_id > 0)
 		_combatInfo->combatOff();
 	_inCombat = false;
-	stopWalking(0);
-	changeAnimationMode(0, 0);
+	stopWalking(false);
+	changeAnimationMode(0, false);
 	int i;
 	for (i = 0; i < (int)_vm->_gameInfo->getActorCount(); i++) {
 		Actor *otherActor = _vm->_actors[i];
@@ -868,4 +975,84 @@ void Actor::countdownTimerUpdate(int timerId) {
 	}
 }
 
+bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float size, Vector3 *newDestination) {
+	newDestination->x = 0.0f;
+	newDestination->y = 0.0f;
+	newDestination->z = 0.0f;
+	int facing = angle_1024(targetPosition, startPosition);
+	int facing1 = 0;
+
+	int facing2 = facing;
+	int facing3 = 0;
+	while (true) {
+		float cos = cos_1024(facing);
+		float sin = sin_1024(facing);
+		float rotatedX = size * sin + targetPosition.x;
+		float rotatedZ = size * cos + targetPosition.z;
+
+		if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) {
+			if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) {
+				newDestination->x = rotatedX;
+				newDestination->y = targetPosition.y;
+				newDestination->z = rotatedZ;
+				return true;
+			}
+		} else {
+			facing += 20;
+			if (facing > 1024) {
+				facing -= 1024;
+			}
+			facing3 += 20;
+		}
+
+		cos = cos_1024(facing2);
+		sin = sin_1024(facing2);
+		rotatedX = size * sin + targetPosition.x;
+		rotatedZ = size * cos + targetPosition.z;
+
+		if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) {
+			if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) {
+				newDestination->x = rotatedX;
+				newDestination->y = targetPosition.y;
+				newDestination->z = rotatedZ;
+				return true;
+			}
+		} else {
+			facing2 -= 20;
+			if (facing2 < 0) {
+				facing2 += 1024;
+			}
+			facing1 += 20;
+		}
+
+		if (facing3 > 1024 && facing1 > 1024) {
+			return false;
+		}
+	}
+}
+
+bool Actor::walkFindU2(Vector3 *newDestination, float targetWidth, int destinationOffset, float targetSize, const Vector3 &startPosition, const Vector3 &targetPosition) {
+	newDestination->x = 0.0f;
+	newDestination->y = 0.0f;
+	newDestination->z = 0.0f;
+	float size = destinationOffset + targetSize * 0.5f + targetWidth * 0.5f;
+	float distance = (startPosition - targetPosition).length() - targetWidth * 0.5f - targetSize * 0.5f;
+	if (size < distance) {
+		return walkFindU1(startPosition, targetPosition, size, newDestination);
+	} else {
+		*newDestination = targetPosition;
+		return true;
+	}
+}
+
+bool Actor::walkToU(const Vector3 &destination, float distance) {
+	Vector3 out;
+	bool isRunning;
+	if (_walkInfo->findU1(_id, destination, distance, &out)) {
+		loopWalk(out, 0, false, false, _position, 0.0f, 24.0f, false, &isRunning, false);
+		return true;
+	}
+	return false;
+}
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor.h b/engines/bladerunner/actor.h
index 1edbea4..b2b52c6 100644
--- a/engines/bladerunner/actor.h
+++ b/engines/bladerunner/actor.h
@@ -72,6 +72,7 @@ private:
 	bool _isTargetable;
 	bool _isInvisible;
 	bool _isImmuneToObstacles;
+	bool _inWalkLoop;
 	bool _isRetired;
 	bool _inCombat;
 	bool _isMoving;
@@ -106,7 +107,7 @@ public:
 
 	void setup(int actorId);
 
-	void setAtXYZ(Vector3 pos, int facing, bool setFacing = true, bool moving = false, bool retired = false);
+	void setAtXYZ(const Vector3 &pos, int facing, bool setFacing = true, bool moving = false, bool retired = false);
 	void setAtWaypoint(int waypointId, int angle, int unknown, bool retired);
 
 	float getX();
@@ -123,9 +124,11 @@ public:
 
 	void processMovement();
 
-	void loopWalkToXYZ(Vector3 destination);
-	void loopWalkToXYZ(float x, float y, float z, int a4, int a5, int a6, int a7);
-	void loopWalkToSceneObject(const char *objectName, int destinationOffset = 0);
+	bool loopWalkToActor(int otherActorId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning);
+	bool loopWalkToItem(int itemId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning);
+	bool loopWalkToSceneObject(const char *objectName, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning);
+	bool loopWalkToWaypoint(int waypointId, int destinationOffset, int a3, bool run, bool a5, bool *isRunning);
+	bool loopWalkToXYZ(const Vector3 &destination, int destinationOffset, bool a3, bool run, bool a5, bool *isRunning);
 
 	bool tick(bool forceUpdate);
 	void draw();
@@ -141,8 +144,9 @@ public:
 	Common::Rect *getScreenRectangle() { return &_screenRectangle; }
 	int getWalkbox() { return _walkboxId; }
 	bool isRetired() { return _isRetired; }
-	bool isTargetable() { return _isTargetable; }
+	bool isTargetable() { return _isTargetable; }	
 	void setTargetable(bool targetable);
+	bool isImmuneToObstacles() { return _isImmuneToObstacles; }
 	bool inCombat() { return _inCombat; }
 	bool isMoving() { return _isMoving; }
 	void setMoving(bool value) { _isMoving = value; }
@@ -198,8 +202,16 @@ public:
 	int soundBalance();
 private:
 	void setFacing(int facing, bool halfOrSet = true);
-	void setBoundingBox(Vector3 position, bool retired);
+	void setBoundingBox(const Vector3 &position, bool retired);
 	float distanceFromView(View* view);
+	
+	bool loopWalk(const Vector3 &destination, int destinationOffset, bool a3, bool run, const Vector3 &start, float a6, float a7, bool a8, bool *isRunning, bool async);
+	bool walkTo(bool run, const Vector3 &destination, bool a3);
+
+	bool walkFindU1(const Vector3 &startPosition, const Vector3 &targetPosition, float a3, Vector3 *newDestination);
+	bool walkFindU2(Vector3 *newDestination, float targetWidth, int destinationOffset, float targetSize, const Vector3 &startPosition, const Vector3 &targetPosition);
+	bool walkToU(const Vector3 &destination, float distance);
+	//bool walkFindU3(int actorId, Vector3 from, int distance, Vector3 *out);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index ed55bd0..717422f 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -25,14 +25,13 @@
 #include "bladerunner/bladerunner.h"
 
 #include "bladerunner/actor.h"
+#include "bladerunner/obstacles.h"
+#include "bladerunner/scene.h"
 #include "bladerunner/scene_objects.h"
+#include "bladerunner/set.h"
 
-namespace BladeRunner {
 
-static int angle_1024(float x1, float z1, float x2, float z2);
-static int angle_1024(Vector3 &v1, Vector3 &v2);
-float distance(float x1, float x2, float z1, float z2);
-float distance(Vector3 &v1, Vector3 &v2);
+namespace BladeRunner {
 
 ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
 	_vm = vm;
@@ -41,36 +40,38 @@ ActorWalk::ActorWalk(BladeRunnerEngine *vm) {
 	_running =  0;
 	_facing  = -1;
 	_status  =  0;
+
+	_entries.clear();
 }
 
 ActorWalk::~ActorWalk() {
 }
 
-int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2) {
+bool ActorWalk::setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped) {
 	Vector3 next;
 
-	*unk2 = 0;
+	*stopped = false;
 	int r = nextOnPath(actorId, from, to, &next);
 
 	if (r == 0) {
 		if (actorId != 0) {
 			_current = from;
 			_destination = to;
-			stop(actorId, false);
+			stop(actorId, false, 4, 0);
 		} else {
-			stop(actorId, true);
+			stop(actorId, true, 4, 0);
 		}
-		return 0;
+		return false;
 	}
 	if (r == -1) {
-		stop(actorId, true);
-		*unk2 = 1;
-		return 0;
+		stop(actorId, true, 4, 0);
+		*stopped = true;
+		return false;
 	}
 
-	// TODO: Init array
-	// TODO: Update screen index
-	// Set actor field e8
+	resetList();
+	_vm->_sceneObjects->setMoving(actorId + SCENE_OBJECTS_ACTORS_OFFSET, true);
+	_vm->_actors[actorId]->setMoving(true);
 
 	if (_running) {
 		run = true;
@@ -95,17 +96,17 @@ int ActorWalk::setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, i
 		_running = run;
 		_status = 2;
 
-		return 1;
+		return true;
 	}
 
-	stop(actorId, true);
-	return 0;
+	stop(actorId, true, 4, 0);
+	return false;
 }
 
 bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
 	if (_status == 5) {
 		if (flag) {
-			stop(actorId, true);
+			stop(actorId, true, 4, 0);
 			return true;
 		}
 
@@ -117,7 +118,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
 	// TODO: Handle collisions?
 
 	if (stepDistance > distance(_current, _destination)) {
-		stop(actorId, true);
+		stop(actorId, true, 4, 0);
 		_current = _destination;
 		// TODO: Update y from walkbox
 		return true;
@@ -127,7 +128,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
 
 	_current = Vector3(
 		_current.x + stepDistance * sinf(angle_rad),
-		_current.y,                    // TODO: Update from walkbox
+		_current.y, // TODO: Update from walkbox
 		_current.z - stepDistance * cosf(angle_rad)
 	);
 
@@ -135,7 +136,7 @@ bool ActorWalk::tick(int actorId, float stepDistance, bool flag) {
 }
 
 void ActorWalk::getCurrentPosition(int actorId, Vector3 *pos, int *facing) {
-	*pos    = _current;
+	*pos = _current;
 	*facing = _facing;
 }
 
@@ -144,14 +145,14 @@ void ActorWalk::setRunning() {
 	// TODO: Set animation mode
 }
 
-void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused) {
-	_vm->_sceneObjects->setMoving(actorId, 0);
-	_vm->_actors[actorId]->setMoving(0);
+void ActorWalk::stop(int actorId, bool unknown, int combatAnimationMode, int animationMode) {
+	_vm->_sceneObjects->setMoving(actorId, false);
+	_vm->_actors[actorId]->setMoving(false);
 
 	if (_vm->_actors[actorId]->inCombat()) {
-		_vm->_actors[actorId]->changeAnimationMode(animationMode, 0);
+		_vm->_actors[actorId]->changeAnimationMode(combatAnimationMode, false);
 	} else {
-		_vm->_actors[actorId]->changeAnimationMode(notused, 0);
+		_vm->_actors[actorId]->changeAnimationMode(animationMode, false);
 	}
 
 	if (unknown) {
@@ -165,45 +166,111 @@ void ActorWalk::stop(int actorId, bool unknown, int animationMode, int notused)
 	}
 }
 
-int ActorWalk::nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next) {
-	if (distance(from, to) < 6.0) {
-		return -1;
+bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) {
+	if (_vm->_scene->_set->findWalkbox(x, z) == -1) {
+		return true;
 	}
-
-	// if (_vm->_actors[actorId]->getImmunityToObstacles()) {
-		*next = to;
-		return 1;
-	// }
-
-	error("TODO!");
+	if (_vm->_actors[actorId]->isImmuneToObstacles()) {
+		return false;
+	}
+	return _vm->_sceneObjects->existsOnXZ(actorId, x, z, false, false);
 }
 
-static int angle_1024(float x1, float z1, float x2, float z2) {
-	float angle_rad = atan2(x2 - x1, z1 - z2);
-	int a = int(512.0 * angle_rad / M_PI);
-	return (a + 1024) % 1024;
-}
+int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) {
+	float cos, sin;
+	bool inWalkbox;
+
+	int facingFound = -1;
+	float distFound = -1.0f;
+	float x = 0.0f;
+	float z = 0.0f;
+
+	out->x = 0.0f;
+	out->y = 0.0f;
+	out->z = 0.0f;
+
+	for (int facing = 0; facing < 1024; facing += 128) {
+		sin = sin_1024(facing);
+		cos = cos_1024(facing);
+		x = to.x + sin * dist;
+		z = to.z + cos * dist;
+		float dist2 = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ());
+
+		if (distFound == -1.0f || distFound > dist2) {
+			distFound = dist2;
+			facingFound = facing;
+		}
+	}
 
-static int angle_1024(Vector3 &v1, Vector3 &v2) {
-	return angle_1024(v1.x, v1.z, v2.x, v2.z);
-}
+	int v23 = facingFound;
+	int v24 = facingFound;
+	int v25 = -1024;
+	while (v25 < 0) {
+		sin = sin_1024(v24);
+		cos = cos_1024(v24);
+		x = to.x + sin * dist;
+		z = to.z + cos * dist;
+
+		if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
+			break;
+		}
 
-float distance(float x1, float z1, float x2, float z2) {
-	float dx = x1 - x2;
-	float dz = z1 - z2;
-	float d = sqrt(dx * dx + dz * dz);
+		sin = sin_1024(v23);
+		cos = cos_1024(v23);
+		x = to.x + sin * dist;
+		z = to.z + cos * dist;
 
-	float int_part = (int)d;
-	float frac_part = d - int_part;
+		if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
+			break;
+		}
 
-	if (frac_part < 0.001)
-		frac_part = 0.0;
+		v24 -= 64;
+		if (v24 < 0) {
+			v24 += 1024;
+		}
+		v23 += 64;
+		if (v23 >= 1024) {
+			v23 -= 1024;
+		}
+		v25 += 64;
+	}
 
-	return int_part + frac_part;
+	float y = _vm->_scene->_set->getAltitudeAtXZ(x, z, &inWalkbox);
+	if (inWalkbox) {
+		out->x = x;
+		out->y = y;
+		out->z = z;
+		return true;
+	}
+	return false;
 }
 
-float distance(Vector3 &v1, Vector3 &v2) {
-	return distance(v1.x, v1.z, v2.x, v2.z);
+int ActorWalk::nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next) {
+	*next = from;
+
+	if (distance(from, to) < 6.0) {
+		return -1;
+	}
+
+	if (_vm->_actors[actorId]->isImmuneToObstacles()) {
+		*next = to;
+		return 1;
+	}
+	if (_vm->_scene->_set->findWalkbox(to.x, to.z) == -1) {
+		return 0;
+	}
+	if (_vm->_sceneObjects->existsOnXZ(actorId, to.x, to.z, false, false)) {
+		return 0;
+	}
+	Vector3 next1;
+	if (_vm->_obstacles->find(from, to, &next1)) {
+		*next = next1;
+		return 1;
+	}
+	return 0;
 }
 
+void ActorWalk::resetList() {
+	_entries.clear();
+}
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index 12da69b..6cd5850 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -24,6 +24,7 @@
 #define BLADERUNNER_ACTOR_WALK_H
 
 #include "bladerunner/vector.h"
+#include "common/array.h"
 
 namespace BladeRunner {
 
@@ -45,8 +46,7 @@ private:
 	Vector3 _current;
 	Vector3 _next;
 	int     _facing;
-	ActorWalkEntry _actors[20];
-	int     _actorsCount;
+	Common::Array<ActorWalk> _entries;
 	int     _field15;
 	int     _status;
 
@@ -54,7 +54,8 @@ public:
 	ActorWalk(BladeRunnerEngine *vm);
 	~ActorWalk();
 
-	int setup(int actorId, int run, Vector3 from, Vector3 to, int unk1, int *unk2);
+	
+	bool setup(int actorId, bool run, const Vector3 &from, const Vector3 &to, bool unk1, bool *stopped);
 	void getCurrentPosition(int actorId, Vector3 *pos, int *facing);
 	bool tick(int actorId, float stepDistance, bool flag);
 
@@ -62,10 +63,15 @@ public:
 	bool isRunning() { return _running; }
 	void setRunning();
 
-	void stop(int actorId, bool unknown, int animationMode = 4, int notused = 0);
+	void stop(int actorId, bool unknown, int combatAnimationMode, int animationMode);
 	// void setWalkingMode(int actorId, int active, int unk2 = 4, int unk3 = 0);
 
-	int nextOnPath(int actorId, Vector3 from, Vector3 to, Vector3 *next);
+	int nextOnPath(int actorId, const Vector3 &from, const Vector3 &to, Vector3 *next);
+
+	void resetList();
+
+	bool isXYZEmpty(float x, float y, float z, int actorId);
+	int findU1(int actorId, const Vector3 &to, int distance, Vector3 *out);
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/adq.cpp b/engines/bladerunner/adq.cpp
index b8611ee..ca72497 100644
--- a/engines/bladerunner/adq.cpp
+++ b/engines/bladerunner/adq.cpp
@@ -32,7 +32,7 @@
 
 namespace BladeRunner {
 
-ADQ::ADQEntry::ADQEntry() {
+ADQEntry::ADQEntry() {
 	this->_isNotPause = false;
 	this->_isPause = false;
 	this->_actorId = -1;
diff --git a/engines/bladerunner/adq.h b/engines/bladerunner/adq.h
index b0619c7..f4e69df 100644
--- a/engines/bladerunner/adq.h
+++ b/engines/bladerunner/adq.h
@@ -28,22 +28,21 @@ namespace BladeRunner {
 
 class BladeRunnerEngine;
 
+struct ADQEntry {
+	bool _isNotPause;
+	bool _isPause;
+	int _actorId;
+	int _sentenceId;
+	int _animationMode;
+	int _delay;
+
+	ADQEntry();
+};
+
 // actor dialogue queue??
 class ADQ {
 	BladeRunnerEngine *_vm;
 
-	class ADQEntry {
-	public:
-		bool _isNotPause;
-		bool _isPause;
-		int _actorId;
-		int _sentenceId;
-		int _animationMode;
-		int _delay;
-
-		ADQEntry();
-	};
-
 	Common::Array<ADQEntry> _entries;
 
 	bool     _isNotPause;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 3365bb1..66ed387 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -37,6 +37,7 @@
 #include "bladerunner/lights.h"
 #include "bladerunner/mouse.h"
 #include "bladerunner/outtake.h"
+#include "bladerunner/obstacles.h"
 #include "bladerunner/scene.h"
 #include "bladerunner/scene_objects.h"
 #include "bladerunner/script/init.h"
@@ -73,6 +74,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_lights = new Lights(this);
 	_combat = new Combat(this);
 	_adq = new ADQ(this);
+	_obstacles = new Obstacles(this);
 
 	_walkSoundId = -1;
 	_walkSoundVolume = 0;
@@ -100,6 +102,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
 
+	delete _obstacles;
 	delete _adq;
 	delete _combat;
 	delete _lights;
@@ -743,7 +746,8 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 	}
 
 	if (sceneObjectId == -1) {
-		_actors[0]->loopWalkToXYZ(mousePosition);
+		bool isRunning;
+		_playerActor->loopWalkToXYZ(mousePosition, 0, false, false, false, &isRunning);
 		debug("Clicked on nothing %f, %f, %f", mousePosition.x, mousePosition.y, mousePosition.z);
 		return;
 	} else if (sceneObjectId >= 0 && sceneObjectId <= 73) {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 273449f..d3759d6 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -49,6 +49,7 @@ class GameInfo;
 class Items;
 class Lights;
 class Mouse;
+class Obstacles;
 class Scene;
 class SceneObjects;
 class Script;
@@ -65,7 +66,7 @@ public:
 	bool      _gameIsRunning;
 	bool      _windowIsActive;
 	int       _playerLosesControlCounter;
-
+	
 	ADQ             *_adq;
 	AIScripts       *_aiScripts;
 	AmbientSounds   *_ambientSounds;
@@ -73,9 +74,13 @@ public:
 	AudioSpeech     *_audioSpeech;
 	Chapters        *_chapters;
 	Clues           *_clues;
+	Combat          *_combat;
 	GameFlags       *_gameFlags;
 	GameInfo        *_gameInfo;
+	Items           *_items;
+	Lights          *_lights;
 	Mouse           *_mouse;
+	Obstacles       *_obstacles;
 	Scene           *_scene;
 	SceneObjects    *_sceneObjects;
 	Script          *_script;
@@ -83,13 +88,9 @@ public:
 	SliceAnimations *_sliceAnimations;
 	SliceRenderer   *_sliceRenderer;
 	View            *_view;
-	int             *_gameVars;
-
-	Lights          *_lights;
 	Waypoints       *_waypoints;
-	Items           *_items;
-	Combat          *_combat;
-
+	int             *_gameVars;
+	
 	TextResource    *_textActorNames;
 	TextResource    *_textCrimes;
 	TextResource    *_textCluetype;
@@ -124,6 +125,7 @@ public:
 	int _walkSoundId;
 	int _walkSoundVolume;
 	int _walkSoundBalance;
+	int _walkingActorId;
 
 private:
 	static const int kArchiveCount = 10;
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index 11e75e9..00f98d3 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -66,6 +66,11 @@ void Item::getXYZ(float *x, float *y, float *z) {
 	*z = _position.z;
 }
 
+void Item::getWidthHeight(int *width, int *height) {
+	*width = _width;
+	*height = _height;
+}
+
 bool Item::isTargetable() {
 	return _isTargetable;
 }
@@ -84,7 +89,7 @@ void Item::tick(bool special) {
 			} else if (_facing < 0) {
 				_facing += 1024;
 			}
-			_angle = M_PI / 512.0f * _facing;
+			_angle = _facing * (M_PI / 512.0f);
 
 			if (_facingChange > 0) {
 				_facingChange = _facingChange - 20;
@@ -108,7 +113,7 @@ void Item::tick(bool special) {
 void Item::setXYZ(Vector3 position) {
 	_position = position;
 	int halfWidth = _width / 2;
-	_boundingBox.setXYZ(_position.x - halfWidth, _position.y,           _position.z - halfWidth,
+	_boundingBox.setXYZ(_position.x - halfWidth, _position.y, _position.z - halfWidth,
 	                    _position.x + halfWidth, _position.y + _height, _position.z + halfWidth);
 	Vector3 screenPosition = _vm->_view->calculateScreenPosition(_position);
 	_screenX = screenPosition.x;
@@ -121,7 +126,7 @@ void Item::setup(int itemId, int setId, int animationId, Vector3 position, int f
 	_setId = setId;
 	_animationId = animationId;
 	_facing = facing;
-	_angle = M_PI / 512.0f * facing;
+	_angle = facing * (M_PI / 512.0f);
 	_width = width;
 	_height = height;
 	_isTargetable = isTargetable;
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index bdcaea7..0035985 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -62,12 +62,16 @@ private:
 public:
 	Item(BladeRunnerEngine* vm);
 	~Item();
-
+	
 	void getXYZ(float *x, float *y, float *z);
+	void setXYZ(Vector3 position);
+	void getWidthHeight(int * width, int * height);
+
 	bool isTargetable();
 	void tick(bool special);
-	void setXYZ(Vector3 position);
+
 	void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy);
+	
 };
 
 }
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index e9cb013..51145a3 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -44,6 +44,13 @@ void Items::getXYZ(int itemId, float* x, float* y, float* z) {
 	_items[itemIndex]->getXYZ(x, y, z);
 }
 
+void Items::getWidthHeight(int itemId, int *width, int *height) {
+	int itemIndex = findItem(itemId);
+	assert(itemIndex != -1);
+
+	_items[itemIndex]->getWidthHeight(width, height);
+}
+
 void Items::tick() {
 	int setId = _vm->_scene->getSetId();
 	for(int i = 0; i < (int)_items.size(); i++) {
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index e6e1cb2..0b5c7e0 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -40,9 +40,12 @@ public:
 	~Items();
 
 	void getXYZ(int itemId, float *x, float *y, float *z);
+	void getWidthHeight(int itemId, int * width, int * height);
+
 	void tick();
 	bool add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool b);
 	bool remove(int itemId);
+	
 private:
 	int findItem(int itemId);
 };
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 3867331..b7c85ce 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -31,6 +31,7 @@ MODULE_OBJS = \
 	matrix.o \
 	mouse.o \
 	movement_track.o \
+	obstacles.o \
 	outtake.o \
 	regions.o \
 	scene.o \
diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp
new file mode 100644
index 0000000..3c9552d
--- /dev/null
+++ b/engines/bladerunner/obstacles.cpp
@@ -0,0 +1,46 @@
+#include "bladerunner/obstacles.h"
+
+#include "bladerunner/bladerunner.h"
+
+namespace BladeRunner {
+
+Obstacles::Obstacles(BladeRunnerEngine* vm) {
+	_vm = vm;
+	_polygons  = new ObstaclesPolygon[50];
+	_polygons2 = new ObstaclesPolygon[50];
+	_unknown = new int[50];
+	clear();
+}
+
+Obstacles::~Obstacles() {
+	delete[] _unknown;
+	delete[] _polygons2;
+	delete[] _polygons;
+}
+
+void Obstacles::clear() {
+	for(int i = 0; i < 50; i++) {
+		_polygons[i]._isPresent = false;
+		_polygons[i]._verticesCount = 0;
+		for(int j = 0; j < 160; j++) {
+			_polygons[i]._vertices[j].x = 0.0f;
+			_polygons[i]._vertices[j].y = 0.0f;
+		}
+	}
+	_count = 0;
+	_processed = false;
+}
+
+void Obstacles::add(float x0, float z0, float x1, float z1) {
+
+}
+
+bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) {
+	//TODO
+	*next = to;
+	return true;
+}
+
+void Obstacles::process() {
+}
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h
new file mode 100644
index 0000000..2caa3cd
--- /dev/null
+++ b/engines/bladerunner/obstacles.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.
+*
+*/
+
+#ifndef BLADERUNNER_OBSTACLES_H
+#define BLADERUNNER_OBSTACLES_H
+#include "vector.h"
+
+namespace BladeRunner {
+
+struct ObstaclesPolygon {
+	bool    _isPresent;
+	int     _verticesCount;
+	float   _left;
+	float   _bottom;
+	float   _right;
+	float   _top;
+	Vector2 _vertices[160];
+	int     _vertexType[160];
+};
+
+class BladeRunnerEngine;
+
+class Obstacles {
+	BladeRunnerEngine *_vm;
+
+private:
+	ObstaclesPolygon *_polygons;
+	ObstaclesPolygon *_polygons2;
+	int              *_unknown;
+	int               _count;
+	bool              _processed;
+
+public:
+	Obstacles(BladeRunnerEngine *vm);
+	~Obstacles();
+
+	void clear();
+	void add(float x0, float z0, float x1, float z1);
+	bool find(const Vector3 &from, const Vector3 &to, Vector3 *next);
+	void process();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index 06563b7..f9a112e 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -236,7 +236,7 @@ void Scene::objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded,
 	if (sceneLoaded) {
 		_vm->_sceneObjects->setIsObstacle(objectId + 198, isObstacle);
 		if(updateWalkpath) {
-			_vm->_sceneObjects->updateWalkpath();
+			_vm->_sceneObjects->updateObstacles();
 		}
 	}
 }
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 4c038fa..59df6c1 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -22,8 +22,12 @@
 
 #include "bladerunner/scene_objects.h"
 
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/obstacles.h"
 #include "bladerunner/view.h"
 
+
 namespace BladeRunner {
 
 SceneObjects::SceneObjects(BladeRunnerEngine *vm, View *view) {
@@ -280,8 +284,18 @@ void SceneObjects::setIsTarget(int sceneObjectId, bool isTarget) {
 }
 
 
-void SceneObjects::updateWalkpath() {
-	//TODO: implement
+void SceneObjects::updateObstacles() {
+	_vm->_obstacles->clear();
+	for(int i = 0; i < _count; i++) {
+		int index = _sceneObjectsSortedByDistance[i];
+		SceneObject sceneObject = _sceneObjects[index];
+		if(sceneObject._isObstacle) {
+			float x0, y0, z0, x1, y1, z1;
+			sceneObject._boundingBox.getXYZ(&x0, &y0, &z0, &x1, &y1, &z1);
+			_vm->_obstacles->add(x0, z0, x1, z1);
+		}
+	}
+	_vm->_obstacles->process();
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.h b/engines/bladerunner/scene_objects.h
index 947ee17..010dc43 100644
--- a/engines/bladerunner/scene_objects.h
+++ b/engines/bladerunner/scene_objects.h
@@ -87,7 +87,7 @@ public:
 	void setIsClickable(int sceneObjectId, bool isClickable);
 	void setIsObstacle(int sceneObjectId, bool isObstacle);
 	void setIsTarget(int sceneObjectId, bool isTarget);
-	void updateWalkpath();
+	void updateObstacles();
 
 private:
 	int findById(int sceneObjectId);
diff --git a/engines/bladerunner/script/nr03.cpp b/engines/bladerunner/script/nr03.cpp
index f0d2f35..a4afdd3 100644
--- a/engines/bladerunner/script/nr03.cpp
+++ b/engines/bladerunner/script/nr03.cpp
@@ -305,7 +305,7 @@ void ScriptNR03::sub_40259C(int frame) {
 	float z = -60.21f * s + 36.49f * c + -408.79f;
 
 	if (Actor_Query_Goal_Number(4) == 201) {
-		facing = angle * (1024.0f / (2.0f * M_PI));
+		facing = angle * (512.0f / M_PI);
 		facing = facing + 144;
 		if (facing < 0) {
 			facing = facing + 1168;
@@ -315,7 +315,7 @@ void ScriptNR03::sub_40259C(int frame) {
 		}
 		Actor_Set_At_XYZ(4, x, -70.19f, z, facing);
 	} else {
-		facing = angle * (1024.0f / (2.0f * M_PI));
+		facing = angle * (512.0f / M_PI);
 		facing = facing + 400;
 		if (facing < 0) {
 			facing = facing + 1424;
diff --git a/engines/bladerunner/script/nr05.cpp b/engines/bladerunner/script/nr05.cpp
index a62052b..d686bce 100644
--- a/engines/bladerunner/script/nr05.cpp
+++ b/engines/bladerunner/script/nr05.cpp
@@ -205,7 +205,7 @@ void ScriptNR05::sub_401F74(int frame) {
 	float x = 6.0f * s - 80.0f * c + -450.0f;
 	float z = 80.0f * s + 6.0f * c + -531.0f;
 
-	int facing = angle * (1024.0f / (2.0f * M_PI));
+	int facing = angle * (512.0f / M_PI);
 	facing = facing + 765;
 	if (facing < 0) {
 		facing = facing + 1789;
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index 9d88d2d..d94f104 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -215,7 +215,7 @@ bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) {
 	}
 
 	if (Object_Query_Click("HYDRANT02", objectName)) {
-		if (!Loop_Actor_Walk_To_Scene_Object(0, "HYDRANT02", 60, 1, false)) {
+		if (!Loop_Actor_Walk_To_Scene_Object(0, "HYDRANT02", 60, true, false)) {
 			if (Actor_Clue_Query(0, 26)) {
 				Actor_Says(0, 6975, 3);
 			} else {
@@ -230,7 +230,7 @@ bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) {
 	}
 
 	if (Object_Query_Click("DOOR LEFT", objectName)) {
-		if (!Loop_Actor_Walk_To_Scene_Object(0, "DOOR LEFT", 48, 1, false)) {
+		if (!Loop_Actor_Walk_To_Scene_Object(0, "DOOR LEFT", 48, true, false)) {
 			Actor_Face_Object(0, "DOOR LEFT", true);
 			if (!Actor_Clue_Query(0, 2) && Actor_Query_In_Set(23, 69) && Global_Variable_Query(1)) {
 				Actor_Set_Goal_Number(23, 0);
@@ -247,7 +247,7 @@ bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) {
 	}
 
 	if (Object_Query_Click("T-CAN01", objectName)) {
-		if (!Loop_Actor_Walk_To_Scene_Object(0, "T-CAN01", 24, 1, false)) {
+		if (!Loop_Actor_Walk_To_Scene_Object(0, "T-CAN01", 24, true, false)) {
 			Actor_Face_Object(0, "T-CAN01", true);
 			Actor_Voice_Over(1810, 99);
 			Actor_Voice_Over(1820, 99);
@@ -530,7 +530,7 @@ bool ScriptRC01::ClickedOnExit(int exitId) {
 }
 
 void ScriptRC01::sub_403850() {
-	if (!Game_Flag_Query(186) && !Loop_Actor_Walk_To_Scene_Object(0, "BARICADE03", 36, 1, false)) {
+	if (!Game_Flag_Query(186) && !Loop_Actor_Walk_To_Scene_Object(0, "BARICADE03", 36, true, false)) {
 		Actor_Set_Goal_Number(23, 0);
 		Actor_Face_Object(0, "BARICADE03", true);
 		Loop_Actor_Walk_To_Actor(23, 0, 36, 1, false);
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 216428c..180e8cb 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -540,48 +540,75 @@ int ScriptBase::Actor_Query_Animation_Mode(int actorId) {
 	return _vm->_actors[actorId]->getAnimationMode();
 }
 
-bool ScriptBase::Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int a3, int a4, bool running) {
+bool ScriptBase::Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int a3, int a4, bool run) {
 	//TODO
-	warning("Loop_Actor_Walk_To_Actor(%d, %d, %d, %d, %d)", actorId, otherActorId, a3, a4, running);
+	warning("Loop_Actor_Walk_To_Actor(%d, %d, %d, %d, %d)", actorId, otherActorId, a3, a4, run);
 	return false;
 }
 
-bool ScriptBase::Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool running) {
+bool ScriptBase::Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool run) {
 	//TODO
-	warning("Loop_Actor_Walk_To_Item(%d, %d, %d, %d, %d)", actorId, itemId, a3, a4, running);
+	warning("Loop_Actor_Walk_To_Item(%d, %d, %d, %d, %d)", actorId, itemId, a3, a4, run);
 	return false;
 }
 
-bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, int a4, bool running) {
+bool ScriptBase::Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int destinationOffset, bool a4, bool run) {
 	_vm->gameWaitForActive();
 
-	_vm->_actors[actorId]->loopWalkToSceneObject(objectName);
-
-	return false;
+	if(_vm->_walkingActorId == actorId) {
+		run = true;
+	}
+	bool isRunning;
+	bool result = _vm->_actors[actorId]->loopWalkToSceneObject(objectName, destinationOffset, a4, run, true, &isRunning);
+	if(isRunning == 1) {
+		_vm->_walkingActorId = actorId;
+	}
+	Global_Variable_Set(37, actorId);
+	Global_Variable_Set(38, isRunning);
+	return result;
 }
 
-bool ScriptBase::Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int a4, bool running) {
+bool ScriptBase::Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int destinationOffset, int a4, bool run) {
 	//TODO
-	warning("Loop_Actor_Walk_To_Waypoint(%d, %d, %d, %d, %d)", actorId, waypointId, a3, a4, running);
+	warning("Loop_Actor_Walk_To_Waypoint(%d, %d, %d, %d, %d)", actorId, waypointId, destinationOffset, a4, run);
 	return false;
 }
 
-bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, bool running, int a7) {
+bool ScriptBase::Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int destinationOffset, int a5, bool run, int a7) {
 	_vm->gameWaitForActive();
 
-	_vm->_actors[actorId]->loopWalkToXYZ(x, y, z, a4, a5, running, 1);
-
-	return false;
+	if(_vm->_walkingActorId == actorId) {
+		if(a7) {
+			_vm->_walkingActorId = -1;
+		} else {
+			run = true;
+		}
+	}
+	//TODO:
+	//PlayerActorIdle = 0;
+	bool isRunning;
+	bool result = _vm->_actors[actorId]->loopWalkToXYZ(Vector3(x, y, z), destinationOffset, a5, run, 1, &isRunning);
+
+//	if (PlayerActorIdle == 1) {
+//		result = 1;
+//		PlayerActorIdle = 0;
+//	}
+	if(isRunning) {
+		_vm->_walkingActorId = actorId;
+	}
+	Global_Variable_Set(37, actorId);
+	Global_Variable_Set(38, isRunning);
+	return result;
 }
 
-void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int running) {
+void ScriptBase::Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int destinationOffset, int run) {
 	//TODO
-	warning("Async_Actor_Walk_To_Waypoint(%d, %d, %d, %d)", actorId, waypointId, a3, running);
+	warning("Async_Actor_Walk_To_Waypoint(%d, %d, %d, %d)", actorId, waypointId, destinationOffset, run);
 }
 
-void ScriptBase::Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool running) {
+void ScriptBase::Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int destinationOffset, bool run) {
 	//TODO
-	warning("Async_Actor_Walk_To_XYZ(%d, %f, %f, %f, %d, %d)", actorId, x, y, z, a5, running);
+	warning("Async_Actor_Walk_To_XYZ(%d, %f, %f, %f, %d, %d)", actorId, x, y, z, destinationOffset, run);
 }
 
 void ScriptBase::Actor_Force_Stop_Walking(int actorId) {
@@ -692,11 +719,11 @@ void ScriptBase::Delay(int miliseconds) {
 }
 
 void ScriptBase::Player_Loses_Control() {
-		_vm->playerLosesControl();
+	_vm->playerLosesControl();
 }
 
 void ScriptBase::Player_Gains_Control() {
-		_vm->playerGainsControl();
+	_vm->playerGainsControl();
 }
 
 void ScriptBase::Player_Set_Combat_Mode(bool activate) {
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index 0e4c0e9..fb38fda 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -99,12 +99,12 @@ protected:
 	void Actor_Change_Animation_Mode(int actorId, int animationMode);
 	int Actor_Query_Animation_Mode(int actorId);
 	bool Loop_Actor_Walk_To_Actor(int actorId, int otherActorId, int a3, int a4, bool running);
-	bool Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool running);
-	bool Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, int a4, bool running);
-	bool Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int a4, bool running);
-	bool Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, bool running, int a7);
-	void Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int running);
-	void Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool running);
+	bool Loop_Actor_Walk_To_Item(int actorId, int itemId, int a3, int a4, bool run);
+	bool Loop_Actor_Walk_To_Scene_Object(int actorId, const char *objectName, int distance, bool a4, bool run);
+	bool Loop_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int a4, bool run);
+	bool Loop_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a4, int a5, bool run, int a7);
+	void Async_Actor_Walk_To_Waypoint(int actorId, int waypointId, int a3, int run);
+	void Async_Actor_Walk_To_XYZ(int actorId, float x, float y, float z, int a5, bool run);
 	void Actor_Force_Stop_Walking(int actorId);
 	bool Loop_Actor_Travel_Stairs(int actorId, int a2, int a3, int a4);
 	bool Loop_Actor_Travel_Ladder(int actorId, int a2, int a3, int a4);
diff --git a/engines/bladerunner/set.cpp b/engines/bladerunner/set.cpp
index 12db84a..f8a480c 100644
--- a/engines/bladerunner/set.cpp
+++ b/engines/bladerunner/set.cpp
@@ -91,10 +91,10 @@ bool Set::open(const Common::String &name) {
 	assert(_walkboxCount <= 95);
 
 	for (int i = 0; i < _walkboxCount; ++i) {
-		float x, y, z;
+		float x, z;
 
 		s->read(_walkboxes[i]._name, 20);
-		y = s->readFloatLE();
+		_walkboxes[i]._altitude = s->readFloatLE();
 		_walkboxes[i]._vertexCount = s->readUint32LE();
 
 		assert(_walkboxes[i]._vertexCount <= 8);
@@ -103,7 +103,7 @@ bool Set::open(const Common::String &name) {
 			x = s->readFloatLE();
 			z = s->readFloatLE();
 
-			_walkboxes[i]._vertices[j] = Vector3(x, y, z);
+			_walkboxes[i]._vertices[j] = Vector3(x, _walkboxes[i]._altitude, z);
 		}
 
 		// debug("WALKBOX: %s", _walkboxes[i]._name);
@@ -166,7 +166,8 @@ static bool isXZInWalkbox(float x, float z, const Walkbox &walkbox) {
 			if (x < lineX)
 				found++;
 		}
-
+		lastX = currentX;
+		lastZ = currentZ;
 	}
 	return found & 1;
 }
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index 070ca86..84e4df6 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -108,6 +108,54 @@ inline Vector4 operator/(Vector4 a, Vector4 b) {
 	return Vector4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
 }
 
+inline
+int angle_1024(float x1, float z1, float x2, float z2)
+{
+	float angle_rad = atan2(x2 - x1, z1 - z2);
+	int a = int(512.0 * angle_rad / M_PI);
+	return (a + 1024) % 1024;
+}
+
+inline
+int angle_1024(const Vector3 &v1, const Vector3 &v2)
+{
+	return angle_1024(v1.x, v1.z, v2.x, v2.z);
+}
+
+inline
+float distance(float x1, float z1, float x2, float z2)
+{
+	float dx = x1 - x2;
+	float dz = z1 - z2;
+	float d = sqrt(dx*dx + dz*dz);
+
+	float int_part = (int)d;
+	float frac_part = d - int_part;
+
+	if (frac_part < 0.001)
+		frac_part = 0.0;
+
+	return int_part + frac_part;
+}
+
+inline
+float distance(const Vector3 &v1, const Vector3 &v2)
+{
+	return distance(v1.x, v1.z, v2.x, v2.z);
+}
+
+inline
+float cos_1024(int angle1024) {
+	return cos(angle1024 * (M_PI / 512.0f));
+}
+
+inline
+float sin_1024(int angle1024) {
+	return sin(angle1024 * (M_PI / 512.0f));
+}
+
+
+
 } // End of namespace BladeRunner
 
 #endif


Commit: 2b835eb14dd5974b89e860066140ee35243f1c9a
    https://github.com/scummvm/scummvm/commit/2b835eb14dd5974b89e860066140ee35243f1c9a
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-04T18:19:45+02:00

Commit Message:
BLADERUNNER: added missing license & code formatting

Changed paths:
    engines/bladerunner/obstacles.cpp



diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp
index 3c9552d..61d2143 100644
--- a/engines/bladerunner/obstacles.cpp
+++ b/engines/bladerunner/obstacles.cpp
@@ -1,14 +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 "bladerunner/obstacles.h"
 
 #include "bladerunner/bladerunner.h"
 
 namespace BladeRunner {
 
-Obstacles::Obstacles(BladeRunnerEngine* vm) {
+Obstacles::Obstacles(BladeRunnerEngine *vm) {
 	_vm = vm;
 	_polygons  = new ObstaclesPolygon[50];
 	_polygons2 = new ObstaclesPolygon[50];
-	_unknown = new int[50];
+	_unknown   = new int[50];
 	clear();
 }
 
@@ -19,10 +41,10 @@ Obstacles::~Obstacles() {
 }
 
 void Obstacles::clear() {
-	for(int i = 0; i < 50; i++) {
+	for (int i = 0; i < 50; i++) {
 		_polygons[i]._isPresent = false;
 		_polygons[i]._verticesCount = 0;
-		for(int j = 0; j < 160; j++) {
+		for (int j = 0; j < 160; j++) {
 			_polygons[i]._vertices[j].x = 0.0f;
 			_polygons[i]._vertices[j].y = 0.0f;
 		}


Commit: 5d1e1131dc48f65de2f7c00bef3989df8d0d809f
    https://github.com/scummvm/scummvm/commit/5d1e1131dc48f65de2f7c00bef3989df8d0d809f
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-04T18:59:25+02:00

Commit Message:
BLADERUNNER: code formatting

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/actor_walk.cpp
    engines/bladerunner/obstacles.h
    engines/bladerunner/vector.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index d1493b9..f6ce1c0 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -985,10 +985,8 @@ bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPositi
 	int facing2 = facing;
 	int facing3 = 0;
 	while (true) {
-		float cos = cos_1024(facing);
-		float sin = sin_1024(facing);
-		float rotatedX = size * sin + targetPosition.x;
-		float rotatedZ = size * cos + targetPosition.z;
+		float rotatedX = size * sin_1024(facing) + targetPosition.x;
+		float rotatedZ = size * cos_1024(facing) + targetPosition.z;
 
 		if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) {
 			if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) {
@@ -1005,10 +1003,8 @@ bool Actor::walkFindU1(const Vector3 &startPosition, const Vector3 &targetPositi
 			facing3 += 20;
 		}
 
-		cos = cos_1024(facing2);
-		sin = sin_1024(facing2);
-		rotatedX = size * sin + targetPosition.x;
-		rotatedZ = size * cos + targetPosition.z;
+		rotatedX = size * sin_1024(facing2) + targetPosition.x;
+		rotatedZ = size * cos_1024(facing2) + targetPosition.z;
 
 		if (!_walkInfo->isXYZEmpty(rotatedX, targetPosition.y, rotatedZ, _id)) {
 			if (_vm->_scene->_set->findWalkbox(rotatedX, rotatedZ) >= 0) {
diff --git a/engines/bladerunner/actor_walk.cpp b/engines/bladerunner/actor_walk.cpp
index 717422f..556f7b9 100644
--- a/engines/bladerunner/actor_walk.cpp
+++ b/engines/bladerunner/actor_walk.cpp
@@ -177,7 +177,6 @@ bool ActorWalk::isXYZEmpty(float x, float y, float z, int actorId) {
 }
 
 int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) {
-	float cos, sin;
 	bool inWalkbox;
 
 	int facingFound = -1;
@@ -190,10 +189,8 @@ int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) {
 	out->z = 0.0f;
 
 	for (int facing = 0; facing < 1024; facing += 128) {
-		sin = sin_1024(facing);
-		cos = cos_1024(facing);
-		x = to.x + sin * dist;
-		z = to.z + cos * dist;
+		x = to.x + sin_1024(facing) * dist;
+		z = to.z + cos_1024(facing) * dist;
 		float dist2 = distance(x, z, _vm->_actors[actorId]->getX(), _vm->_actors[actorId]->getZ());
 
 		if (distFound == -1.0f || distFound > dist2) {
@@ -206,19 +203,15 @@ int ActorWalk::findU1(int actorId, const Vector3 &to, int dist, Vector3 *out) {
 	int v24 = facingFound;
 	int v25 = -1024;
 	while (v25 < 0) {
-		sin = sin_1024(v24);
-		cos = cos_1024(v24);
-		x = to.x + sin * dist;
-		z = to.z + cos * dist;
+		x = to.x + sin_1024(v24) * dist;
+		z = to.z + cos_1024(v24) * dist;
 
 		if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
 			break;
 		}
 
-		sin = sin_1024(v23);
-		cos = cos_1024(v23);
-		x = to.x + sin * dist;
-		z = to.z + cos * dist;
+		x = to.x + sin_1024(v23) * dist;
+		z = to.z + cos_1024(v23) * dist;
 
 		if (!_vm->_sceneObjects->existsOnXZ(actorId, x, z, true, true) && _vm->_scene->_set->findWalkbox(x, z) >= 0) {
 			break;
diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h
index 2caa3cd..9cf3ffa 100644
--- a/engines/bladerunner/obstacles.h
+++ b/engines/bladerunner/obstacles.h
@@ -1,28 +1,29 @@
 /* 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.
-*
-*/
+ *
+ * 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 BLADERUNNER_OBSTACLES_H
 #define BLADERUNNER_OBSTACLES_H
-#include "vector.h"
+
+#include "bladerunner/vector.h"
 
 namespace BladeRunner {
 
diff --git a/engines/bladerunner/vector.h b/engines/bladerunner/vector.h
index 84e4df6..d04070f 100644
--- a/engines/bladerunner/vector.h
+++ b/engines/bladerunner/vector.h
@@ -108,26 +108,20 @@ inline Vector4 operator/(Vector4 a, Vector4 b) {
 	return Vector4(a.x / b.x, a.y / b.y, a.z / b.z, a.w / b.w);
 }
 
-inline
-int angle_1024(float x1, float z1, float x2, float z2)
-{
+inline int angle_1024(float x1, float z1, float x2, float z2) {
 	float angle_rad = atan2(x2 - x1, z1 - z2);
 	int a = int(512.0 * angle_rad / M_PI);
 	return (a + 1024) % 1024;
 }
 
-inline
-int angle_1024(const Vector3 &v1, const Vector3 &v2)
-{
+inline int angle_1024(const Vector3 &v1, const Vector3 &v2) {
 	return angle_1024(v1.x, v1.z, v2.x, v2.z);
 }
 
-inline
-float distance(float x1, float z1, float x2, float z2)
-{
+inline float distance(float x1, float z1, float x2, float z2) {
 	float dx = x1 - x2;
 	float dz = z1 - z2;
-	float d = sqrt(dx*dx + dz*dz);
+	float d = sqrt(dx * dx + dz * dz);
 
 	float int_part = (int)d;
 	float frac_part = d - int_part;
@@ -138,24 +132,17 @@ float distance(float x1, float z1, float x2, float z2)
 	return int_part + frac_part;
 }
 
-inline
-float distance(const Vector3 &v1, const Vector3 &v2)
-{
+inline float distance(const Vector3 &v1, const Vector3 &v2) {
 	return distance(v1.x, v1.z, v2.x, v2.z);
 }
 
-inline
-float cos_1024(int angle1024) {
+inline float cos_1024(int angle1024) {
 	return cos(angle1024 * (M_PI / 512.0f));
 }
 
-inline
-float sin_1024(int angle1024) {
+inline float sin_1024(int angle1024) {
 	return sin(angle1024 * (M_PI / 512.0f));
 }
-
-
-
 } // End of namespace BladeRunner
 
 #endif


Commit: e0efee2eba7328914741340c2330056be8f27205
    https://github.com/scummvm/scummvm/commit/e0efee2eba7328914741340c2330056be8f27205
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-06T00:59:11+02:00

Commit Message:
BLADERUNNER: added suspects db & fixed crimes db

Changed paths:
  A engines/bladerunner/crimes_database.cpp
  A engines/bladerunner/crimes_database.h
  A engines/bladerunner/suspects_database.cpp
  A engines/bladerunner/suspects_database.h
  R engines/bladerunner/clues.cpp
  R engines/bladerunner/clues.h
    engines/bladerunner/actor_clues.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/gameinfo.cpp
    engines/bladerunner/gameinfo.h
    engines/bladerunner/items.cpp
    engines/bladerunner/module.mk
    engines/bladerunner/obstacles.cpp
    engines/bladerunner/obstacles.h
    engines/bladerunner/scene_objects.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/script/script.h



diff --git a/engines/bladerunner/actor_clues.cpp b/engines/bladerunner/actor_clues.cpp
index 9c0a61c..a84d549 100644
--- a/engines/bladerunner/actor_clues.cpp
+++ b/engines/bladerunner/actor_clues.cpp
@@ -22,7 +22,7 @@
 
 #include "bladerunner/actor_clues.h"
 
-#include "bladerunner/clues.h"
+#include "bladerunner/crimes_database.h"
 
 #include "common/debug.h"
 
@@ -53,20 +53,23 @@ ActorClues::ActorClues(BladeRunnerEngine *vm, int cluesType) {
 		return;
 	}
 
-	if (_maxCount > 0)
+	if (_maxCount > 0) {
 		_clues = new ActorClue[_maxCount];
-	else
-		_clues = NULL;
+	} else {
+		_clues = nullptr;
+	}
 
-	if (_clues)
+	if (_clues) {
 		removeAll();
-	else
+	} else {
 		_maxCount = 0;
+	}
 }
 
 ActorClues::~ActorClues() {
-	if (_clues)
+	if (_clues) {
 		delete[] _clues;
+	}
 
 	_maxCount = 0;
 	_count = 0;
@@ -78,7 +81,7 @@ void ActorClues::acquire(int clueId, char flag2, int fromActorId) {
 	_clues[_count]._flags = (_clues[_count]._flags & ~0x02) | ((flag2 << 1) & 0x02);
 	_clues[clueIndex]._fromActorId = fromActorId;
 
-	debug("Actor acquired clue: \"%s\" from %d", _vm->_clues->getClueText(clueId), fromActorId);
+	debug("Actor acquired clue: \"%s\" from %d", _vm->_crimesDatabase->getClueText(clueId), fromActorId);
 }
 
 void ActorClues::lose(int clueId) {
@@ -88,51 +91,58 @@ void ActorClues::lose(int clueId) {
 
 bool ActorClues::isAcquired(int clueId) {
 	int clueIndex = findClueIndex(clueId);
-	if (clueIndex == -1)
-		return 0;
+	if (clueIndex == -1) {
+		return false;
+	}
 
 	return _clues[clueIndex]._flags & 0x01;
 }
 
 int ActorClues::getFromActorId(int clueId) {
 	int clueIndex = findClueIndex(clueId);
-	if (clueIndex == -1)
+	if (clueIndex == -1) {
 		return  -1;
+	}
 
 	return _clues[clueIndex]._fromActorId;
 }
 
 bool ActorClues::isFlag2(int clueId) {
 	int clueIndex = findClueIndex(clueId);
-	if (clueIndex == -1)
-		return 0;
+	if (clueIndex == -1) {
+		return false;
+	}
 
 	return (_clues[clueIndex]._flags & 0x02) >> 1;
 }
 
 bool ActorClues::isFlag3(int clueId) {
 	int clueIndex = findClueIndex(clueId);
-	if (clueIndex == -1)
-		return 0;
+	if (clueIndex == -1) {
+		return false;
+	}
 
 	return (_clues[clueIndex]._flags & 0x04) >> 2;
 }
 
 bool ActorClues::isFlag4(int clueId) {
 	int clueIndex = findClueIndex(clueId);
-	if (clueIndex == -1)
-		return 0;
+	if (clueIndex == -1) {
+		return false;
+	}
 
 	return (_clues[clueIndex]._flags & 0x08) >> 3;
 }
 
 int ActorClues::getField1(int clueId) {
-	if (!_count)
+	if (!_count) {
 		return 0;
+	}
 
 	int clueIndex = findClueIndex(clueId);
-	if (clueIndex == -1)
+	if (clueIndex == -1) {
 		return 0;
+	}
 
 	return _clues[clueIndex]._field1;
 }
@@ -160,7 +170,7 @@ int ActorClues::findClueIndex(int clueId) {
 void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool unknownFlag, int fromActorId) {
 	assert(_count < _maxCount);
 
-	debug("Actor %d added clue: \"%s\" from %d", actorId, _vm->_clues->getClueText(clueId), fromActorId);
+	debug("Actor %d added clue: \"%s\" from %d", actorId, _vm->_crimesDatabase->getClueText(clueId), fromActorId);
 
 	_clues[_count]._clueId = clueId;
 	_clues[_count]._field1 = unknown;
@@ -174,8 +184,8 @@ void ActorClues::add(int actorId, int clueId, int unknown, bool acquired, bool u
 }
 
 void ActorClues::remove(int index) {
-	if (_vm->_clues)
-		debug("Actor removed clue: \"%s\"", _vm->_clues->getClueText(_clues[index]._clueId));
+	if (_vm->_crimesDatabase)
+		debug("Actor removed clue: \"%s\"", _vm->_crimesDatabase->getClueText(_clues[index]._clueId));
 
 	_clues[index]._clueId = -1;
 	_clues[index]._field1 = 0;
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 66ed387..804bfbd 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -28,8 +28,8 @@
 #include "bladerunner/audio_player.h"
 #include "bladerunner/audio_speech.h"
 #include "bladerunner/chapters.h"
-#include "bladerunner/clues.h"
 #include "bladerunner/combat.h"
+#include "bladerunner/crimes_database.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
@@ -58,6 +58,7 @@
 #include "engines/util.h"
 
 #include "graphics/pixelformat.h"
+#include "suspects_database.h"
 
 namespace BladeRunner {
 
@@ -68,7 +69,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_gameIsRunning  = true;
 	_playerLosesControlCounter = 0;
 
-	_clues = nullptr;
+	_crimesDatabase = nullptr;
 	_script = new Script(this);
 	_settings = new Settings(this);
 	_lights = new Lights(this);
@@ -267,7 +268,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	// TODO: Dialogue Menu (DLGMENU.TRE)
 
-	// TODO: SDB
+	_suspectsDatabase = new SuspectsDatabase(this, _gameInfo->getSuspectsDatabaseSize());
 
 	// TODO: KIA
 
@@ -312,7 +313,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	_sliceRenderer = new SliceRenderer(this);
 
-	_clues = new Clues(this, "CLUES", _gameInfo->getClueCount());
+	_crimesDatabase = new CrimesDatabase(this, "CLUES", _gameInfo->getClueCount());
 
 	// TODO: Scene
 	_scene = new Scene(this);
@@ -368,8 +369,8 @@ void BladeRunnerEngine::shutdown() {
 		_chapters = nullptr;
 	}
 
-	delete _clues;
-	_clues = nullptr;
+	delete _crimesDatabase;
+	_crimesDatabase = nullptr;
 
 	delete _sliceRenderer;
 	_sliceRenderer = nullptr;
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index d3759d6..525aedf 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -32,6 +32,7 @@
 #include "engines/engine.h"
 
 #include "graphics/surface.h"
+#include "suspects_database.h"
 
 namespace BladeRunner {
 
@@ -42,7 +43,7 @@ class AmbientSounds;
 class AudioPlayer;
 class AudioSpeech;
 class Chapters;
-class Clues;
+class CrimesDatabase;
 class Combat;
 class GameFlags;
 class GameInfo;
@@ -67,29 +68,30 @@ public:
 	bool      _windowIsActive;
 	int       _playerLosesControlCounter;
 	
-	ADQ             *_adq;
-	AIScripts       *_aiScripts;
-	AmbientSounds   *_ambientSounds;
-	AudioPlayer     *_audioPlayer;
-	AudioSpeech     *_audioSpeech;
-	Chapters        *_chapters;
-	Clues           *_clues;
-	Combat          *_combat;
-	GameFlags       *_gameFlags;
-	GameInfo        *_gameInfo;
-	Items           *_items;
-	Lights          *_lights;
-	Mouse           *_mouse;
-	Obstacles       *_obstacles;
-	Scene           *_scene;
-	SceneObjects    *_sceneObjects;
-	Script          *_script;
-	Settings        *_settings;
-	SliceAnimations *_sliceAnimations;
-	SliceRenderer   *_sliceRenderer;
-	View            *_view;
-	Waypoints       *_waypoints;
-	int             *_gameVars;
+	ADQ              *_adq;
+	AIScripts        *_aiScripts;
+	AmbientSounds    *_ambientSounds;
+	AudioPlayer      *_audioPlayer;
+	AudioSpeech      *_audioSpeech;
+	Chapters         *_chapters;
+	CrimesDatabase   *_crimesDatabase;
+	Combat           *_combat;
+	GameFlags        *_gameFlags;
+	GameInfo         *_gameInfo;
+	Items            *_items;
+	Lights           *_lights;
+	Mouse            *_mouse;
+	Obstacles        *_obstacles;
+	Scene            *_scene;
+	SceneObjects     *_sceneObjects;
+	Script           *_script;
+	Settings         *_settings;
+	SliceAnimations  *_sliceAnimations;
+	SliceRenderer    *_sliceRenderer;
+	SuspectsDatabase *_suspectsDatabase;
+	View             *_view;
+	Waypoints        *_waypoints;
+	int              *_gameVars;
 	
 	TextResource    *_textActorNames;
 	TextResource    *_textCrimes;
@@ -125,8 +127,7 @@ public:
 	int _walkSoundId;
 	int _walkSoundVolume;
 	int _walkSoundBalance;
-	int _walkingActorId;
-
+	int _walkingActorId;	
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
diff --git a/engines/bladerunner/clues.cpp b/engines/bladerunner/clues.cpp
deleted file mode 100644
index b87761b..0000000
--- a/engines/bladerunner/clues.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "bladerunner/clues.h"
-
-#include "bladerunner/bladerunner.h"
-
-#include "bladerunner/text_resource.h"
-
-namespace BladeRunner {
-
-Clues::Clues(BladeRunnerEngine *vm, const char *cluesResource, int clueCount) : _clueCount(clueCount) {
-	// reset();
-
-	_crimes     = new int[_clueCount];
-	_assetTypes = new int[_clueCount];
-
-	_cluesText = new TextResource(vm);
-	_cluesText->open(cluesResource);
-
-	for (int i = 0; i != _clueCount; ++i) {
-		_crimes[i] = -1;
-		_assetTypes[i] = -1;
-	}
-}
-
-Clues::~Clues() {
-	delete   _cluesText;
-	delete[] _assetTypes;
-	delete[] _crimes;
-}
-
-const char *Clues::getClueText(int id) {
-	return _cluesText->getText(id);
-}
-
-} // End of namespace BladeRunner
diff --git a/engines/bladerunner/clues.h b/engines/bladerunner/clues.h
deleted file mode 100644
index 4afdef6..0000000
--- a/engines/bladerunner/clues.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#ifndef BLADERUNNER_CLUES_H
-#define BLADERUNNER_CLUES_H
-
-namespace BladeRunner {
-
-class BladeRunnerEngine;
-class TextResource;
-
-class Clues {
-	int           _clueCount;
-	int          *_crimes;
-	int          *_assetTypes;
-	TextResource *_cluesText;
-
-public:
-	Clues(BladeRunnerEngine *vm, const char *cluesResource, int clueCount);
-	~Clues();
-
-	const char *getClueText(int id);
-};
-
-} // End of namespace BladeRunner
-
-#endif
diff --git a/engines/bladerunner/crimes_database.cpp b/engines/bladerunner/crimes_database.cpp
new file mode 100644
index 0000000..c142a05
--- /dev/null
+++ b/engines/bladerunner/crimes_database.cpp
@@ -0,0 +1,72 @@
+/* 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 "bladerunner/crimes_database.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/text_resource.h"
+
+namespace BladeRunner {
+
+CrimesDatabase::CrimesDatabase(BladeRunnerEngine *vm, const char *cluesResource, int crimesCount) : _crimesCount(crimesCount) {
+	// reset();
+
+	_crimes     = new int[_crimesCount];
+	_assetTypes = new int[_crimesCount];
+
+	_cluesText = new TextResource(vm);
+	_cluesText->open(cluesResource);
+
+	for (int i = 0; i != _crimesCount; ++i) {
+		_crimes[i] = -1;
+		_assetTypes[i] = -1;
+	}
+}
+
+CrimesDatabase::~CrimesDatabase() {
+	delete   _cluesText;
+	delete[] _assetTypes;
+	delete[] _crimes;
+}
+
+void CrimesDatabase::setCrime(int crimeId, int value) {
+	_crimes[crimeId] = value;
+}
+
+int CrimesDatabase::getCrime(int crimeId) {
+	return _crimes[crimeId];
+}
+
+void CrimesDatabase::setAssetType(int assetId, int assetType) {
+	_assetTypes[assetId] = assetType;
+}
+
+int CrimesDatabase::getAssetType(int assetId) {
+	return _assetTypes[assetId];
+}
+
+const char *CrimesDatabase::getClueText(int id) {
+	return _cluesText->getText(id);
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/crimes_database.h b/engines/bladerunner/crimes_database.h
new file mode 100644
index 0000000..fc82bf2
--- /dev/null
+++ b/engines/bladerunner/crimes_database.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.
+ *
+ */
+
+#ifndef BLADERUNNER_CRIMES_DATABASE_H
+#define BLADERUNNER_CRIMES_DATABASE_H
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class TextResource;
+
+class CrimesDatabase {
+	int           _crimesCount;
+	int          *_crimes;
+	int          *_assetTypes;
+	TextResource *_cluesText;
+
+public:
+	CrimesDatabase(BladeRunnerEngine *vm, const char *cluesResource, int crimesCount);
+	~CrimesDatabase();
+
+	void setCrime(int crimeId, int value);
+	int getCrime(int crimeId);
+
+	void setAssetType(int assetId, int assetType);
+	int getAssetType(int assetId);
+
+	const char *getClueText(int id);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/gameinfo.cpp b/engines/bladerunner/gameinfo.cpp
index 5f30e51..487c39d 100644
--- a/engines/bladerunner/gameinfo.cpp
+++ b/engines/bladerunner/gameinfo.cpp
@@ -66,7 +66,7 @@ bool GameInfo::open(const Common::String &name) {
 	_music_track_count    = s->readUint32LE();   /* 12 */
 	_outtake_count        = s->readUint32LE();   /* 13 */
 	unk                   = s->readUint32LE();   /* 14 */
-	unk                   = s->readUint32LE();   /* 15 */
+	_suspectsDatabaseSize = s->readUint32LE();   /* 15 */
 	_cover_waypoint_count = s->readUint32LE();   /* 16 */
 	_flee_waypoint_count  = s->readUint32LE();   /* 17 */
 
diff --git a/engines/bladerunner/gameinfo.h b/engines/bladerunner/gameinfo.h
index b77251d..6f9aab5 100644
--- a/engines/bladerunner/gameinfo.h
+++ b/engines/bladerunner/gameinfo.h
@@ -46,6 +46,7 @@ class GameInfo {
 	uint32 _sfx_track_count;
 	uint32 _music_track_count;
 	uint32 _outtake_count;
+	uint32 _suspectsDatabaseSize;
 	uint32 _cover_waypoint_count;
 	uint32 _flee_waypoint_count;
 
@@ -53,27 +54,28 @@ class GameInfo {
 	char (*_sfx_tracks)[13];
 	char (*_music_tracks)[13];
 	char (*_outtakes)[13];
-
+	
 public:
 	GameInfo(BladeRunnerEngine *vm);
 	~GameInfo();
 
 	bool open(const Common::String &name);
 
-	uint32 getActorCount()         { return _actor_count; }
-	uint32 getPlayerId()           { return _player_id; }
-	uint32 getFlagCount()          { return _flag_count; }
-	uint32 getClueCount()          { return _clue_count; }
-	uint32 getGlobalVarCount()     { return _global_var_count; }
-	uint32 getSetNamesCount()      { return _set_names_count; }
-	uint32 getInitialSceneId()     { return _initial_scene_id; }
-	uint32 getInitialSetId()       { return _initial_set_id; }
-	uint32 getWaypointCount()      { return _waypoint_count; }
-	uint32 getSfxTrackCount()      { return _sfx_track_count; }
-	uint32 getMusicTrackCount()    { return _music_track_count; }
-	uint32 getOuttakeCount()       { return _outtake_count; }
-	uint32 getCoverWaypointCount() { return _cover_waypoint_count; }
-	uint32 getFleeWaypointCount()  { return _flee_waypoint_count; }
+	uint32 getActorCount()           { return _actor_count; }
+	uint32 getPlayerId()             { return _player_id; }
+	uint32 getFlagCount()            { return _flag_count; }
+	uint32 getClueCount()            { return _clue_count; }
+	uint32 getGlobalVarCount()       { return _global_var_count; }
+	uint32 getSetNamesCount()        { return _set_names_count; }
+	uint32 getInitialSceneId()       { return _initial_scene_id; }
+	uint32 getInitialSetId()         { return _initial_set_id; }
+	uint32 getWaypointCount()        { return _waypoint_count; }
+	uint32 getSfxTrackCount()        { return _sfx_track_count; }
+	uint32 getMusicTrackCount()      { return _music_track_count; }
+	uint32 getOuttakeCount()         { return _outtake_count; }
+	uint32 getSuspectsDatabaseSize() { return _suspectsDatabaseSize; }
+	uint32 getCoverWaypointCount()   { return _cover_waypoint_count; }
+	uint32 getFleeWaypointCount()    { return _flee_waypoint_count; }
 
 	const char *getSceneName(int i)  { return _scene_names[i]; }
 	const char *getSfxTrack(int i)   { return _sfx_tracks[i]; }
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 51145a3..66ae132 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -32,7 +32,7 @@ Items::Items(BladeRunnerEngine *vm) {
 }
 
 Items::~Items() {
-	for(int i = _items.size() -1; i >= 0; i--) {
+	for(int i = _items.size() - 1; i >= 0; i--) {
 		delete _items.remove_at(i);
 	}
 }
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index b7c85ce..2aa3c24 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -15,8 +15,8 @@ MODULE_OBJS = \
 	bladerunner.o \
 	boundingbox.o \
 	chapters.o \
-	clues.o \
 	combat.o \
+	crimes_database.o \
 	decompress_lcw.o \
 	decompress_lzo.o \
 	detection.o \
@@ -160,6 +160,7 @@ MODULE_OBJS = \
 	shape.o \
 	slice_animations.o \
 	slice_renderer.o \
+	suspects_database.o \
 	text_resource.o \
 	view.o \
 	vqa_decoder.o \
diff --git a/engines/bladerunner/obstacles.cpp b/engines/bladerunner/obstacles.cpp
index 61d2143..9e701a9 100644
--- a/engines/bladerunner/obstacles.cpp
+++ b/engines/bladerunner/obstacles.cpp
@@ -28,15 +28,15 @@ namespace BladeRunner {
 
 Obstacles::Obstacles(BladeRunnerEngine *vm) {
 	_vm = vm;
-	_polygons  = new ObstaclesPolygon[50];
-	_polygons2 = new ObstaclesPolygon[50];
-	_unknown   = new int[50];
+	_polygons       = new ObstaclesPolygon[50];
+	_polygonsBackup = new ObstaclesPolygon[50];
+	_vertices       = new Vector2[150];
 	clear();
 }
 
 Obstacles::~Obstacles() {
-	delete[] _unknown;
-	delete[] _polygons2;
+	delete[] _vertices;
+	delete[] _polygonsBackup;
 	delete[] _polygons;
 }
 
@@ -49,12 +49,12 @@ void Obstacles::clear() {
 			_polygons[i]._vertices[j].y = 0.0f;
 		}
 	}
+	_verticesCount = 0;
+	_backup = false;
 	_count = 0;
-	_processed = false;
 }
 
 void Obstacles::add(float x0, float z0, float x1, float z1) {
-
 }
 
 bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) {
@@ -63,6 +63,8 @@ bool Obstacles::find(const Vector3 &from, const Vector3 &to, Vector3 *next) {
 	return true;
 }
 
-void Obstacles::process() {
+void Obstacles::backup() {
 }
+
+
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/obstacles.h b/engines/bladerunner/obstacles.h
index 9cf3ffa..f9641bf 100644
--- a/engines/bladerunner/obstacles.h
+++ b/engines/bladerunner/obstacles.h
@@ -45,10 +45,11 @@ class Obstacles {
 
 private:
 	ObstaclesPolygon *_polygons;
-	ObstaclesPolygon *_polygons2;
-	int              *_unknown;
+	ObstaclesPolygon *_polygonsBackup;
+	Vector2          *_vertices;
+	int               _verticesCount;
 	int               _count;
-	bool              _processed;
+	bool              _backup;
 
 public:
 	Obstacles(BladeRunnerEngine *vm);
@@ -57,7 +58,8 @@ public:
 	void clear();
 	void add(float x0, float z0, float x1, float z1);
 	bool find(const Vector3 &from, const Vector3 &to, Vector3 *next);
-	void process();
+	void backup();
+	void restore();
 };
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/scene_objects.cpp b/engines/bladerunner/scene_objects.cpp
index 59df6c1..6d10edd 100644
--- a/engines/bladerunner/scene_objects.cpp
+++ b/engines/bladerunner/scene_objects.cpp
@@ -295,7 +295,7 @@ void SceneObjects::updateObstacles() {
 			_vm->_obstacles->add(x0, z0, x1, z1);
 		}
 	}
-	_vm->_obstacles->process();
+	_vm->_obstacles->backup();
 }
 
 } // End of namespace BladeRunner
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 180e8cb..8c6afc6 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -30,7 +30,7 @@
 #include "bladerunner/ambient_sounds.h"
 #include "bladerunner/audio_player.h"
 #include "bladerunner/audio_speech.h"
-#include "bladerunner/clues.h"
+#include "bladerunner/crimes_database.h"
 #include "bladerunner/combat.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
@@ -1122,62 +1122,51 @@ void ScriptBase::Police_Maze_Set_Pause_State(int a1) {
 }
 
 void ScriptBase::CDB_Set_Crime(int crimeId, int value) {
-	//TODO
-	warning("CDB_Set_Crime(%d, %d)", crimeId, value);
+	_vm->_crimesDatabase->setCrime(crimeId, value);
 }
 
 void ScriptBase::CDB_Set_Clue_Asset_Type(int assetId, int type) {
-	//TODO
-	warning("CDB_Set_Clue_Asset_Type(%d, %d)", assetId, type);
+	_vm->_crimesDatabase->setAssetType(assetId, type);
 }
 
-void ScriptBase::SDB_Set_Actor(int actorId, int a2) {
-	//TODO
-	warning("SDB_Set_Actor(%d, %d)", actorId, a2);
+void ScriptBase::SDB_Set_Actor(int suspectId, int actorId) {
+	_vm->_suspectsDatabase->get(suspectId)->setActor(actorId);
 }
 
-void ScriptBase::SDB_Add_Photo_Clue(int actorId, int a2, int a3) {
-	//TODO
-	warning("SDB_Add_Photo_Clue(%d, %d, %d)", actorId, a2, a3);
+bool ScriptBase::SDB_Add_Photo_Clue(int suspectId, int a2, int a3) {
+	return _vm->_suspectsDatabase->get(suspectId)->addPhotoClue(a2, a3);
 }
 
 void ScriptBase::SDB_Set_Name(int actorId) {
 	// not implemented in game
 }
 
-void ScriptBase::SDB_Set_Sex(int actorId, int a2) {
-	//TODO
-	warning("SDB_Set_Sex(%d, %d)", actorId, a2);
+void ScriptBase::SDB_Set_Sex(int suspectId, int sex) {
+	_vm->_suspectsDatabase->get(suspectId)->setSex(sex);
 }
 
-void ScriptBase::SDB_Add_Identity_Clue(int actorId, int a2) {
-	//TODO
-	warning("SDB_Add_Identity_Clue(%d, %d)", actorId, a2);
+bool ScriptBase::SDB_Add_Identity_Clue(int suspectId, int clueId) {
+	return _vm->_suspectsDatabase->get(suspectId)->addIdentityClue(clueId);
 }
 
-void ScriptBase::SDB_Add_MO_Clue(int actorId, int a2) {
-	//TODO
-	warning("SDB_Add_MO_Clue(%d, %d)", actorId, a2);
+bool ScriptBase::SDB_Add_MO_Clue(int suspectId, int clueId) {
+	return _vm->_suspectsDatabase->get(suspectId)->addMOClue(clueId);
 }
 
-void ScriptBase::SDB_Add_Whereabouts_Clue(int actorId, int a2) {
-	//TODO
-	warning("SDB_Add_Whereabouts_Clue(%d, %d)", actorId, a2);
+bool ScriptBase::SDB_Add_Whereabouts_Clue(int suspectId, int clueId) {
+	return _vm->_suspectsDatabase->get(suspectId)->addWhereaboutsClue(clueId);
 }
 
-void ScriptBase::SDB_Add_Replicant_Clue(int actorId, int a2) {
-	//TODO
-	warning("SDB_Add_Replicant_Clue(%d, %d)", actorId, a2);
+bool ScriptBase::SDB_Add_Replicant_Clue(int suspectId, int clueId) {
+	return _vm->_suspectsDatabase->get(suspectId)->addReplicantClue(clueId);
 }
 
-void ScriptBase::SDB_Add_Non_Replicant_Clue(int actorId, int a2) {
-	//TODO
-	warning("SDB_Add_Non_Replicant_Clue(%d, %d)", actorId, a2);
+bool ScriptBase::SDB_Add_Non_Replicant_Clue(int suspectId, int clueId) {
+	return _vm->_suspectsDatabase->get(suspectId)->addNonReplicantClue(clueId);
 }
 
-void ScriptBase::SDB_Add_Other_Clue(int actorId, int a2) {
-	//TODO
-	warning("SDB_Add_Other_Clue(%d, %d)", actorId, a2);
+bool ScriptBase::SDB_Add_Other_Clue(int suspectId, int clueId) {
+	return _vm->_suspectsDatabase->get(suspectId)->addOtherClue(clueId);
 }
 
 void ScriptBase::Spinner_Set_Selectable_Destination_Flag(int a1, int a2) {
diff --git a/engines/bladerunner/script/script.h b/engines/bladerunner/script/script.h
index fb38fda..5966b67 100644
--- a/engines/bladerunner/script/script.h
+++ b/engines/bladerunner/script/script.h
@@ -213,16 +213,16 @@ protected:
 	void Police_Maze_Set_Pause_State(int a1);
 	void CDB_Set_Crime(int crimeId, int value);
 	void CDB_Set_Clue_Asset_Type(int assetId, int type);
-	void SDB_Set_Actor(int actorId, int a2);
-	void SDB_Add_Photo_Clue(int actorId, int a2, int a3);
-	void SDB_Set_Name(int actorId);
-	void SDB_Set_Sex(int actorId, int a2);
-	void SDB_Add_Identity_Clue(int actorId, int a2);
-	void SDB_Add_MO_Clue(int actorId, int a2);
-	void SDB_Add_Whereabouts_Clue(int actorId, int a2);
-	void SDB_Add_Replicant_Clue(int actorId, int a2);
-	void SDB_Add_Non_Replicant_Clue(int actorId, int a2);
-	void SDB_Add_Other_Clue(int actorId, int a2);
+	void SDB_Set_Actor(int suspectId, int actorId);
+	bool SDB_Add_Photo_Clue(int suspectId, int a2, int a3);
+	void SDB_Set_Name(int suspectId);
+	void SDB_Set_Sex(int suspectId, int sex);
+	bool SDB_Add_Identity_Clue(int suspectId, int clueId);
+	bool SDB_Add_MO_Clue(int suspectId, int clueId);
+	bool SDB_Add_Whereabouts_Clue(int suspectId, int clueId);
+	bool SDB_Add_Replicant_Clue(int suspectId, int clueId);
+	bool SDB_Add_Non_Replicant_Clue(int suspectId, int clueId);
+	bool SDB_Add_Other_Clue(int suspectId, int clueId);
 	void Spinner_Set_Selectable_Destination_Flag(int a1, int a2);
 	// Spinner_Query_Selectable_Destination_Flag
 	int Spinner_Interface_Choose_Dest(int a1, int a2);
diff --git a/engines/bladerunner/suspects_database.cpp b/engines/bladerunner/suspects_database.cpp
new file mode 100644
index 0000000..9c44784
--- /dev/null
+++ b/engines/bladerunner/suspects_database.cpp
@@ -0,0 +1,236 @@
+/* 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 "bladerunner/suspects_database.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/text_resource.h"
+
+namespace BladeRunner {
+
+SuspectDatabaseEntry::SuspectDatabaseEntry(BladeRunnerEngine *vm) {
+	_vm = vm;
+	reset();
+}
+
+SuspectDatabaseEntry::~SuspectDatabaseEntry() {
+}
+
+void SuspectDatabaseEntry::setActor(int actorId) {
+	_actorId = actorId;
+}
+
+void SuspectDatabaseEntry::setSex(int sex) {
+	_sex = sex;
+}
+
+bool SuspectDatabaseEntry::addMOClue(int clueId) {
+	if (_moCluesCount >= MO_CLUES_COUNT) {
+		return false;
+	}
+	_moClues[_moCluesCount++] = clueId;
+	return true;
+}
+
+bool SuspectDatabaseEntry::addWhereaboutsClue(int clueId) {
+	if (_whereaboutsCluesCount >= WHEREABOUTS_CLUES_COUNT) {
+		return false;
+	}
+	_whereaboutsClues[_whereaboutsCluesCount++] = clueId;
+	return true;
+}
+
+bool SuspectDatabaseEntry::addReplicantClue(int clueId) {
+	if (_replicantCluesCount >= REPLICANT_CLUES_COUNT) {
+		return false;
+	}
+	_replicantClues[_replicantCluesCount++] = clueId;
+	return true;
+}
+
+bool SuspectDatabaseEntry::addNonReplicantClue(int clueId) {
+	if (_nonReplicantCluesCount >= NONREPLICANT_CLUES_COUNT) {
+		return false;
+	}
+	_nonReplicantClues[_nonReplicantCluesCount++] = clueId;
+	return true;
+}
+
+bool SuspectDatabaseEntry::addOtherClue(int clueId) {
+	if (_otherCluesCount >= OTHER_CLUES_COUNT) {
+		return false;
+	}
+	_otherClues[_otherCluesCount++] = clueId;
+	return true;
+}
+
+bool SuspectDatabaseEntry::addIdentityClue(int clueId) {
+	if (_identityCluesCount >= IDENTITY_CLUES_COUNT) {
+		return false;
+	}
+	_identityClues[_identityCluesCount++] = clueId;
+	return true;
+}
+
+bool SuspectDatabaseEntry::addPhotoClue(int a1, int a2) {
+	if (_photoCluesCount >= PHOTO_CLUES_COUNT) {
+		return false;
+	}
+	_photoClues[_photoCluesCount][0] = a2;
+	_photoClues[_photoCluesCount][1] = a1;
+	_photoClues[_photoCluesCount][2] = -1;
+
+	_photoCluesCount++;
+	return true;
+}
+
+const char *SuspectDatabaseEntry::getName() {
+	return _vm->_textActorNames->getText(_actorId);
+}
+
+bool SuspectDatabaseEntry::hasMOClue(int clueId) {
+	for (int i = 0; i < _moCluesCount; i++) {
+		if (_moClues[i] == clueId) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SuspectDatabaseEntry::hasWhereaboutsClue(int clueId) {
+	for (int i = 0; i < _whereaboutsCluesCount; i++) {
+		if (_whereaboutsClues[i] == clueId) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SuspectDatabaseEntry::hasReplicantClue(int clueId) {
+	for (int i = 0; i < _replicantCluesCount; i++) {
+		if (_replicantClues[i] == clueId) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SuspectDatabaseEntry::hasNonReplicantClue(int clueId) {
+	for (int i = 0; i < _nonReplicantCluesCount; i++) {
+		if (_nonReplicantClues[i] == clueId) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SuspectDatabaseEntry::hasOtherClue(int clueId) {
+	for (int i = 0; i < _otherCluesCount; i++) {
+		if (_otherClues[i] == clueId) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SuspectDatabaseEntry::hasIdentityClue(int clueId) {
+	for (int i = 0; i < _identityCluesCount; i++) {
+		if (_identityClues[i] == clueId) {
+			return true;
+		}
+	}
+	return false;
+}
+
+bool SuspectDatabaseEntry::hasClue(int clueId) {
+	return hasMOClue(clueId)
+		|| hasWhereaboutsClue(clueId)
+		|| hasReplicantClue(clueId)
+		|| hasNonReplicantClue(clueId)
+		|| hasOtherClue(clueId);
+}
+
+int SuspectDatabaseEntry::getPhotoClue1(int photoId) {
+	return _photoClues[photoId][0];
+}
+
+int SuspectDatabaseEntry::getPhotoClue2(int photoId) {
+	return _photoClues[photoId][1];
+}
+
+int SuspectDatabaseEntry::getPhotoClue3(int photoId) {
+	return _photoClues[photoId][2];
+}
+
+void SuspectDatabaseEntry::reset() {
+	_actorId = -1;
+	_sex = -1;
+	for (int i = 0; i < MO_CLUES_COUNT; i++) {
+		_moClues[i] = -1;
+	}
+	for (int i = 0; i < WHEREABOUTS_CLUES_COUNT; i++) {
+		_whereaboutsClues[i] = -1;
+	}
+	for (int i = 0; i < IDENTITY_CLUES_COUNT; i++) {
+		_identityClues[i] = -1;
+	}
+	for (int i = 0; i < REPLICANT_CLUES_COUNT; i++) {
+		_replicantClues[i] = -1;
+	}
+	for (int i = 0; i < NONREPLICANT_CLUES_COUNT; i++) {
+		_nonReplicantClues[i] = -1;
+	}
+	for (int i = 0; i < OTHER_CLUES_COUNT; i++) {
+		_otherClues[i] = -1;
+	}
+
+	// photo clues are not reseted in original game
+
+	_moCluesCount = 0;
+	_whereaboutsCluesCount = 0;
+	_replicantCluesCount = 0;
+	_nonReplicantCluesCount = 0;
+	_otherCluesCount = 0;
+	_identityCluesCount = 0;
+	_photoCluesCount = 0;
+}
+
+SuspectsDatabase::SuspectsDatabase(BladeRunnerEngine *vm, int size) {
+	_vm = vm;
+	for (int i = 0; i < size; i++) {
+		_suspects.push_back(new SuspectDatabaseEntry(_vm));
+	}
+}
+
+SuspectsDatabase::~SuspectsDatabase() {
+	for (int i = _suspects.size() - 1; i >= 0; i--) {
+		delete _suspects.remove_at(i);
+	}
+	_suspects.clear();
+}
+
+SuspectDatabaseEntry *SuspectsDatabase::get(int suspectId) {
+	return _suspects[suspectId];
+}
+
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/suspects_database.h b/engines/bladerunner/suspects_database.h
new file mode 100644
index 0000000..83e551b
--- /dev/null
+++ b/engines/bladerunner/suspects_database.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.
+ *
+ */
+
+#ifndef BLADERUNNER_SUSPECTS_DATABASE_H
+#define BLADERUNNER_SUSPECTS_DATABASE_H
+#include "common/array.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+class TextResource;
+
+#define MO_CLUES_COUNT 10
+#define WHEREABOUTS_CLUES_COUNT 10
+#define REPLICANT_CLUES_COUNT 20
+#define NONREPLICANT_CLUES_COUNT 20
+#define OTHER_CLUES_COUNT 20
+#define IDENTITY_CLUES_COUNT 10
+#define PHOTO_CLUES_COUNT 10
+
+class SuspectDatabaseEntry {
+	BladeRunnerEngine *_vm;
+
+	int _actorId;
+	int _sex;
+	int _moClues[MO_CLUES_COUNT];
+	int _whereaboutsClues[WHEREABOUTS_CLUES_COUNT];
+	int _replicantClues[REPLICANT_CLUES_COUNT];
+	int _nonReplicantClues[NONREPLICANT_CLUES_COUNT];
+	int _otherClues[OTHER_CLUES_COUNT];
+	int _identityClues[IDENTITY_CLUES_COUNT];
+	int _photoClues[6][3];
+	int _moCluesCount;
+	int _whereaboutsCluesCount;
+	int _replicantCluesCount;
+	int _nonReplicantCluesCount;
+	int _otherCluesCount;
+	int _identityCluesCount;
+	int _photoCluesCount;
+
+public:
+	SuspectDatabaseEntry(BladeRunnerEngine *_vm);
+	~SuspectDatabaseEntry();
+
+	void setActor(int actorId);
+	void setSex(int sex);
+	bool addMOClue(int clueId);
+	bool addWhereaboutsClue(int clueId);
+	bool addReplicantClue(int clueId);
+	bool addNonReplicantClue(int clueId);
+	bool addOtherClue(int clueId);
+	bool addIdentityClue(int clueId);
+	bool addPhotoClue(int a1, int a2);
+
+	const char *getName();
+	bool hasMOClue(int clueId);
+	bool hasWhereaboutsClue(int clueId);
+	bool hasReplicantClue(int clueId);
+	bool hasNonReplicantClue(int clueId);
+	bool hasOtherClue(int clueId);
+	bool hasIdentityClue(int clueId);
+	bool hasClue(int clueId);
+	int getPhotoClue1(int photoId);
+	int getPhotoClue2(int photoId);
+	int getPhotoClue3(int photoId);
+
+private:
+	void reset();
+};
+
+class SuspectsDatabase {
+	BladeRunnerEngine *_vm;
+
+	Common::Array<SuspectDatabaseEntry*> _suspects;
+
+public:
+	SuspectsDatabase(BladeRunnerEngine *_vm, int size);
+	~SuspectsDatabase();
+
+	SuspectDatabaseEntry *get(int suspectId);
+};
+
+} // End of namespace BladeRunner
+
+#endif


Commit: 566da748e16f90218aab6bd1f7ea19adc57e098a
    https://github.com/scummvm/scummvm/commit/566da748e16f90218aab6bd1f7ea19adc57e098a
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-06T21:23:46+02:00

Commit Message:
BLADERUNNER: added support for fonts

Changed paths:
  A engines/bladerunner/font.cpp
  A engines/bladerunner/font.h
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/module.mk
    engines/bladerunner/shape.cpp
    engines/bladerunner/shape.h



diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 804bfbd..fb8751c 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -30,6 +30,7 @@
 #include "bladerunner/chapters.h"
 #include "bladerunner/combat.h"
 #include "bladerunner/crimes_database.h"
+#include "bladerunner/font.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
@@ -278,9 +279,9 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	// TODO: Scores
 
-	// TODO: Font
-
-	// TODO: KIA6PT.FON
+	_mainFont = new Font(this);
+	_mainFont->open("KIA6PT.FON", 640, 480, -1, 0, 0x252D);
+	_mainFont->setSpacing(1, 0);	
 
 	for (int i = 0; i != 43; ++i) {
 		Shape *shape = new Shape(this);
@@ -422,7 +423,11 @@ void BladeRunnerEngine::shutdown() {
 	if (isArchiveOpen("SPCHSFX.TLK"))
 		closeArchive("SPCHSFX.TLK");
 
-	// TODO: Delete KIA6PT.FON
+	if(_mainFont) {
+		_mainFont->close();
+		delete _mainFont;
+		_mainFont = nullptr;
+	}
 
 	delete _items;
 	_items = nullptr;
@@ -652,6 +657,19 @@ void BladeRunnerEngine::gameTick() {
 
 					sceneObject->_sceneObjectId;
 					drawBBox(a, b, _view, &_surface2, color);
+
+					Vector3 pos = _view->calculateScreenPosition(0.5 * (a + b));
+					switch(sceneObject->_sceneObjectType) {
+					case SceneObjectTypeActor:
+						_mainFont->drawColor(_textActorNames->getText(sceneObject->_sceneObjectId - SCENE_OBJECTS_ACTORS_OFFSET), _surface2, pos.x, pos.y, color);
+						break;
+					case SceneObjectTypeItem:
+						_mainFont->draw("item", _surface2, pos.x, pos.y);
+						break;
+					case SceneObjectTypeObject:
+						_mainFont->drawColor(_scene->objectGetName(sceneObject->_sceneObjectId - SCENE_OBJECTS_OBJECTS_OFFSET), _surface2, pos.x, pos.y, color);
+						break;
+					}
 				}
 			}
 
@@ -673,9 +691,11 @@ void BladeRunnerEngine::gameTick() {
 
 				for (int j = 0; j < walkbox->_vertexCount; j++) {
 					Vector3 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
-					Vector3 end = _view->calculateScreenPosition(walkbox->_vertices[(j+1) % walkbox->_vertexCount]);
+					Vector3 end = _view->calculateScreenPosition(walkbox->_vertices[(j + 1) % walkbox->_vertexCount]);
 					//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
 					_surface2.drawLine(start.x, start.y, end.x, end.y, 0b111111111100000);
+					Vector3 pos = _view->calculateScreenPosition(0.5 * (start + end));
+					_mainFont->drawColor(walkbox->_name, _surface2, pos.x, pos.y, 0b111111111100000);
 				}
 
 			}
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 525aedf..3546fa8 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -45,6 +45,7 @@ class AudioSpeech;
 class Chapters;
 class CrimesDatabase;
 class Combat;
+class Font;
 class GameFlags;
 class GameInfo;
 class Items;
@@ -80,6 +81,7 @@ public:
 	GameInfo         *_gameInfo;
 	Items            *_items;
 	Lights           *_lights;
+	Font             *_mainFont;
 	Mouse            *_mouse;
 	Obstacles        *_obstacles;
 	Scene            *_scene;
diff --git a/engines/bladerunner/font.cpp b/engines/bladerunner/font.cpp
new file mode 100644
index 0000000..2f15780
--- /dev/null
+++ b/engines/bladerunner/font.cpp
@@ -0,0 +1,203 @@
+/* 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 "bladerunner/font.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "common/debug.h"
+
+namespace BladeRunner {
+
+Font::Font(BladeRunnerEngine *vm) : _vm(vm) {
+	reset();
+}
+
+Font::~Font() {
+	close();
+}
+
+bool Font::open(const Common::String &fileName, int screenWidth, int screenHeight, int spacing1, int spacing2, uint16 color) {
+	reset();
+
+	_screenWidth = screenWidth;
+	_screenHeight = screenHeight;
+	_spacing1 = spacing1;
+	_spacing2 = spacing2;
+	_color = color;
+
+	Common::ScopedPtr<Common::SeekableReadStream> stream(_vm->getResourceStream(fileName));
+	if (!stream) {
+		debug("Font::open failed to open '%s'", fileName.c_str());
+		return false;
+	}
+
+	_characterCount = stream->readUint32LE();
+	_maxWidth = stream->readUint32LE();
+	_maxHeight = stream->readUint32LE();
+	_dataSize = stream->readUint32LE();
+	_data = new uint16[_dataSize];
+	if (!_data) {
+		debug("Font::open failed to allocate font buffer");
+		return false;
+	}
+
+	stream->read(_characters, _characterCount * sizeof(FontCharacter));
+	stream->read(_data, _dataSize * sizeof(uint16));
+	return true;
+}
+
+void Font::close() {
+	if (_data != nullptr) {
+		delete[] _data;
+	}
+	reset();
+}
+
+void Font::setSpacing(int spacing1, int spacing2) {
+	if (_data) {
+		_spacing1 = spacing1;
+		_spacing2 = spacing2;
+	}
+}
+
+void Font::setColor(uint16 color) {
+	if (_data && _color != color) {
+		replaceColor(_color, color);
+		_color = color;
+	}
+}
+
+void Font::draw(const Common::String &text, Graphics::Surface &surface, int x, int y) {
+	if (_data) {
+		if (x < 0) {
+			x = 0;
+		}
+		if (y < 0) {
+			y = 0;
+		}
+
+		int textWidth = getTextWidth(text);
+		if (textWidth + x >= _screenWidth) {
+			x = _screenWidth - (textWidth + 1);
+		}
+		if (_maxHeight + y >= _screenHeight) {
+			y = _screenHeight - _maxHeight;
+		}
+
+		const char *character = text.c_str();
+		while (*character != 0) {
+			drawCharacter(*character, surface, x, y);
+			x += _spacing1 + _characters[*character + 1]._width;
+			character++;
+		}
+	}
+
+}
+
+void Font::drawColor(const Common::String &text, Graphics::Surface &surface, int x, int y, uint16 color) {
+	if (_color != color) {
+		setColor(color);
+	}
+	draw(text, surface, x, y);
+}
+
+int Font::getTextWidth(const Common::String &text) {
+	const char *character = text.c_str();
+
+	if (!_data) {
+		return 0;
+	}
+	int totalWidth = 0;
+	if (*character == 0) {
+		return 0;
+	}
+	while (*character != 0) {
+		totalWidth = _spacing1 + _characters[*character + 1]._width;
+		character++;
+	}
+	return totalWidth - _spacing1;
+}
+
+void Font::reset() {
+	_maxWidth = 0;
+	_maxHeight = 0;
+	_characterCount = 0;
+	_data = nullptr;
+	_dataSize = 0;
+	_screenWidth = 0;
+	_screenHeight = 0;
+	_spacing1 = 0;
+	_spacing2 = 0;
+	_color = 0x7FFF;
+	_intersperse = 0;
+
+	memset(_characters, 0, 5120);
+}
+
+void Font::replaceColor(uint16 oldColor, uint16 newColor) {
+	if (!_data || !_dataSize) {
+		return;
+	}
+	for (int i = 0; i < _dataSize; i++) {
+		if (_data[i] == oldColor) {
+			_data[i] = newColor;
+		}
+	}
+}
+
+void Font::drawCharacter(const char character, Graphics::Surface &surface, int x, int y) {
+	if (x < 0 || x >= this->_screenWidth || y < 0 || y >= _screenHeight || !_data || character + 1 >= _characterCount) {
+		return;
+	}
+
+	uint16 *dstPtr = (uint16*)surface.getBasePtr(x + _characters[character + 1]._x, y + _characters[character + 1]._y);
+	uint16 *srcPtr = &_data[_characters[character + 1]._dataOffset];
+	int width = _characters[character + 1]._width;
+	int height = _characters[character + 1]._height;
+	if (_intersperse && y & 1) {
+		dstPtr += surface.w;
+	}
+
+	int endY = height + y - 1;
+	int currentY = y;
+	while (currentY <= endY && currentY < _screenHeight) {
+		int currentX = x;
+		int endX = width + x - 1;
+		while (currentX <= endX && currentX < _screenWidth) {
+			if (!(*srcPtr & 0x8000)) {
+				*dstPtr = *srcPtr;
+			}
+			dstPtr++;
+			srcPtr++;
+			currentX++;
+		}
+		dstPtr += surface.w - width;
+		if (_intersperse) {
+			srcPtr += width;
+			dstPtr += surface.w;
+			currentY++;
+		}
+		currentY++;
+	}
+}
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/font.h b/engines/bladerunner/font.h
new file mode 100644
index 0000000..329bc48
--- /dev/null
+++ b/engines/bladerunner/font.h
@@ -0,0 +1,88 @@
+/* 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 BLADERUNNER_FONT_H
+#define BLADERUNNER_FONT_H
+
+#include "common/str.h"
+
+namespace Graphics {
+struct Surface;
+}
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+#include "common/pack-start.h"
+
+struct FontCharacter {
+	int _x;
+	int _y;
+	int _width;
+	int _height;
+	int _dataOffset;
+} PACKED_STRUCT;
+
+#include "common/pack-end.h"
+
+class Font {
+	BladeRunnerEngine *_vm;
+
+	int           _characterCount;
+	int           _maxWidth;
+	int           _maxHeight;
+	FontCharacter _characters[256];
+	int           _dataSize;
+	uint16       *_data;
+	int           _screenWidth;
+	int           _screenHeight;
+	int           _spacing1;
+	int           _spacing2;
+	uint16        _color;
+	int           _intersperse;
+
+public:
+	Font(BladeRunnerEngine *vm);
+	~Font();
+
+	bool open(const Common::String &fileName, int screenWidth, int screenHeight, int spacing1, int spacing2, uint16 color);
+	void close();
+
+	void setSpacing(int spacing1, int spacing2);
+	void setColor(uint16 color);
+
+	void draw(const Common::String &text, Graphics::Surface &surface, int x, int y);
+	void drawColor(const Common::String &text, Graphics::Surface &surface, int x, int y, uint16 color);
+
+	int getTextWidth(const Common::String &text);
+
+private:
+	void reset();
+	void replaceColor(uint16 oldColor, uint16 newColor);
+
+	void drawCharacter(const char character, Graphics::Surface &surface, int x, int y);
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 2aa3c24..85dd8d5 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -21,6 +21,7 @@ MODULE_OBJS = \
 	decompress_lzo.o \
 	detection.o \
 	fog.o \
+	font.o \
 	gameflags.o \
 	gameinfo.o \
 	image.o \
diff --git a/engines/bladerunner/shape.cpp b/engines/bladerunner/shape.cpp
index 59fc103..8e62aa4 100644
--- a/engines/bladerunner/shape.cpp
+++ b/engines/bladerunner/shape.cpp
@@ -33,7 +33,7 @@
 namespace BladeRunner {
 
 Shape::Shape(BladeRunnerEngine *vm)
-	: _vm(vm), _data(0) {
+	: _vm(vm), _data(nullptr) {
 }
 
 Shape::~Shape() {
diff --git a/engines/bladerunner/shape.h b/engines/bladerunner/shape.h
index 782d20f..e2e77b1 100644
--- a/engines/bladerunner/shape.h
+++ b/engines/bladerunner/shape.h
@@ -23,7 +23,7 @@
 #ifndef BLADERUNNER_SHAPE_H
 #define BLADERUNNER_SHAPE_H
 
-#include "common/substream.h"
+#include "common/str.h"
 
 namespace Graphics {
 	struct Surface;


Commit: c934941e4f1d72723924f6f6fb7b76712784ff82
    https://github.com/scummvm/scummvm/commit/c934941e4f1d72723924f6f6fb7b76712784ff82
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-06T22:32:27+02:00

Commit Message:
BLADERUNNER: fixed some of endianness issues

Changed paths:
    engines/bladerunner/fog.cpp
    engines/bladerunner/font.cpp
    engines/bladerunner/font.h
    engines/bladerunner/light.cpp



diff --git a/engines/bladerunner/fog.cpp b/engines/bladerunner/fog.cpp
index b51ec10..73e8026 100644
--- a/engines/bladerunner/fog.cpp
+++ b/engines/bladerunner/fog.cpp
@@ -44,8 +44,12 @@ int Fog::readCommon(Common::ReadStream *stream) {
 
 void Fog::readAnimationData(Common::ReadStream *stream, int size) {
 	_animatedParameters = stream->readUint32LE();
-	_animationData = new float[size / sizeof(float)];
-	stream->read(_animationData, size);
+	
+	int floatsCount = size / 4;
+	_animationData = new float[floatsCount];
+	for (int i = 0; i < floatsCount; i++) {
+		_animationData[i] = stream->readFloatLE();
+	}
 
 	_m11ptr = _animationData;
 	_m12ptr = _m11ptr + (_animatedParameters & 0x1 ? _framesCount : 1);
diff --git a/engines/bladerunner/font.cpp b/engines/bladerunner/font.cpp
index 2f15780..972f50a 100644
--- a/engines/bladerunner/font.cpp
+++ b/engines/bladerunner/font.cpp
@@ -61,8 +61,16 @@ bool Font::open(const Common::String &fileName, int screenWidth, int screenHeigh
 		return false;
 	}
 
-	stream->read(_characters, _characterCount * sizeof(FontCharacter));
-	stream->read(_data, _dataSize * sizeof(uint16));
+	for (int i = 0; i < _characterCount; i++) {
+		_characters[i]._x = stream->readUint32LE();
+		_characters[i]._y = stream->readUint32LE();
+		_characters[i]._width = stream->readUint32LE();
+		_characters[i]._height = stream->readUint32LE();
+		_characters[i]._dataOffset = stream->readUint32LE();
+	}
+	for(int i = 0; i < _dataSize; i++) {
+		_data[i] = stream->readUint16LE();
+	}
 	return true;
 }
 
@@ -88,28 +96,30 @@ void Font::setColor(uint16 color) {
 }
 
 void Font::draw(const Common::String &text, Graphics::Surface &surface, int x, int y) {
-	if (_data) {
-		if (x < 0) {
-			x = 0;
-		}
-		if (y < 0) {
-			y = 0;
-		}
+	if (!_data) {
+		return;
+	}
 
-		int textWidth = getTextWidth(text);
-		if (textWidth + x >= _screenWidth) {
-			x = _screenWidth - (textWidth + 1);
-		}
-		if (_maxHeight + y >= _screenHeight) {
-			y = _screenHeight - _maxHeight;
-		}
+	if (x < 0) {
+		x = 0;
+	}
+	if (y < 0) {
+		y = 0;
+	}
 
-		const char *character = text.c_str();
-		while (*character != 0) {
-			drawCharacter(*character, surface, x, y);
-			x += _spacing1 + _characters[*character + 1]._width;
-			character++;
-		}
+	int textWidth = getTextWidth(text);
+	if (textWidth + x >= _screenWidth) {
+		x = _screenWidth - (textWidth + 1);
+	}
+	if (_maxHeight + y >= _screenHeight) {
+		y = _screenHeight - _maxHeight;
+	}
+
+	const char *character = text.c_str();
+	while (*character != 0) {
+		drawCharacter(*character, surface, x, y);
+		x += _spacing1 + _characters[*character + 1]._width;
+		character++;
 	}
 
 }
@@ -151,7 +161,7 @@ void Font::reset() {
 	_color = 0x7FFF;
 	_intersperse = 0;
 
-	memset(_characters, 0, 5120);
+	memset(_characters, 0, 256 * sizeof(FontCharacter));
 }
 
 void Font::replaceColor(uint16 oldColor, uint16 newColor) {
@@ -166,7 +176,7 @@ void Font::replaceColor(uint16 oldColor, uint16 newColor) {
 }
 
 void Font::drawCharacter(const char character, Graphics::Surface &surface, int x, int y) {
-	if (x < 0 || x >= this->_screenWidth || y < 0 || y >= _screenHeight || !_data || character + 1 >= _characterCount) {
+	if (x < 0 || x >= _screenWidth || y < 0 || y >= _screenHeight || !_data || character + 1 >= _characterCount) {
 		return;
 	}
 
diff --git a/engines/bladerunner/font.h b/engines/bladerunner/font.h
index 329bc48..de790b0 100644
--- a/engines/bladerunner/font.h
+++ b/engines/bladerunner/font.h
@@ -33,17 +33,13 @@ namespace BladeRunner {
 
 class BladeRunnerEngine;
 
-#include "common/pack-start.h"
-
 struct FontCharacter {
 	int _x;
 	int _y;
 	int _width;
 	int _height;
 	int _dataOffset;
-} PACKED_STRUCT;
-
-#include "common/pack-end.h"
+};
 
 class Font {
 	BladeRunnerEngine *_vm;
diff --git a/engines/bladerunner/light.cpp b/engines/bladerunner/light.cpp
index fbbf595..08eb8ab 100644
--- a/engines/bladerunner/light.cpp
+++ b/engines/bladerunner/light.cpp
@@ -43,8 +43,11 @@ void Light::read(Common::ReadStream *stream, int framesCount, int frame, int ani
 
 	_animatedParameters = stream->readUint32LE();
 
-	_animationData = new float[size / sizeof(float)];
-	stream->read(_animationData, size);
+	int floatsCount = size / 4;
+	_animationData = new float[floatsCount];
+	for (int i = 0; i < floatsCount; i++) {
+		_animationData[i] = stream->readFloatLE();
+	}
 
 	_m11ptr          = _animationData;
 	_m12ptr          = _m11ptr          + (_animatedParameters &     0x1 ? framesCount : 1);
@@ -77,8 +80,11 @@ void Light::readVqa(Common::ReadStream *stream, int framesCount, int frame, int
 
 	int size = stream->readUint32LE();
 
-	_animationData = new float[size / sizeof(float)];
-	stream->read(_animationData, size);
+	int floatsCount = size / 4;
+	_animationData = new float[floatsCount];
+	for (int i = 0; i < floatsCount; i++) {
+		_animationData[i] = stream->readFloatLE();
+	}
 
 	_m11ptr          = _animationData;
 	_m12ptr          = _m11ptr          + (_animatedParameters &     0x1 ? framesCount : 1);


Commit: f30f3c46e38d91729983a36e87f629d6b3a47a34
    https://github.com/scummvm/scummvm/commit/f30f3c46e38d91729983a36e87f629d6b3a47a34
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-08T21:06:22+02:00

Commit Message:
BLADERUNNER: added item pickup effect

also added support for rendering items on screen (not in the world)
pickup effect can be tested in debug compilation by clicking on any object (not item, but object like, hydrant, or doors) in first scene

Changed paths:
  A engines/bladerunner/item_pickup.cpp
  A engines/bladerunner/item_pickup.h
    engines/bladerunner/actor.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/font.cpp
    engines/bladerunner/item.cpp
    engines/bladerunner/module.mk
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index f6ce1c0..8ead0d4 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -510,7 +510,7 @@ void Actor::draw() {
 
 	// TODO: Handle SHORTY mode
 
-	_vm->_sliceRenderer->drawFrame(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zBuffer2);
+	_vm->_sliceRenderer->drawInWorld(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zBuffer2);
 	//todo udpate screenrect
 }
 
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index fb8751c..1f05046 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -34,6 +34,7 @@
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
 #include "bladerunner/image.h"
+#include "bladerunner/item_pickup.h"
 #include "bladerunner/items.h"
 #include "bladerunner/lights.h"
 #include "bladerunner/mouse.h"
@@ -77,6 +78,7 @@ BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
 	_combat = new Combat(this);
 	_adq = new ADQ(this);
 	_obstacles = new Obstacles(this);
+	_itemPickup = new ItemPickup(this);
 
 	_walkSoundId = -1;
 	_walkSoundVolume = 0;
@@ -104,6 +106,7 @@ BladeRunnerEngine::~BladeRunnerEngine() {
 	// delete[] _zBuffer1;
 	// delete[] _zBuffer2;
 
+	delete _itemPickup;
 	delete _obstacles;
 	delete _adq;
 	delete _combat;
@@ -158,6 +161,8 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 	if (!r)
 		return false;
 
+	// TODO: Create datetime - not used
+
 	// TODO: Create graphics surfaces 1-4
 
 	// TODO: Allocate audio cache
@@ -463,9 +468,10 @@ void BladeRunnerEngine::shutdown() {
 
 	// TODO: Delete KIA
 
-	// TODO: Delete SDB
+	delete _suspectsDatabase;
+	_suspectsDatabase = nullptr;
 
-	// TODO: Delete unknown stuff
+	// TODO: Delete datetime - not used
 
 	// TODO: Delete actors
 
@@ -614,7 +620,9 @@ void BladeRunnerEngine::gameTick() {
 
 			_items->tick();
 
-			// TODO: Draw item pickup
+			_itemPickup->tick();
+			_itemPickup->draw();
+
 			// TODO: Draw dialogue menu
 
 			Common::Point p = _eventMan->getMousePos();
@@ -630,7 +638,7 @@ void BladeRunnerEngine::gameTick() {
 				_walkSoundId = -1;
 			}
 
-#if _DEBUG
+#if false
 			//draw scene objects
 			int count = _sceneObjects->_count;
 			if (count > 0) {
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 3546fa8..3c9cc2a 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -48,6 +48,7 @@ class Combat;
 class Font;
 class GameFlags;
 class GameInfo;
+class ItemPickup;
 class Items;
 class Lights;
 class Mouse;
@@ -79,6 +80,7 @@ public:
 	Combat           *_combat;
 	GameFlags        *_gameFlags;
 	GameInfo         *_gameInfo;
+	ItemPickup       *_itemPickup;
 	Items            *_items;
 	Lights           *_lights;
 	Font             *_mainFont;
diff --git a/engines/bladerunner/font.cpp b/engines/bladerunner/font.cpp
index 972f50a..124e9c9 100644
--- a/engines/bladerunner/font.cpp
+++ b/engines/bladerunner/font.cpp
@@ -68,7 +68,7 @@ bool Font::open(const Common::String &fileName, int screenWidth, int screenHeigh
 		_characters[i]._height = stream->readUint32LE();
 		_characters[i]._dataOffset = stream->readUint32LE();
 	}
-	for(int i = 0; i < _dataSize; i++) {
+	for (int i = 0; i < _dataSize; i++) {
 		_data[i] = stream->readUint16LE();
 	}
 	return true;
@@ -100,20 +100,8 @@ void Font::draw(const Common::String &text, Graphics::Surface &surface, int x, i
 		return;
 	}
 
-	if (x < 0) {
-		x = 0;
-	}
-	if (y < 0) {
-		y = 0;
-	}
-
-	int textWidth = getTextWidth(text);
-	if (textWidth + x >= _screenWidth) {
-		x = _screenWidth - (textWidth + 1);
-	}
-	if (_maxHeight + y >= _screenHeight) {
-		y = _screenHeight - _maxHeight;
-	}
+	x = CLIP(x, 0, _screenWidth - getTextWidth(text) + 1);
+	y = CLIP(y, 0, _screenHeight - _maxHeight);
 
 	const char *character = text.c_str();
 	while (*character != 0) {
@@ -176,16 +164,17 @@ void Font::replaceColor(uint16 oldColor, uint16 newColor) {
 }
 
 void Font::drawCharacter(const char character, Graphics::Surface &surface, int x, int y) {
-	if (x < 0 || x >= _screenWidth || y < 0 || y >= _screenHeight || !_data || character + 1 >= _characterCount) {
+	char characterIndex = character + 1;
+	if (x < 0 || x >= _screenWidth || y < 0 || y >= _screenHeight || !_data || characterIndex >= _characterCount) {
 		return;
 	}
 
-	uint16 *dstPtr = (uint16*)surface.getBasePtr(x + _characters[character + 1]._x, y + _characters[character + 1]._y);
-	uint16 *srcPtr = &_data[_characters[character + 1]._dataOffset];
-	int width = _characters[character + 1]._width;
-	int height = _characters[character + 1]._height;
+	uint16 *dstPtr = (uint16*)surface.getBasePtr(x + _characters[characterIndex]._x, y + _characters[characterIndex]._y);
+	uint16 *srcPtr = &_data[_characters[characterIndex]._dataOffset];
+	int width = _characters[characterIndex]._width;
+	int height = _characters[characterIndex]._height;
 	if (_intersperse && y & 1) {
-		dstPtr += surface.w;
+		dstPtr += surface.pitch / 2;
 	}
 
 	int endY = height + y - 1;
@@ -194,17 +183,17 @@ void Font::drawCharacter(const char character, Graphics::Surface &surface, int x
 		int currentX = x;
 		int endX = width + x - 1;
 		while (currentX <= endX && currentX < _screenWidth) {
-			if (!(*srcPtr & 0x8000)) {
+			if ((*srcPtr & 0x8000) == 0) {
 				*dstPtr = *srcPtr;
 			}
 			dstPtr++;
 			srcPtr++;
 			currentX++;
 		}
-		dstPtr += surface.w - width;
+		dstPtr += surface.pitch / 2 - width;
 		if (_intersperse) {
 			srcPtr += width;
-			dstPtr += surface.w;
+			dstPtr += surface.pitch / 2;
 			currentY++;
 		}
 		currentY++;
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index 00f98d3..0a616d4 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -79,7 +79,7 @@ void Item::tick(bool special) {
 	if (_isVisible) {
 		Vector3 postition(_position.x, -_position.z, _position.y);
 		int animationId = _animationId + (special ? 1 : 0);
-		_vm->_sliceRenderer->drawFrame(animationId, 0, postition, M_PI - _angle, 1.0f, _vm->_surface2, _vm->_zBuffer2);
+		_vm->_sliceRenderer->drawInWorld(animationId, 0, postition, M_PI - _angle, 1.0f, _vm->_surface2, _vm->_zBuffer2);
 		//todo udpate screenrect
 		if (_isSpinning) {
 			_facing += _facingChange;
diff --git a/engines/bladerunner/item_pickup.cpp b/engines/bladerunner/item_pickup.cpp
new file mode 100644
index 0000000..ff5f5e9
--- /dev/null
+++ b/engines/bladerunner/item_pickup.cpp
@@ -0,0 +1,108 @@
+/* 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 "bladerunner/item_pickup.h"
+
+#include "bladerunner/bladerunner.h"
+
+#include "bladerunner/audio_player.h"
+#include "bladerunner/gameinfo.h"
+#include "slice_animations.h"
+#include "slice_renderer.h"
+
+namespace BladeRunner {
+
+ItemPickup::ItemPickup(BladeRunnerEngine *vm) {
+	_vm = vm;
+	_facingStep = float(1.0f / 3000.0f * M_PI);
+	reset();
+}
+
+ItemPickup::~ItemPickup() {
+}
+
+void ItemPickup::setup(int animationId, int screenX, int screenY) {
+	_animationId = animationId;
+	_animationFrame = 0;
+	_facing = 0.0;
+	_timeLeft = 3000;
+	_scale = 0;
+	_screenX = CLIP(screenX, 40, 600);
+	_screenY = CLIP(screenY, 40, 440);
+	_screenRect.left = _screenX - 40;
+	_screenRect.right = _screenX + 40;
+	_screenRect.top = _screenY - 40;
+	_screenRect.bottom = _screenY + 40;
+
+	int pan = (150 * _screenX - 48000) / 640;
+	_vm->_audioPlayer->playAud(_vm->_gameInfo->getSfxTrack(335), 80, pan, pan, 50, 0);
+
+	_timeLast = _vm->getTotalPlayTime();
+}
+
+void ItemPickup::reset() {
+	_animationId = -1;
+	_screenX = 0;
+	_screenY = 0;
+	_facing = 0.0f;
+	_scale = 1.0f;
+	_animationFrame = 0;
+	_timeLeft = 0;
+	_timeLast = 0;
+}
+
+void ItemPickup::tick() {
+	if (_timeLeft == 0) {
+		return;
+	}
+
+	int timeNow = _vm->getTotalPlayTime();
+	int timeDiff = timeNow - _timeLast;
+	_timeLast = timeNow;
+	timeDiff = MIN(MIN(timeDiff, 67), _timeLeft);
+	_timeLeft -= timeDiff;
+
+	if (_timeLeft >= 2000) {
+		_scale = 1.0f - (((2000.0f - _timeLeft) / 1000.0f) * ((2000.0f - _timeLeft) / 1000.0f));
+	} else if (_timeLeft < 1000) {
+		_scale = 1.0f - (((1000.0f - _timeLeft) / 1000.0f) * ((1000.0f - _timeLeft) / 1000.0f));
+	} else {
+		_scale = 1.0f;
+	}
+	_scale *= 75.0f;
+
+	_facing += _facingStep * timeDiff;
+	if (_facing > float(2.0f * M_PI)) {
+		_facing -= float(2.0f * M_PI);
+	}
+
+	_animationFrame = (_animationFrame + 1) % _vm->_sliceAnimations->getFrameCount(_animationId);
+}
+
+void ItemPickup::draw() {
+	if (_timeLeft == 0) {
+		return;
+	}
+
+	_vm->_sliceRenderer->drawOnScreen(_animationId, _animationFrame, _screenX, _screenY, _facing, _scale, _vm->_surface2, _vm->_zBuffer2);
+}
+} // End of namespace BladeRunner
diff --git a/engines/bladerunner/item_pickup.h b/engines/bladerunner/item_pickup.h
new file mode 100644
index 0000000..0e7bc51
--- /dev/null
+++ b/engines/bladerunner/item_pickup.h
@@ -0,0 +1,61 @@
+/* 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 BLADERUNNER_ITEMPICKUP_H
+#define BLADERUNNER_ITEMPICKUP_H
+
+#include "common/rect.h"
+#include "graphics/surface.h"
+
+namespace BladeRunner {
+
+class BladeRunnerEngine;
+
+class ItemPickup {
+	BladeRunnerEngine *_vm;
+
+	float        _facingStep;
+
+	int          _animationId;
+	int          _screenX;
+	int          _screenY;
+	float        _facing;
+	float        _scale;
+	int          _animationFrame;
+	int          _timeLeft;
+	int          _timeLast;
+	Common::Rect _screenRect;
+	
+public:
+	ItemPickup(BladeRunnerEngine *vm);
+	~ItemPickup();
+
+	void setup(int animationId, int screenX, int screenY);
+	void reset();
+
+	void tick();
+	void draw();
+};
+
+} // End of namespace BladeRunner
+
+#endif
diff --git a/engines/bladerunner/module.mk b/engines/bladerunner/module.mk
index 85dd8d5..fb656ef 100644
--- a/engines/bladerunner/module.mk
+++ b/engines/bladerunner/module.mk
@@ -26,6 +26,7 @@ MODULE_OBJS = \
 	gameinfo.o \
 	image.o \
 	item.o \
+	item_pickup.o \
 	items.o \
 	light.o \
 	lights.o \
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index d94f104..ebb67b7 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -202,6 +202,9 @@ bool ScriptRC01::MouseClick(int x, int y) {
 }
 
 bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) {
+#if _DEBUG
+	Item_Pickup_Spin_Effect(938, 426, 316);
+#endif
 	if (Object_Query_Click("BARICADE01", objectName)
 		|| Object_Query_Click("BARICADE03", objectName)
 		|| Object_Query_Click("BARICADE04", objectName)
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 8c6afc6..9e11402 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -34,6 +34,8 @@
 #include "bladerunner/combat.h"
 #include "bladerunner/gameflags.h"
 #include "bladerunner/gameinfo.h"
+#include "bladerunner/items.h"
+#include "bladerunner/item_pickup.h"
 #include "bladerunner/movement_track.h"
 #include "bladerunner/settings.h"
 #include "bladerunner/set_effects.h"
@@ -47,7 +49,6 @@
 
 #include "bladerunner/script/ai_00_mccoy.h"
 #include "bladerunner/script/aiscript_officer_leroy.h"
-#include "bladerunner/items.h"
 
 namespace BladeRunner {
 
@@ -680,9 +681,8 @@ void ScriptBase::Item_Flag_As_Non_Target(int itemId) {
 	warning("Item_Flag_As_Non_Target(%d)", itemId);
 }
 
-void ScriptBase::Item_Pickup_Spin_Effect(int a1, int a2, int a3) {
-	//TODO
-	warning("Item_Pickup_Spin_Effect(%d, %d, %d)", a1, a2, a3);
+void ScriptBase::Item_Pickup_Spin_Effect(int animationId, int x, int y) {
+	_vm->_itemPickup->setup(animationId, x, y);
 }
 
 int ScriptBase::Animation_Open() {
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 0972598..6398b2c 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -342,7 +342,7 @@ static void setupLookupTable(int t[256], int inc) {
 	}
 }
 
-void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer) {
+void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer) {
 	assert(_sliceFramePtr);
 	assert(_lights);
 	assert(_setEffects);
@@ -425,7 +425,7 @@ void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 posit
 		_setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f;
 
 		if (frameY >= 0 && frameY < 480)
-			drawSlice((int)sliceLine, frameLinePtr, zBufferLinePtr);
+			drawSlice((int)sliceLine, true, frameLinePtr, zBufferLinePtr);
 
 		sliceLineIterator.advance();
 		frameY += 1;
@@ -434,7 +434,83 @@ void SliceRenderer::drawFrame(int animationId, int animationFrame, Vector3 posit
 	}
 }
 
-void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr) {
+void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screenX, int screenY, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer) {
+	if (scale == 0.0f) {
+		return;
+	}
+	_animation = -1;// animationId;
+	_frame = animationFrame;
+	_position.x = 0;
+	_position.y = 0;
+	_position.z = 0;
+	_facing = facing;
+	_sliceFramePtr = _vm->_sliceAnimations->getFramePtr(animationId, animationFrame);
+	if(_sliceFramePtr == nullptr) {
+		return;
+	}
+
+	Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[animationId].frameSize);
+
+	_frameScale.x = stream.readFloatLE();
+	_frameScale.y = stream.readFloatLE();
+	_frameSliceHeight = stream.readFloatLE();
+	_framePos.x = stream.readFloatLE();
+	_framePos.y = stream.readFloatLE();
+	_frameBottomZ = stream.readFloatLE();
+	_framePaletteIndex = stream.readUint32LE();
+	_frameSliceCount = stream.readUint32LE();
+
+	float v47 = _frameSliceHeight * _frameSliceCount;
+	float v50 = sqrtf(_frameScale.x * 255.0f * _frameScale.x * 255.0f + _frameScale.y * 255.0f * _frameScale.y * 255.0f);
+	float v16 = MAX(v50, v47);
+	float v51 = scale / v16;
+	
+	float s = sinf(_facing);
+	float c = cosf(_facing);
+
+	Matrix3x2 m_rotation(c, -s, 0.0f,
+	                     s,  c, 0.0f);
+
+	Matrix3x2 m_frame(_frameScale.x, 0.0f, _framePos.x,
+	                  0.0f, _frameScale.y, _framePos.y);
+
+	Matrix3x2 m_scale_v51_25_5(v51,   0.0f, 0.0f,
+	                           0.0f, 25.5f, 0.0f);
+
+	Matrix3x2 m_translate_x_32k(1.0f, 0.0f, screenX,
+	                            0.0f, 1.0f, 32768.0f);
+
+	Matrix3x2 m_scale_64k_64(65536.0f,  0.0f, 0.0f,
+	                             0.0f, 64.0f, 0.0f);
+
+	Matrix3x2 m = m_scale_64k_64 * (m_translate_x_32k * (m_scale_v51_25_5 * (m_rotation * m_frame)));
+
+	setupLookupTable(_m11lookup, m(0,0));
+	setupLookupTable(_m12lookup, m(0,1));
+	_m13 = m(0, 2);
+	setupLookupTable(_m21lookup, m(1,0));
+	setupLookupTable(_m22lookup, m(1,1));
+	_m23 = m(1, 2);
+	
+	float v32 = 1.0f / v51 / _frameSliceHeight;
+	float currentSlice = 0;// _frameSliceCount;
+	
+	int frameY = screenY + (v51 / 2.0f * v47);
+	int currentY = frameY;
+	uint16 *frameLinePtr = (uint16*)surface.getPixels() + 640 * frameY;
+	uint16 lineZbuffer[640];
+	while(currentSlice < _frameSliceCount) {
+		if(currentY >= 0 && currentY < 480) {
+			memset(lineZbuffer, 0xFF, 640 * 2);
+			drawSlice(currentSlice, false, frameLinePtr, lineZbuffer);
+			currentSlice += v32;
+			currentY--;
+			frameLinePtr -= 640;
+		}
+	}
+}
+
+void SliceRenderer::drawSlice(int slice, bool advanced, uint16 *frameLinePtr, uint16 *zbufLinePtr) {
 	if (slice < 0 || (uint32)slice >= _frameSliceCount)
 		return;
 
@@ -467,16 +543,18 @@ void SliceRenderer::drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLineP
 				int vertexZ = (_m21lookup[p[0]] + _m22lookup[p[1]] + _m23) >> 6;
 
 				if (vertexZ >= 0 && vertexZ < 65536) {
-					Color256 color = palette.color[p[2]];
-
-					color.r = (int)(_setEffectColor.r + _lightsColor.r * color.r) >> 16;
-					color.g = (int)(_setEffectColor.g + _lightsColor.g * color.g) >> 16;
-					color.b = (int)(_setEffectColor.b + _lightsColor.b * color.b) >> 16;
+					int color555 = palette.color555[p[2]];
+					if (advanced) {
+						Color256 color = palette.color[p[2]];
 
-					int bladeToScummVmConstant = 256 / 32;
+						color.r = (int)(_setEffectColor.r + _lightsColor.r * color.r) >> 16;
+						color.g = (int)(_setEffectColor.g + _lightsColor.g * color.g) >> 16;
+						color.b = (int)(_setEffectColor.b + _lightsColor.b * color.b) >> 16;
 
-					int color555 = _pixelFormat.RGBToColor(CLIP(color.r * bladeToScummVmConstant, 0, 255), CLIP(color.g * bladeToScummVmConstant, 0, 255), CLIP(color.b * bladeToScummVmConstant, 0, 255));
+						int bladeToScummVmConstant = 256 / 32;
 
+						color555 = _pixelFormat.RGBToColor(CLIP(color.r * bladeToScummVmConstant, 0, 255), CLIP(color.g * bladeToScummVmConstant, 0, 255), CLIP(color.b * bladeToScummVmConstant, 0, 255));
+					}
 					for (int x = previousVertexX; x != vertexX; ++x) {
 						if (vertexZ < zbufLinePtr[x]) {
 							frameLinePtr[x] = color555;
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index c1c0dc4..7e8c2b7 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -88,7 +88,7 @@ class SliceRenderer {
 	Graphics::PixelFormat _pixelFormat;
 
 	Matrix3x2 calculateFacingRotationMatrix();
-	void drawSlice(int slice, uint16 *frameLinePtr, uint16 *zbufLinePtr);
+	void drawSlice(int slice, bool advanced, uint16 *frameLinePtr, uint16 *zbufLinePtr);
 
 public:
 	SliceRenderer(BladeRunnerEngine *vm);
@@ -100,9 +100,9 @@ public:
 
 	void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f);
 	void calculateBoundingRect();
-
-	//void drawFrame(Graphics::Surface &surface, uint16 *zbuffer);
-	void drawFrame(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
+	
+	void drawInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
+	void drawOnScreen(int animationId, int animationFrame, int screenX, int screenY, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
 
 	void preload(int animationId);
 


Commit: b5c4e09cec2a1c7280db969e4129609acf17e1c2
    https://github.com/scummvm/scummvm/commit/b5c4e09cec2a1c7280db969e4129609acf17e1c2
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-09T10:02:22+02:00

Commit Message:
BLADERUNNER: Fix compilation

Changed paths:
    engines/bladerunner/item_pickup.cpp



diff --git a/engines/bladerunner/item_pickup.cpp b/engines/bladerunner/item_pickup.cpp
index ff5f5e9..9792493 100644
--- a/engines/bladerunner/item_pickup.cpp
+++ b/engines/bladerunner/item_pickup.cpp
@@ -95,7 +95,7 @@ void ItemPickup::tick() {
 		_facing -= float(2.0f * M_PI);
 	}
 
-	_animationFrame = (_animationFrame + 1) % _vm->_sliceAnimations->getFrameCount(_animationId);
+	_animationFrame = ((int)(_animationFrame + 1)) % ((int)_vm->_sliceAnimations->getFrameCount(_animationId));
 }
 
 void ItemPickup::draw() {


Commit: f7acbcb057a2fcd455d3e163a99da9851a2e83ea
    https://github.com/scummvm/scummvm/commit/f7acbcb057a2fcd455d3e163a99da9851a2e83ea
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-09T12:03:19+02:00

Commit Message:
BLADERUNNER: fixed speed of pickup effect

formating, small fixes

Changed paths:
    engines/bladerunner/font.cpp
    engines/bladerunner/item_pickup.cpp
    engines/bladerunner/item_pickup.h
    engines/bladerunner/slice_animations.h
    engines/bladerunner/slice_renderer.cpp



diff --git a/engines/bladerunner/font.cpp b/engines/bladerunner/font.cpp
index 124e9c9..fd8b9f2 100644
--- a/engines/bladerunner/font.cpp
+++ b/engines/bladerunner/font.cpp
@@ -164,7 +164,7 @@ void Font::replaceColor(uint16 oldColor, uint16 newColor) {
 }
 
 void Font::drawCharacter(const char character, Graphics::Surface &surface, int x, int y) {
-	char characterIndex = character + 1;
+	uint8 characterIndex = (uint8)character + 1;
 	if (x < 0 || x >= _screenWidth || y < 0 || y >= _screenHeight || !_data || characterIndex >= _characterCount) {
 		return;
 	}
diff --git a/engines/bladerunner/item_pickup.cpp b/engines/bladerunner/item_pickup.cpp
index 9792493..aa293c2 100644
--- a/engines/bladerunner/item_pickup.cpp
+++ b/engines/bladerunner/item_pickup.cpp
@@ -33,7 +33,7 @@ namespace BladeRunner {
 
 ItemPickup::ItemPickup(BladeRunnerEngine *vm) {
 	_vm = vm;
-	_facingStep = float(1.0f / 3000.0f * M_PI);
+	_facingStep = float(2.0f / 3000.0f * (2.0f * M_PI));
 	reset();
 }
 
@@ -95,7 +95,7 @@ void ItemPickup::tick() {
 		_facing -= float(2.0f * M_PI);
 	}
 
-	_animationFrame = ((int)(_animationFrame + 1)) % ((int)_vm->_sliceAnimations->getFrameCount(_animationId));
+	_animationFrame = (_animationFrame + 1) % _vm->_sliceAnimations->getFrameCount(_animationId);
 }
 
 void ItemPickup::draw() {
diff --git a/engines/bladerunner/item_pickup.h b/engines/bladerunner/item_pickup.h
index 0e7bc51..97d98ea 100644
--- a/engines/bladerunner/item_pickup.h
+++ b/engines/bladerunner/item_pickup.h
@@ -24,7 +24,6 @@
 #define BLADERUNNER_ITEMPICKUP_H
 
 #include "common/rect.h"
-#include "graphics/surface.h"
 
 namespace BladeRunner {
 
diff --git a/engines/bladerunner/slice_animations.h b/engines/bladerunner/slice_animations.h
index bed4271..b5b60ef 100644
--- a/engines/bladerunner/slice_animations.h
+++ b/engines/bladerunner/slice_animations.h
@@ -103,7 +103,7 @@ public:
 	SlicePalette &getPalette(int i) { return _palettes[i]; };
 	void *getFramePtr(uint32 animation, uint32 frame);
 
-	float getFrameCount(int animation){ return _animations[animation].frameCount; }
+	int getFrameCount(int animation){ return _animations[animation].frameCount; }
 	float getFPS(int animation){ return _animations[animation].fps; }
 
 	Vector3 getPositionChange(int animation);
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 6398b2c..510f029 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -445,7 +445,7 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
 	_position.z = 0;
 	_facing = facing;
 	_sliceFramePtr = _vm->_sliceAnimations->getFramePtr(animationId, animationFrame);
-	if(_sliceFramePtr == nullptr) {
+	if (_sliceFramePtr == nullptr) {
 		return;
 	}
 
@@ -460,11 +460,10 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
 	_framePaletteIndex = stream.readUint32LE();
 	_frameSliceCount = stream.readUint32LE();
 
-	float v47 = _frameSliceHeight * _frameSliceCount;
-	float v50 = sqrtf(_frameScale.x * 255.0f * _frameScale.x * 255.0f + _frameScale.y * 255.0f * _frameScale.y * 255.0f);
-	float v16 = MAX(v50, v47);
-	float v51 = scale / v16;
-	
+	float frameHeight = _frameSliceHeight * _frameSliceCount;
+	float frameSize = sqrtf(_frameScale.x * 255.0f * _frameScale.x * 255.0f + _frameScale.y * 255.0f * _frameScale.y * 255.0f);
+	float size = scale / MAX(frameSize, frameHeight);
+
 	float s = sinf(_facing);
 	float c = cosf(_facing);
 
@@ -474,8 +473,8 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
 	Matrix3x2 m_frame(_frameScale.x, 0.0f, _framePos.x,
 	                  0.0f, _frameScale.y, _framePos.y);
 
-	Matrix3x2 m_scale_v51_25_5(v51,   0.0f, 0.0f,
-	                           0.0f, 25.5f, 0.0f);
+	Matrix3x2 m_scale_size_25_5(size,  0.0f, 0.0f,
+	                            0.0f, 25.5f, 0.0f);
 
 	Matrix3x2 m_translate_x_32k(1.0f, 0.0f, screenX,
 	                            0.0f, 1.0f, 32768.0f);
@@ -483,27 +482,29 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
 	Matrix3x2 m_scale_64k_64(65536.0f,  0.0f, 0.0f,
 	                             0.0f, 64.0f, 0.0f);
 
-	Matrix3x2 m = m_scale_64k_64 * (m_translate_x_32k * (m_scale_v51_25_5 * (m_rotation * m_frame)));
+	Matrix3x2 m = m_scale_64k_64 * (m_translate_x_32k * (m_scale_size_25_5 * (m_rotation * m_frame)));
 
-	setupLookupTable(_m11lookup, m(0,0));
-	setupLookupTable(_m12lookup, m(0,1));
+	setupLookupTable(_m11lookup, m(0, 0));
+	setupLookupTable(_m12lookup, m(0, 1));
 	_m13 = m(0, 2);
-	setupLookupTable(_m21lookup, m(1,0));
-	setupLookupTable(_m22lookup, m(1,1));
+	setupLookupTable(_m21lookup, m(1, 0));
+	setupLookupTable(_m22lookup, m(1, 1));
 	_m23 = m(1, 2);
-	
-	float v32 = 1.0f / v51 / _frameSliceHeight;
-	float currentSlice = 0;// _frameSliceCount;
-	
-	int frameY = screenY + (v51 / 2.0f * v47);
+
+	int frameY = screenY + (size / 2.0f * frameHeight);
 	int currentY = frameY;
+	
+	float currentSlice = 0;
+	float sliceStep = 1.0f / size / _frameSliceHeight;
+
 	uint16 *frameLinePtr = (uint16*)surface.getPixels() + 640 * frameY;
 	uint16 lineZbuffer[640];
-	while(currentSlice < _frameSliceCount) {
-		if(currentY >= 0 && currentY < 480) {
+
+	while (currentSlice < _frameSliceCount) {
+		if (currentY >= 0 && currentY < 480) {
 			memset(lineZbuffer, 0xFF, 640 * 2);
 			drawSlice(currentSlice, false, frameLinePtr, lineZbuffer);
-			currentSlice += v32;
+			currentSlice += sliceStep;
 			currentY--;
 			frameLinePtr -= 640;
 		}


Commit: 8720c3a98f8d5e36c612c4806bd6d025d409fab5
    https://github.com/scummvm/scummvm/commit/8720c3a98f8d5e36c612c4806bd6d025d409fab5
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-09T20:26:53+02:00

Commit Message:
BLADERUNNER: fixed some compilation warnings

Changed paths:
    engines/bladerunner/actor_walk.h
    engines/bladerunner/combat.h
    engines/bladerunner/movement_track.h
    engines/bladerunner/script/ct01.cpp
    engines/bladerunner/set.h
    engines/bladerunner/waypoints.cpp



diff --git a/engines/bladerunner/actor_walk.h b/engines/bladerunner/actor_walk.h
index 6cd5850..e0558a6 100644
--- a/engines/bladerunner/actor_walk.h
+++ b/engines/bladerunner/actor_walk.h
@@ -47,7 +47,7 @@ private:
 	Vector3 _next;
 	int     _facing;
 	Common::Array<ActorWalk> _entries;
-	int     _field15;
+//	int     _field15;
 	int     _status;
 
 public:
diff --git a/engines/bladerunner/combat.h b/engines/bladerunner/combat.h
index f5deec5..abb2a32 100644
--- a/engines/bladerunner/combat.h
+++ b/engines/bladerunner/combat.h
@@ -34,8 +34,8 @@ class Combat {
 	bool _enabled;
 	int _hitSoundId[9];
 	int _missSoundId[9];
-	int _random1;
-	int _random2;
+//	int _random1;
+//	int _random2;
 
 public:
 	int _ammoDamage[3];
diff --git a/engines/bladerunner/movement_track.h b/engines/bladerunner/movement_track.h
index f5cb03f..4505922 100644
--- a/engines/bladerunner/movement_track.h
+++ b/engines/bladerunner/movement_track.h
@@ -38,7 +38,7 @@ struct MovementTrackEntry {
 };
 
 class MovementTrack {
-	BladeRunnerEngine *_vm;
+//	BladeRunnerEngine *_vm;
 
 private:
 	int _currentIndex;
diff --git a/engines/bladerunner/script/ct01.cpp b/engines/bladerunner/script/ct01.cpp
index c5d633f..001c702 100644
--- a/engines/bladerunner/script/ct01.cpp
+++ b/engines/bladerunner/script/ct01.cpp
@@ -103,7 +103,8 @@ bool ScriptCT01::MouseClick(int x, int y) {
 }
 
 bool ScriptCT01::ClickedOn3DObject(const char *objectName, bool a2) {
-	if ("ASIANSITTINGANDEATI" == objectName) { //bug?
+//	if ("ASIANSITTINGANDEATI" == objectName) { //bug?
+	if (Object_Query_Click("ASIANSITTINGANDEATI", objectName)) {
 		Actor_Face_Object(0, "ASIANSITTINGANDEATI", true);
 		Actor_Says(0, 365, 13);
 		Actor_Says(28, 160, 13);
diff --git a/engines/bladerunner/set.h b/engines/bladerunner/set.h
index 8d9c97b..4b4a4d9 100644
--- a/engines/bladerunner/set.h
+++ b/engines/bladerunner/set.h
@@ -67,7 +67,7 @@ class Set {
 	Walkbox    *_walkboxes;
 	int         _walkboxStepSound[85];
 	int         _footstepSoundOverride;
-	float       _unknown[10];
+//	float       _unknown[10];
 public:
 	SetEffects *_effects;
 
diff --git a/engines/bladerunner/waypoints.cpp b/engines/bladerunner/waypoints.cpp
index 2d7fd19..bd78693 100644
--- a/engines/bladerunner/waypoints.cpp
+++ b/engines/bladerunner/waypoints.cpp
@@ -24,6 +24,7 @@
 namespace BladeRunner {
 
 Waypoints::Waypoints(BladeRunnerEngine *vm, int count) {
+	_vm = vm;
 	_count = count;
 	_waypoints = new Waypoint[count];
 }


Commit: 577c3b56a528cd58e26882b8924b2a8b9d56148a
    https://github.com/scummvm/scummvm/commit/577c3b56a528cd58e26882b8924b2a8b9d56148a
Author: Peter Kohaut (peter.kohaut at gmail.com)
Date: 2016-10-12T23:00:33+02:00

Commit Message:
BLADERUNNER: added picking up of items

and some formatting

Changed paths:
    engines/bladerunner/actor.cpp
    engines/bladerunner/bladerunner.cpp
    engines/bladerunner/bladerunner.h
    engines/bladerunner/item.cpp
    engines/bladerunner/item.h
    engines/bladerunner/items.cpp
    engines/bladerunner/items.h
    engines/bladerunner/scene.cpp
    engines/bladerunner/script/rc01.cpp
    engines/bladerunner/script/script.cpp
    engines/bladerunner/slice_renderer.cpp
    engines/bladerunner/slice_renderer.h



diff --git a/engines/bladerunner/actor.cpp b/engines/bladerunner/actor.cpp
index 8ead0d4..7509bb9 100644
--- a/engines/bladerunner/actor.cpp
+++ b/engines/bladerunner/actor.cpp
@@ -228,7 +228,7 @@ bool Actor::loopWalk(const Vector3 &destination, int destinationOffset, bool a3,
 				break;
 		}
 		return false;
-	} else { 
+	} else {
 		//TODO:
 		// original code, not yet working
 		*isRunning = false;
@@ -511,7 +511,7 @@ void Actor::draw() {
 	// TODO: Handle SHORTY mode
 
 	_vm->_sliceRenderer->drawInWorld(_animationId, _animationFrame, drawPosition, drawAngle, drawScale, _vm->_surface2, _vm->_zBuffer2);
-	//todo udpate screenrect
+	_vm->_sliceRenderer->getScreenRectangle(&_screenRectangle, _animationId, _animationFrame, drawPosition, drawAngle, drawScale);
 }
 
 int Actor::getSetId() {
diff --git a/engines/bladerunner/bladerunner.cpp b/engines/bladerunner/bladerunner.cpp
index 1f05046..9cd0e0d 100644
--- a/engines/bladerunner/bladerunner.cpp
+++ b/engines/bladerunner/bladerunner.cpp
@@ -65,10 +65,10 @@
 namespace BladeRunner {
 
 BladeRunnerEngine::BladeRunnerEngine(OSystem *syst)
-		: Engine(syst),
-		  _rnd("bladerunner") {
+	: Engine(syst),
+	  _rnd("bladerunner") {
 	_windowIsActive = true;
-	_gameIsRunning  = true;
+	_gameIsRunning = true;
 	_playerLosesControlCounter = 0;
 
 	_crimesDatabase = nullptr;
@@ -286,7 +286,7 @@ bool BladeRunnerEngine::startup(bool hasSavegames) {
 
 	_mainFont = new Font(this);
 	_mainFont->open("KIA6PT.FON", 640, 480, -1, 0, 0x252D);
-	_mainFont->setSpacing(1, 0);	
+	_mainFont->setSpacing(1, 0);
 
 	for (int i = 0; i != 43; ++i) {
 		Shape *shape = new Shape(this);
@@ -428,7 +428,7 @@ void BladeRunnerEngine::shutdown() {
 	if (isArchiveOpen("SPCHSFX.TLK"))
 		closeArchive("SPCHSFX.TLK");
 
-	if(_mainFont) {
+	if (_mainFont) {
 		_mainFont->close();
 		delete _mainFont;
 		_mainFont = nullptr;
@@ -524,7 +524,7 @@ void BladeRunnerEngine::gameLoop() {
 
 #if _DEBUG
 
-void drawBBox(Vector3 start, Vector3 end, View* view, Graphics::Surface *surface, int color) {
+void drawBBox(Vector3 start, Vector3 end, View *view, Graphics::Surface *surface, int color) {
 	Vector3 bfl = view->calculateScreenPosition(Vector3(start.x, start.y, start.z));
 	Vector3 bfr = view->calculateScreenPosition(Vector3(start.x, end.y, start.z));
 	Vector3 bbr = view->calculateScreenPosition(Vector3(end.x, end.y, start.z));
@@ -584,7 +584,7 @@ void BladeRunnerEngine::gameTick() {
 		}
 		(void)backgroundChanged;
 		_surface2.copyFrom(_surface1);
-		memcpy(_zBuffer2, _zBuffer1, 640*480*2);
+		memcpy(_zBuffer2, _zBuffer1, 640 * 480 * 2);
 
 #if 0
 		{
@@ -613,7 +613,7 @@ void BladeRunnerEngine::gameTick() {
 			//int setId = _scene->_setId;
 			for (int i = 0, end = _gameInfo->getActorCount(); i != end; ++i) {
 				//if (_actors[i]->getSetId() == setId) {
-					if (i == 0 || i == 23){ // Currently limited to McCoy and Officer Leroy
+				if (i == 0 || i == 23) { // Currently limited to McCoy and Officer Leroy
 					_actors[i]->tick(backgroundChanged);
 				}
 			}
@@ -638,7 +638,7 @@ void BladeRunnerEngine::gameTick() {
 				_walkSoundId = -1;
 			}
 
-#if false
+#if 0
 			//draw scene objects
 			int count = _sceneObjects->_count;
 			if (count > 0) {
@@ -655,24 +655,25 @@ void BladeRunnerEngine::gameTick() {
 					}
 					if (sceneObject->_sceneObjectType == SceneObjectTypeObject) {
 						color = 0b011110111101111;
-						//if (sceneObject->_isObstacle)
-						//	color += 0b100000000000000;
+			//if (sceneObject->_isObstacle)
+			//	color += 0b100000000000000;
 						if (sceneObject->_isClickable)
 							color = 0b000001111100000;
-						//if (sceneObject->_isTarget)
-						//	color += 0b000000000010000;
+			//if (sceneObject->_isTarget)
+			//	color += 0b000000000010000;
 					}
 
-					sceneObject->_sceneObjectId;
 					drawBBox(a, b, _view, &_surface2, color);
 
+			//_surface2.frameRect(sceneObject->_screenRectangle, color);
+
 					Vector3 pos = _view->calculateScreenPosition(0.5 * (a + b));
-					switch(sceneObject->_sceneObjectType) {
+					switch (sceneObject->_sceneObjectType) {
 					case SceneObjectTypeActor:
 						_mainFont->drawColor(_textActorNames->getText(sceneObject->_sceneObjectId - SCENE_OBJECTS_ACTORS_OFFSET), _surface2, pos.x, pos.y, color);
 						break;
 					case SceneObjectTypeItem:
-						_mainFont->draw("item", _surface2, pos.x, pos.y);
+						_mainFont->drawColor("item", _surface2, pos.x, pos.y, color);
 						break;
 					case SceneObjectTypeObject:
 						_mainFont->drawColor(_scene->objectGetName(sceneObject->_sceneObjectId - SCENE_OBJECTS_OBJECTS_OFFSET), _surface2, pos.x, pos.y, color);
@@ -683,13 +684,13 @@ void BladeRunnerEngine::gameTick() {
 
 			//draw regions
 			for (int i = 0; i < 10; i++) {
-				Region* region  =  &_scene->_regions->_regions[i];
+				Region *region = &_scene->_regions->_regions[i];
 				if (!region->_present) continue;
 				_surface2.frameRect(region->_rectangle, 0b000000000011111);
 			}
 
 			for (int i = 0; i < 10; i++) {
-				Region* region = &_scene->_exits->_regions[i];
+				Region *region = &_scene->_exits->_regions[i];
 				if (!region->_present) continue;
 				_surface2.frameRect(region->_rectangle, 0b111111111111111);
 			}
@@ -700,7 +701,7 @@ void BladeRunnerEngine::gameTick() {
 				for (int j = 0; j < walkbox->_vertexCount; j++) {
 					Vector3 start = _view->calculateScreenPosition(walkbox->_vertices[j]);
 					Vector3 end = _view->calculateScreenPosition(walkbox->_vertices[(j + 1) % walkbox->_vertexCount]);
-					//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
+			//debug("walkbox[%i][%i] =  x=%f y=%f x=%f y=%f", i, j, start.x, start.y, end.x, end.y);
 					_surface2.drawLine(start.x, start.y, end.x, end.y, 0b111111111100000);
 					Vector3 pos = _view->calculateScreenPosition(0.5 * (start + end));
 					_mainFont->drawColor(walkbox->_name, _surface2, pos.x, pos.y, 0b111111111100000);
@@ -717,7 +718,7 @@ void BladeRunnerEngine::gameTick() {
 				int colorG = (light->_color.g * 31.0f);
 				int colorB = (light->_color.b * 31.0f);
 				int color = (colorR << 10) + (colorG << 5) + colorB;
-				drawBBox(pos-size, pos+size, _view, &_surface2, color);
+				drawBBox(pos - size, pos + size, _view, &_surface2, color);
 
 			}
 #endif
@@ -759,7 +760,7 @@ void BladeRunnerEngine::handleMouseClick(int x, int y) {
 	int isTarget;
 
 	int sceneObjectId = _sceneObjects->findByXYZ(&isClickable, &isObstacle, &isTarget, mousePosition.x, mousePosition.y, mousePosition.z, 1, 0, 1);
-	int exitIndex     = _scene->_exits->getRegionAtXY(x, y);
+	int exitIndex = _scene->_exits->getRegionAtXY(x, y);
 
 	debug("%d %d", sceneObjectId, exitIndex);
 
@@ -819,7 +820,7 @@ void BladeRunnerEngine::handleMouseClickActor(int x, int y, int actorId) {
 }
 
 void BladeRunnerEngine::gameWaitForActive() {
-	while(!_windowIsActive) {
+	while (!_windowIsActive) {
 		handleEvents();
 	}
 }
@@ -873,7 +874,7 @@ bool BladeRunnerEngine::openArchive(const Common::String &name) {
 
 bool BladeRunnerEngine::closeArchive(const Common::String &name) {
 	for (uint i = 0; i != 10; ++i) {
-		if (_archives[i].isOpen() &&_archives[i].getName() == name) {
+		if (_archives[i].isOpen() && _archives[i].getName() == name) {
 			_archives[i].close();
 			return true;
 		}
@@ -885,7 +886,7 @@ bool BladeRunnerEngine::closeArchive(const Common::String &name) {
 
 bool BladeRunnerEngine::isArchiveOpen(const Common::String &name) {
 	for (uint i = 0; i != 10; ++i) {
-		if (_archives[i].isOpen() &&_archives[i].getName() == name)
+		if (_archives[i].isOpen() && _archives[i].getName() == name)
 			return true;
 	}
 
diff --git a/engines/bladerunner/bladerunner.h b/engines/bladerunner/bladerunner.h
index 3c9cc2a..bbef178 100644
--- a/engines/bladerunner/bladerunner.h
+++ b/engines/bladerunner/bladerunner.h
@@ -131,7 +131,7 @@ public:
 	int _walkSoundId;
 	int _walkSoundVolume;
 	int _walkSoundBalance;
-	int _walkingActorId;	
+	int _walkingActorId;
 private:
 	static const int kArchiveCount = 10;
 	MIXArchive _archives[kArchiveCount];
@@ -178,8 +178,7 @@ public:
 	void ISez(const char *str);
 };
 
-static inline
-const Graphics::PixelFormat createRGB555() {
+static inline const Graphics::PixelFormat createRGB555() {
 	return Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
 }
 
diff --git a/engines/bladerunner/item.cpp b/engines/bladerunner/item.cpp
index 0a616d4..6200668 100644
--- a/engines/bladerunner/item.cpp
+++ b/engines/bladerunner/item.cpp
@@ -80,7 +80,8 @@ void Item::tick(bool special) {
 		Vector3 postition(_position.x, -_position.z, _position.y);
 		int animationId = _animationId + (special ? 1 : 0);
 		_vm->_sliceRenderer->drawInWorld(animationId, 0, postition, M_PI - _angle, 1.0f, _vm->_surface2, _vm->_zBuffer2);
-		//todo udpate screenrect
+		_vm->_sliceRenderer->getScreenRectangle(&_screenRectangle, animationId, 0, postition, M_PI - _angle, 1.0f);
+
 		if (_isSpinning) {
 			_facing += _facingChange;
 
diff --git a/engines/bladerunner/item.h b/engines/bladerunner/item.h
index 0035985..3f12a6a 100644
--- a/engines/bladerunner/item.h
+++ b/engines/bladerunner/item.h
@@ -60,18 +60,17 @@ private:
 	bool         _isPoliceMazeEnemy;
 
 public:
-	Item(BladeRunnerEngine* vm);
+	Item(BladeRunnerEngine *vm);
 	~Item();
-	
+
 	void getXYZ(float *x, float *y, float *z);
 	void setXYZ(Vector3 position);
-	void getWidthHeight(int * width, int * height);
+	void getWidthHeight(int *width, int *height);
 
 	bool isTargetable();
 	void tick(bool special);
 
 	void setup(int itemId, int setId, int animationId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy);
-	
 };
 
 }
diff --git a/engines/bladerunner/items.cpp b/engines/bladerunner/items.cpp
index 66ae132..2bc06e0 100644
--- a/engines/bladerunner/items.cpp
+++ b/engines/bladerunner/items.cpp
@@ -32,12 +32,12 @@ Items::Items(BladeRunnerEngine *vm) {
 }
 
 Items::~Items() {
-	for(int i = _items.size() - 1; i >= 0; i--) {
+	for (int i = _items.size() - 1; i >= 0; i--) {
 		delete _items.remove_at(i);
 	}
 }
 
-void Items::getXYZ(int itemId, float* x, float* y, float* z) {
+void Items::getXYZ(int itemId, float *x, float *y, float *z) {
 	int itemIndex = findItem(itemId);
 	assert(itemIndex != -1);
 
@@ -53,8 +53,8 @@ void Items::getWidthHeight(int itemId, int *width, int *height) {
 
 void Items::tick() {
 	int setId = _vm->_scene->getSetId();
-	for(int i = 0; i < (int)_items.size(); i++) {
-		if(_items[i]->_setId != setId) {
+	for (int i = 0; i < (int)_items.size(); i++) {
+		if (_items[i]->_setId != setId) {
 			continue;
 		}
 		bool set14NotTarget = setId == 14 && !_items[i]->isTargetable();
@@ -62,12 +62,12 @@ void Items::tick() {
 	}
 }
 
-bool Items::add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool addToSet) {
+bool Items::addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool addToSet) {
 	if (_items.size() >= 100) {
 		return false;
 	}
 	int itemIndex = findItem(itemId);
-	if(itemIndex == -1) {
+	if (itemIndex == -1) {
 		itemIndex = _items.size();
 	}
 
@@ -75,18 +75,32 @@ bool Items::add(int itemId, int animationId, int setId, Vector3 position, int fa
 	item->setup(itemId, setId, animationId, position, facing, height, width, isTargetable, isVisible, isPoliceMazeEnemy);
 	_items.push_back(item);
 
-	if(addToSet && setId == _vm->_scene->getSetId()) {
+	if (addToSet && setId == _vm->_scene->getSetId()) {
 		return _vm->_sceneObjects->addItem(itemId + SCENE_OBJECTS_ITEMS_OFFSET, &item->_boundingBox, &item->_screenRectangle, isTargetable, isVisible);
 	}
 	return true;
 }
 
+bool Items::addToSet(int setId) {
+	int itemsCount = _vm->_items->_items.size();
+	if (itemsCount == 0) {
+		return true;
+	}
+	for (int i = 0; i < itemsCount; i++) {
+		Item *item = _vm->_items->_items[i];
+		if (item->_setId == setId) {
+			_vm->_sceneObjects->addItem(item->_itemId + SCENE_OBJECTS_ITEMS_OFFSET, &item->_boundingBox, &item->_screenRectangle, item->isTargetable(), item->_isVisible);
+		}
+	}
+	return true;
+}
+
 bool Items::remove(int itemId) {
 	if (_items.size() == 0) {
 		return false;
 	}
 	int itemIndex = findItem(itemId);
-	if(itemIndex == -1) {
+	if (itemIndex == -1) {
 		return false;
 	}
 
diff --git a/engines/bladerunner/items.h b/engines/bladerunner/items.h
index 0b5c7e0..667117f 100644
--- a/engines/bladerunner/items.h
+++ b/engines/bladerunner/items.h
@@ -40,12 +40,13 @@ public:
 	~Items();
 
 	void getXYZ(int itemId, float *x, float *y, float *z);
-	void getWidthHeight(int itemId, int * width, int * height);
+	void getWidthHeight(int itemId, int *width, int *height);
 
 	void tick();
-	bool add(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool b);
+	bool addToWorld(int itemId, int animationId, int setId, Vector3 position, int facing, int height, int width, bool isTargetable, bool isVisible, bool isPoliceMazeEnemy, bool b);
+	bool addToSet(int itemId);
 	bool remove(int itemId);
-	
+
 private:
 	int findItem(int itemId);
 };
diff --git a/engines/bladerunner/scene.cpp b/engines/bladerunner/scene.cpp
index f9a112e..a629b42 100644
--- a/engines/bladerunner/scene.cpp
+++ b/engines/bladerunner/scene.cpp
@@ -28,6 +28,7 @@
 #include "bladerunner/adq.h"
 #include "bladerunner/chapters.h"
 #include "bladerunner/gameinfo.h"
+#include "bladerunner/items.h"
 #include "bladerunner/scene_objects.h"
 #include "bladerunner/script/script.h"
 #include "bladerunner/slice_renderer.h"
@@ -54,12 +55,12 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		// TODO: Reset aesc
 		// TODO: Clear regions
 		// TODO: Destroy all overlays
-		_defaultLoop         =  0;
-		_defaultLoopSet      =  0;
-		_field_20_loop_stuff =  0;
-		_specialLoopMode     = -1;
-		_specialLoop         = -1;
-		_frame               = -1;
+		_defaultLoop = 0;
+		_defaultLoopSet = 0;
+		_field_20_loop_stuff = 0;
+		_specialLoopMode = -1;
+		_specialLoop = -1;
+		_frame = -1;
 	}
 
 	Common::String vqaName;
@@ -114,23 +115,25 @@ bool Scene::open(int setId, int sceneId, bool isLoadingGame) {
 		Actor *actor = _vm->_actors[i];
 		if (actor->getSetId() == setId) {
 			_vm->_sceneObjects->addActor(
-				i,
-				actor->getBoundingBox(),
-				actor->getScreenRectangle(),
-				1,
-				0,
-				actor->isTargetable(),
-				actor->isRetired());
+				   i,
+				   actor->getBoundingBox(),
+				   actor->getScreenRectangle(),
+				   1,
+				   0,
+				   actor->isTargetable(),
+				   actor->isRetired());
 		}
 	}
 
 	_set->addObjectsToScene(_vm->_sceneObjects);
+	_vm->_items->addToSet(setId);
+	_vm->_sceneObjects->updateObstacles();
 	// TODO: add all items to scene
 	// TODO: calculate walking obstacles??
 
-	 if (_specialLoopMode) {
-	 	_vm->_script->PlayerWalkedIn();
-	 }
+	if (_specialLoopMode) {
+		_vm->_script->PlayerWalkedIn();
+	}
 
 	return true;
 }
@@ -144,10 +147,10 @@ bool Scene::close(bool isLoadingGame) {
 	//_vm->_policeMaze->clear(!isLoadingGame);
 	if (isLoadingGame) {
 		_vm->_script->PlayerWalkedOut();
-	}	
-//	if (SceneScript_isLoaded() && !SceneScript_unload()) {
-//		result = false;
-//	}
+	}
+	//	if (SceneScript_isLoaded() && !SceneScript_unload()) {
+	//		result = false;
+	//	}
 	if (_vqaPlayer != nullptr) {
 		//_vqaPlayer->stop();
 		delete _vqaPlayer;
@@ -163,7 +166,7 @@ int Scene::advanceFrame(Graphics::Surface &surface, uint16 *&zBuffer) {
 	int frame = _vqaPlayer->update();
 	if (frame >= 0) {
 		surface.copyFrom(*_vqaPlayer->getSurface());
-		memcpy(zBuffer, _vqaPlayer->getZBuffer(), 640*480*2);
+		memcpy(zBuffer, _vqaPlayer->getZBuffer(), 640 * 480 * 2);
 		_vqaPlayer->updateView(_vm->_view);
 		_vqaPlayer->updateLights(_vm->_lights);
 	}
@@ -220,7 +223,7 @@ bool Scene::objectSetHotMouse(int objectId) {
 	return _set->objectSetHotMouse(objectId);
 }
 
-bool Scene::objectGetBoundingBox(int objectId, BoundingBox* boundingBox) {
+bool Scene::objectGetBoundingBox(int objectId, BoundingBox *boundingBox) {
 	return _set->objectGetBoundingBox(objectId, boundingBox);
 }
 
@@ -235,7 +238,7 @@ void Scene::objectSetIsObstacle(int objectId, bool isObstacle, bool sceneLoaded,
 	_set->objectSetIsObstacle(objectId, isObstacle);
 	if (sceneLoaded) {
 		_vm->_sceneObjects->setIsObstacle(objectId + 198, isObstacle);
-		if(updateWalkpath) {
+		if (updateWalkpath) {
 			_vm->_sceneObjects->updateObstacles();
 		}
 	}
diff --git a/engines/bladerunner/script/rc01.cpp b/engines/bladerunner/script/rc01.cpp
index ebb67b7..d94f104 100644
--- a/engines/bladerunner/script/rc01.cpp
+++ b/engines/bladerunner/script/rc01.cpp
@@ -202,9 +202,6 @@ bool ScriptRC01::MouseClick(int x, int y) {
 }
 
 bool ScriptRC01::ClickedOn3DObject(const char *objectName, bool a2) {
-#if _DEBUG
-	Item_Pickup_Spin_Effect(938, 426, 316);
-#endif
 	if (Object_Query_Click("BARICADE01", objectName)
 		|| Object_Query_Click("BARICADE03", objectName)
 		|| Object_Query_Click("BARICADE04", objectName)
diff --git a/engines/bladerunner/script/script.cpp b/engines/bladerunner/script/script.cpp
index 9e11402..cf607a4 100644
--- a/engines/bladerunner/script/script.cpp
+++ b/engines/bladerunner/script/script.cpp
@@ -662,7 +662,7 @@ void ScriptBase::Actor_Set_Immunity_To_Obstacles(int actorId, bool isImmune) {
 }
 
 void ScriptBase::Item_Add_To_World(int itemId, int animationId, int setId, float x, float y, float z, signed int facing, int height, int width, bool isTargetable, bool isObstacle, bool isPoliceMazeEnemy, bool updateOnly) {
-	_vm->_items->add(itemId, animationId, setId, Vector3(x, y, z), facing, height, width, isTargetable, isObstacle, isPoliceMazeEnemy, updateOnly == 0);
+	_vm->_items->addToWorld(itemId, animationId, setId, Vector3(x, y, z), facing, height, width, isTargetable, isObstacle, isPoliceMazeEnemy, updateOnly == 0);
 }
 
 void ScriptBase::Item_Remove_From_World(int itemId) {
diff --git a/engines/bladerunner/slice_renderer.cpp b/engines/bladerunner/slice_renderer.cpp
index 510f029..f8d9a48 100644
--- a/engines/bladerunner/slice_renderer.cpp
+++ b/engines/bladerunner/slice_renderer.cpp
@@ -27,33 +27,13 @@
 #include "bladerunner/set_effects.h"
 #include "bladerunner/slice_animations.h"
 
-#include "common/debug.h"
 #include "common/memstream.h"
 #include "common/rect.h"
 #include "common/util.h"
 
 namespace BladeRunner {
 
-#if 0
-void dump(const char *str, Vector3 v) {
-	debug("%s %g %g %g", str, v.x, v.y, v.z);
-}
-
-void dump(const char *str, Matrix3x2 m) {
-	debug("%s", str);
-	debug("%11.6g %11.6g %11.6g", m(0, 0), m(0, 1), m(0, 2));
-	debug("%11.6g %11.6g %11.6g", m(1, 0), m(1, 1), m(1, 2));
-}
-
-void dump(const char *str, Matrix4x3 m) {
-	debug("%s", str);
-	debug("%11.6g %11.6g %11.6g %11.6g", m(0, 0), m(0, 1), m(0, 2), m(0, 3));
-	debug("%11.6g %11.6g %11.6g %11.6g", m(1, 0), m(1, 1), m(1, 2), m(1, 3));
-	debug("%11.6g %11.6g %11.6g %11.6g", m(2, 0), m(2, 1), m(2, 2), m(2, 3));
-}
-#endif
-
-SliceRenderer::SliceRenderer(BladeRunnerEngine* vm) {
+SliceRenderer::SliceRenderer(BladeRunnerEngine *vm) {
 	_vm = vm;
 	_pixelFormat = createRGB555();
 	int i;
@@ -70,37 +50,30 @@ void SliceRenderer::setView(const View &view) {
 	_view = view;
 }
 
-void SliceRenderer::setLights(Lights* lights){
+void SliceRenderer::setLights(Lights *lights) {
 	_lights = lights;
 }
 
-void SliceRenderer::setSetEffects(SetEffects* setEffects){
+void SliceRenderer::setSetEffects(SetEffects *setEffects) {
 	_setEffects = setEffects;
 }
 
-void SliceRenderer::setupFrame(int animation, int frame, Vector3 position, float facing, float scale) {
-	_animation = animation;
-	_frame = frame;
+void SliceRenderer::setupFrameInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale) {
 	_position = position;
 	_facing = facing;
 	_scale = scale;
 
-	_sliceFramePtr = _vm->_sliceAnimations->getFramePtr(_animation, _frame);
-
-	Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[_animation].frameSize);
-
-	_frameScale.x      = stream.readFloatLE();
-	_frameScale.y      = stream.readFloatLE();
-	_frameSliceHeight  = stream.readFloatLE();
-	_framePos.x        = stream.readFloatLE();
-	_framePos.y        = stream.readFloatLE();
-	_frameBottomZ      = stream.readFloatLE();
-	_framePaletteIndex = stream.readUint32LE();
-	_frameSliceCount   = stream.readUint32LE();
+	loadFrame(animationId, animationFrame);
 
 	calculateBoundingRect();
 }
 
+void SliceRenderer::getScreenRectangle(Common::Rect *screenRectangle, int animationId, int animationFrame, Vector3 position, float facing, float scale) {
+	assert(screenRectangle);
+	setupFrameInWorld(animationId, animationFrame, position, facing, scale);
+	*screenRectangle = _screenRectangle;
+}
+
 Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
 	assert(_sliceFramePtr);
 
@@ -122,10 +95,10 @@ Matrix3x2 SliceRenderer::calculateFacingRotationMatrix() {
 void SliceRenderer::calculateBoundingRect() {
 	assert(_sliceFramePtr);
 
-	_minX = 0.0f;
-	_maxX = 0.0f;
-	_minY = 0.0f;
-	_maxY = 0.0f;
+	_screenRectangle.left   = 0;
+	_screenRectangle.right  = 0;
+	_screenRectangle.top    = 0;
+	_screenRectangle.bottom = 0;
 
 	Matrix4x3 viewMatrix = _view._sliceViewMatrix;
 
@@ -142,13 +115,13 @@ void SliceRenderer::calculateBoundingRect() {
 
 	Matrix3x2 facingRotation = calculateFacingRotationMatrix();
 
-	Matrix3x2 m4(_view._viewportDistance / bottom.z,  0.0f, 0.0f,
-	                                           0.0f, 25.5f, 0.0f);
+	Matrix3x2 m_projection(_view._viewportDistance / bottom.z,  0.0f, 0.0f,
+	                                                     0.0f, 25.5f, 0.0f);
 
-	Matrix3x2 m2(_frameScale.x,          0.0f, _framePos.x,
-	                      0.0f, _frameScale.y, _framePos.y);
+	Matrix3x2 m_frame(_frameScale.x,          0.0f, _framePos.x,
+	                           0.0f, _frameScale.y, _framePos.y);
 
-	_field_109E = m4 * (facingRotation * m2);
+	_modelMatrix = m_projection * (facingRotation * m_frame);
 
 	Vector4 startScreenVector(
 	           _view._viewportHalfWidth   + top.x / top.z * _view._viewportDistance,
@@ -173,8 +146,9 @@ void SliceRenderer::calculateBoundingRect() {
 
 	Vector4 delta = endScreenVector - startScreenVector;
 
-	if (delta.y == 0.0f)
+	if (delta.y == 0.0f) {
 		return;
+	}
 
 	/*
 	 * Calculate min and max Y
@@ -212,8 +186,8 @@ void SliceRenderer::calculateBoundingRect() {
 	 * Calculate min and max X
 	 */
 
-	Matrix3x2 mB6 = _field_109E + Vector2(startScreenVector.x, 25.5f / startScreenVector.z);
-	Matrix3x2 mC2 = _field_109E + Vector2(endScreenVector.x,   25.5f / endScreenVector.z);
+	Matrix3x2 mB6 = _modelMatrix + Vector2(startScreenVector.x, 25.5f / startScreenVector.z);
+	Matrix3x2 mC2 = _modelMatrix + Vector2(endScreenVector.x,   25.5f / endScreenVector.z);
 
 	float min_x =  640.0f;
 	float max_x =    0.0f;
@@ -232,8 +206,8 @@ void SliceRenderer::calculateBoundingRect() {
 		}
 	}
 
-	int bbox_min_x = MIN(MAX((int)min_x,     0), 640);
-	int bbox_max_x = MIN(MAX((int)max_x + 1, 0), 640);
+	int bbox_min_x = CLIP((int)min_x,     0, 640);
+	int bbox_max_x = CLIP((int)max_x + 1, 0, 640);
 
 	_startScreenVector.x = startScreenVector.x;
 	_startScreenVector.y = startScreenVector.y;
@@ -244,10 +218,27 @@ void SliceRenderer::calculateBoundingRect() {
 	_startSlice          = startScreenVector.w;
 	_endSlice            = endScreenVector.w;
 
-	_minX = bbox_min_x;
-	_minY = bbox_min_y;
-	_maxX = bbox_max_x;
-	_maxY = bbox_max_y;
+	_screenRectangle.left   = bbox_min_x;
+	_screenRectangle.right  = bbox_max_x;
+	_screenRectangle.top    = bbox_min_y;
+	_screenRectangle.bottom = bbox_max_y;
+}
+
+void SliceRenderer::loadFrame(int animation, int frame) {
+	_animation = animation;
+	_frame = frame;
+	_sliceFramePtr = _vm->_sliceAnimations->getFramePtr(_animation, _frame);
+
+	Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[_animation].frameSize);
+
+	_frameScale.x = stream.readFloatLE();
+	_frameScale.y = stream.readFloatLE();
+	_frameSliceHeight = stream.readFloatLE();
+	_framePos.x = stream.readFloatLE();
+	_framePos.y = stream.readFloatLE();
+	_frameBottomZ = stream.readFloatLE();
+	_framePaletteIndex = stream.readUint32LE();
+	_frameSliceCount = stream.readUint32LE();
 }
 
 struct SliceLineIterator {
@@ -348,14 +339,14 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 	assert(_setEffects);
 	//assert(_view);
 
-	_vm->_sliceRenderer->setupFrame(animationId, animationFrame, position, facing);
+	_vm->_sliceRenderer->setupFrameInWorld(animationId, animationFrame, position, facing);
 
 	SliceLineIterator sliceLineIterator;
 	sliceLineIterator.setup(
 		_endScreenVector.x,   _endScreenVector.y,   _endScreenVector.z,
 		_startScreenVector.x, _startScreenVector.y, _startScreenVector.z,
 		_endSlice,            _startSlice,
-		_field_109E              // 3x2 matrix
+		_modelMatrix
 	);
 
 	SliceRendererLights sliceRendererLights = SliceRendererLights(_lights);
@@ -388,8 +379,11 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 
 	setupLookupTable(_m11lookup, sliceLineIterator._sliceMatrix[0][0]);
 	setupLookupTable(_m12lookup, sliceLineIterator._sliceMatrix[0][1]);
+	_m13 = sliceLineIterator._sliceMatrix[0][2];
 	setupLookupTable(_m21lookup, sliceLineIterator._sliceMatrix[1][0]);
 	setupLookupTable(_m22lookup, sliceLineIterator._sliceMatrix[1][1]);
+	_m23 = sliceLineIterator._sliceMatrix[1][2];
+
 
 	if(_animationsShadowEnabled[_animation]) {
 		//TODO: draw shadows
@@ -401,9 +395,6 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 	uint16 *zBufferLinePtr = zbuffer + 640 * frameY;
 
 	while (sliceLineIterator._currentY <= sliceLineIterator._endY) {
-		_m13 = sliceLineIterator._sliceMatrix[0][2];
-		_m23 = sliceLineIterator._sliceMatrix[1][2];
-
 		sliceLine = sliceLineIterator.line();
 
 		sliceRendererLights.calculateColorSlice(Vector3(_position.x, _position.y, _position.z + _frameBottomZ + sliceLine * _frameSliceHeight));
@@ -424,8 +415,9 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 		_setEffectColor.g = setEffectColor.g * 31.0f * 65536.0f;
 		_setEffectColor.b = setEffectColor.b * 31.0f * 65536.0f;
 
-		if (frameY >= 0 && frameY < 480)
+		if (frameY >= 0 && frameY < 480) {
 			drawSlice((int)sliceLine, true, frameLinePtr, zBufferLinePtr);
+		}
 
 		sliceLineIterator.advance();
 		frameY += 1;
@@ -437,28 +429,13 @@ void SliceRenderer::drawInWorld(int animationId, int animationFrame, Vector3 pos
 void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screenX, int screenY, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer) {
 	if (scale == 0.0f) {
 		return;
-	}
-	_animation = -1;// animationId;
-	_frame = animationFrame;
+	}	
 	_position.x = 0;
 	_position.y = 0;
 	_position.z = 0;
 	_facing = facing;
-	_sliceFramePtr = _vm->_sliceAnimations->getFramePtr(animationId, animationFrame);
-	if (_sliceFramePtr == nullptr) {
-		return;
-	}
-
-	Common::MemoryReadStream stream((byte*)_sliceFramePtr, _vm->_sliceAnimations->_animations[animationId].frameSize);
-
-	_frameScale.x = stream.readFloatLE();
-	_frameScale.y = stream.readFloatLE();
-	_frameSliceHeight = stream.readFloatLE();
-	_framePos.x = stream.readFloatLE();
-	_framePos.y = stream.readFloatLE();
-	_frameBottomZ = stream.readFloatLE();
-	_framePaletteIndex = stream.readUint32LE();
-	_frameSliceCount = stream.readUint32LE();
+	
+	loadFrame(animationId, animationFrame);
 
 	float frameHeight = _frameSliceHeight * _frameSliceCount;
 	float frameSize = sqrtf(_frameScale.x * 255.0f * _frameScale.x * 255.0f + _frameScale.y * 255.0f * _frameScale.y * 255.0f);
@@ -493,7 +470,7 @@ void SliceRenderer::drawOnScreen(int animationId, int animationFrame, int screen
 
 	int frameY = screenY + (size / 2.0f * frameHeight);
 	int currentY = frameY;
-	
+
 	float currentSlice = 0;
 	float sliceStep = 1.0f / size / _frameSliceHeight;
 
@@ -591,21 +568,20 @@ SliceRenderer::SliceRendererLights::SliceRendererLights(Lights *lights) {
 
 	_lights = lights;
 
-	for(int i = 0; i < 20; i++) {
+	for (int i = 0; i < 20; i++) {
 		_colors[i].r = 0.0f;
 		_colors[i].g = 0.0f;
 		_colors[i].b = 0.0f;
 	}
 }
 
-
 void SliceRenderer::SliceRendererLights::calculateColorBase(Vector3 position1, Vector3 position2, float height) {
 	_finalColor.r = 0.0f;
 	_finalColor.g = 0.0f;
 	_finalColor.b = 0.0f;
 	_hmm3 = 0;
 	if (_lights) {
-		for(uint i = 0; i < _lights->_lights.size(); i++) {
+		for (uint i = 0; i < _lights->_lights.size(); i++) {
 			Light *light = _lights->_lights[i];
 			if (i < 20) {
 				float v8 = light->calculate(position1, position2/*, height*/);
diff --git a/engines/bladerunner/slice_renderer.h b/engines/bladerunner/slice_renderer.h
index 7e8c2b7..d1659ec 100644
--- a/engines/bladerunner/slice_renderer.h
+++ b/engines/bladerunner/slice_renderer.h
@@ -28,6 +28,8 @@
 #include "bladerunner/view.h"
 #include "bladerunner/matrix.h"
 
+#include "common/rect.h"
+
 #include "graphics/surface.h"
 
 namespace Common {
@@ -49,7 +51,7 @@ class SliceRenderer {
 	float     _facing;
 	float     _scale;
 
-	View      _view;
+	View        _view;
 	Lights     *_lights;
 	SetEffects *_setEffects;
 
@@ -63,15 +65,12 @@ class SliceRenderer {
 	uint32  _framePaletteIndex;
 	uint32  _frameSliceCount;
 
-	Matrix3x2 _field_109E;
-	Vector3   _startScreenVector;
-	Vector3   _endScreenVector;
-	float     _startSlice;
-	float     _endSlice;
-	int       _minX;
-	int       _maxX;
-	int       _minY;
-	int       _maxY;
+	Matrix3x2    _modelMatrix;
+	Vector3      _startScreenVector;
+	Vector3      _endScreenVector;
+	float        _startSlice;
+	float        _endSlice;
+	Common::Rect _screenRectangle;
 
 	int _m11lookup[256];
 	int _m12lookup[256];
@@ -98,10 +97,10 @@ public:
 	void setLights(Lights *lights);
 	void setSetEffects(SetEffects *setEffects);
 
-	void setupFrame(int animation, int frame, Vector3 position, float facing, float scale = 1.0f);
-	void calculateBoundingRect();
-	
+	void setupFrameInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale = 1.0f);
+	void getScreenRectangle(Common::Rect *screenRectangle, int animationId, int animationFrame, Vector3 position, float facing, float scale);
 	void drawInWorld(int animationId, int animationFrame, Vector3 position, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
+
 	void drawOnScreen(int animationId, int animationFrame, int screenX, int screenY, float facing, float scale, Graphics::Surface &surface, uint16 *zbuffer);
 
 	void preload(int animationId);
@@ -109,6 +108,10 @@ public:
 	void disableShadows(int *animationsIdsList, int listSize);
 
 private:
+
+	void calculateBoundingRect();
+	void loadFrame(int animation, int frame);
+
 	class SliceRendererLights {
 		Lights *_lights;
 		Color   _colors[20];


Commit: e89c76f63c25e4703a44489d987f1ce481e6d1cf
    https://github.com/scummvm/scummvm/commit/e89c76f63c25e4703a44489d987f1ce481e6d1cf
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-13T23:48:50+02:00

Commit Message:
Merge pull request #836 from peterkohaut/bladerunner

BLADERUNNER: added basic support for blade runner game

Changed paths:
  A engines/bladerunner/actor.cpp
  A engines/bladerunner/actor.h
  A engines/bladerunner/actor_clues.cpp
  A engines/bladerunner/actor_clues.h
  A engines/bladerunner/actor_combat.cpp
  A engines/bladerunner/actor_combat.h
  A engines/bladerunner/actor_walk.cpp
  A engines/bladerunner/actor_walk.h
  A engines/bladerunner/adpcm_decoder.cpp
  A engines/bladerunner/adpcm_decoder.h
  A engines/bladerunner/adq.cpp
  A engines/bladerunner/adq.h
  A engines/bladerunner/ambient_sounds.cpp
  A engines/bladerunner/ambient_sounds.h
  A engines/bladerunner/archive.cpp
  A engines/bladerunner/archive.h
  A engines/bladerunner/aud_stream.cpp
  A engines/bladerunner/aud_stream.h
  A engines/bladerunner/audio_player.cpp
  A engines/bladerunner/audio_player.h
  A engines/bladerunner/audio_speech.cpp
  A engines/bladerunner/audio_speech.h
  A engines/bladerunner/bladerunner.cpp
  A engines/bladerunner/bladerunner.h
  A engines/bladerunner/boundingbox.cpp
  A engines/bladerunner/boundingbox.h
  A engines/bladerunner/chapters.cpp
  A engines/bladerunner/chapters.h
  A engines/bladerunner/color.h
  A engines/bladerunner/combat.cpp
  A engines/bladerunner/combat.h
  A engines/bladerunner/configure.engine
  A engines/bladerunner/crimes_database.cpp
  A engines/bladerunner/crimes_database.h
  A engines/bladerunner/decompress_lcw.cpp
  A engines/bladerunner/decompress_lcw.h
  A engines/bladerunner/decompress_lzo.cpp
  A engines/bladerunner/decompress_lzo.h
  A engines/bladerunner/detection.cpp
  A engines/bladerunner/detection_tables.h
  A engines/bladerunner/fog.cpp
  A engines/bladerunner/fog.h
  A engines/bladerunner/font.cpp
  A engines/bladerunner/font.h
  A engines/bladerunner/gameflags.cpp
  A engines/bladerunner/gameflags.h
  A engines/bladerunner/gameinfo.cpp
  A engines/bladerunner/gameinfo.h
  A engines/bladerunner/image.cpp
  A engines/bladerunner/image.h
  A engines/bladerunner/item.cpp
  A engines/bladerunner/item.h
  A engines/bladerunner/item_pickup.cpp
  A engines/bladerunner/item_pickup.h
  A engines/bladerunner/items.cpp
  A engines/bladerunner/items.h
  A engines/bladerunner/light.cpp
  A engines/bladerunner/light.h
  A engines/bladerunner/lights.cpp
  A engines/bladerunner/lights.h
  A engines/bladerunner/matrix.cpp
  A engines/bladerunner/matrix.h
  A engines/bladerunner/module.mk
  A engines/bladerunner/mouse.cpp
  A engines/bladerunner/mouse.h
  A engines/bladerunner/movement_track.cpp
  A engines/bladerunner/movement_track.h
  A engines/bladerunner/obstacles.cpp
  A engines/bladerunner/obstacles.h
  A engines/bladerunner/outtake.cpp
  A engines/bladerunner/outtake.h
  A engines/bladerunner/regions.cpp
  A engines/bladerunner/regions.h
  A engines/bladerunner/scene.cpp
  A engines/bladerunner/scene.h
  A engines/bladerunner/scene_objects.cpp
  A engines/bladerunner/scene_objects.h
  A engines/bladerunner/script/ai_00_mccoy.cpp
  A engines/bladerunner/script/ai_00_mccoy.h
  A engines/bladerunner/script/aiscript_officer_leroy.cpp
  A engines/bladerunner/script/aiscript_officer_leroy.h
  A engines/bladerunner/script/ar01.cpp
  A engines/bladerunner/script/ar02.cpp
  A engines/bladerunner/script/bb01.cpp
  A engines/bladerunner/script/bb02.cpp
  A engines/bladerunner/script/bb03.cpp
  A engines/bladerunner/script/bb04.cpp
  A engines/bladerunner/script/bb05.cpp
  A engines/bladerunner/script/bb06.cpp
  A engines/bladerunner/script/bb07.cpp
  A engines/bladerunner/script/bb08.cpp
  A engines/bladerunner/script/bb09.cpp
  A engines/bladerunner/script/bb10.cpp
  A engines/bladerunner/script/bb11.cpp
  A engines/bladerunner/script/bb12.cpp
  A engines/bladerunner/script/bb51.cpp
  A engines/bladerunner/script/ct01.cpp
  A engines/bladerunner/script/ct02.cpp
  A engines/bladerunner/script/ct03.cpp
  A engines/bladerunner/script/ct04.cpp
  A engines/bladerunner/script/ct05.cpp
  A engines/bladerunner/script/ct06.cpp
  A engines/bladerunner/script/ct07.cpp
  A engines/bladerunner/script/ct08.cpp
  A engines/bladerunner/script/ct09.cpp
  A engines/bladerunner/script/ct10.cpp
  A engines/bladerunner/script/ct11.cpp
  A engines/bladerunner/script/ct12.cpp
  A engines/bladerunner/script/ct51.cpp
  A engines/bladerunner/script/dr01.cpp
  A engines/bladerunner/script/dr02.cpp
  A engines/bladerunner/script/dr03.cpp
  A engines/bladerunner/script/dr04.cpp
  A engines/bladerunner/script/dr05.cpp
  A engines/bladerunner/script/dr06.cpp
  A engines/bladerunner/script/esper.cpp
  A engines/bladerunner/script/esper.h
  A engines/bladerunner/script/hc01.cpp
  A engines/bladerunner/script/hc02.cpp
  A engines/bladerunner/script/hc03.cpp
  A engines/bladerunner/script/hc04.cpp
  A engines/bladerunner/script/hf01.cpp
  A engines/bladerunner/script/hf02.cpp
  A engines/bladerunner/script/hf03.cpp
  A engines/bladerunner/script/hf04.cpp
  A engines/bladerunner/script/hf05.cpp
  A engines/bladerunner/script/hf06.cpp
  A engines/bladerunner/script/hf07.cpp
  A engines/bladerunner/script/init.cpp
  A engines/bladerunner/script/init.h
  A engines/bladerunner/script/kia.cpp
  A engines/bladerunner/script/kia.h
  A engines/bladerunner/script/kp01.cpp
  A engines/bladerunner/script/kp02.cpp
  A engines/bladerunner/script/kp03.cpp
  A engines/bladerunner/script/kp04.cpp
  A engines/bladerunner/script/kp05.cpp
  A engines/bladerunner/script/kp06.cpp
  A engines/bladerunner/script/kp07.cpp
  A engines/bladerunner/script/ma01.cpp
  A engines/bladerunner/script/ma02.cpp
  A engines/bladerunner/script/ma04.cpp
  A engines/bladerunner/script/ma05.cpp
  A engines/bladerunner/script/ma06.cpp
  A engines/bladerunner/script/ma07.cpp
  A engines/bladerunner/script/ma08.cpp
  A engines/bladerunner/script/nr01.cpp
  A engines/bladerunner/script/nr02.cpp
  A engines/bladerunner/script/nr03.cpp
  A engines/bladerunner/script/nr04.cpp
  A engines/bladerunner/script/nr05.cpp
  A engines/bladerunner/script/nr06.cpp
  A engines/bladerunner/script/nr07.cpp
  A engines/bladerunner/script/nr08.cpp
  A engines/bladerunner/script/nr09.cpp
  A engines/bladerunner/script/nr10.cpp
  A engines/bladerunner/script/nr11.cpp
  A engines/bladerunner/script/ps01.cpp
  A engines/bladerunner/script/ps02.cpp
  A engines/bladerunner/script/ps03.cpp
  A engines/bladerunner/script/ps04.cpp
  A engines/bladerunner/script/ps05.cpp
  A engines/bladerunner/script/ps06.cpp
  A engines/bladerunner/script/ps07.cpp
  A engines/bladerunner/script/ps09.cpp
  A engines/bladerunner/script/ps10.cpp
  A engines/bladerunner/script/ps11.cpp
  A engines/bladerunner/script/ps12.cpp
  A engines/bladerunner/script/ps13.cpp
  A engines/bladerunner/script/ps14.cpp
  A engines/bladerunner/script/ps15.cpp
  A engines/bladerunner/script/rc01.cpp
  A engines/bladerunner/script/rc02.cpp
  A engines/bladerunner/script/rc03.cpp
  A engines/bladerunner/script/rc04.cpp
  A engines/bladerunner/script/rc51.cpp
  A engines/bladerunner/script/script.cpp
  A engines/bladerunner/script/script.h
  A engines/bladerunner/script/tb02.cpp
  A engines/bladerunner/script/tb03.cpp
  A engines/bladerunner/script/tb05.cpp
  A engines/bladerunner/script/tb06.cpp
  A engines/bladerunner/script/tb07.cpp
  A engines/bladerunner/script/ug01.cpp
  A engines/bladerunner/script/ug02.cpp
  A engines/bladerunner/script/ug03.cpp
  A engines/bladerunner/script/ug04.cpp
  A engines/bladerunner/script/ug05.cpp
  A engines/bladerunner/script/ug06.cpp
  A engines/bladerunner/script/ug07.cpp
  A engines/bladerunner/script/ug08.cpp
  A engines/bladerunner/script/ug09.cpp
  A engines/bladerunner/script/ug10.cpp
  A engines/bladerunner/script/ug12.cpp
  A engines/bladerunner/script/ug13.cpp
  A engines/bladerunner/script/ug14.cpp
  A engines/bladerunner/script/ug15.cpp
  A engines/bladerunner/script/ug16.cpp
  A engines/bladerunner/script/ug17.cpp
  A engines/bladerunner/script/ug18.cpp
  A engines/bladerunner/script/ug19.cpp
  A engines/bladerunner/script/vk.cpp
  A engines/bladerunner/script/vk.h
  A engines/bladerunner/set.cpp
  A engines/bladerunner/set.h
  A engines/bladerunner/set_effects.cpp
  A engines/bladerunner/set_effects.h
  A engines/bladerunner/settings.cpp
  A engines/bladerunner/settings.h
  A engines/bladerunner/shape.cpp
  A engines/bladerunner/shape.h
  A engines/bladerunner/slice_animations.cpp
  A engines/bladerunner/slice_animations.h
  A engines/bladerunner/slice_renderer.cpp
  A engines/bladerunner/slice_renderer.h
  A engines/bladerunner/suspects_database.cpp
  A engines/bladerunner/suspects_database.h
  A engines/bladerunner/text_resource.cpp
  A engines/bladerunner/text_resource.h
  A engines/bladerunner/vector.h
  A engines/bladerunner/view.cpp
  A engines/bladerunner/view.h
  A engines/bladerunner/vqa_decoder.cpp
  A engines/bladerunner/vqa_decoder.h
  A engines/bladerunner/vqa_player.cpp
  A engines/bladerunner/vqa_player.h
  A engines/bladerunner/waypoints.cpp
  A engines/bladerunner/waypoints.h
    common/stream.h








More information about the Scummvm-git-logs mailing list