[Scummvm-cvs-logs] scummvm master -> b408b94bf1e188da7202895eab547f08cfa30450

bluegr bluegr at gmail.com
Sat Oct 5 13:53:42 CEST 2013


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

Summary:
9715318932 NEVERHOOD: Split sprites from their scenes in modules 2100 and 2200
b963fcbfa8 NEVERHOOD: Split sprites from their scenes in modules 1700 and 1800
b408b94bf1 NEVERHOOD: Split sprites from their scenes in module 1600


Commit: 97153189325b375c8cd1ef18eb6cb20734d8a2f1
    https://github.com/scummvm/scummvm/commit/97153189325b375c8cd1ef18eb6cb20734d8a2f1
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2013-10-05T04:21:53-07:00

Commit Message:
NEVERHOOD: Split sprites from their scenes in modules 2100 and 2200

This also reduces inter-header dependencies

Changed paths:
  A engines/neverhood/modules/module2100_sprites.cpp
  A engines/neverhood/modules/module2100_sprites.h
  A engines/neverhood/modules/module2200_sprites.cpp
  A engines/neverhood/modules/module2200_sprites.h
    engines/neverhood/module.mk
    engines/neverhood/modules/module1300.cpp
    engines/neverhood/modules/module1400.cpp
    engines/neverhood/modules/module1600.cpp
    engines/neverhood/modules/module1600.h
    engines/neverhood/modules/module2100.cpp
    engines/neverhood/modules/module2100.h
    engines/neverhood/modules/module2200.cpp
    engines/neverhood/modules/module2200.h
    engines/neverhood/modules/module2400.cpp
    engines/neverhood/modules/module2400.h
    engines/neverhood/modules/module2500.cpp
    engines/neverhood/modules/module2500.h
    engines/neverhood/modules/module2700.cpp
    engines/neverhood/modules/module2700.h
    engines/neverhood/modules/module2700_sprites.h
    engines/neverhood/modules/module2800.cpp



diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index c31a711..917913f 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -26,7 +26,9 @@ MODULE_OBJS = \
 	modules/module1900.o \
 	modules/module2000.o \
 	modules/module2100.o \
+	modules/module2100_sprites.o \
 	modules/module2200.o \
+	modules/module2200_sprites.o \
 	modules/module2300.o \
 	modules/module2400.o \
 	modules/module2400_sprites.o \
diff --git a/engines/neverhood/modules/module1300.cpp b/engines/neverhood/modules/module1300.cpp
index 0b883b2..88f5784 100644
--- a/engines/neverhood/modules/module1300.cpp
+++ b/engines/neverhood/modules/module1300.cpp
@@ -24,7 +24,7 @@
 #include "neverhood/modules/module1000.h"
 #include "neverhood/modules/module1200.h"
 #include "neverhood/modules/module1400.h"
-#include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/gamemodule.h"
 #include "neverhood/diskplayerscene.h"
 #include "neverhood/menumodule.h"
diff --git a/engines/neverhood/modules/module1400.cpp b/engines/neverhood/modules/module1400.cpp
index 0a02963..7244d3c 100644
--- a/engines/neverhood/modules/module1400.cpp
+++ b/engines/neverhood/modules/module1400.cpp
@@ -22,8 +22,8 @@
 
 #include "neverhood/modules/module1400.h"
 #include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module2100.h"
-#include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module2100_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/diskplayerscene.h"
 #include "neverhood/gamemodule.h"
 
diff --git a/engines/neverhood/modules/module1600.cpp b/engines/neverhood/modules/module1600.cpp
index e675eae..631d90d 100644
--- a/engines/neverhood/modules/module1600.cpp
+++ b/engines/neverhood/modules/module1600.cpp
@@ -23,7 +23,7 @@
 #include "neverhood/modules/module1600.h"
 #include "neverhood/gamemodule.h"
 #include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/modules/module3000_sprites.h"
 
 namespace Neverhood {
diff --git a/engines/neverhood/modules/module1600.h b/engines/neverhood/modules/module1600.h
index 5f0da52..0d1ceaa 100644
--- a/engines/neverhood/modules/module1600.h
+++ b/engines/neverhood/modules/module1600.h
@@ -27,7 +27,6 @@
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
 #include "neverhood/console.h"
-#include "neverhood/modules/module3000.h"
 
 namespace Neverhood {
 
@@ -162,6 +161,8 @@ protected:
 	void updateKlaymenCliprect();
 };
 
+class AsScene3011Symbol;
+
 class Scene1609 : public Scene {
 	friend class Console;
 public:
diff --git a/engines/neverhood/modules/module2100.cpp b/engines/neverhood/modules/module2100.cpp
index bcff9d9..21df622 100644
--- a/engines/neverhood/modules/module2100.cpp
+++ b/engines/neverhood/modules/module2100.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "neverhood/modules/module2100.h"
+#include "neverhood/modules/module2100_sprites.h"
 #include "neverhood/gamemodule.h"
 #include "neverhood/modules/module1200.h"
 
@@ -74,125 +75,6 @@ void Module2100::updateScene() {
 	}
 }
 
-// Scene2101
-
-AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen)
-	: AnimatedSprite(vm, 1100) {
-
-	createSurface(100, 328, 347);
-	_x = 320;
-	_y = 240;
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene2101Door::handleMessage);
-	if (isOpen) {
-		startAnimation(0x0C202B9C, -1, -1);
-		_newStickFrameIndex = STICK_LAST_FRAME;
-	} else
-		setVisible(false);
-}
-
-uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x3002:
-		gotoNextState();
-		break;
-	case 0x4808:
-		stOpenDoor();
-		break;
-	case 0x4809:
-		stCloseDoor();
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2101Door::stOpenDoor() {
-	startAnimation(0x0C202B9C, 0, -1);
-	_newStickFrameIndex = STICK_LAST_FRAME;
-	setVisible(true);
-	playSound(0, calcHash("fxDoorOpen32"));
-}
-
-void AsScene2101Door::stCloseDoor() {
-	startAnimation(0xC222A8D4, 0, -1);
-	_newStickFrameIndex = STICK_LAST_FRAME;
-	setVisible(true);
-	playSound(0, calcHash("fxDoorClose32"));
-	NextState(&AsScene2101Door::stCloseDoorDone);
-}
-
-void AsScene2101Door::stCloseDoorDone() {
-	stopAnimation();
-	setVisible(false);
-}
-
-AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen)
-	: AnimatedSprite(vm, 1400), _klaymen(klaymen) {
-
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage);
-	createSurface(1200, 88, 165);
-	setVisible(false);
-}
-
-uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x2001:
-		_x = _klaymen->getX();
-		_y = _klaymen->getY() - 132;
-		startAnimation(0x0422255A, 0, -1);
-		setVisible(true);
-		break;
-	case 0x3002:
-		stopAnimation();
-		setVisible(false);
-		break;
-	}
-	return messageResult;
-}
-
-SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
-	: StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0),
-	_fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) {
-
-	SetUpdateHandler(&SsCommonFloorButton::update);
-	SetMessageHandler(&SsCommonFloorButton::handleMessage);
-	if (_soundFileHash == 0)
-		_soundFileHash = 0x44141000;
-	createSurface(1010, 61, 30);
-	if (_fileHash1)
-		loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
-	else
-		setVisible(false);
-}
-
-void SsCommonFloorButton::update() {
-	if (_countdown != 0 && (--_countdown == 0)) {
-		sendMessage(_parentScene, 0x1022, 1010);
-		if (_fileHash1)
-			loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
-		else
-			setVisible(false);
-	}
-}
-
-uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x480B:
-		sendMessage(_parentScene, 0x480B, 0);
-		setVisible(true);
-		sendMessage(_parentScene, 0x1022, 990);
-		loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition);
-		_countdown = 16;
-		playSound(0, _soundFileHash);
-		break;
-	}
-	return messageResult;
-}
-
 Scene2101::Scene2101(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule) {
 
diff --git a/engines/neverhood/modules/module2100.h b/engines/neverhood/modules/module2100.h
index d76bed0..c525643 100644
--- a/engines/neverhood/modules/module2100.h
+++ b/engines/neverhood/modules/module2100.h
@@ -40,38 +40,6 @@ protected:
 	void updateScene();
 };
 
-// Scene1901
-
-class AsScene2101Door : public AnimatedSprite {
-public:
-	AsScene2101Door(NeverhoodEngine *vm, bool isOpen);
-protected:
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void stOpenDoor();
-	void stCloseDoor();
-	void stCloseDoorDone();
-};
-
-class AsScene2101HitByDoorEffect : public AnimatedSprite {
-public:
-	AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen);
-protected:
-	Sprite *_klaymen;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class SsCommonFloorButton : public StaticSprite {
-public:
-	SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash);
-protected:
-	Scene *_parentScene;
-	uint32 _soundFileHash;
-	uint32 _fileHash1, _fileHash2;
-	int16 _countdown;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
 class Scene2101 : public Scene {
 public:
 	Scene2101(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2100_sprites.cpp b/engines/neverhood/modules/module2100_sprites.cpp
new file mode 100644
index 0000000..dbc866e
--- /dev/null
+++ b/engines/neverhood/modules/module2100_sprites.cpp
@@ -0,0 +1,146 @@
+/* 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 "neverhood/modules/module2100_sprites.h"
+#include "neverhood/gamemodule.h"
+#include "neverhood/modules/module1200.h"
+
+namespace Neverhood {
+
+AsScene2101Door::AsScene2101Door(NeverhoodEngine *vm, bool isOpen)
+	: AnimatedSprite(vm, 1100) {
+
+	createSurface(100, 328, 347);
+	_x = 320;
+	_y = 240;
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene2101Door::handleMessage);
+	if (isOpen) {
+		startAnimation(0x0C202B9C, -1, -1);
+		_newStickFrameIndex = STICK_LAST_FRAME;
+	} else
+		setVisible(false);
+}
+
+uint32 AsScene2101Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x3002:
+		gotoNextState();
+		break;
+	case 0x4808:
+		stOpenDoor();
+		break;
+	case 0x4809:
+		stCloseDoor();
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2101Door::stOpenDoor() {
+	startAnimation(0x0C202B9C, 0, -1);
+	_newStickFrameIndex = STICK_LAST_FRAME;
+	setVisible(true);
+	playSound(0, calcHash("fxDoorOpen32"));
+}
+
+void AsScene2101Door::stCloseDoor() {
+	startAnimation(0xC222A8D4, 0, -1);
+	_newStickFrameIndex = STICK_LAST_FRAME;
+	setVisible(true);
+	playSound(0, calcHash("fxDoorClose32"));
+	NextState(&AsScene2101Door::stCloseDoorDone);
+}
+
+void AsScene2101Door::stCloseDoorDone() {
+	stopAnimation();
+	setVisible(false);
+}
+
+AsScene2101HitByDoorEffect::AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen)
+	: AnimatedSprite(vm, 1400), _klaymen(klaymen) {
+
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene2101HitByDoorEffect::handleMessage);
+	createSurface(1200, 88, 165);
+	setVisible(false);
+}
+
+uint32 AsScene2101HitByDoorEffect::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x2001:
+		_x = _klaymen->getX();
+		_y = _klaymen->getY() - 132;
+		startAnimation(0x0422255A, 0, -1);
+		setVisible(true);
+		break;
+	case 0x3002:
+		stopAnimation();
+		setVisible(false);
+		break;
+	}
+	return messageResult;
+}
+
+SsCommonFloorButton::SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash)
+	: StaticSprite(vm, 1100), _parentScene(parentScene), _countdown(0),
+	_fileHash1(fileHash1), _fileHash2(fileHash2), _soundFileHash(soundFileHash) {
+
+	SetUpdateHandler(&SsCommonFloorButton::update);
+	SetMessageHandler(&SsCommonFloorButton::handleMessage);
+	if (_soundFileHash == 0)
+		_soundFileHash = 0x44141000;
+	createSurface(1010, 61, 30);
+	if (_fileHash1)
+		loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
+	else
+		setVisible(false);
+}
+
+void SsCommonFloorButton::update() {
+	if (_countdown != 0 && (--_countdown == 0)) {
+		sendMessage(_parentScene, 0x1022, 1010);
+		if (_fileHash1)
+			loadSprite(_fileHash1, kSLFDefDrawOffset | kSLFDefPosition);
+		else
+			setVisible(false);
+	}
+}
+
+uint32 SsCommonFloorButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x480B:
+		sendMessage(_parentScene, 0x480B, 0);
+		setVisible(true);
+		sendMessage(_parentScene, 0x1022, 990);
+		loadSprite(_fileHash2, kSLFDefDrawOffset | kSLFDefPosition);
+		_countdown = 16;
+		playSound(0, _soundFileHash);
+		break;
+	}
+	return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2100_sprites.h b/engines/neverhood/modules/module2100_sprites.h
new file mode 100644
index 0000000..a10d06f
--- /dev/null
+++ b/engines/neverhood/modules/module2100_sprites.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 NEVERHOOD_MODULES_MODULE2100_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2100_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsScene2101Door : public AnimatedSprite {
+public:
+	AsScene2101Door(NeverhoodEngine *vm, bool isOpen);
+protected:
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void stOpenDoor();
+	void stCloseDoor();
+	void stCloseDoorDone();
+};
+
+class AsScene2101HitByDoorEffect : public AnimatedSprite {
+public:
+	AsScene2101HitByDoorEffect(NeverhoodEngine *vm, Sprite *klaymen);
+protected:
+	Sprite *_klaymen;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class SsCommonFloorButton : public StaticSprite {
+public:
+	SsCommonFloorButton(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int surfacePriority, uint32 soundFileHash);
+protected:
+	Scene *_parentScene;
+	uint32 _soundFileHash;
+	uint32 _fileHash1, _fileHash2;
+	int16 _countdown;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2100_SPRITES_H */
diff --git a/engines/neverhood/modules/module2200.cpp b/engines/neverhood/modules/module2200.cpp
index 99f21ca..7220c25 100644
--- a/engines/neverhood/modules/module2200.cpp
+++ b/engines/neverhood/modules/module2200.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/modules/module1000.h"
 #include "neverhood/modules/module1200.h"
 #include "neverhood/gamemodule.h"
@@ -445,95 +446,6 @@ void Module2200::createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId)
 	_childObject = new HallOfRecordsScene(_vm, this, which, hallOfRecordsInfoId);
 }
 
-// Scene2201
-
-AsScene2201CeilingFan::AsScene2201CeilingFan(NeverhoodEngine *vm)
-	: AnimatedSprite(vm, 1100) {
-
-	_x = 403;
-	_y = 259;
-	createSurface(100, 233, 96);
-	startAnimation(0x8600866, 0, -1);
-	SetUpdateHandler(&AnimatedSprite::update);
-}
-
-AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen)
-	: AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) {
-
-	_x = 408;
-	_y = 290;
-	createSurface(900, 63, 266);
-	SetUpdateHandler(&AsScene2201Door::update);
-	SetMessageHandler(&AsScene2201Door::handleMessage);
-	if (_isOpen) {
-		startAnimation(0xE2CB0412, -1, -1);
-		_countdown = 48;
-		_newStickFrameIndex = STICK_LAST_FRAME;
-	} else {
-		startAnimation(0xE2CB0412, 0, -1);
-		_newStickFrameIndex = 0;
-		_ssDoorLight->setVisible(false);
-	}
-}
-
-void AsScene2201Door::update() {
-	if (_countdown != 0 && _isOpen && (--_countdown == 0))
-		stCloseDoor();
-	AnimatedSprite::update();
-}
-
-uint32 AsScene2201Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x100D:
-		if (param.asInteger() == 0x11001090) {
-			if (_isOpen)
-				_ssDoorLight->setVisible(true);
-		} else if (param.asInteger() == 0x11283090) {
-			if (!_isOpen)
-				_ssDoorLight->setVisible(false);
-		}
-		break;
-	case 0x2000:
-		if (_isOpen)
-			_countdown = 144;
-		messageResult = _isOpen ? 1 : 0;
-		break;
-	case 0x3002:
-		gotoNextState();
-		break;
-	case 0x4808:
-		_countdown = 144;
-		if (!_isOpen)
-			stOpenDoor();
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2201Door::stOpenDoor() {
-	_isOpen = true;
-	startAnimation(0xE2CB0412, 0, -1);
-	_newStickFrameIndex = STICK_LAST_FRAME;
-	playSound(0, calcHash("fxDoorOpen33"));
-}
-
-void AsScene2201Door::stCloseDoor() {
-	_isOpen = false;
-	startAnimation(0xE2CB0412, -1, -1);
-	_playBackwards = true;
-	_newStickFrameIndex = 0;
-	playSound(0, calcHash("fxDoorClose33"));
-}
-
-SsScene2201PuzzleCube::SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex)
-	: StaticSprite(vm, 900) {
-
-	createSurface(100, 16, 16);
-	loadSprite(kSsScene2201PuzzleCubeFileHashes[cubeIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 0,
-		kSsScene2201PuzzleCubePoints[positionIndex].x, kSsScene2201PuzzleCubePoints[positionIndex].y);
-}
-
 Scene2201::Scene2201(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule), _isSoundPlaying(false) {
 
@@ -661,215 +573,6 @@ uint32 Scene2201::handleMessage(int messageNum, const MessageParam &param, Entit
 	return 0;
 }
 
-static const NPoint kSsScene2202PuzzleCubePoints[] = {
-	{196, 105}, {323, 102}, {445, 106},
-	{192, 216}, {319, 220}, {446, 216},
-	{188, 320}, {319, 319}, {443, 322}
-};
-
-static const uint32 kSsScene2202PuzzleCubeFileHashes1[] = {
-	0xA500800C, 0x2182910C, 0x2323980C,
-	0x23049084, 0x21008080, 0x2303900C,
-	0x6120980C, 0x2504D808
-};
-
-static const uint32 kSsScene2202PuzzleCubeFileHashes2[] = {
-	0x0AAD8080, 0x0A290291, 0x0A2BA398,
-	0x822B8490, 0x86298080, 0x0A2B8390,
-	0x0A69A098, 0x0E2D84D8
-};
-
-SsScene2202PuzzleCube::SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol)
-	: StaticSprite(vm, 900), _parentScene(parentScene), _cubeSymbol(cubeSymbol), _cubePosition(cubePosition), _isMoving(false) {
-
-	int surfacePriority;
-
-	SetUpdateHandler(&SsScene2202PuzzleCube::update);
-	SetMessageHandler(&SsScene2202PuzzleCube::handleMessage);
-	if (_cubePosition >= 0 && _cubePosition <= 2)
-		surfacePriority = 100;
-	else if (_cubePosition >= 3 && _cubePosition <= 5)
-		surfacePriority = 300;
-	else
-		surfacePriority = 500;
-	debug(1, "TODO: Unused SurfacePriority: %d", surfacePriority);
-	loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset | kSLFSetPosition | kSLFDefCollisionBoundsOffset, 0,
-		kSsScene2202PuzzleCubePoints[_cubePosition].x, kSsScene2202PuzzleCubePoints[_cubePosition].y);
-	loadSound(0, 0x40958621);
-	loadSound(1, 0x51108241);
-}
-
-void SsScene2202PuzzleCube::update() {
-	handleSpriteUpdate();
-	updatePosition();
-}
-
-uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		if (!_isMoving && !getGlobalVar(V_TILE_PUZZLE_SOLVED))
-			sendMessage(_parentScene, 0x2000, _cubePosition);
-		messageResult = 1;
-		break;
-	case 0x2001:
-		_isMoving = true;
-		moveCube(param.asInteger());
-		break;
-	}
-	return messageResult;
-}
-
-void SsScene2202PuzzleCube::suMoveCubeX() {
-
-	bool done = false;
-
-	if (_counterDirection) {
-		if (_counter > 2)
-			_counter -= 2;
-	} else {
-		if (_counter < 20)
-			_counter += 2;
-	}
-
-	for (int16 i = 0; i < _counter; i++) {
-		_x += _xIncr;
-		_errValue += _yDelta;
-		if (_errValue >= _xDelta) {
-			_errValue -= _xDelta;
-			_y += _yIncr;
-		}
-		if (_x == _newX && _y == _newY) {
-			done = true;
-			break;
-		}
-		if (_x == _xFlagPos)
-			_counterDirection = true;
-	}
-
-	if (done)
-		stopMoving();
-
-	updateBounds();
-
-}
-
-void SsScene2202PuzzleCube::suMoveCubeY() {
-
-	bool done = false;
-
-	if (_counterDirection) {
-		if (_counter > 2)
-			_counter -= 2;
-	} else {
-		if (_counter < 20)
-			_counter += 2;
-	}
-
-	for (int16 i = 0; i < _counter; i++) {
-		_y += _yIncr;
-		_errValue += _xDelta;
-		if (_errValue >= _yDelta) {
-			_errValue -= _yDelta;
-			_x += _xIncr;
-		}
-		if (_x == _newX && _y == _newY) {
-			done = true;
-			break;
-		}
-		if (_x == _xFlagPos)
-			_counterDirection = true;
-	}
-
-	if (done)
-		stopMoving();
-
-	updateBounds();
-
-}
-
-void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
-
-	loadSprite(kSsScene2202PuzzleCubeFileHashes1[_cubeSymbol], kSLFCenteredDrawOffset);
-
-	setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1);
-	setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol);
-
-	_cubePosition = newCubePosition;
-	_errValue = 0;
-	_counterDirection = false;
-	_counter = 0;
-	_newX = kSsScene2202PuzzleCubePoints[newCubePosition].x;
-	_newY = kSsScene2202PuzzleCubePoints[newCubePosition].y;
-
-	if (_x == _newX && _y == _newY)
-		return;
-
-	if (_x <= _newX) {
-		if (_y <= _newY) {
-			_xDelta = _newX - _x;
-			_yDelta = _newY - _y;
-			_xIncr = 1;
-			_yIncr = 1;
-		} else {
-			_xDelta = _newX - _x;
-			_yDelta = _y - _newY;
-			_xIncr = 1;
-			_yIncr = -1;
-		}
-	} else {
-		if (_y <= _newY) {
-			_xDelta = _x - _newX;
-			_yDelta = _newY - _y;
-			_xIncr = -1;
-			_yIncr = 1;
-		} else {
-			_xDelta = _x - _newX;
-			_yDelta = _y - _newY;
-			_xIncr = -1;
-			_yIncr = -1;
-		}
-	}
-
-	if (_xDelta > _yDelta) {
-		SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeX);
-		if (_xIncr > 0) {
-			if (_newX - _x >= 180)
-				_xFlagPos = _newX - 90;
-			else
-				_xFlagPos = _x + _newX / 2;
-		} else {
-			if (_x - _newX >= 180)
-				_xFlagPos = _x + 90;
-			else
-				_xFlagPos = _x / 2 + _newX;
-		}
-		playSound(0);
-	} else {
-		SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeY);
-		if (_yIncr > 0) {
-			if (_newY - _y >= 180)
-				_xFlagPos = _newY - 90;
-			else
-				_xFlagPos = _y + _newY / 2;
-		} else {
-			if (_y - _newY >= 180)
-				_xFlagPos = _y + 90;
-			else
-				_xFlagPos = _y / 2 + _newY;
-		}
-		playSound(1);
-	}
-
-}
-
-void SsScene2202PuzzleCube::stopMoving() {
-	loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset);
-	SetSpriteUpdate(NULL);
-	_isMoving = false;
-	sendMessage(_parentScene, 0x2002, _cubePosition);
-}
-
 Scene2202::Scene2202(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule), _isSolved(false), _leaveScene(false), _isCubeMoving(false),
 	_ssMovingCube(NULL), _ssDoneMovingCube(NULL) {
@@ -991,100 +694,6 @@ bool Scene2202::testIsSolved() {
 		getSubVar(VA_CUBE_POSITIONS, 8) == 7;
 }
 
-static const uint32 kAsCommonKeyFileHashes[] = {
-	0x2450D850,	0x0C9CE8D0,	0x2C58A152
-};
-
-AsCommonKey::AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y)
-	: AnimatedSprite(vm, kAsCommonKeyFileHashes[keyIndex], surfacePriority, x, y), _parentScene(parentScene), _keyIndex(keyIndex) {
-
-	if (!getSubVar(VA_HAS_KEY, _keyIndex) && !getSubVar(VA_IS_KEY_INSERTED, _keyIndex)) {
-		SetMessageHandler(&AsCommonKey::handleMessage);
-	} else {
-		// If Klaymen already has the key or it's already inserted then don't show it
-		setVisible(false);
-		SetMessageHandler(NULL);
-	}
-}
-
-uint32 AsCommonKey::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		sendMessage(_parentScene, 0x4826, 0);
-		messageResult = 1;
-		break;
-	case 0x4806:
-		setSubVar(VA_HAS_KEY, _keyIndex, 1);
-		setVisible(false);
-		SetMessageHandler(NULL);
-	}
-	return messageResult;
-}
-
-static const uint32 kAsScene2203DoorFileHashes[] = {
-	0x7868AE10,	0x1A488110
-};
-
-AsScene2203Door::AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex)
-	: AnimatedSprite(vm, 1100), _parentScene(parentScene), _doorIndex(doorIndex) {
-
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene2203Door::handleMessage);
-	_x = 320;
-	_y = 240;
-	createSurface1(kAsScene2203DoorFileHashes[_doorIndex], 900);
-	if (getGlobalVar(V_LARGE_DOOR_NUMBER) == _doorIndex) {
-		startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
-		_newStickFrameIndex = STICK_LAST_FRAME;
-	} else {
-		startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 0, -1);
-		_newStickFrameIndex = 0;
-	}
-}
-
-uint32 AsScene2203Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
-			sendMessage(_parentScene, 0x2002, 0);
-		else
-			sendMessage(_parentScene, 0x2001, 0);
-		messageResult = 1;
-		break;
-	case 0x2000:
-		_otherDoor = (Sprite*)param.asEntity();
-		break;
-	case 0x3002:
-		if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
-			sendMessage(_parentScene, 0x4808, 0);
-		stopAnimation();
-		break;
-	case 0x4808:
-		setGlobalVar(V_LARGE_DOOR_NUMBER, _doorIndex);
-		sendMessage(_otherDoor, 0x4809, 0);
-		openDoor();
-		break;
-	case 0x4809:
-		closeDoor();
-		sendMessage(_parentScene, 0x2003, 0);
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2203Door::openDoor() {
-	playSound(0, 0x341014C4);
-	startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 1, -1);
-}
-
-void AsScene2203Door::closeDoor() {
-	startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
-	_playBackwards = true;
-	_newStickFrameIndex = 0;
-}
-
 Scene2203::Scene2203(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule) {
 
@@ -1197,24 +806,6 @@ uint32 Scene2203::handleMessage(int messageNum, const MessageParam &param, Entit
 	return messageResult;
 }
 
-SsScene2205DoorFrame::SsScene2205DoorFrame(NeverhoodEngine *vm)
-	: StaticSprite(vm, 900) {
-
-	SetMessageHandler(&SsScene2205DoorFrame::handleMessage);
-	createSurface(1100, 45, 206);
-	loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
-}
-
-uint32 SsScene2205DoorFrame::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x2000:
-		loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
-		break;
-	}
-	return messageResult;
-}
-
 Scene2205::Scene2205(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule) {
 
@@ -1325,134 +916,6 @@ static const int16 kScene2206XPositions[] = {
 	384, 480, 572
 };
 
-static const uint32 kScene2206MessageIds1[] = {
-	0x004B8998, 0x004B89B8, 0x004B89D8
-};
-
-static const uint32 kScene2206MessageIds2[] = {
-	0x004B89F8, 0x004B8A20, 0x004B8A48
-};
-
-static const int16 kAsScene2206DoorSpikesXDeltasOpen[] = {
-	-24, -28, -18, 6, 9, -8
-};
-
-static const int16 kAsScene2206DoorSpikesXDeltasClose[] = {
-	-8, 7, 11, 26, 13, 14
-};
-
-AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash)
-	: StaticSprite(vm, fileHash, 200) {
-
-	if (getGlobalVar(V_SPIKES_RETRACTED))
-		_x -= 63;
-	SetUpdateHandler(&AsScene2206DoorSpikes::update);
-	SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
-	SetSpriteUpdate(NULL);
-}
-
-void AsScene2206DoorSpikes::update() {
-	handleSpriteUpdate();
-	updatePosition();
-}
-
-uint32 AsScene2206DoorSpikes::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x4808:
-		_deltaIndex = 0;
-		playSound(0, 0x032746E0);
-		SetMessageHandler(NULL);
-		SetSpriteUpdate(&AsScene2206DoorSpikes::suOpen);
-		break;
-	case 0x4809:
-		_deltaIndex = 0;
-		playSound(0, 0x002642C0);
-		SetMessageHandler(NULL);
-		SetSpriteUpdate(&AsScene2206DoorSpikes::suClose);
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2206DoorSpikes::suOpen() {
-	if (_deltaIndex < 6) {
-		_x += kAsScene2206DoorSpikesXDeltasOpen[_deltaIndex];
-		_deltaIndex++;
-	} else {
-		SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
-		SetSpriteUpdate(NULL);
-	}
-}
-
-void AsScene2206DoorSpikes::suClose() {
-	if (_deltaIndex < 6) {
-		_x += kAsScene2206DoorSpikesXDeltasClose[_deltaIndex];
-		_deltaIndex++;
-	} else {
-		SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
-		SetSpriteUpdate(NULL);
-	}
-}
-
-AsScene2206Platform::AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash)
-	: StaticSprite(vm, fileHash, 50) {
-
-	SetUpdateHandler(&AsScene2206Platform::update);
-	SetMessageHandler(&AsScene2206Platform::handleMessage);
-	SetSpriteUpdate(NULL);
-}
-
-void AsScene2206Platform::update() {
-	handleSpriteUpdate();
-	updatePosition();
-}
-
-uint32 AsScene2206Platform::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x4803:
-		_yDelta = 0;
-		SetMessageHandler(NULL);
-		SetSpriteUpdate(&AsScene2206Platform::suMoveDown);
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2206Platform::suMoveDown() {
-	_yDelta++;
-	_y += _yDelta;
-}
-
-SsScene2206TestTube::SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash)
-	: StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene) {
-
-	if (getGlobalVar(V_HAS_TEST_TUBE)) {
-		setVisible(false);
-		SetMessageHandler(NULL);
-	} else
-		SetMessageHandler(&SsScene2206TestTube::handleMessage);
-	_collisionBoundsOffset = _drawOffset;
-	updateBounds();
-}
-
-uint32 SsScene2206TestTube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		sendMessage(_parentScene, 0x4826, 0);
-		messageResult = 1;
-		break;
-	case 0x4806:
-		setGlobalVar(V_HAS_TEST_TUBE, 1);
-		setVisible(false);
-		SetMessageHandler(NULL);
-		break;
-	}
-	return messageResult;
-}
-
 Scene2206::Scene2206(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule) {
 
@@ -1597,6 +1060,14 @@ void Scene2206::klaymenBehindSpikes() {
 	_klaymen->setClipRect(_sprite2->getDrawRect().x, 0, _sprite3->getDrawRect().x2(), _sprite1->getDrawRect().y2());
 }
 
+static const uint32 kScene2206MessageIds1[] = {
+	0x004B8998, 0x004B89B8, 0x004B89D8
+};
+
+static const uint32 kScene2206MessageIds2[] = {
+	0x004B89F8, 0x004B8A20, 0x004B8A48
+};
+
 void Scene2206::readClickedColumn() {
 	setGlobalVar(V_CLICKED_COLUMN_INDEX, (_mouseClickPos.x - 354) / 96);
 	if (getGlobalVar(V_CLICKED_COLUMN_INDEX) > 2)
@@ -1617,317 +1088,6 @@ static const uint32 kScene2207FileHashes[] = {
 	0x3BB1E12E, 0x23B1E12E, 0x13B1E12E
 };
 
-AsScene2207Elevator::AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene)
-	: AnimatedSprite(vm, 900), _parentScene(parentScene), _pointIndex(0), _destPointIndex(0), _destPointIndexDelta(0) {
-
-	NPoint pt;
-
-	_dataResource.load(0x00524846);
-	_pointArray = _dataResource.getPointArray(0x005B02B7);
-	pt = _dataResource.getPoint(0x403A82B1);
-	_x = pt.x;
-	_y = pt.y;
-	createSurface(1100, 129, 103);
-	startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, 0, 0);
-	_newStickFrameIndex = 0;
-	SetUpdateHandler(&AsScene2207Elevator::update);
-	SetMessageHandler(&AsScene2207Elevator::handleMessage);
-	SetSpriteUpdate(&AsScene2207Elevator::suSetPosition);
-}
-
-AsScene2207Elevator::~AsScene2207Elevator() {
-	_vm->_soundMan->deleteSoundGroup(0x02700413);
-}
-
-void AsScene2207Elevator::update() {
-
-	if (_destPointIndex + _destPointIndexDelta > _pointIndex) {
-		_pointIndex++;
-		startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
-		_newStickFrameIndex = _pointIndex;
-		if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
-			if (_destPointIndexDelta != 0)
-				_destPointIndexDelta = 0;
-			else {
-				_vm->_soundMan->deleteSound(0xD3B02847);
-				playSound(0, 0x53B8284A);
-			}
-		}
-	}
-
-	if (_destPointIndex + _destPointIndexDelta < _pointIndex) {
-		_pointIndex--;
-		if (_pointIndex == 0)
-			sendMessage(_parentScene, 0x2003, 0);
-		startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
-		_newStickFrameIndex = _pointIndex;
-		if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
-			if (_destPointIndexDelta != 0)
-				_destPointIndexDelta = 0;
-			else {
-				_vm->_soundMan->deleteSound(0xD3B02847);
-				playSound(0, 0x53B8284A);
-			}
-		}
-	}
-
-	if (_pointIndex > 20 && _surface->getPriority() != 900)
-		sendMessage(_parentScene, 0x2002, 900);
-	else if (_pointIndex < 20 && _surface->getPriority() != 1100)
-		sendMessage(_parentScene, 0x2002, 1100);
-
-	AnimatedSprite::update();
-
-	if (_destPointIndex + _destPointIndexDelta == _pointIndex && _isMoving) {
-		sendMessage(_parentScene, 0x2004, 0);
-		_isMoving = false;
-	}
-
-}
-
-void AsScene2207Elevator::suSetPosition() {
-	_x = (*_pointArray)[_pointIndex].x;
-	_y = (*_pointArray)[_pointIndex].y - 60;
-	updateBounds();
-}
-
-uint32 AsScene2207Elevator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x2000:
-		moveToY(param.asInteger());
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2207Elevator::moveToY(int16 y) {
-	int16 minDistance = 480;
-
-	if (!_pointArray || _pointArray->size() == 0)
-		return;
-
-	for (uint i = 0; i < _pointArray->size(); i++) {
-		int16 distance = ABS(y - (*_pointArray)[i].y);
-		if (distance < minDistance) {
-			minDistance = distance;
-			_destPointIndex = i;
-		}
-	}
-
-	if (_destPointIndex != _pointIndex) {
-		if (_destPointIndex == 0 || _destPointIndex == (int)_pointArray->size() - 1)
-			_destPointIndexDelta = 0;
-		else if (_destPointIndex < _pointIndex)
-			_destPointIndexDelta = -2;
-		else
-			_destPointIndexDelta = 2;
-		_vm->_soundMan->addSound(0x02700413, 0xD3B02847);
-		_vm->_soundMan->playSoundLooping(0xD3B02847);
-	}
-
-	_isMoving = true;
-
-}
-
-AsScene2207Lever::AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX)
-	: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
-
-	_x = x;
-	_y = y;
-	createSurface(1010, 71, 73);
-	setDoDeltaX(doDeltaX);
-	startAnimation(0x80880090, 0, -1);
-	_newStickFrameIndex = 0;
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene2207Lever::handleMessage);
-}
-
-uint32 AsScene2207Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		sendMessage(_parentScene, 0x4826, 0);
-		messageResult = 1;
-		break;
-	case 0x3002:
-		gotoNextState();
-		stopAnimation();
-		break;
-	case 0x4807:
-		stLeverUp();
-		break;
-	case 0x480F:
-		stLeverDown();
-		break;
-	case 0x482A:
-		sendMessage(_parentScene, 0x1022, 990);
-		break;
-	case 0x482B:
-		sendMessage(_parentScene, 0x1022, 1010);
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2207Lever::stLeverDown() {
-	startAnimation(0x80880090, 1, -1);
-	playSound(0, 0x40581882);
-	FinalizeState(&AsScene2207Lever::stLeverDownEvent);
-}
-
-void AsScene2207Lever::stLeverDownEvent() {
-	sendMessage(_parentScene, 0x480F, 0);
-}
-
-void AsScene2207Lever::stLeverUp() {
-	startAnimation(0x80880090, 6, -1);
-	_playBackwards = true;
-	playSound(0, 0x40581882);
-	FinalizeState(&AsScene2207Lever::stLeverUpEvent);
-}
-
-void AsScene2207Lever::stLeverUpEvent() {
-	sendMessage(_parentScene, 0x4807, 0);
-}
-
-AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene)
-	: AnimatedSprite(vm, 1200), _idle(true) {
-
-	_x = 309;
-	_y = 320;
-	createSurface1(0xCCFD6090, 100);
-	startAnimation(0xCCFD6090, 0, -1);
-	_newStickFrameIndex = 0;
-	loadSound(1, 0x40330872);
-	loadSound(2, 0x72A2914A);
-	loadSound(3, 0xD4226080);
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene2207WallRobotAnimation::handleMessage);
-}
-
-AsScene2207WallRobotAnimation::~AsScene2207WallRobotAnimation() {
-	_vm->_soundMan->deleteSoundGroup(0x80D00820);
-}
-
-uint32 AsScene2207WallRobotAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x100D:
-		if (!_idle) {
-			if (param.asInteger() == 0x3423093) {
-				_vm->_soundMan->addSound(0x80D00820, 0x12121943);
-				_vm->_soundMan->playSoundLooping(0x12121943);
-			} else if (param.asInteger() == 0x834AB011) {
-				stopSound(0);
-				stopSound(1);
-				stopSound(2);
-				stopSound(3);
-				_vm->_soundMan->deleteSound(0x12121943);
-			} else if (param.asInteger() == 0x3A980501)
-				playSound(1);
-			else if (param.asInteger() == 0x2A2AD498)
-				playSound(2);
-			else if (param.asInteger() == 0xC4980008)
-				playSound(3);
-			else if (param.asInteger() == 0x06B84228)
-				playSound(0, 0xE0702146);
-		}
-		break;
-	case 0x2006:
-		stStartAnimation();
-		break;
-	case 0x2007:
-		stStopAnimation();
-		break;
-	case 0x3002:
-		gotoNextState();
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2207WallRobotAnimation::stStartAnimation() {
-	if (!_idle) {
-		NextState(NULL);
-	} else {
-		startAnimation(0xCCFD6090, 0, -1);
-		_idle = false;
-		setVisible(true);
-	}
-}
-
-void AsScene2207WallRobotAnimation::stStopAnimation() {
-	NextState(&AsScene2207WallRobotAnimation::cbStopAnimation);
-}
-
-void AsScene2207WallRobotAnimation::cbStopAnimation() {
-	stopAnimation();
-	stopSound(0);
-	stopSound(1);
-	stopSound(2);
-	stopSound(3);
-	_vm->_soundMan->deleteSound(0x12121943);
-	_idle = true;
-	setVisible(false);
-}
-
-AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm)
-	: AnimatedSprite(vm, 1200), _idle(true) {
-
-	_x = 309;
-	_y = 320;
-	createSurface1(0x8CAA0099, 100);
-	startAnimation(0x8CAA0099, 0, -1);
-	_newStickFrameIndex = 0;
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene2207WallCannonAnimation::handleMessage);
-}
-
-uint32 AsScene2207WallCannonAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x2006:
-		stStartAnimation();
-		break;
-	case 0x2007:
-		stStopAnimation();
-		break;
-	case 0x3002:
-		gotoNextState();
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene2207WallCannonAnimation::stStartAnimation() {
-	if (!_idle) {
-		NextState(NULL);
-	} else {
-		setVisible(true);
-		startAnimation(0x8CAA0099, 0, -1);
-		_idle = false;
-	}
-}
-
-void AsScene2207WallCannonAnimation::stStopAnimation() {
-	NextState(&AsScene2207WallCannonAnimation::cbStopAnimation);
-}
-
-void AsScene2207WallCannonAnimation::cbStopAnimation() {
-	stopAnimation();
-	setVisible(false);
-	_idle = true;
-}
-
-SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index)
-	: StaticSprite(vm, fileHash, 100) {
-
-	_x = 330;
-	_y = 246 + index * 50;
-	updatePosition();
-}
-
 Scene2207::Scene2207(NeverhoodEngine *vm, Module *parentModule)
 	: Scene(vm, parentModule), _klaymenAtElevator(true), _elevatorSurfacePriority(0) {
 
diff --git a/engines/neverhood/modules/module2200.h b/engines/neverhood/modules/module2200.h
index 5c19f2a..89f00ad 100644
--- a/engines/neverhood/modules/module2200.h
+++ b/engines/neverhood/modules/module2200.h
@@ -31,8 +31,6 @@
 
 namespace Neverhood {
 
-// Module2200
-
 class Module2200 : public Module {
 public:
 	Module2200(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -44,43 +42,6 @@ protected:
 	void createHallOfRecordsScene(int which, uint32 hallOfRecordsInfoId);
 };
 
-// Scene2201
-
-static const NPoint kSsScene2201PuzzleCubePoints[] = {
-	{305, 305},	{321, 305},	{336, 305},	{305, 319},
-	{321, 319},	{336, 319},	{305, 332},	{321, 332},
-	{336, 333}
-};
-
-static const uint32 kSsScene2201PuzzleCubeFileHashes[] = {
-	0x88134A44,	0xAA124340,	0xB8124602,	0xA902464C,
-	0x890A4244,	0xA8124642,	0xB812C204,	0x381A4A4C
-};
-
-class AsScene2201CeilingFan : public AnimatedSprite {
-public:
-	AsScene2201CeilingFan(NeverhoodEngine *vm);
-};
-
-class AsScene2201Door : public AnimatedSprite {
-public:
-	AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen);
-protected:
-	Klaymen *_klaymen;
-	Sprite *_ssDoorLight;
-	bool _isOpen;
-	int _countdown;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void stOpenDoor();
-	void stCloseDoor();
-};
-
-class SsScene2201PuzzleCube : public StaticSprite {
-public:
-	SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex);
-};
-
 class Scene2201 : public Scene {
 public:
 	Scene2201(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -96,30 +57,6 @@ protected:
 	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
 };
 
-class SsScene2202PuzzleCube : public StaticSprite {
-public:
-	SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol);
-protected:
-	Scene *_parentScene;
-	int16 _cubeSymbol;
-	int16 _cubePosition;
-	int16 _newX, _newY;
-	int16 _xDelta, _yDelta;
-	int16 _xIncr;
-	int16 _yIncr;
-	int16 _errValue;
-	int16 _counter;
-	int16 _xFlagPos;
-	bool _counterDirection;
-	bool _isMoving;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void suMoveCubeX();
-	void suMoveCubeY();
-	void moveCube(int16 newCubePosition);
-	void stopMoving();
-};
-
 class Scene2202 : public Scene {
 public:
 	Scene2202(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -138,27 +75,6 @@ protected:
 	bool testIsSolved();
 };
 
-class AsCommonKey : public AnimatedSprite {
-public:
-	AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y);
-protected:
-	Scene *_parentScene;
-	int _keyIndex;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
-class AsScene2203Door : public AnimatedSprite {
-public:
-	AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex);
-protected:
-	Scene *_parentScene;
-	Sprite *_otherDoor;
-	uint _doorIndex;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void openDoor();
-	void closeDoor();
-};
-
 class Scene2203 : public Scene {
 public:
 	Scene2203(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -175,13 +91,6 @@ protected:
 	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
 };
 
-class SsScene2205DoorFrame : public StaticSprite {
-public:
-	SsScene2205DoorFrame(NeverhoodEngine *vm);
-protected:
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
 class Scene2205 : public Scene {
 public:
 	Scene2205(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -194,35 +103,6 @@ protected:
 	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
 };
 
-class AsScene2206DoorSpikes : public StaticSprite {
-public:
-	AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash);
-protected:
-	int _deltaIndex;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void suOpen();
-	void suClose();
-};
-
-class AsScene2206Platform : public StaticSprite {
-public:
-	AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash);
-protected:
-	int16 _yDelta;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void suMoveDown();
-};
-
-class SsScene2206TestTube : public StaticSprite {
-public:
-	SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash);
-protected:
-	Scene *_parentScene;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
 class Scene2206 : public Scene {
 public:
 	Scene2206(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -241,62 +121,6 @@ protected:
 	void readClickedColumn();
 };
 
-class AsScene2207Elevator : public AnimatedSprite {
-public:
-	AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene);
-	~AsScene2207Elevator();
-protected:
-	Scene *_parentScene;
-	NPointArray *_pointArray;
-	int16 _pointIndex;
-	int16 _destPointIndex, _destPointIndexDelta;
-	bool _isMoving;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void suSetPosition();
-	void moveToY(int16 y);
-};
-
-class AsScene2207Lever : public AnimatedSprite {
-public:
-	AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX);
-protected:
-	Scene *_parentScene;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void stLeverDown();
-	void stLeverDownEvent();
-	void stLeverUp();
-	void stLeverUpEvent();
-};
-
-class AsScene2207WallRobotAnimation : public AnimatedSprite {
-public:
-	AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene);
-	~AsScene2207WallRobotAnimation();
-protected:
-	bool _idle;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void stStartAnimation();
-	void stStopAnimation();
-	void cbStopAnimation();
-};
-
-class AsScene2207WallCannonAnimation : public AnimatedSprite {
-public:
-	AsScene2207WallCannonAnimation(NeverhoodEngine *vm);
-protected:
-	bool _idle;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	void stStartAnimation();
-	void stStopAnimation();
-	void cbStopAnimation();
-};
-
-class SsScene2207Symbol : public StaticSprite {
-public:
-	SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index);
-};
-
 class Scene2207 : public Scene {
 public:
 	Scene2207(NeverhoodEngine *vm, Module *parentModule);
diff --git a/engines/neverhood/modules/module2200_sprites.cpp b/engines/neverhood/modules/module2200_sprites.cpp
new file mode 100644
index 0000000..fecca35
--- /dev/null
+++ b/engines/neverhood/modules/module2200_sprites.cpp
@@ -0,0 +1,870 @@
+/* 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 "neverhood/modules/module2200_sprites.h"
+#include "neverhood/modules/module1000.h"
+#include "neverhood/modules/module1200.h"
+#include "neverhood/gamemodule.h"
+#include "neverhood/diskplayerscene.h"
+
+namespace Neverhood {
+
+AsScene2201CeilingFan::AsScene2201CeilingFan(NeverhoodEngine *vm)
+	: AnimatedSprite(vm, 1100) {
+
+	_x = 403;
+	_y = 259;
+	createSurface(100, 233, 96);
+	startAnimation(0x8600866, 0, -1);
+	SetUpdateHandler(&AnimatedSprite::update);
+}
+
+AsScene2201Door::AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen)
+	: AnimatedSprite(vm, 1100), _klaymen(klaymen), _ssDoorLight(ssDoorLight), _countdown(0), _isOpen(isOpen) {
+
+	_x = 408;
+	_y = 290;
+	createSurface(900, 63, 266);
+	SetUpdateHandler(&AsScene2201Door::update);
+	SetMessageHandler(&AsScene2201Door::handleMessage);
+	if (_isOpen) {
+		startAnimation(0xE2CB0412, -1, -1);
+		_countdown = 48;
+		_newStickFrameIndex = STICK_LAST_FRAME;
+	} else {
+		startAnimation(0xE2CB0412, 0, -1);
+		_newStickFrameIndex = 0;
+		_ssDoorLight->setVisible(false);
+	}
+}
+
+void AsScene2201Door::update() {
+	if (_countdown != 0 && _isOpen && (--_countdown == 0))
+		stCloseDoor();
+	AnimatedSprite::update();
+}
+
+uint32 AsScene2201Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x100D:
+		if (param.asInteger() == 0x11001090) {
+			if (_isOpen)
+				_ssDoorLight->setVisible(true);
+		} else if (param.asInteger() == 0x11283090) {
+			if (!_isOpen)
+				_ssDoorLight->setVisible(false);
+		}
+		break;
+	case 0x2000:
+		if (_isOpen)
+			_countdown = 144;
+		messageResult = _isOpen ? 1 : 0;
+		break;
+	case 0x3002:
+		gotoNextState();
+		break;
+	case 0x4808:
+		_countdown = 144;
+		if (!_isOpen)
+			stOpenDoor();
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2201Door::stOpenDoor() {
+	_isOpen = true;
+	startAnimation(0xE2CB0412, 0, -1);
+	_newStickFrameIndex = STICK_LAST_FRAME;
+	playSound(0, calcHash("fxDoorOpen33"));
+}
+
+void AsScene2201Door::stCloseDoor() {
+	_isOpen = false;
+	startAnimation(0xE2CB0412, -1, -1);
+	_playBackwards = true;
+	_newStickFrameIndex = 0;
+	playSound(0, calcHash("fxDoorClose33"));
+}
+
+SsScene2201PuzzleCube::SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex)
+	: StaticSprite(vm, 900) {
+
+	createSurface(100, 16, 16);
+	loadSprite(kSsScene2201PuzzleCubeFileHashes[cubeIndex], kSLFCenteredDrawOffset | kSLFSetPosition, 0,
+		kSsScene2201PuzzleCubePoints[positionIndex].x, kSsScene2201PuzzleCubePoints[positionIndex].y);
+}
+
+static const NPoint kSsScene2202PuzzleCubePoints[] = {
+	{196, 105}, {323, 102}, {445, 106},
+	{192, 216}, {319, 220}, {446, 216},
+	{188, 320}, {319, 319}, {443, 322}
+};
+
+static const uint32 kSsScene2202PuzzleCubeFileHashes1[] = {
+	0xA500800C, 0x2182910C, 0x2323980C,
+	0x23049084, 0x21008080, 0x2303900C,
+	0x6120980C, 0x2504D808
+};
+
+static const uint32 kSsScene2202PuzzleCubeFileHashes2[] = {
+	0x0AAD8080, 0x0A290291, 0x0A2BA398,
+	0x822B8490, 0x86298080, 0x0A2B8390,
+	0x0A69A098, 0x0E2D84D8
+};
+
+SsScene2202PuzzleCube::SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol)
+	: StaticSprite(vm, 900), _parentScene(parentScene), _cubeSymbol(cubeSymbol), _cubePosition(cubePosition), _isMoving(false) {
+
+	int surfacePriority;
+
+	SetUpdateHandler(&SsScene2202PuzzleCube::update);
+	SetMessageHandler(&SsScene2202PuzzleCube::handleMessage);
+	if (_cubePosition >= 0 && _cubePosition <= 2)
+		surfacePriority = 100;
+	else if (_cubePosition >= 3 && _cubePosition <= 5)
+		surfacePriority = 300;
+	else
+		surfacePriority = 500;
+	debug(1, "TODO: Unused SurfacePriority: %d", surfacePriority);
+	loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset | kSLFSetPosition | kSLFDefCollisionBoundsOffset, 0,
+		kSsScene2202PuzzleCubePoints[_cubePosition].x, kSsScene2202PuzzleCubePoints[_cubePosition].y);
+	loadSound(0, 0x40958621);
+	loadSound(1, 0x51108241);
+}
+
+void SsScene2202PuzzleCube::update() {
+	handleSpriteUpdate();
+	updatePosition();
+}
+
+uint32 SsScene2202PuzzleCube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		if (!_isMoving && !getGlobalVar(V_TILE_PUZZLE_SOLVED))
+			sendMessage(_parentScene, 0x2000, _cubePosition);
+		messageResult = 1;
+		break;
+	case 0x2001:
+		_isMoving = true;
+		moveCube(param.asInteger());
+		break;
+	}
+	return messageResult;
+}
+
+void SsScene2202PuzzleCube::suMoveCubeX() {
+
+	bool done = false;
+
+	if (_counterDirection) {
+		if (_counter > 2)
+			_counter -= 2;
+	} else {
+		if (_counter < 20)
+			_counter += 2;
+	}
+
+	for (int16 i = 0; i < _counter; i++) {
+		_x += _xIncr;
+		_errValue += _yDelta;
+		if (_errValue >= _xDelta) {
+			_errValue -= _xDelta;
+			_y += _yIncr;
+		}
+		if (_x == _newX && _y == _newY) {
+			done = true;
+			break;
+		}
+		if (_x == _xFlagPos)
+			_counterDirection = true;
+	}
+
+	if (done)
+		stopMoving();
+
+	updateBounds();
+
+}
+
+void SsScene2202PuzzleCube::suMoveCubeY() {
+
+	bool done = false;
+
+	if (_counterDirection) {
+		if (_counter > 2)
+			_counter -= 2;
+	} else {
+		if (_counter < 20)
+			_counter += 2;
+	}
+
+	for (int16 i = 0; i < _counter; i++) {
+		_y += _yIncr;
+		_errValue += _xDelta;
+		if (_errValue >= _yDelta) {
+			_errValue -= _yDelta;
+			_x += _xIncr;
+		}
+		if (_x == _newX && _y == _newY) {
+			done = true;
+			break;
+		}
+		if (_x == _xFlagPos)
+			_counterDirection = true;
+	}
+
+	if (done)
+		stopMoving();
+
+	updateBounds();
+
+}
+
+void SsScene2202PuzzleCube::moveCube(int16 newCubePosition) {
+
+	loadSprite(kSsScene2202PuzzleCubeFileHashes1[_cubeSymbol], kSLFCenteredDrawOffset);
+
+	setSubVar(VA_CUBE_POSITIONS, _cubePosition, (uint32)-1);
+	setSubVar(VA_CUBE_POSITIONS, newCubePosition, (uint32)_cubeSymbol);
+
+	_cubePosition = newCubePosition;
+	_errValue = 0;
+	_counterDirection = false;
+	_counter = 0;
+	_newX = kSsScene2202PuzzleCubePoints[newCubePosition].x;
+	_newY = kSsScene2202PuzzleCubePoints[newCubePosition].y;
+
+	if (_x == _newX && _y == _newY)
+		return;
+
+	if (_x <= _newX) {
+		if (_y <= _newY) {
+			_xDelta = _newX - _x;
+			_yDelta = _newY - _y;
+			_xIncr = 1;
+			_yIncr = 1;
+		} else {
+			_xDelta = _newX - _x;
+			_yDelta = _y - _newY;
+			_xIncr = 1;
+			_yIncr = -1;
+		}
+	} else {
+		if (_y <= _newY) {
+			_xDelta = _x - _newX;
+			_yDelta = _newY - _y;
+			_xIncr = -1;
+			_yIncr = 1;
+		} else {
+			_xDelta = _x - _newX;
+			_yDelta = _y - _newY;
+			_xIncr = -1;
+			_yIncr = -1;
+		}
+	}
+
+	if (_xDelta > _yDelta) {
+		SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeX);
+		if (_xIncr > 0) {
+			if (_newX - _x >= 180)
+				_xFlagPos = _newX - 90;
+			else
+				_xFlagPos = _x + _newX / 2;
+		} else {
+			if (_x - _newX >= 180)
+				_xFlagPos = _x + 90;
+			else
+				_xFlagPos = _x / 2 + _newX;
+		}
+		playSound(0);
+	} else {
+		SetSpriteUpdate(&SsScene2202PuzzleCube::suMoveCubeY);
+		if (_yIncr > 0) {
+			if (_newY - _y >= 180)
+				_xFlagPos = _newY - 90;
+			else
+				_xFlagPos = _y + _newY / 2;
+		} else {
+			if (_y - _newY >= 180)
+				_xFlagPos = _y + 90;
+			else
+				_xFlagPos = _y / 2 + _newY;
+		}
+		playSound(1);
+	}
+
+}
+
+void SsScene2202PuzzleCube::stopMoving() {
+	loadSprite(kSsScene2202PuzzleCubeFileHashes2[_cubeSymbol], kSLFCenteredDrawOffset);
+	SetSpriteUpdate(NULL);
+	_isMoving = false;
+	sendMessage(_parentScene, 0x2002, _cubePosition);
+}
+
+static const uint32 kAsCommonKeyFileHashes[] = {
+	0x2450D850,	0x0C9CE8D0,	0x2C58A152
+};
+
+AsCommonKey::AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y)
+	: AnimatedSprite(vm, kAsCommonKeyFileHashes[keyIndex], surfacePriority, x, y), _parentScene(parentScene), _keyIndex(keyIndex) {
+
+	if (!getSubVar(VA_HAS_KEY, _keyIndex) && !getSubVar(VA_IS_KEY_INSERTED, _keyIndex)) {
+		SetMessageHandler(&AsCommonKey::handleMessage);
+	} else {
+		// If Klaymen already has the key or it's already inserted then don't show it
+		setVisible(false);
+		SetMessageHandler(NULL);
+	}
+}
+
+uint32 AsCommonKey::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		sendMessage(_parentScene, 0x4826, 0);
+		messageResult = 1;
+		break;
+	case 0x4806:
+		setSubVar(VA_HAS_KEY, _keyIndex, 1);
+		setVisible(false);
+		SetMessageHandler(NULL);
+	}
+	return messageResult;
+}
+
+static const uint32 kAsScene2203DoorFileHashes[] = {
+	0x7868AE10,	0x1A488110
+};
+
+AsScene2203Door::AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex)
+	: AnimatedSprite(vm, 1100), _parentScene(parentScene), _doorIndex(doorIndex) {
+
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene2203Door::handleMessage);
+	_x = 320;
+	_y = 240;
+	createSurface1(kAsScene2203DoorFileHashes[_doorIndex], 900);
+	if (getGlobalVar(V_LARGE_DOOR_NUMBER) == _doorIndex) {
+		startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
+		_newStickFrameIndex = STICK_LAST_FRAME;
+	} else {
+		startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 0, -1);
+		_newStickFrameIndex = 0;
+	}
+}
+
+uint32 AsScene2203Door::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
+			sendMessage(_parentScene, 0x2002, 0);
+		else
+			sendMessage(_parentScene, 0x2001, 0);
+		messageResult = 1;
+		break;
+	case 0x2000:
+		_otherDoor = (Sprite*)param.asEntity();
+		break;
+	case 0x3002:
+		if (_doorIndex == getGlobalVar(V_LARGE_DOOR_NUMBER))
+			sendMessage(_parentScene, 0x4808, 0);
+		stopAnimation();
+		break;
+	case 0x4808:
+		setGlobalVar(V_LARGE_DOOR_NUMBER, _doorIndex);
+		sendMessage(_otherDoor, 0x4809, 0);
+		openDoor();
+		break;
+	case 0x4809:
+		closeDoor();
+		sendMessage(_parentScene, 0x2003, 0);
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2203Door::openDoor() {
+	playSound(0, 0x341014C4);
+	startAnimation(kAsScene2203DoorFileHashes[_doorIndex], 1, -1);
+}
+
+void AsScene2203Door::closeDoor() {
+	startAnimation(kAsScene2203DoorFileHashes[_doorIndex], -1, -1);
+	_playBackwards = true;
+	_newStickFrameIndex = 0;
+}
+
+SsScene2205DoorFrame::SsScene2205DoorFrame(NeverhoodEngine *vm)
+	: StaticSprite(vm, 900) {
+
+	SetMessageHandler(&SsScene2205DoorFrame::handleMessage);
+	createSurface(1100, 45, 206);
+	loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
+}
+
+uint32 SsScene2205DoorFrame::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x2000:
+		loadSprite(getGlobalVar(V_LIGHTS_ON) ? 0x24306227 : 0xD90032A0, kSLFDefDrawOffset | kSLFDefPosition);
+		break;
+	}
+	return messageResult;
+}
+
+static const int16 kAsScene2206DoorSpikesXDeltasOpen[] = {
+	-24, -28, -18, 6, 9, -8
+};
+
+static const int16 kAsScene2206DoorSpikesXDeltasClose[] = {
+	-8, 7, 11, 26, 13, 14
+};
+
+AsScene2206DoorSpikes::AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash)
+	: StaticSprite(vm, fileHash, 200) {
+
+	if (getGlobalVar(V_SPIKES_RETRACTED))
+		_x -= 63;
+	SetUpdateHandler(&AsScene2206DoorSpikes::update);
+	SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
+	SetSpriteUpdate(NULL);
+}
+
+void AsScene2206DoorSpikes::update() {
+	handleSpriteUpdate();
+	updatePosition();
+}
+
+uint32 AsScene2206DoorSpikes::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x4808:
+		_deltaIndex = 0;
+		playSound(0, 0x032746E0);
+		SetMessageHandler(NULL);
+		SetSpriteUpdate(&AsScene2206DoorSpikes::suOpen);
+		break;
+	case 0x4809:
+		_deltaIndex = 0;
+		playSound(0, 0x002642C0);
+		SetMessageHandler(NULL);
+		SetSpriteUpdate(&AsScene2206DoorSpikes::suClose);
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2206DoorSpikes::suOpen() {
+	if (_deltaIndex < 6) {
+		_x += kAsScene2206DoorSpikesXDeltasOpen[_deltaIndex];
+		_deltaIndex++;
+	} else {
+		SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
+		SetSpriteUpdate(NULL);
+	}
+}
+
+void AsScene2206DoorSpikes::suClose() {
+	if (_deltaIndex < 6) {
+		_x += kAsScene2206DoorSpikesXDeltasClose[_deltaIndex];
+		_deltaIndex++;
+	} else {
+		SetMessageHandler(&AsScene2206DoorSpikes::handleMessage);
+		SetSpriteUpdate(NULL);
+	}
+}
+
+AsScene2206Platform::AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash)
+	: StaticSprite(vm, fileHash, 50) {
+
+	SetUpdateHandler(&AsScene2206Platform::update);
+	SetMessageHandler(&AsScene2206Platform::handleMessage);
+	SetSpriteUpdate(NULL);
+}
+
+void AsScene2206Platform::update() {
+	handleSpriteUpdate();
+	updatePosition();
+}
+
+uint32 AsScene2206Platform::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x4803:
+		_yDelta = 0;
+		SetMessageHandler(NULL);
+		SetSpriteUpdate(&AsScene2206Platform::suMoveDown);
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2206Platform::suMoveDown() {
+	_yDelta++;
+	_y += _yDelta;
+}
+
+SsScene2206TestTube::SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash)
+	: StaticSprite(vm, fileHash, surfacePriority), _parentScene(parentScene) {
+
+	if (getGlobalVar(V_HAS_TEST_TUBE)) {
+		setVisible(false);
+		SetMessageHandler(NULL);
+	} else
+		SetMessageHandler(&SsScene2206TestTube::handleMessage);
+	_collisionBoundsOffset = _drawOffset;
+	updateBounds();
+}
+
+uint32 SsScene2206TestTube::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		sendMessage(_parentScene, 0x4826, 0);
+		messageResult = 1;
+		break;
+	case 0x4806:
+		setGlobalVar(V_HAS_TEST_TUBE, 1);
+		setVisible(false);
+		SetMessageHandler(NULL);
+		break;
+	}
+	return messageResult;
+}
+
+AsScene2207Elevator::AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene)
+	: AnimatedSprite(vm, 900), _parentScene(parentScene), _pointIndex(0), _destPointIndex(0), _destPointIndexDelta(0) {
+
+	NPoint pt;
+
+	_dataResource.load(0x00524846);
+	_pointArray = _dataResource.getPointArray(0x005B02B7);
+	pt = _dataResource.getPoint(0x403A82B1);
+	_x = pt.x;
+	_y = pt.y;
+	createSurface(1100, 129, 103);
+	startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, 0, 0);
+	_newStickFrameIndex = 0;
+	SetUpdateHandler(&AsScene2207Elevator::update);
+	SetMessageHandler(&AsScene2207Elevator::handleMessage);
+	SetSpriteUpdate(&AsScene2207Elevator::suSetPosition);
+}
+
+AsScene2207Elevator::~AsScene2207Elevator() {
+	_vm->_soundMan->deleteSoundGroup(0x02700413);
+}
+
+void AsScene2207Elevator::update() {
+
+	if (_destPointIndex + _destPointIndexDelta > _pointIndex) {
+		_pointIndex++;
+		startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
+		_newStickFrameIndex = _pointIndex;
+		if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
+			if (_destPointIndexDelta != 0)
+				_destPointIndexDelta = 0;
+			else {
+				_vm->_soundMan->deleteSound(0xD3B02847);
+				playSound(0, 0x53B8284A);
+			}
+		}
+	}
+
+	if (_destPointIndex + _destPointIndexDelta < _pointIndex) {
+		_pointIndex--;
+		if (_pointIndex == 0)
+			sendMessage(_parentScene, 0x2003, 0);
+		startAnimation(getGlobalVar(V_LIGHTS_ON) ? 0xC858CC19 : 0x294B3377, _pointIndex, _pointIndex);
+		_newStickFrameIndex = _pointIndex;
+		if (_destPointIndex + _destPointIndexDelta == _pointIndex) {
+			if (_destPointIndexDelta != 0)
+				_destPointIndexDelta = 0;
+			else {
+				_vm->_soundMan->deleteSound(0xD3B02847);
+				playSound(0, 0x53B8284A);
+			}
+		}
+	}
+
+	if (_pointIndex > 20 && _surface->getPriority() != 900)
+		sendMessage(_parentScene, 0x2002, 900);
+	else if (_pointIndex < 20 && _surface->getPriority() != 1100)
+		sendMessage(_parentScene, 0x2002, 1100);
+
+	AnimatedSprite::update();
+
+	if (_destPointIndex + _destPointIndexDelta == _pointIndex && _isMoving) {
+		sendMessage(_parentScene, 0x2004, 0);
+		_isMoving = false;
+	}
+
+}
+
+void AsScene2207Elevator::suSetPosition() {
+	_x = (*_pointArray)[_pointIndex].x;
+	_y = (*_pointArray)[_pointIndex].y - 60;
+	updateBounds();
+}
+
+uint32 AsScene2207Elevator::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x2000:
+		moveToY(param.asInteger());
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2207Elevator::moveToY(int16 y) {
+	int16 minDistance = 480;
+
+	if (!_pointArray || _pointArray->size() == 0)
+		return;
+
+	for (uint i = 0; i < _pointArray->size(); i++) {
+		int16 distance = ABS(y - (*_pointArray)[i].y);
+		if (distance < minDistance) {
+			minDistance = distance;
+			_destPointIndex = i;
+		}
+	}
+
+	if (_destPointIndex != _pointIndex) {
+		if (_destPointIndex == 0 || _destPointIndex == (int)_pointArray->size() - 1)
+			_destPointIndexDelta = 0;
+		else if (_destPointIndex < _pointIndex)
+			_destPointIndexDelta = -2;
+		else
+			_destPointIndexDelta = 2;
+		_vm->_soundMan->addSound(0x02700413, 0xD3B02847);
+		_vm->_soundMan->playSoundLooping(0xD3B02847);
+	}
+
+	_isMoving = true;
+
+}
+
+AsScene2207Lever::AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX)
+	: AnimatedSprite(vm, 1100), _parentScene(parentScene) {
+
+	_x = x;
+	_y = y;
+	createSurface(1010, 71, 73);
+	setDoDeltaX(doDeltaX);
+	startAnimation(0x80880090, 0, -1);
+	_newStickFrameIndex = 0;
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene2207Lever::handleMessage);
+}
+
+uint32 AsScene2207Lever::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		sendMessage(_parentScene, 0x4826, 0);
+		messageResult = 1;
+		break;
+	case 0x3002:
+		gotoNextState();
+		stopAnimation();
+		break;
+	case 0x4807:
+		stLeverUp();
+		break;
+	case 0x480F:
+		stLeverDown();
+		break;
+	case 0x482A:
+		sendMessage(_parentScene, 0x1022, 990);
+		break;
+	case 0x482B:
+		sendMessage(_parentScene, 0x1022, 1010);
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2207Lever::stLeverDown() {
+	startAnimation(0x80880090, 1, -1);
+	playSound(0, 0x40581882);
+	FinalizeState(&AsScene2207Lever::stLeverDownEvent);
+}
+
+void AsScene2207Lever::stLeverDownEvent() {
+	sendMessage(_parentScene, 0x480F, 0);
+}
+
+void AsScene2207Lever::stLeverUp() {
+	startAnimation(0x80880090, 6, -1);
+	_playBackwards = true;
+	playSound(0, 0x40581882);
+	FinalizeState(&AsScene2207Lever::stLeverUpEvent);
+}
+
+void AsScene2207Lever::stLeverUpEvent() {
+	sendMessage(_parentScene, 0x4807, 0);
+}
+
+AsScene2207WallRobotAnimation::AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene)
+	: AnimatedSprite(vm, 1200), _idle(true) {
+
+	_x = 309;
+	_y = 320;
+	createSurface1(0xCCFD6090, 100);
+	startAnimation(0xCCFD6090, 0, -1);
+	_newStickFrameIndex = 0;
+	loadSound(1, 0x40330872);
+	loadSound(2, 0x72A2914A);
+	loadSound(3, 0xD4226080);
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene2207WallRobotAnimation::handleMessage);
+}
+
+AsScene2207WallRobotAnimation::~AsScene2207WallRobotAnimation() {
+	_vm->_soundMan->deleteSoundGroup(0x80D00820);
+}
+
+uint32 AsScene2207WallRobotAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x100D:
+		if (!_idle) {
+			if (param.asInteger() == 0x3423093) {
+				_vm->_soundMan->addSound(0x80D00820, 0x12121943);
+				_vm->_soundMan->playSoundLooping(0x12121943);
+			} else if (param.asInteger() == 0x834AB011) {
+				stopSound(0);
+				stopSound(1);
+				stopSound(2);
+				stopSound(3);
+				_vm->_soundMan->deleteSound(0x12121943);
+			} else if (param.asInteger() == 0x3A980501)
+				playSound(1);
+			else if (param.asInteger() == 0x2A2AD498)
+				playSound(2);
+			else if (param.asInteger() == 0xC4980008)
+				playSound(3);
+			else if (param.asInteger() == 0x06B84228)
+				playSound(0, 0xE0702146);
+		}
+		break;
+	case 0x2006:
+		stStartAnimation();
+		break;
+	case 0x2007:
+		stStopAnimation();
+		break;
+	case 0x3002:
+		gotoNextState();
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2207WallRobotAnimation::stStartAnimation() {
+	if (!_idle) {
+		NextState(NULL);
+	} else {
+		startAnimation(0xCCFD6090, 0, -1);
+		_idle = false;
+		setVisible(true);
+	}
+}
+
+void AsScene2207WallRobotAnimation::stStopAnimation() {
+	NextState(&AsScene2207WallRobotAnimation::cbStopAnimation);
+}
+
+void AsScene2207WallRobotAnimation::cbStopAnimation() {
+	stopAnimation();
+	stopSound(0);
+	stopSound(1);
+	stopSound(2);
+	stopSound(3);
+	_vm->_soundMan->deleteSound(0x12121943);
+	_idle = true;
+	setVisible(false);
+}
+
+AsScene2207WallCannonAnimation::AsScene2207WallCannonAnimation(NeverhoodEngine *vm)
+	: AnimatedSprite(vm, 1200), _idle(true) {
+
+	_x = 309;
+	_y = 320;
+	createSurface1(0x8CAA0099, 100);
+	startAnimation(0x8CAA0099, 0, -1);
+	_newStickFrameIndex = 0;
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene2207WallCannonAnimation::handleMessage);
+}
+
+uint32 AsScene2207WallCannonAnimation::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x2006:
+		stStartAnimation();
+		break;
+	case 0x2007:
+		stStopAnimation();
+		break;
+	case 0x3002:
+		gotoNextState();
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene2207WallCannonAnimation::stStartAnimation() {
+	if (!_idle) {
+		NextState(NULL);
+	} else {
+		setVisible(true);
+		startAnimation(0x8CAA0099, 0, -1);
+		_idle = false;
+	}
+}
+
+void AsScene2207WallCannonAnimation::stStopAnimation() {
+	NextState(&AsScene2207WallCannonAnimation::cbStopAnimation);
+}
+
+void AsScene2207WallCannonAnimation::cbStopAnimation() {
+	stopAnimation();
+	setVisible(false);
+	_idle = true;
+}
+
+SsScene2207Symbol::SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index)
+	: StaticSprite(vm, fileHash, 100) {
+
+	_x = 330;
+	_y = 246 + index * 50;
+	updatePosition();
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module2200_sprites.h b/engines/neverhood/modules/module2200_sprites.h
new file mode 100644
index 0000000..696f3a6
--- /dev/null
+++ b/engines/neverhood/modules/module2200_sprites.h
@@ -0,0 +1,207 @@
+/* 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 NEVERHOOD_MODULES_MODULE2200_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE2200_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+#include "neverhood/graphics.h"
+
+namespace Neverhood {
+
+static const NPoint kSsScene2201PuzzleCubePoints[] = {
+	{305, 305},	{321, 305},	{336, 305},	{305, 319},
+	{321, 319},	{336, 319},	{305, 332},	{321, 332},
+	{336, 333}
+};
+
+static const uint32 kSsScene2201PuzzleCubeFileHashes[] = {
+	0x88134A44,	0xAA124340,	0xB8124602,	0xA902464C,
+	0x890A4244,	0xA8124642,	0xB812C204,	0x381A4A4C
+};
+
+class AsScene2201CeilingFan : public AnimatedSprite {
+public:
+	AsScene2201CeilingFan(NeverhoodEngine *vm);
+};
+
+class AsScene2201Door : public AnimatedSprite {
+public:
+	AsScene2201Door(NeverhoodEngine *vm, Klaymen *klaymen, Sprite *ssDoorLight, bool isOpen);
+protected:
+	Klaymen *_klaymen;
+	Sprite *_ssDoorLight;
+	bool _isOpen;
+	int _countdown;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void stOpenDoor();
+	void stCloseDoor();
+};
+
+class SsScene2201PuzzleCube : public StaticSprite {
+public:
+	SsScene2201PuzzleCube(NeverhoodEngine *vm, uint32 positionIndex, uint32 cubeIndex);
+};
+
+class SsScene2202PuzzleCube : public StaticSprite {
+public:
+	SsScene2202PuzzleCube(NeverhoodEngine *vm, Scene *parentScene, int16 cubePosition, int16 cubeSymbol);
+protected:
+	Scene *_parentScene;
+	int16 _cubeSymbol;
+	int16 _cubePosition;
+	int16 _newX, _newY;
+	int16 _xDelta, _yDelta;
+	int16 _xIncr;
+	int16 _yIncr;
+	int16 _errValue;
+	int16 _counter;
+	int16 _xFlagPos;
+	bool _counterDirection;
+	bool _isMoving;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void suMoveCubeX();
+	void suMoveCubeY();
+	void moveCube(int16 newCubePosition);
+	void stopMoving();
+};
+
+class AsCommonKey : public AnimatedSprite {
+public:
+	AsCommonKey(NeverhoodEngine *vm, Scene *parentScene, int keyIndex, int surfacePriority, int16 x, int16 y);
+protected:
+	Scene *_parentScene;
+	int _keyIndex;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2203Door : public AnimatedSprite {
+public:
+	AsScene2203Door(NeverhoodEngine *vm, Scene *parentScene, uint doorIndex);
+protected:
+	Scene *_parentScene;
+	Sprite *_otherDoor;
+	uint _doorIndex;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void openDoor();
+	void closeDoor();
+};
+
+class SsScene2205DoorFrame : public StaticSprite {
+public:
+	SsScene2205DoorFrame(NeverhoodEngine *vm);
+protected:
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2206DoorSpikes : public StaticSprite {
+public:
+	AsScene2206DoorSpikes(NeverhoodEngine *vm, uint32 fileHash);
+protected:
+	int _deltaIndex;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void suOpen();
+	void suClose();
+};
+
+class AsScene2206Platform : public StaticSprite {
+public:
+	AsScene2206Platform(NeverhoodEngine *vm, uint32 fileHash);
+protected:
+	int16 _yDelta;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void suMoveDown();
+};
+
+class SsScene2206TestTube : public StaticSprite {
+public:
+	SsScene2206TestTube(NeverhoodEngine *vm, Scene *parentScene, int surfacePriority, uint32 fileHash);
+protected:
+	Scene *_parentScene;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+class AsScene2207Elevator : public AnimatedSprite {
+public:
+	AsScene2207Elevator(NeverhoodEngine *vm, Scene *parentScene);
+	~AsScene2207Elevator();
+protected:
+	Scene *_parentScene;
+	NPointArray *_pointArray;
+	int16 _pointIndex;
+	int16 _destPointIndex, _destPointIndexDelta;
+	bool _isMoving;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void suSetPosition();
+	void moveToY(int16 y);
+};
+
+class AsScene2207Lever : public AnimatedSprite {
+public:
+	AsScene2207Lever(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y, int doDeltaX);
+protected:
+	Scene *_parentScene;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void stLeverDown();
+	void stLeverDownEvent();
+	void stLeverUp();
+	void stLeverUpEvent();
+};
+
+class AsScene2207WallRobotAnimation : public AnimatedSprite {
+public:
+	AsScene2207WallRobotAnimation(NeverhoodEngine *vm, Scene *parentScene);
+	~AsScene2207WallRobotAnimation();
+protected:
+	bool _idle;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void stStartAnimation();
+	void stStopAnimation();
+	void cbStopAnimation();
+};
+
+class AsScene2207WallCannonAnimation : public AnimatedSprite {
+public:
+	AsScene2207WallCannonAnimation(NeverhoodEngine *vm);
+protected:
+	bool _idle;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	void stStartAnimation();
+	void stStopAnimation();
+	void cbStopAnimation();
+};
+
+class SsScene2207Symbol : public StaticSprite {
+public:
+	SsScene2207Symbol(NeverhoodEngine *vm, uint32 fileHash, int index);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE2200_SPRITES_H */
diff --git a/engines/neverhood/modules/module2400.cpp b/engines/neverhood/modules/module2400.cpp
index 0e2056d..a045dcd 100644
--- a/engines/neverhood/modules/module2400.cpp
+++ b/engines/neverhood/modules/module2400.cpp
@@ -20,8 +20,13 @@
  *
  */
 
+#include "neverhood/modules/module1000.h"
+#include "neverhood/modules/module1200.h"
 #include "neverhood/modules/module2400.h"
+#include "neverhood/modules/module2100_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/modules/module2400_sprites.h"
+#include "neverhood/modules/module2800_sprites.h"
 
 namespace Neverhood {
 
diff --git a/engines/neverhood/modules/module2400.h b/engines/neverhood/modules/module2400.h
index ba58ce3..61603f3 100644
--- a/engines/neverhood/modules/module2400.h
+++ b/engines/neverhood/modules/module2400.h
@@ -27,13 +27,6 @@
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
 #include "neverhood/gamemodule.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1100.h"
-#include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module2100.h"
-#include "neverhood/modules/module2200.h"
-#include "neverhood/modules/module2800.h"
-#include "neverhood/modules/module2800_sprites.h"
 #include "neverhood/diskplayerscene.h"
 
 namespace Neverhood {
diff --git a/engines/neverhood/modules/module2500.cpp b/engines/neverhood/modules/module2500.cpp
index dcb3e94..b606659 100644
--- a/engines/neverhood/modules/module2500.cpp
+++ b/engines/neverhood/modules/module2500.cpp
@@ -20,10 +20,11 @@
  *
  */
 
+#include "neverhood/modules/module1600.h"
 #include "neverhood/modules/module2500.h"
 #include "neverhood/modules/module2500_sprites.h"
+#include "neverhood/modules/module2700.h"
 #include "neverhood/modules/module2700_sprites.h"
-#include "neverhood/modules/module1600.h"
 
 namespace Neverhood {
 
diff --git a/engines/neverhood/modules/module2500.h b/engines/neverhood/modules/module2500.h
index 2f07f24..33464cf 100644
--- a/engines/neverhood/modules/module2500.h
+++ b/engines/neverhood/modules/module2500.h
@@ -26,9 +26,6 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1600.h"
-#include "neverhood/modules/module2700.h"
 
 namespace Neverhood {
 
@@ -47,6 +44,9 @@ protected:
 	void createScene2704(int which, uint32 sceneInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL);
 };
 
+class AsCommonCar;
+class Tracks;
+
 class Scene2501 : public Scene {
 public:
 	Scene2501(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index f0bda6f..69e21dd 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -20,10 +20,11 @@
  *
  */
 
-#include "neverhood/modules/module2700.h"
-#include "neverhood/modules/module2700_sprites.h"
 #include "neverhood/gamemodule.h"
 #include "neverhood/modules/module1000.h"
+#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module2700.h"
+#include "neverhood/modules/module2700_sprites.h"
 
 namespace Neverhood {
 
diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h
index 20cc014..5e42eea 100644
--- a/engines/neverhood/modules/module2700.h
+++ b/engines/neverhood/modules/module2700.h
@@ -26,7 +26,6 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/modules/module1600.h"
 
 namespace Neverhood {
 
@@ -49,6 +48,9 @@ protected:
 	void createScene2704(int which, uint32 trackInfoId, int16 value, const uint32 *staticSprites = NULL, const NRect *clipRect = NULL);
 };
 
+class AsCommonCar;
+class Tracks;
+
 class Scene2701 : public Scene {
 public:
 	Scene2701(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2700_sprites.h b/engines/neverhood/modules/module2700_sprites.h
index b9575df..662a357 100644
--- a/engines/neverhood/modules/module2700_sprites.h
+++ b/engines/neverhood/modules/module2700_sprites.h
@@ -26,7 +26,6 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/modules/module1600.h"
 
 namespace Neverhood {
 
diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp
index 3a33598..e0112a6 100644
--- a/engines/neverhood/modules/module2800.cpp
+++ b/engines/neverhood/modules/module2800.cpp
@@ -25,7 +25,7 @@
 #include "neverhood/modules/module1000.h"
 #include "neverhood/modules/module1200.h"
 #include "neverhood/modules/module1700.h"
-#include "neverhood/modules/module2200.h"
+#include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/modules/module2800_sprites.h"
 #include "neverhood/diskplayerscene.h"
 


Commit: b963fcbfa8794c807d831ab3b117634ce7c8550e
    https://github.com/scummvm/scummvm/commit/b963fcbfa8794c807d831ab3b117634ce7c8550e
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2013-10-05T04:41:02-07:00

Commit Message:
NEVERHOOD: Split sprites from their scenes in modules 1700 and 1800

This also reduces inter-header dependencies

Changed paths:
  A engines/neverhood/modules/module1700_sprites.cpp
  A engines/neverhood/modules/module1700_sprites.h
  A engines/neverhood/modules/module1900_sprites.cpp
  A engines/neverhood/modules/module1900_sprites.h
    engines/neverhood/module.mk
    engines/neverhood/modules/module1700.cpp
    engines/neverhood/modules/module1700.h
    engines/neverhood/modules/module1900.cpp
    engines/neverhood/modules/module1900.h
    engines/neverhood/modules/module2000.h
    engines/neverhood/modules/module2800.cpp



diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index 917913f..e49d9f6 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -22,8 +22,10 @@ MODULE_OBJS = \
 	modules/module1500.o \
 	modules/module1600.o \
 	modules/module1700.o \
+	modules/module1700_sprites.o \
 	modules/module1800.o \
 	modules/module1900.o \
+	modules/module1900_sprites.o \
 	modules/module2000.o \
 	modules/module2100.o \
 	modules/module2100_sprites.o \
diff --git a/engines/neverhood/modules/module1700.cpp b/engines/neverhood/modules/module1700.cpp
index 2aeae46..4681e59 100644
--- a/engines/neverhood/modules/module1700.cpp
+++ b/engines/neverhood/modules/module1700.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "neverhood/modules/module1700.h"
+#include "neverhood/modules/module1700_sprites.h"
 #include "neverhood/gamemodule.h"
 
 namespace Neverhood {
@@ -126,8 +127,6 @@ void Module1700::updateScene() {
 	}
 }
 
-// Scene1705
-
 static const uint32 kScene1705FileHashes[] = {
 	0x910EA801, 0x920EA801, 0x940EA801,
 	0x980EA801, 0x800EA801, 0xB00EA801,
@@ -135,47 +134,6 @@ static const uint32 kScene1705FileHashes[] = {
 	0xD10EA801, 0x110EA801, 0x910EA800
 };
 
-SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex)
-	: StaticSprite(vm, fileHash, 100) {
-
-	_x = _spriteResource.getPosition().x + symbolIndex * 30;
-	_y = _spriteResource.getPosition().y + 160;
-	updatePosition();
-}
-
-SsScene1705Tape::SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash)
-	: StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _tapeIndex(tapeIndex) {
-
-	if (!getSubVar(VA_HAS_TAPE, _tapeIndex) && !getSubVar(VA_IS_TAPE_INSERTED, _tapeIndex)) {
-		SetMessageHandler(&SsScene1705Tape::handleMessage);
-	} else {
-		setVisible(false);
-		SetMessageHandler(NULL);
-	}
-	_collisionBoundsOffset = _drawOffset;
-	_collisionBoundsOffset.x -= 4;
-	_collisionBoundsOffset.y -= 8;
-	_collisionBoundsOffset.width += 8;
-	_collisionBoundsOffset.height += 16;
-	Sprite::updateBounds();
-}
-
-uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		sendMessage(_parentScene, 0x4826, 0);
-		messageResult = 1;
-		break;
-	case 0x4806:
-		setSubVar(VA_HAS_TAPE, _tapeIndex, 1);
-		setVisible(false);
-		SetMessageHandler(NULL);
-		break;
-	}
-	return messageResult;
-}
-
 Scene1705::Scene1705(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule), _paletteArea(1) {
 
diff --git a/engines/neverhood/modules/module1700.h b/engines/neverhood/modules/module1700.h
index deb5573..09daff2 100644
--- a/engines/neverhood/modules/module1700.h
+++ b/engines/neverhood/modules/module1700.h
@@ -26,7 +26,6 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/smackerscene.h"
 
 namespace Neverhood {
 
@@ -40,22 +39,6 @@ protected:
 	void updateScene();
 };
 
-// Scene1705
-
-class SsScene1705WallSymbol : public StaticSprite {
-public:
-	SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex);
-};
-
-class SsScene1705Tape : public StaticSprite {
-public:
-	SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash);
-protected:
-	Scene *_parentScene;
-	uint32 _tapeIndex;
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
-
 class Scene1705 : public Scene {
 public:
 	Scene1705(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module1700_sprites.cpp b/engines/neverhood/modules/module1700_sprites.cpp
new file mode 100644
index 0000000..1a8dda3
--- /dev/null
+++ b/engines/neverhood/modules/module1700_sprites.cpp
@@ -0,0 +1,69 @@
+/* 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 "neverhood/gamemodule.h"
+#include "neverhood/modules/module1700_sprites.h"
+
+namespace Neverhood {
+
+SsScene1705WallSymbol::SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex)
+	: StaticSprite(vm, fileHash, 100) {
+
+	_x = _spriteResource.getPosition().x + symbolIndex * 30;
+	_y = _spriteResource.getPosition().y + 160;
+	updatePosition();
+}
+
+SsScene1705Tape::SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash)
+	: StaticSprite(vm, fileHash, surfacePriority, x - 24, y - 4), _parentScene(parentScene), _tapeIndex(tapeIndex) {
+
+	if (!getSubVar(VA_HAS_TAPE, _tapeIndex) && !getSubVar(VA_IS_TAPE_INSERTED, _tapeIndex)) {
+		SetMessageHandler(&SsScene1705Tape::handleMessage);
+	} else {
+		setVisible(false);
+		SetMessageHandler(NULL);
+	}
+	_collisionBoundsOffset = _drawOffset;
+	_collisionBoundsOffset.x -= 4;
+	_collisionBoundsOffset.y -= 8;
+	_collisionBoundsOffset.width += 8;
+	_collisionBoundsOffset.height += 16;
+	Sprite::updateBounds();
+}
+
+uint32 SsScene1705Tape::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		sendMessage(_parentScene, 0x4826, 0);
+		messageResult = 1;
+		break;
+	case 0x4806:
+		setSubVar(VA_HAS_TAPE, _tapeIndex, 1);
+		setVisible(false);
+		SetMessageHandler(NULL);
+		break;
+	}
+	return messageResult;
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1700_sprites.h b/engines/neverhood/modules/module1700_sprites.h
new file mode 100644
index 0000000..3d04325
--- /dev/null
+++ b/engines/neverhood/modules/module1700_sprites.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 NEVERHOOD_MODULES_MODULE1700_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1700_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class SsScene1705WallSymbol : public StaticSprite {
+public:
+	SsScene1705WallSymbol(NeverhoodEngine *vm, uint32 fileHash, int symbolIndex);
+};
+
+class SsScene1705Tape : public StaticSprite {
+public:
+	SsScene1705Tape(NeverhoodEngine *vm, Scene *parentScene, uint32 tapeIndex, int surfacePriority, int16 x, int16 y, uint32 fileHash);
+protected:
+	Scene *_parentScene;
+	uint32 _tapeIndex;
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1700_SPRITES_H */
diff --git a/engines/neverhood/modules/module1900.cpp b/engines/neverhood/modules/module1900.cpp
index 29c2008..3538c14 100644
--- a/engines/neverhood/modules/module1900.cpp
+++ b/engines/neverhood/modules/module1900.cpp
@@ -20,8 +20,9 @@
  *
  */
 
-#include "neverhood/modules/module1900.h"
 #include "neverhood/gamemodule.h"
+#include "neverhood/modules/module1900.h"
+#include "neverhood/modules/module1900_sprites.h"
 
 namespace Neverhood {
 
@@ -84,8 +85,6 @@ void Module1900::updateScene() {
 	}
 }
 
-// Scene1901
-
 Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule) {
 
@@ -126,395 +125,6 @@ Scene1901::Scene1901(NeverhoodEngine *vm, Module *parentModule, int which)
 
 }
 
-static const NPoint kAsScene1907SymbolGroundPositions[] = {
-	{160, 310}, { 90, 340}, {210, 335},
-	{210, 380}, {310, 340}, {290, 400},
-	{400, 375}, {370, 435}, {475, 415}
-};
-
-static const NPoint kAsScene1907SymbolPluggedInPositions[] = {
-	{275, 125}, {244, 125}, {238, 131},
-	{221, 135}, {199, 136}, {168, 149},
-	{145, 152}, {123, 154}, {103, 157}
-};
-
-static const NPoint kAsScene1907SymbolGroundHitPositions[] = {
-	{275, 299}, {244, 299}, {238, 305},
-	{221, 309}, {199, 310}, {168, 323},
-	{145, 326}, {123, 328}, {103, 331}
-};
-
-static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = {
-	{275, 136}, {244, 156}, {238, 183},
-	{221, 207}, {199, 228}, {168, 262},
-	{145, 285}, {123, 307}, {103, 331}
-};
-
-static const uint32 kAsScene1907SymbolFileHashes[] = {
-	0x006A1034, 0x006A1010, 0x006A1814,
-	0x006A1016, 0x006A0014, 0x002A1014,
-	0x00EA1014, 0x206A1014, 0x046A1414
-};
-
-bool AsScene1907Symbol::_plugInFailed = false;
-int AsScene1907Symbol::_plugInTryCount = 0;
-
-AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex)
-	: AnimatedSprite(vm, 1000 - positionIndex), _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) {
-
-	_plugInFailed = false;
-	_plugInTryCount = 0;
-
-	if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
-		_isPluggedIn = true;
-		_currPositionIndex = elementIndex;
-		if (!getGlobalVar(V_STAIRS_DOWN)) {
-			_x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
-			_y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
-		} else {
-			_x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x;
-			_y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y;
-		}
-		createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
-		startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
-		_newStickFrameIndex = STICK_LAST_FRAME;
-	} else {
-		_isPluggedIn = false;
-		_currPositionIndex = positionIndex;
-		loadSound(0, 0x74231924);
-		loadSound(1, 0x36691914);
-		loadSound(2, 0x5421D806);
-		_parentScene->setPositionFree(_currPositionIndex, false);
-		_x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x;
-		_y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y;
-		createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
-		startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
-		_newStickFrameIndex = 0;
-	}
-	_collisionBoundsOffset.set(0, 0, 80, 80);
-	Sprite::updateBounds();
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene1907Symbol::handleMessage);
-
-}
-
-void AsScene1907Symbol::update() {
-	updateAnim();
-	handleSpriteUpdate();
-	updatePosition();
-	if (_plugInFailed && _plugInTryCount == 0)
-		_plugInFailed = false;
-}
-
-uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		if (!_isPluggedIn && !_plugInFailed) {
-			tryToPlugIn();
-			messageResult = 1;
-		} else
-			messageResult = 0;
-		break;
-	}
-	return messageResult;
-}
-
-uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x3002:
-		gotoNextState();
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene1907Symbol::suTryToPlugIn() {
-	_currStep++;
-	_x -= _deltaX;
-	_y -= _deltaY;
-	if (_currStep == 16) {
-		_x -= _smallDeltaX;
-		_y -= _smallDeltaY;
-		SetSpriteUpdate(NULL);
-	}
-}
-
-void AsScene1907Symbol::suFallOff() {
-	if (_fallOffDelay != 0) {
-		_fallOffDelay--;
-	} else {
-		_y += _yAccel;
-		_yAccel += 8;
-		if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
-			_y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y;
-			stFallOffHitGround();
-		}
-	}
-}
-
-void AsScene1907Symbol::suFallOffHitGround() {
-
-	if (_x == _someX - _xBreak)
-		_x -= _smallDeltaX;
-	else
-		_x -= _deltaX;
-
-	if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
-		_y -= _someY;
-	}
-
-	if (_currStep < 8) {
-		_y -= _yAccel;
-		_yAccel -= 4;
-		if (_yAccel < 0)
-			_yAccel = 0;
-	} else if (_currStep < 15) {
-		_y += _yAccel;
-		_yAccel += 4;
-	} else {
-		_y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
-		cbFallOffHitGroundEvent();
-	}
-
-	_currStep++;
-}
-
-void AsScene1907Symbol::suMoveDown() {
-	_y += _yIncr;
-	if (_yIncr < 11)
-		_yIncr++;
-	if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) {
-		_y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y;
-		_isMoving = false;
-		SetSpriteUpdate(NULL);
-	}
-}
-
-void AsScene1907Symbol::suMoveUp() {
-	_y -= _yIncr;
-	if (getGlobalVar(V_WALL_BROKEN)) {
-		if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y)
-			_yIncr--;
-		else
-			_yIncr++;
-	} else
-		_yIncr = 2;
-	if (_yIncr > 9)
-		_yIncr = 9;
-	else if (_yIncr < 1)
-		_yIncr = 1;
-	if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) {
-		_y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y;
-		_isMoving = false;
-		SetSpriteUpdate(NULL);
-	}
-}
-
-void AsScene1907Symbol::tryToPlugIn() {
-	_isPluggedIn = true;
-	_plugInTryCount++;
-	_newPositionIndex = _parentScene->getNextPosition();
-	_parentScene->setPositionFree(_currPositionIndex, true);
-	sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex);
-	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
-	SetUpdateHandler(&AsScene1907Symbol::update);
-	SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn);
-	SetSpriteUpdate(&AsScene1907Symbol::suTryToPlugIn);
-	_currStep = 0;
-	_deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16;
-	_smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x;
-	_deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16;
-	_smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y;
-	if (_elementIndex == _newPositionIndex) {
-		NextState(&AsScene1907Symbol::stPlugIn);
-	} else {
-		_plugInFailed = true;
-		NextState(&AsScene1907Symbol::stPlugInFail);
-	}
-}
-
-void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) {
-	_isPluggedIn = false;
-	_newPositionIndex = newPositionIndex;
-	_fallOffDelay = fallOffDelay;
-	_parentScene->setPositionFree(_newPositionIndex, false);
-	_x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
-	_y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
-	_someX = _x;
-	_someY = _y;
-	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0);
-	_playBackwards = true;
-	_newStickFrameIndex = STICK_LAST_FRAME;
-	_currStep = 0;
-	_yAccel = 1;
-	SetUpdateHandler(&AsScene1907Symbol::update);
-	SetMessageHandler(&AsScene1907Symbol::handleMessage);
-	SetSpriteUpdate(&AsScene1907Symbol::suFallOff);
-}
-
-void AsScene1907Symbol::stFallOffHitGround() {
-	playSound(1);
-	sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex);
-	Entity::_priority = 1000 - _newPositionIndex;
-	_parentScene->removeCollisionSprite(this);
-	_parentScene->addCollisionSprite(this);
-	SetSpriteUpdate(&AsScene1907Symbol::suFallOffHitGround);
-	NextState(&AsScene1907Symbol::cbFallOffHitGroundEvent);
-	_newStickFrameIndex = 0;
-	_currStep = 0;
-	_yAccel = 30;
-	_deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15;
-	_xBreak = _deltaX * 15;
-	_smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak;
-	_someY = 0;
-	if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y)
-		_someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
-}
-
-void AsScene1907Symbol::cbFallOffHitGroundEvent() {
-	_currPositionIndex = _newPositionIndex;
-	if (_plugInTryCount > 0)
-		_plugInTryCount--;
-	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
-	_newStickFrameIndex = 0;
-	SetUpdateHandler(&AnimatedSprite::update);
-	SetMessageHandler(&AsScene1907Symbol::handleMessage);
-	SetSpriteUpdate(NULL);
-	updateBounds();
-	playSound(2);
-}
-
-void AsScene1907Symbol::stPlugIn() {
-	playSound(0);
-	_currPositionIndex = _newPositionIndex;
-	stopAnimation();
-	SetMessageHandler(&AsScene1907Symbol::handleMessage);
-	SetSpriteUpdate(NULL);
-	if (_elementIndex == 8)
-		sendMessage(_parentScene, 0x2001, 0);
-}
-
-void AsScene1907Symbol::stPlugInFail() {
-	_currPositionIndex = _newPositionIndex;
-	stopAnimation();
-	_parentScene->plugInFailed();
-}
-
-void AsScene1907Symbol::moveUp() {
-	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
-	stopAnimation();
-	SetMessageHandler(&AsScene1907Symbol::handleMessage);
-	SetSpriteUpdate(&AsScene1907Symbol::suMoveUp);
-	_yIncr = 1;
-	_isMoving = true;
-}
-
-void AsScene1907Symbol::moveDown() {
-	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
-	stopAnimation();
-	SetMessageHandler(&AsScene1907Symbol::handleMessage);
-	SetSpriteUpdate(&AsScene1907Symbol::suMoveDown);
-	_yIncr = 4;
-	_isMoving = true;
-}
-
-SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol)
-	: StaticSprite(vm, 1400), _parentScene(parentScene), _asScene1907Symbol(asScene1907Symbol),
-	_countdown1(0) {
-
-	loadSprite(0x64516424, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1400);
-	setVisible(false);
-	loadSound(0, 0x44061000);
-	SetUpdateHandler(&SsScene1907UpDownButton::update);
-	SetMessageHandler(&SsScene1907UpDownButton::handleMessage);
-	if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
-		if (getGlobalVar(V_STAIRS_DOWN))
-			setToDownPosition();
-		else
-			setToUpPosition();
-	}
-}
-
-void SsScene1907UpDownButton::update() {
-	updatePosition();
-	if (_countdown1 != 0 && (--_countdown1 == 0)) {
-		setVisible(false);
-		sendMessage(_parentScene, 0x2000, 0);
-	}
-}
-
-uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1011:
-		if (_countdown1 == 0 && !_asScene1907Symbol->isMoving() && getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
-			setVisible(true);
-			_countdown1 = 4;
-			updatePosition();
-			playSound(0);
-		}
-		messageResult = 1;
-	}
-	return messageResult;
-}
-
-void SsScene1907UpDownButton::setToUpPosition() {
-	_y = _spriteResource.getPosition().y;
-	updateBounds();
-	updatePosition();
-}
-
-void SsScene1907UpDownButton::setToDownPosition() {
-	_y = _spriteResource.getPosition().y + 174;
-	updateBounds();
-	updatePosition();
-}
-
-AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm)
-	: AnimatedSprite(vm, 1400) {
-
-	createSurface1(0x110A1061, 1500);
-	_x = 320;
-	_y = 240;
-	startAnimation(0x110A1061, 0, -1);
-	_newStickFrameIndex = 0;
-	setVisible(false);
-	_needRefresh = true;
-	AnimatedSprite::updatePosition();
-	SetUpdateHandler(&AsScene1907WaterHint::update);
-	SetMessageHandler(&Sprite::handleMessage);
-}
-
-void AsScene1907WaterHint::update() {
-	updateAnim();
-	updatePosition();
-}
-
-uint32 AsScene1907WaterHint::hmShowing(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x3002:
-		gotoNextState();
-		break;
-	}
-	return messageResult;
-}
-
-void AsScene1907WaterHint::show() {
-	setVisible(true);
-	startAnimation(0x110A1061, 0, -1);
-	SetMessageHandler(&AsScene1907WaterHint::hmShowing);
-	NextState(&AsScene1907WaterHint::hide);
-}
-
-void AsScene1907WaterHint::hide() {
-	stopAnimation();
-	setVisible(false);
-	SetMessageHandler(&Sprite::handleMessage);
-}
-
 Scene1907::Scene1907(NeverhoodEngine *vm, Module *parentModule)
 	: Scene(vm, parentModule), _currMovingSymbolIndex(0), _pluggedInCount(0),
 	_moveDownCountdown(0), _moveUpCountdown(0), _countdown3(0), _hasPlugInFailed(false) {
diff --git a/engines/neverhood/modules/module1900.h b/engines/neverhood/modules/module1900.h
index abb5eb1..d785c6f 100644
--- a/engines/neverhood/modules/module1900.h
+++ b/engines/neverhood/modules/module1900.h
@@ -26,7 +26,6 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/modules/module1200.h"
 
 namespace Neverhood {
 
@@ -41,80 +40,14 @@ protected:
 	void updateScene();
 };
 
-// Scene1901
-
 class Scene1901 : public Scene {
 public:
 	Scene1901(NeverhoodEngine *vm, Module *parentModule, int which);
 };
 
-// Scene1907
-
-class Scene1907;
-
-class AsScene1907Symbol : public AnimatedSprite {
-public:
-	AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex);
-	void moveUp();
-	void moveDown();
-	void fallOff(int newPositionIndex, int fallOffDelay);
-	bool isPluggedIn() { return _isPluggedIn; }
-	bool isMoving() { return _isMoving; }
-protected:
-	Scene1907 *_parentScene;
-	int _elementIndex;
-	int _currPositionIndex;
-	int _newPositionIndex;
-	bool _isPluggedIn;
-	bool _isMoving;
-	int _someX, _someY;
-	int _xBreak;
-	int _currStep;
-	int _yAccel;
-	int _yIncr;
-	int _fallOffDelay;
-	int _deltaX, _smallDeltaX;
-	int _deltaY, _smallDeltaY;
-	// Dumb, change if possible
-	static bool _plugInFailed;
-	static int _plugInTryCount;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	uint32 hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender);
-	void suTryToPlugIn();
-	void suFallOff();
-	void suFallOffHitGround();
-	void suMoveDown();
-	void suMoveUp();
-	void tryToPlugIn();
-	void stFallOffHitGround();
-	void cbFallOffHitGroundEvent();
-	void stPlugIn();
-	void stPlugInFail();
-};
-
-class AsScene1907WaterHint : public AnimatedSprite {
-public:
-	AsScene1907WaterHint(NeverhoodEngine *vm);
-	void show();
-protected:
-	void update();
-	uint32 hmShowing(int messageNum, const MessageParam &param, Entity *sender);
-	void hide();
-};
-
-class SsScene1907UpDownButton : public StaticSprite {
-public:
-	SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol);
-	void setToUpPosition();
-	void setToDownPosition();
-protected:
-	Scene1907 *_parentScene;
-	AsScene1907Symbol *_asScene1907Symbol;
-	int _countdown1;
-	void update();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-};
+class AsScene1907Symbol;
+class SsScene1907UpDownButton;
+class AsScene1907WaterHint;
 
 class Scene1907 : public Scene {
 public:
diff --git a/engines/neverhood/modules/module1900_sprites.cpp b/engines/neverhood/modules/module1900_sprites.cpp
new file mode 100644
index 0000000..d7e4898
--- /dev/null
+++ b/engines/neverhood/modules/module1900_sprites.cpp
@@ -0,0 +1,418 @@
+/* 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 "neverhood/gamemodule.h"
+#include "neverhood/modules/module1900.h"
+#include "neverhood/modules/module1900_sprites.h"
+
+namespace Neverhood {
+
+static const NPoint kAsScene1907SymbolGroundPositions[] = {
+	{160, 310}, { 90, 340}, {210, 335},
+	{210, 380}, {310, 340}, {290, 400},
+	{400, 375}, {370, 435}, {475, 415}
+};
+
+static const NPoint kAsScene1907SymbolPluggedInPositions[] = {
+	{275, 125}, {244, 125}, {238, 131},
+	{221, 135}, {199, 136}, {168, 149},
+	{145, 152}, {123, 154}, {103, 157}
+};
+
+static const NPoint kAsScene1907SymbolGroundHitPositions[] = {
+	{275, 299}, {244, 299}, {238, 305},
+	{221, 309}, {199, 310}, {168, 323},
+	{145, 326}, {123, 328}, {103, 331}
+};
+
+static const NPoint kAsScene1907SymbolPluggedInDownPositions[] = {
+	{275, 136}, {244, 156}, {238, 183},
+	{221, 207}, {199, 228}, {168, 262},
+	{145, 285}, {123, 307}, {103, 331}
+};
+
+static const uint32 kAsScene1907SymbolFileHashes[] = {
+	0x006A1034, 0x006A1010, 0x006A1814,
+	0x006A1016, 0x006A0014, 0x002A1014,
+	0x00EA1014, 0x206A1014, 0x046A1414
+};
+
+bool AsScene1907Symbol::_plugInFailed = false;
+int AsScene1907Symbol::_plugInTryCount = 0;
+
+AsScene1907Symbol::AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex)
+	: AnimatedSprite(vm, 1000 - positionIndex), _parentScene(parentScene), _elementIndex(elementIndex), _isMoving(false) {
+
+	_plugInFailed = false;
+	_plugInTryCount = 0;
+
+	if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
+		_isPluggedIn = true;
+		_currPositionIndex = elementIndex;
+		if (!getGlobalVar(V_STAIRS_DOWN)) {
+			_x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
+			_y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
+		} else {
+			_x = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].x;
+			_y = kAsScene1907SymbolPluggedInDownPositions[_currPositionIndex].y;
+		}
+		createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
+		startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+		_newStickFrameIndex = STICK_LAST_FRAME;
+	} else {
+		_isPluggedIn = false;
+		_currPositionIndex = positionIndex;
+		loadSound(0, 0x74231924);
+		loadSound(1, 0x36691914);
+		loadSound(2, 0x5421D806);
+		_parentScene->setPositionFree(_currPositionIndex, false);
+		_x = kAsScene1907SymbolGroundPositions[_currPositionIndex].x;
+		_y = kAsScene1907SymbolGroundPositions[_currPositionIndex].y;
+		createSurface1(kAsScene1907SymbolFileHashes[_elementIndex], 1000 + _currPositionIndex);
+		startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+		_newStickFrameIndex = 0;
+	}
+	_collisionBoundsOffset.set(0, 0, 80, 80);
+	Sprite::updateBounds();
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene1907Symbol::handleMessage);
+
+}
+
+void AsScene1907Symbol::update() {
+	updateAnim();
+	handleSpriteUpdate();
+	updatePosition();
+	if (_plugInFailed && _plugInTryCount == 0)
+		_plugInFailed = false;
+}
+
+uint32 AsScene1907Symbol::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		if (!_isPluggedIn && !_plugInFailed) {
+			tryToPlugIn();
+			messageResult = 1;
+		} else
+			messageResult = 0;
+		break;
+	}
+	return messageResult;
+}
+
+uint32 AsScene1907Symbol::hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x3002:
+		gotoNextState();
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene1907Symbol::suTryToPlugIn() {
+	_currStep++;
+	_x -= _deltaX;
+	_y -= _deltaY;
+	if (_currStep == 16) {
+		_x -= _smallDeltaX;
+		_y -= _smallDeltaY;
+		SetSpriteUpdate(NULL);
+	}
+}
+
+void AsScene1907Symbol::suFallOff() {
+	if (_fallOffDelay != 0) {
+		_fallOffDelay--;
+	} else {
+		_y += _yAccel;
+		_yAccel += 8;
+		if (_y >= kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
+			_y = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y;
+			stFallOffHitGround();
+		}
+	}
+}
+
+void AsScene1907Symbol::suFallOffHitGround() {
+
+	if (_x == _someX - _xBreak)
+		_x -= _smallDeltaX;
+	else
+		_x -= _deltaX;
+
+	if (_y == kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y) {
+		_y -= _someY;
+	}
+
+	if (_currStep < 8) {
+		_y -= _yAccel;
+		_yAccel -= 4;
+		if (_yAccel < 0)
+			_yAccel = 0;
+	} else if (_currStep < 15) {
+		_y += _yAccel;
+		_yAccel += 4;
+	} else {
+		_y = kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
+		cbFallOffHitGroundEvent();
+	}
+
+	_currStep++;
+}
+
+void AsScene1907Symbol::suMoveDown() {
+	_y += _yIncr;
+	if (_yIncr < 11)
+		_yIncr++;
+	if (_y >= kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y) {
+		_y = kAsScene1907SymbolPluggedInDownPositions[_elementIndex].y;
+		_isMoving = false;
+		SetSpriteUpdate(NULL);
+	}
+}
+
+void AsScene1907Symbol::suMoveUp() {
+	_y -= _yIncr;
+	if (getGlobalVar(V_WALL_BROKEN)) {
+		if (_y - (9 + (_elementIndex > 5 ? 31 : 0)) < kAsScene1907SymbolPluggedInPositions[_elementIndex].y)
+			_yIncr--;
+		else
+			_yIncr++;
+	} else
+		_yIncr = 2;
+	if (_yIncr > 9)
+		_yIncr = 9;
+	else if (_yIncr < 1)
+		_yIncr = 1;
+	if (_y < kAsScene1907SymbolPluggedInPositions[_elementIndex].y) {
+		_y = kAsScene1907SymbolPluggedInPositions[_elementIndex].y;
+		_isMoving = false;
+		SetSpriteUpdate(NULL);
+	}
+}
+
+void AsScene1907Symbol::tryToPlugIn() {
+	_isPluggedIn = true;
+	_plugInTryCount++;
+	_newPositionIndex = _parentScene->getNextPosition();
+	_parentScene->setPositionFree(_currPositionIndex, true);
+	sendMessage(_parentScene, 0x1022, 1100 + _newPositionIndex);
+	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+	SetUpdateHandler(&AsScene1907Symbol::update);
+	SetMessageHandler(&AsScene1907Symbol::hmTryToPlugIn);
+	SetSpriteUpdate(&AsScene1907Symbol::suTryToPlugIn);
+	_currStep = 0;
+	_deltaX = (_x - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x) / 16;
+	_smallDeltaX = _x - _deltaX * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].x;
+	_deltaY = (_y - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y) / 16;
+	_smallDeltaY = _y - _deltaY * 16 - kAsScene1907SymbolPluggedInPositions[_newPositionIndex].y;
+	if (_elementIndex == _newPositionIndex) {
+		NextState(&AsScene1907Symbol::stPlugIn);
+	} else {
+		_plugInFailed = true;
+		NextState(&AsScene1907Symbol::stPlugInFail);
+	}
+}
+
+void AsScene1907Symbol::fallOff(int newPositionIndex, int fallOffDelay) {
+	_isPluggedIn = false;
+	_newPositionIndex = newPositionIndex;
+	_fallOffDelay = fallOffDelay;
+	_parentScene->setPositionFree(_newPositionIndex, false);
+	_x = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].x;
+	_y = kAsScene1907SymbolPluggedInPositions[_currPositionIndex].y;
+	_someX = _x;
+	_someY = _y;
+	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, 0);
+	_playBackwards = true;
+	_newStickFrameIndex = STICK_LAST_FRAME;
+	_currStep = 0;
+	_yAccel = 1;
+	SetUpdateHandler(&AsScene1907Symbol::update);
+	SetMessageHandler(&AsScene1907Symbol::handleMessage);
+	SetSpriteUpdate(&AsScene1907Symbol::suFallOff);
+}
+
+void AsScene1907Symbol::stFallOffHitGround() {
+	playSound(1);
+	sendMessage(_parentScene, 0x1022, 1000 + _newPositionIndex);
+	Entity::_priority = 1000 - _newPositionIndex;
+	_parentScene->removeCollisionSprite(this);
+	_parentScene->addCollisionSprite(this);
+	SetSpriteUpdate(&AsScene1907Symbol::suFallOffHitGround);
+	NextState(&AsScene1907Symbol::cbFallOffHitGroundEvent);
+	_newStickFrameIndex = 0;
+	_currStep = 0;
+	_yAccel = 30;
+	_deltaX = (_x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x) / 15;
+	_xBreak = _deltaX * 15;
+	_smallDeltaX = _x - kAsScene1907SymbolGroundPositions[_newPositionIndex].x - _xBreak;
+	_someY = 0;
+	if (kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y > kAsScene1907SymbolGroundPositions[_newPositionIndex].y)
+		_someY = kAsScene1907SymbolGroundHitPositions[_currPositionIndex].y - kAsScene1907SymbolGroundPositions[_newPositionIndex].y;
+}
+
+void AsScene1907Symbol::cbFallOffHitGroundEvent() {
+	_currPositionIndex = _newPositionIndex;
+	if (_plugInTryCount > 0)
+		_plugInTryCount--;
+	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], 0, -1);
+	_newStickFrameIndex = 0;
+	SetUpdateHandler(&AnimatedSprite::update);
+	SetMessageHandler(&AsScene1907Symbol::handleMessage);
+	SetSpriteUpdate(NULL);
+	updateBounds();
+	playSound(2);
+}
+
+void AsScene1907Symbol::stPlugIn() {
+	playSound(0);
+	_currPositionIndex = _newPositionIndex;
+	stopAnimation();
+	SetMessageHandler(&AsScene1907Symbol::handleMessage);
+	SetSpriteUpdate(NULL);
+	if (_elementIndex == 8)
+		sendMessage(_parentScene, 0x2001, 0);
+}
+
+void AsScene1907Symbol::stPlugInFail() {
+	_currPositionIndex = _newPositionIndex;
+	stopAnimation();
+	_parentScene->plugInFailed();
+}
+
+void AsScene1907Symbol::moveUp() {
+	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+	stopAnimation();
+	SetMessageHandler(&AsScene1907Symbol::handleMessage);
+	SetSpriteUpdate(&AsScene1907Symbol::suMoveUp);
+	_yIncr = 1;
+	_isMoving = true;
+}
+
+void AsScene1907Symbol::moveDown() {
+	startAnimation(kAsScene1907SymbolFileHashes[_elementIndex], -1, -1);
+	stopAnimation();
+	SetMessageHandler(&AsScene1907Symbol::handleMessage);
+	SetSpriteUpdate(&AsScene1907Symbol::suMoveDown);
+	_yIncr = 4;
+	_isMoving = true;
+}
+
+SsScene1907UpDownButton::SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol)
+	: StaticSprite(vm, 1400), _parentScene(parentScene), _asScene1907Symbol(asScene1907Symbol),
+	_countdown1(0) {
+
+	loadSprite(0x64516424, kSLFDefDrawOffset | kSLFDefPosition | kSLFDefCollisionBoundsOffset, 1400);
+	setVisible(false);
+	loadSound(0, 0x44061000);
+	SetUpdateHandler(&SsScene1907UpDownButton::update);
+	SetMessageHandler(&SsScene1907UpDownButton::handleMessage);
+	if (getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
+		if (getGlobalVar(V_STAIRS_DOWN))
+			setToDownPosition();
+		else
+			setToUpPosition();
+	}
+}
+
+void SsScene1907UpDownButton::update() {
+	updatePosition();
+	if (_countdown1 != 0 && (--_countdown1 == 0)) {
+		setVisible(false);
+		sendMessage(_parentScene, 0x2000, 0);
+	}
+}
+
+uint32 SsScene1907UpDownButton::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1011:
+		if (_countdown1 == 0 && !_asScene1907Symbol->isMoving() && getGlobalVar(V_STAIRS_PUZZLE_SOLVED)) {
+			setVisible(true);
+			_countdown1 = 4;
+			updatePosition();
+			playSound(0);
+		}
+		messageResult = 1;
+	}
+	return messageResult;
+}
+
+void SsScene1907UpDownButton::setToUpPosition() {
+	_y = _spriteResource.getPosition().y;
+	updateBounds();
+	updatePosition();
+}
+
+void SsScene1907UpDownButton::setToDownPosition() {
+	_y = _spriteResource.getPosition().y + 174;
+	updateBounds();
+	updatePosition();
+}
+
+AsScene1907WaterHint::AsScene1907WaterHint(NeverhoodEngine *vm)
+	: AnimatedSprite(vm, 1400) {
+
+	createSurface1(0x110A1061, 1500);
+	_x = 320;
+	_y = 240;
+	startAnimation(0x110A1061, 0, -1);
+	_newStickFrameIndex = 0;
+	setVisible(false);
+	_needRefresh = true;
+	AnimatedSprite::updatePosition();
+	SetUpdateHandler(&AsScene1907WaterHint::update);
+	SetMessageHandler(&Sprite::handleMessage);
+}
+
+void AsScene1907WaterHint::update() {
+	updateAnim();
+	updatePosition();
+}
+
+uint32 AsScene1907WaterHint::hmShowing(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x3002:
+		gotoNextState();
+		break;
+	}
+	return messageResult;
+}
+
+void AsScene1907WaterHint::show() {
+	setVisible(true);
+	startAnimation(0x110A1061, 0, -1);
+	SetMessageHandler(&AsScene1907WaterHint::hmShowing);
+	NextState(&AsScene1907WaterHint::hide);
+}
+
+void AsScene1907WaterHint::hide() {
+	stopAnimation();
+	setVisible(false);
+	SetMessageHandler(&Sprite::handleMessage);
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1900_sprites.h b/engines/neverhood/modules/module1900_sprites.h
new file mode 100644
index 0000000..7035e50
--- /dev/null
+++ b/engines/neverhood/modules/module1900_sprites.h
@@ -0,0 +1,100 @@
+/* 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 NEVERHOOD_MODULES_MODULE1900_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1900_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class Scene1907;
+
+class AsScene1907Symbol : public AnimatedSprite {
+public:
+	AsScene1907Symbol(NeverhoodEngine *vm, Scene1907 *parentScene, int elementIndex, int positionIndex);
+	void moveUp();
+	void moveDown();
+	void fallOff(int newPositionIndex, int fallOffDelay);
+	bool isPluggedIn() { return _isPluggedIn; }
+	bool isMoving() { return _isMoving; }
+protected:
+	Scene1907 *_parentScene;
+	int _elementIndex;
+	int _currPositionIndex;
+	int _newPositionIndex;
+	bool _isPluggedIn;
+	bool _isMoving;
+	int _someX, _someY;
+	int _xBreak;
+	int _currStep;
+	int _yAccel;
+	int _yIncr;
+	int _fallOffDelay;
+	int _deltaX, _smallDeltaX;
+	int _deltaY, _smallDeltaY;
+	// Dumb, change if possible
+	static bool _plugInFailed;
+	static int _plugInTryCount;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	uint32 hmTryToPlugIn(int messageNum, const MessageParam &param, Entity *sender);
+	void suTryToPlugIn();
+	void suFallOff();
+	void suFallOffHitGround();
+	void suMoveDown();
+	void suMoveUp();
+	void tryToPlugIn();
+	void stFallOffHitGround();
+	void cbFallOffHitGroundEvent();
+	void stPlugIn();
+	void stPlugInFail();
+};
+
+class AsScene1907WaterHint : public AnimatedSprite {
+public:
+	AsScene1907WaterHint(NeverhoodEngine *vm);
+	void show();
+protected:
+	void update();
+	uint32 hmShowing(int messageNum, const MessageParam &param, Entity *sender);
+	void hide();
+};
+
+class SsScene1907UpDownButton : public StaticSprite {
+public:
+	SsScene1907UpDownButton(NeverhoodEngine *vm, Scene1907 *parentScene, AsScene1907Symbol *asScene1907Symbol);
+	void setToUpPosition();
+	void setToDownPosition();
+protected:
+	Scene1907 *_parentScene;
+	AsScene1907Symbol *_asScene1907Symbol;
+	int _countdown1;
+	void update();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1900_SPRITES_H */
diff --git a/engines/neverhood/modules/module2000.h b/engines/neverhood/modules/module2000.h
index fa62f9a..8dc72c5 100644
--- a/engines/neverhood/modules/module2000.h
+++ b/engines/neverhood/modules/module2000.h
@@ -26,7 +26,6 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/modules/module1200.h"
 
 namespace Neverhood {
 
@@ -41,8 +40,6 @@ protected:
 	void updateScene();
 };
 
-// Scene2001
-
 class Scene2001 : public Scene {
 public:
 	Scene2001(NeverhoodEngine *vm, Module *parentModule, int which);
diff --git a/engines/neverhood/modules/module2800.cpp b/engines/neverhood/modules/module2800.cpp
index e0112a6..289fc88 100644
--- a/engines/neverhood/modules/module2800.cpp
+++ b/engines/neverhood/modules/module2800.cpp
@@ -24,7 +24,7 @@
 #include "neverhood/gamemodule.h"
 #include "neverhood/modules/module1000.h"
 #include "neverhood/modules/module1200.h"
-#include "neverhood/modules/module1700.h"
+#include "neverhood/modules/module1700_sprites.h"
 #include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/modules/module2800_sprites.h"
 #include "neverhood/diskplayerscene.h"


Commit: b408b94bf1e188da7202895eab547f08cfa30450
    https://github.com/scummvm/scummvm/commit/b408b94bf1e188da7202895eab547f08cfa30450
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2013-10-05T04:52:48-07:00

Commit Message:
NEVERHOOD: Split sprites from their scenes in module 1600

Changed paths:
  A engines/neverhood/modules/module1600_sprites.cpp
  A engines/neverhood/modules/module1600_sprites.h
    engines/neverhood/module.mk
    engines/neverhood/modules/module1600.cpp
    engines/neverhood/modules/module1600.h
    engines/neverhood/modules/module2500.cpp
    engines/neverhood/modules/module2500.h
    engines/neverhood/modules/module2700.cpp
    engines/neverhood/modules/module2700.h



diff --git a/engines/neverhood/module.mk b/engines/neverhood/module.mk
index e49d9f6..cd0a9fa 100644
--- a/engines/neverhood/module.mk
+++ b/engines/neverhood/module.mk
@@ -21,6 +21,7 @@ MODULE_OBJS = \
 	modules/module1400.o \
 	modules/module1500.o \
 	modules/module1600.o \
+	modules/module1600_sprites.o \
 	modules/module1700.o \
 	modules/module1700_sprites.o \
 	modules/module1800.o \
diff --git a/engines/neverhood/modules/module1600.cpp b/engines/neverhood/modules/module1600.cpp
index 631d90d..165855a 100644
--- a/engines/neverhood/modules/module1600.cpp
+++ b/engines/neverhood/modules/module1600.cpp
@@ -20,9 +20,10 @@
  *
  */
 
-#include "neverhood/modules/module1600.h"
 #include "neverhood/gamemodule.h"
 #include "neverhood/modules/module1200.h"
+#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module1600_sprites.h"
 #include "neverhood/modules/module2200_sprites.h"
 #include "neverhood/modules/module3000_sprites.h"
 
@@ -184,825 +185,6 @@ void Module1600::updateScene() {
 	}
 }
 
-AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
-	: AnimatedSprite(vm, 1000), _parentScene(parentScene) {
-
-	createSurface(200, 556, 328);
-	_x = x;
-	_y = y;
-
-	_inMainArea = false;
-	_exitDirection = 0;
-	_currPointIndex = 0;
-	_hasAgainDestPoint = false;
-	_stepError = 0;
-	_hasAgainDestPointIndex = false;
-	_steps = 0;
-	_isBraking = false;
-	_yMoveTotalSteps = 0;
-	_isBusy = false;
-	_isIdle = false;
-	_isMoving = true;
-	_rectFlag = false;
-	_newDeltaXType = -1;
-	_soundCounter = 0;
-	_pathPoints = NULL;
-	_currMoveDirection = 0;
-
-	startAnimation(0xD4220027, 0, -1);
-	setDoDeltaX(getGlobalVar(V_CAR_DELTA_X));
-
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::handleMessage);
-	SetSpriteUpdate(NULL);
-}
-
-AsCommonCar::~AsCommonCar() {
-	if (_finalizeStateCb == AnimationCallback(&AsCommonCar::evTurnCarDone))
-		setGlobalVar(V_CAR_DELTA_X, !getGlobalVar(V_CAR_DELTA_X));
-}
-
-void AsCommonCar::setPathPoints(NPointArray *pathPoints) {
-	_pathPoints = pathPoints;
-}
-
-void AsCommonCar::update() {
-	if (_newDeltaXType >= 0) {
-		setDoDeltaX(_newDeltaXType);
-		_newDeltaXType = -1;
-	}
-	AnimatedSprite::update();
-	if (_hasAgainDestPoint && _yMoveTotalSteps == 0 && !_isBusy) {
-		_hasAgainDestPoint = false;
-		_hasAgainDestPointIndex = false;
-		sendPointMessage(this, 0x2004, _againDestPoint);
-	} else if (_hasAgainDestPointIndex && _yMoveTotalSteps == 0 && !_isBusy) {
-		_hasAgainDestPointIndex = false;
-		sendMessage(this, 0x2003, _againDestPointIndex);
-	}
-	updateMovement();
-	updateSound();
-}
-
-void AsCommonCar::upIdle() {
-	update();
-	if (++_idleCounter >= _idleCounterMax)
-		stIdleBlink();
-	updateSound();
-}
-
-uint32 AsCommonCar::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x1019:
-		SetSpriteUpdate(NULL);
-		break;
-	case 0x2002:
-		// Set the current position without moving
-		_currPointIndex = param.asInteger();
-		_stepError = 0;
-		_x = pathPoint(_currPointIndex).x;
-		_y = pathPoint(_currPointIndex).y;
-		break;
-	case 0x2003:
-		// Move to a point by its index
-		{
-			int newPointIndex = param.asInteger();
-			if (_yMoveTotalSteps <= 0 && !_isBusy) {
-				_destX = pathPoint(newPointIndex).x;
-				_destY = pathPoint(newPointIndex).y;
-				if (_currPointIndex < newPointIndex) {
-					moveToNextPoint();
-				} else if (_currPointIndex == newPointIndex && _stepError == 0) {
-					if (_currPointIndex == 0) {
-						_yMoveTotalSteps = 0;
-						sendMessage(_parentScene, 0x2005, 0);
-					} else if (_currPointIndex == (int)_pathPoints->size()) {
-						_yMoveTotalSteps = 0;
-						sendMessage(_parentScene, 0x2006, 0);
-					}
-				} else {
-					moveToPrevPoint();
-				}
-			} else {
-				_hasAgainDestPointIndex = true;
-				_againDestPointIndex = newPointIndex;
-			}
-		}
-		break;
-	case 0x2004:
-		// Move to the point closest to the parameter point
-		{
-			int minMatchIndex = -1;
-			int minMatchDistance, distance;
-			NPoint pt = param.asPoint();
-			if (_yMoveTotalSteps <= 0 && !_isBusy) {
-				// Check if we're already exiting (or something)
-				if ((pt.x <= 20 && _exitDirection == 1) ||
-					(pt.x >= 620 && _exitDirection == 3) ||
-					(pt.y <= 20 && _exitDirection == 2) ||
-					(pt.y >= 460 && _exitDirection == 4))
-					break;
-				_destX = pt.x;
-				_destY = pt.y;
-				minMatchDistance = calcDistance(_destX, _destY, _x, _y) + 1;
-				for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) {
-					distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
-					if (distance >= minMatchDistance)
-						break;
-					minMatchDistance = distance;
-					minMatchIndex = i;
-				}
-				for (int i = _currPointIndex; i >= 0; i--) {
-					distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
-					if (distance >= minMatchDistance)
-						break;
-					minMatchDistance = distance;
-					minMatchIndex = i;
-				}
-				if (minMatchIndex == -1) {
-					if (_currPointIndex == 0)
-						moveToPrevPoint();
-					else
-						SetSpriteUpdate(NULL);
-				} else {
-					if (minMatchIndex > _currPointIndex)
-						moveToNextPoint();
-					else
-						moveToPrevPoint();
-				}
-			} else {
-				_hasAgainDestPoint = true;
-				_againDestPoint = pt;
-			}
-		}
-		break;
-	case 0x2007:
-		_yMoveTotalSteps = param.asInteger();
-		_steps = 0;
-		_isBraking = false;
-		_lastDistance = 640;
-		SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
-		break;
-	case 0x2008:
-		_yMoveTotalSteps = param.asInteger();
-		_steps = 0;
-		_isBraking = false;
-		_lastDistance = 640;
-		SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
-		break;
-	case 0x2009:
-		stEnterCar();
-		break;
-	case 0x200A:
-		stLeaveCar();
-		break;
-	case 0x200E:
-		stTurnCar();
-		break;
-	case 0x200F:
-		stCarAtHome();
-		_newDeltaXType = param.asInteger();
-		break;
-	}
-	return messageResult;
-}
-
-uint32 AsCommonCar::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
-	uint32 messageResult = AsCommonCar::handleMessage(messageNum, param, sender);
-	switch (messageNum) {
-	case 0x100D:
-		if (_isBusy && param.asInteger() == 0x025424A2)
-			gotoNextState();
-		break;
-	case 0x3002:
-		gotoNextState();
-		break;
-	}
-	return messageResult;
-}
-
-uint32 AsCommonCar::hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender) {
-	switch (messageNum) {
-	case 0x2009:
-		stEnterCar();
-		break;
-	case 0x3002:
-		sendMessage(_parentScene, 0x200A, 0);
-		SetMessageHandler(&AsCommonCar::handleMessage);
-		break;
-	}
-	return 0;
-}
-
-void AsCommonCar::stCarAtHome() {
-	bool doDeltaX = _doDeltaX;
-	SetSpriteUpdate(NULL);
-	_hasAgainDestPoint = false;
-	_hasAgainDestPointIndex = false;
-	_isBraking = false;
-	_isBusy = false;
-	_isIdle = false;
-	_isMoving = false;
-	_rectFlag = false;
-	NextState(&AsCommonCar::stLeanForwardIdle);
-	startAnimation(0x35698F78, 0, -1);
-	setDoDeltaX(doDeltaX ? 1 : 0);
-	_currMoveDirection = 0;
-	_newMoveDirection = 0;
-	_steps = 0;
-	_idleCounter = 0;
-	_idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
-	SetUpdateHandler(&AsCommonCar::upIdle);
-	SetMessageHandler(&AsCommonCar::handleMessage);
-	FinalizeState(&AsCommonCar::evIdleDone);
-}
-
-void AsCommonCar::updateTurnMovement() {
-	if (_turnMoveStatus == 1) {
-		_lastDistance = 640;
-		_isIdle = false;
-		_isBraking = false;
-		SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
-	} else if (_turnMoveStatus == 2) {
-		_lastDistance = 640;
-		_isIdle = false;
-		_isBraking = false;
-		SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
-	}
-}
-
-void AsCommonCar::updateMovement() {
-	if (_isBraking && !_isIdle && !_isBusy) {
-		gotoNextState();
-		_isMoving = false;
-		_isIdle = true;
-		startAnimation(0x192ADD30, 0, -1);
-		SetUpdateHandler(&AsCommonCar::update);
-		SetMessageHandler(&AsCommonCar::hmAnimation);
-		NextState(&AsCommonCar::stLeanForwardIdle);
-	} else if (!_isBraking && _steps && _isIdle) {
-		gotoNextState();
-		_isIdle = false;
-		startAnimation(0x9966B138, 0, -1);
-		SetUpdateHandler(&AsCommonCar::update);
-		SetMessageHandler(&AsCommonCar::hmAnimation);
-		NextState(&AsCommonCar::stUpdateMoveDirection);
-	} else if (_newMoveDirection != _currMoveDirection && _isMoving && !_isBusy) {
-		gotoNextState();
-		_currMoveDirection = _newMoveDirection;
-		stUpdateMoveDirection();
-	}
-}
-
-void AsCommonCar::stEnterCar() {
-	startAnimation(0xA86A9538, 0, -1);
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	NextState(&AsCommonCar::stLeanForwardIdle);
-}
-
-void AsCommonCar::stLeaveCar() {
-	startAnimation(0xA86A9538, -1, -1);
-	_playBackwards = true;
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmLeaveCar);
-}
-
-void AsCommonCar::stLeanForwardIdle() {
-	startAnimation(0x35698F78, 0, -1);
-	_currMoveDirection = 0;
-	_newMoveDirection = 0;
-	_steps = 0;
-	_idleCounter = 0;
-	_idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
-	SetUpdateHandler(&AsCommonCar::upIdle);
-	SetMessageHandler(&AsCommonCar::handleMessage);
-	FinalizeState(&AsCommonCar::evIdleDone);
-}
-
-void AsCommonCar::evIdleDone() {
-	SetUpdateHandler(&AsCommonCar::update);
-}
-
-void AsCommonCar::stIdleBlink() {
-	startAnimation(0xB579A77C, 0, -1);
-	_idleCounter = 0;
-	_idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	NextState(&AsCommonCar::stLeanForwardIdle);
-}
-
-void AsCommonCar::stUpdateMoveDirection() {
-	_isMoving = true;
-	if (_currMoveDirection == 1)
-		startAnimation(0xD4AA03A4, 0, -1);
-	else if (_currMoveDirection == 3)
-		startAnimation(0xD00A1364, 0, -1);
-	else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX))
-		stTurnCar();
-	else
-		startAnimation(0xD4220027, 0, -1);
-	setGlobalVar(V_CAR_DELTA_X, _doDeltaX ? 1 : 0);
-}
-
-void AsCommonCar::moveToNextPoint() {
-	if (_currPointIndex >= (int)_pathPoints->size() - 1) {
-		_yMoveTotalSteps = 0;
-		sendMessage(this, 0x1019, 0);
-		sendMessage(_parentScene, 0x2006, 0);
-	} else {
-		NPoint nextPt = pathPoint(_currPointIndex + 1);
-		NPoint currPt = pathPoint(_currPointIndex);
-		if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) &&
-			((_currMoveDirection == 2 && nextPt.x < currPt.x) ||
-			(_currMoveDirection == 4 && nextPt.x >= currPt.x))) {
-			if (_currMoveDirection == 2)
-				_currMoveDirection = 4;
-			else if (_currMoveDirection == 4)
-				_currMoveDirection = 2;
-			if (_isIdle)
-				stTurnCarMoveToNextPoint();
-			else
-				stBrakeMoveToNextPoint();
-		} else {
-			if (_steps == 0) {
-				gotoNextState();
-				_isIdle = false;
-				startAnimation(0x9966B138, 0, -1);
-				SetMessageHandler(&AsCommonCar::hmAnimation);
-				SetUpdateHandler(&AsCommonCar::update);
-				NextState(&AsCommonCar::stUpdateMoveDirection);
-			}
-			_isBraking = false;
-			SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
-			_lastDistance = 640;
-		}
-	}
-}
-
-void AsCommonCar::stBrakeMoveToNextPoint() {
-	gotoNextState();
-	_isBusy = true;
-	_isBraking = true;
-	startAnimation(0x192ADD30, 0, -1);
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	NextState(&AsCommonCar::stTurnCarMoveToNextPoint);
-}
-
-void AsCommonCar::stTurnCar() {
-	// Turn to left/right #1
-	gotoNextState();
-	_isBusy = true;
-	startAnimation(0xF46A0324, 0, -1);
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	FinalizeState(&AsCommonCar::evTurnCarDone);
-	_turnMoveStatus = 0;
-	updateTurnMovement();
-}
-
-void AsCommonCar::stTurnCarMoveToNextPoint() {
-	// Turn to left/right #2
-	gotoNextState();
-	_isBusy = true;
-	startAnimation(0xF46A0324, 0, -1);
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	FinalizeState(&AsCommonCar::evTurnCarDone);
-	_turnMoveStatus = 1;
-	updateTurnMovement();
-}
-
-void AsCommonCar::stTurnCarMoveToPrevPoint() {
-	// Turn to left/right #3
-	FinalizeState(NULL);
-	_isBusy = true;
-	startAnimation(0xF46A0324, 0, -1);
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	FinalizeState(&AsCommonCar::evTurnCarDone);
-	_turnMoveStatus = 2;
-	updateTurnMovement();
-}
-
-void AsCommonCar::moveToPrevPoint() {
-	if (_currPointIndex == 0 && _stepError == 0) {
-		_yMoveTotalSteps = 0;
-		sendMessage(this, 0x1019, 0);
-		sendMessage(_parentScene, 0x2005, 0);
-	} else {
-		NPoint prevPt;
-		NPoint currPt;
-		if (_stepError == 0) {
-			prevPt = pathPoint(_currPointIndex - 1);
-			currPt = pathPoint(_currPointIndex);
-		} else {
-			prevPt = pathPoint(_currPointIndex);
-			currPt = pathPoint(_currPointIndex + 1);
-		}
-		if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) &&
-			((_currMoveDirection == 2 && prevPt.x < currPt.x) ||
-			(_currMoveDirection == 4 && prevPt.x >= currPt.x))) {
-			if (_currMoveDirection == 2)
-				_currMoveDirection = 4;
-			else if (_currMoveDirection == 4)
-				_currMoveDirection = 2;
-			if (_isIdle)
-				stTurnCarMoveToPrevPoint();
-			else
-				stBrakeMoveToPrevPoint();
-		} else {
-			if (_steps == 0) {
-				gotoNextState();
-				_isIdle = false;
-				startAnimation(0x9966B138, 0, -1);
-				SetMessageHandler(&AsCommonCar::hmAnimation);
-				SetUpdateHandler(&AsCommonCar::update);
-				NextState(&AsCommonCar::stUpdateMoveDirection);
-			}
-			_isBraking = false;
-			SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
-			_lastDistance = 640;
-		}
-	}
-}
-
-void AsCommonCar::stBrakeMoveToPrevPoint() {
-	FinalizeState(NULL);
-	_isBusy = true;
-	_isBraking = true;
-	startAnimation(0x192ADD30, 0, -1);
-	SetUpdateHandler(&AsCommonCar::update);
-	SetMessageHandler(&AsCommonCar::hmAnimation);
-	NextState(&AsCommonCar::stTurnCarMoveToPrevPoint);
-}
-
-void AsCommonCar::evTurnCarDone() {
-	_isBusy = false;
-	setDoDeltaX(2);
-	_newMoveDirection = 0;
-	stUpdateMoveDirection();
-}
-
-void AsCommonCar::suMoveToNextPoint() {
-	int16 newX = _x, newY = _y;
-
-	if (_currPointIndex >= (int)_pathPoints->size()) {
-		_yMoveTotalSteps = 0;
-		sendMessage(this, 0x1019, 0);
-		sendMessage(_parentScene, 0x2006, 0);
-		return;
-	}
-
-	if (_isBraking) {
-		if (_steps <= 0) {
-			sendMessage(this, 0x1019, 0);
-			return;
-		} else
-			_steps--;
-	} else if (_steps < 11)
-		_steps++;
-
-	bool firstTime = true;
-	_ySteps = _steps;
-	int stepsCtr = _steps;
-
-	while (stepsCtr > 0) {
-		NPoint pt1;
-		NPoint pt2 = pathPoint(_currPointIndex);
-		if (_currPointIndex + 1 >= (int)_pathPoints->size())
-			pt1 = pathPoint(0);
-		else
-			pt1 = pathPoint(_currPointIndex + 1);
-		int16 deltaX = ABS(pt1.x - pt2.x);
-		int16 deltaY = ABS(pt1.y - pt2.y);
-		if (deltaX >= deltaY) {
-			_newMoveDirection = 2;
-			if (pt1.x < pt2.x)
-				_newMoveDirection = 4;
-			if (stepsCtr + _stepError >= deltaX) {
-				stepsCtr -= deltaX;
-				stepsCtr += _stepError;
-				_stepError = 0;
-				_currPointIndex++;
-				if (_currPointIndex == (int)_pathPoints->size() - 1)
-					stepsCtr = 0;
-				newX = pathPoint(_currPointIndex).x;
-				newY = pathPoint(_currPointIndex).y;
-			} else {
-				_stepError += stepsCtr;
-				if (pt1.x >= pt2.x)
-					newX += stepsCtr;
-				else
-					newX -= stepsCtr;
-				if (pt1.y >= pt2.y)
-					newY = pt2.y + (deltaY * _stepError) / deltaX;
-				else
-					newY = pt2.y - (deltaY * _stepError) / deltaX;
-				stepsCtr = 0;
-			}
-		} else {
-			_newMoveDirection = 3;
-			if (pt1.y < pt2.y)
-				_newMoveDirection = 1;
-			if (firstTime) {
-				if (pt1.y >= pt2.y)
-					stepsCtr += 7;
-				else {
-					stepsCtr -= 4;
-					if (stepsCtr < 0)
-						stepsCtr = 0;
-				}
-				_ySteps = stepsCtr;
-			}
-			if (stepsCtr + _stepError >= deltaY) {
-				stepsCtr -= deltaY;
-				stepsCtr += _stepError;
-				_stepError = 0;
-				_currPointIndex++;
-				if (_currPointIndex == (int)_pathPoints->size() - 1)
-					stepsCtr = 0;
-				newX = pathPoint(_currPointIndex).x;
-				newY = pathPoint(_currPointIndex).y;
-			} else {
-				_stepError += stepsCtr;
-				if (pt1.x >= pt2.x)
-					newX = pt2.x + (deltaX * _stepError) / deltaY;
-				else
-					newX = pt2.x - (deltaX * _stepError) / deltaY;
-				if (pt1.y >= pt2.y)
-					newY += stepsCtr;
-				else
-					newY -= stepsCtr;
-				stepsCtr = 0;
-			}
-		}
-		firstTime = false;
-	}
-
-	if (_yMoveTotalSteps != 0) {
-		_x = newX;
-		_y = newY;
-		_yMoveTotalSteps -= _ySteps;
-		if (_yMoveTotalSteps <= 0) {
-			_isBraking = true;
-			_yMoveTotalSteps = 0;
-		}
-	} else {
-		int distance = calcDistance(_destX, _destY, _x, _y);
-		_x = newX;
-		_y = newY;
-		if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
-			_exitDirection = 0;
-			_inMainArea = true;
-		} else if (_inMainArea) {
-			_destX = pathPoint(_pathPoints->size() - 1).x;
-			_destY = pathPoint(_pathPoints->size() - 1).y;
-			_inMainArea = false;
-			if (_x <= 20)
-				_exitDirection = 1;
-			else if (_x >= 620)
-				_exitDirection = 3;
-			else if (_y <= 20)
-				_exitDirection = 2;
-			else if (_y >= 460)
-				_exitDirection = 4;
-			if (_exitDirection != 0 && _isBraking) {
-				_isBraking = false;
-				_steps = 11;
-			}
-		}
-		if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
-			(_exitDirection == 0 && _lastDistance + 20 < distance))
-			_isBraking = true;
-		if (distance < _lastDistance)
-			_lastDistance = distance;
-		if (_currPointIndex == (int)_pathPoints->size() - 1) {
-			_isBraking = true;
-			_yMoveTotalSteps = 0;
-			sendMessage(this, 0x1019, 0);
-			sendMessage(_parentScene, 0x2006, 0);
-		}
-	}
-
-}
-
-void AsCommonCar::suMoveToPrevPoint() {
-	int16 newX = _x, newY = _y;
-
-	if (_currPointIndex == 0 && _stepError == 0) {
-		_yMoveTotalSteps = 0;
-		sendMessage(this, 0x1019, 0);
-		sendMessage(_parentScene, 0x2005, 0);
-		return;
-	}
-
-	if (_isBraking) {
-		if (_steps <= 0) {
-			sendMessage(this, 0x1019, 0);
-			return;
-		} else
-			_steps--;
-	} else if (_steps < 11)
-		_steps++;
-
-	bool firstTime = true;
-	_ySteps = _steps;
-	int stepsCtr = _steps;
-
-	while (stepsCtr > 0) {
-		if (_stepError == 0)
-			_currPointIndex--;
-		NPoint pt1;
-		NPoint pt2 = pathPoint(_currPointIndex);
-		if (_currPointIndex + 1 >= (int)_pathPoints->size())
-			pt1 = pathPoint(0);
-		else
-			pt1 = pathPoint(_currPointIndex + 1);
-		int16 deltaX = ABS(pt1.x - pt2.x);
-		int16 deltaY = ABS(pt1.y - pt2.y);
-		if (deltaX >= deltaY) {
-			_newMoveDirection = 4;
-			if (pt1.x < pt2.x)
-				_newMoveDirection = 2;
-			if (_stepError == 0)
-				_stepError = deltaX;
-			if (stepsCtr > _stepError) {
-				stepsCtr -= _stepError;
-				_stepError = 0;
-				if (_currPointIndex == 0)
-					stepsCtr = 0;
-				newX = pathPoint(_currPointIndex).x;
-				newY = pathPoint(_currPointIndex).y;
-			} else {
-				_stepError -= stepsCtr;
-				if (pt1.x >= pt2.x)
-					newX -= stepsCtr;
-				else
-					newX += stepsCtr;
-				if (pt1.y >= pt2.y)
-					newY = pt2.y + (deltaY * _stepError) / deltaX;
-				else
-					newY = pt2.y - (deltaY * _stepError) / deltaX;
-				stepsCtr = 0;
-			}
-		} else {
-			_newMoveDirection = 1;
-			if (pt1.y < pt2.y)
-				_newMoveDirection = 3;
-			if (firstTime) {
-				if (pt1.y >= pt2.y) {
-					stepsCtr -= 4;
-					if (stepsCtr < 0)
-						stepsCtr = 0;
-				} else {
-					stepsCtr += 7;
-				}
-				_ySteps = stepsCtr;
-			}
-			if (_stepError == 0)
-				_stepError = deltaY;
-			if (stepsCtr > _stepError) {
-				stepsCtr -= _stepError;
-				_stepError = 0;
-				if (_currPointIndex == 0)
-					stepsCtr = 0;
-				newX = pathPoint(_currPointIndex).x;
-				newY = pathPoint(_currPointIndex).y;
-			} else {
-				_stepError -= stepsCtr;
-				if (pt1.x >= pt2.x)
-					newX = pt2.x + (deltaX * _stepError) / deltaY;
-				else
-					newX = pt2.x - (deltaX * _stepError) / deltaY;
-				if (pt1.y >= pt2.y)
-					newY -= stepsCtr;
-				else
-					newY += stepsCtr;
-				stepsCtr = 0;
-			}
-		}
-		firstTime = false;
-	}
-
-	if (_yMoveTotalSteps != 0) {
-		_x = newX;
-		_y = newY;
-		_yMoveTotalSteps -= _ySteps;
-		if (_yMoveTotalSteps <= 0) {
-			_isBraking = true;
-			_yMoveTotalSteps = 0;
-		}
-	} else {
-		int distance = calcDistance(_destX, _destY, _x, _y);
-		_x = newX;
-		_y = newY;
-		if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
-			_exitDirection = 0;
-			_inMainArea = true;
-		} else if (_inMainArea) {
-			_destX = pathPoint(0).x;
-			_destY = pathPoint(0).y;
-			_inMainArea = false;
-			if (_x <= 20)
-				_exitDirection = 1;
-			else if (_x >= 620)
-				_exitDirection = 3;
-			else if (_y <= 20)
-				_exitDirection = 2;
-			else if (_y >= 460)
-				_exitDirection = 4;
-			if (_exitDirection != 0 && _isBraking) {
-				_isBraking = false;
-				_steps = 11;
-			}
-		}
-		if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
-			(_exitDirection == 0 && _lastDistance + 20 < distance))
-			_isBraking = true;
-		if (distance < _lastDistance)
-			_lastDistance = distance;
-		if (_currPointIndex == 0 && _stepError == 0) {
-			_isBraking = true;
-			_yMoveTotalSteps = 0;
-			sendMessage(this, 0x1019, 0);
-			sendMessage(_parentScene, 0x2005, 0);
-		}
-	}
-
-}
-
-void AsCommonCar::updateSound() {
-	int maxSoundCounter = 0;
-	_soundCounter++;
-	if (_steps != 0 && !_isIdle) {
-		if (_currMoveDirection == 1)
-			maxSoundCounter = 18 - _steps;
-		else if (_currMoveDirection == 3) {
-			maxSoundCounter = 5 - _steps;
-			if (maxSoundCounter < 1)
-				maxSoundCounter = 1;
-		} else
-			maxSoundCounter = 14 - _steps;
-	} else
-		maxSoundCounter = 21;
-	if (_soundCounter >= maxSoundCounter) {
-		sendMessage(_parentScene, 0x200D, 0);
-		_soundCounter = 0;
-	}
-}
-
-AsCommonIdleCarLower::AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y)
-	: AnimatedSprite(vm, 0x1209E09F, 1100, x, y) {
-
-	setDoDeltaX(1);
-	startAnimation(0x1209E09F, 1, -1);
-	_newStickFrameIndex = 1;
-}
-
-AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y)
-	: AnimatedSprite(vm, 0x1209E09F, 100, x, y) {
-
-	setDoDeltaX(1);
-	_newStickFrameIndex = 0;
-}
-
-AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar)
-	: AnimatedSprite(vm, 1100), _asCar(asCar) {
-
-	createSurface1(0x60281C10, 150);
-	startAnimation(0x60281C10, -1, -1);
-	_newStickFrameIndex = STICK_LAST_FRAME;
-	SetUpdateHandler(&AsCommonCarConnector::update);
-}
-
-void AsCommonCarConnector::update() {
-	_x = _asCar->getX();
-	_y = _asCar->getY();
-	AnimatedSprite::update();
-}
-
-void Tracks::findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
-	DataResource &dataResource) {
-	const uint trackCount = size();
-	minMatchTrackIndex = -1;
-	minMatchDistance = 640;
-	for (uint trackIndex = 0; trackIndex < trackCount; trackIndex++) {
-		NPointArray *pointList = dataResource.getPointArray((*this)[trackIndex]->trackPointsName);
-		for (uint pointIndex = 0; pointIndex < pointList->size(); pointIndex++) {
-			NPoint testPt = (*pointList)[pointIndex];
-			int distance = calcDistance(testPt.x, testPt.y, pt.x, pt.y);
-			if (distance < minMatchDistance) {
-				minMatchTrackIndex = trackIndex;
-				minMatchDistance = distance;
-			}
-		}
-	}
-}
-
 Scene1608::Scene1608(NeverhoodEngine *vm, Module *parentModule, int which)
 	: Scene(vm, parentModule), _asCar(NULL), _countdown1(0) {
 
diff --git a/engines/neverhood/modules/module1600.h b/engines/neverhood/modules/module1600.h
index 0d1ceaa..f08eaad 100644
--- a/engines/neverhood/modules/module1600.h
+++ b/engines/neverhood/modules/module1600.h
@@ -26,12 +26,9 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
-#include "neverhood/console.h"
 
 namespace Neverhood {
 
-// Module1600
-
 class Module1600 : public Module {
 public:
 	Module1600(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -42,90 +39,7 @@ protected:
 	void updateScene();
 };
 
-class AsCommonCar : public AnimatedSprite {
-public:
-	AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
-	~AsCommonCar();
-	void setPathPoints(NPointArray *pathPoints);
-protected:
-	Scene *_parentScene;
-	NPointArray *_pathPoints;
-	int _newMoveDirection;
-	int _currMoveDirection;
-	int _exitDirection;
-	int _currPointIndex;
-	bool _hasAgainDestPoint;
-	NPoint _againDestPoint;
-	bool _hasAgainDestPointIndex;
-	int _againDestPointIndex;
-	bool _inMainArea;
-	bool _isBraking;
-	bool _isBusy;
-	bool _isIdle;
-	bool _isMoving;
-	bool _rectFlag;
-	int _idleCounter;
-	int _idleCounterMax;
-	int _steps;
-	int _stepError;
-	int _lastDistance;
-	int _yMoveTotalSteps;
-	int _ySteps;
-	int _newDeltaXType;
-	int _soundCounter;
-	int _turnMoveStatus;
-	int16 _destX, _destY;
-	NPoint pathPoint(uint index) { return (*_pathPoints)[index]; }
-	void update();
-	void upIdle();
-	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
-	uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
-	uint32 hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender);
-	void stCarAtHome();
-	void updateTurnMovement();
-	void updateMovement();
-	void stEnterCar();
-	void stLeaveCar();
-	void stLeanForwardIdle();
-	void evIdleDone();
-	void stIdleBlink();
-	void stUpdateMoveDirection();
-	void stTurnCar();
-	void moveToNextPoint();
-	void stBrakeMoveToNextPoint();
-	void stTurnCarMoveToNextPoint();
-	void moveToPrevPoint();
-	void stBrakeMoveToPrevPoint();
-	void stTurnCarMoveToPrevPoint();
-	void evTurnCarDone();
-	void suMoveToNextPoint();
-	void suMoveToPrevPoint();
-	void updateSound();
-};
-
-class AsCommonIdleCarLower : public AnimatedSprite {
-public:
-	AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y);
-};
-
-class AsCommonIdleCarFull : public AnimatedSprite {
-public:
-	AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y);
-};
-
-class AsCommonCarConnector : public AnimatedSprite {
-public:
-	AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar);
-protected:
-	AsCommonCar *_asCar;
-	void update();
-};
-
-class Tracks : public Common::Array<TrackInfo*> {
-public:
-	void findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
-		DataResource &dataResource);
-};
+class AsCommonCar;
 
 class Scene1608 : public Scene {
 public:
diff --git a/engines/neverhood/modules/module1600_sprites.cpp b/engines/neverhood/modules/module1600_sprites.cpp
new file mode 100644
index 0000000..b12a070
--- /dev/null
+++ b/engines/neverhood/modules/module1600_sprites.cpp
@@ -0,0 +1,850 @@
+/* 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 "neverhood/gamemodule.h"
+#include "neverhood/modules/module1200.h"
+#include "neverhood/modules/module1600_sprites.h"
+#include "neverhood/modules/module2200_sprites.h"
+#include "neverhood/modules/module3000_sprites.h"
+
+namespace Neverhood {
+
+AsCommonCar::AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y)
+	: AnimatedSprite(vm, 1000), _parentScene(parentScene) {
+
+	createSurface(200, 556, 328);
+	_x = x;
+	_y = y;
+
+	_inMainArea = false;
+	_exitDirection = 0;
+	_currPointIndex = 0;
+	_hasAgainDestPoint = false;
+	_stepError = 0;
+	_hasAgainDestPointIndex = false;
+	_steps = 0;
+	_isBraking = false;
+	_yMoveTotalSteps = 0;
+	_isBusy = false;
+	_isIdle = false;
+	_isMoving = true;
+	_rectFlag = false;
+	_newDeltaXType = -1;
+	_soundCounter = 0;
+	_pathPoints = NULL;
+	_currMoveDirection = 0;
+
+	startAnimation(0xD4220027, 0, -1);
+	setDoDeltaX(getGlobalVar(V_CAR_DELTA_X));
+
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::handleMessage);
+	SetSpriteUpdate(NULL);
+}
+
+AsCommonCar::~AsCommonCar() {
+	if (_finalizeStateCb == AnimationCallback(&AsCommonCar::evTurnCarDone))
+		setGlobalVar(V_CAR_DELTA_X, !getGlobalVar(V_CAR_DELTA_X));
+}
+
+void AsCommonCar::setPathPoints(NPointArray *pathPoints) {
+	_pathPoints = pathPoints;
+}
+
+void AsCommonCar::update() {
+	if (_newDeltaXType >= 0) {
+		setDoDeltaX(_newDeltaXType);
+		_newDeltaXType = -1;
+	}
+	AnimatedSprite::update();
+	if (_hasAgainDestPoint && _yMoveTotalSteps == 0 && !_isBusy) {
+		_hasAgainDestPoint = false;
+		_hasAgainDestPointIndex = false;
+		sendPointMessage(this, 0x2004, _againDestPoint);
+	} else if (_hasAgainDestPointIndex && _yMoveTotalSteps == 0 && !_isBusy) {
+		_hasAgainDestPointIndex = false;
+		sendMessage(this, 0x2003, _againDestPointIndex);
+	}
+	updateMovement();
+	updateSound();
+}
+
+void AsCommonCar::upIdle() {
+	update();
+	if (++_idleCounter >= _idleCounterMax)
+		stIdleBlink();
+	updateSound();
+}
+
+uint32 AsCommonCar::handleMessage(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = Sprite::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x1019:
+		SetSpriteUpdate(NULL);
+		break;
+	case 0x2002:
+		// Set the current position without moving
+		_currPointIndex = param.asInteger();
+		_stepError = 0;
+		_x = pathPoint(_currPointIndex).x;
+		_y = pathPoint(_currPointIndex).y;
+		break;
+	case 0x2003:
+		// Move to a point by its index
+		{
+			int newPointIndex = param.asInteger();
+			if (_yMoveTotalSteps <= 0 && !_isBusy) {
+				_destX = pathPoint(newPointIndex).x;
+				_destY = pathPoint(newPointIndex).y;
+				if (_currPointIndex < newPointIndex) {
+					moveToNextPoint();
+				} else if (_currPointIndex == newPointIndex && _stepError == 0) {
+					if (_currPointIndex == 0) {
+						_yMoveTotalSteps = 0;
+						sendMessage(_parentScene, 0x2005, 0);
+					} else if (_currPointIndex == (int)_pathPoints->size()) {
+						_yMoveTotalSteps = 0;
+						sendMessage(_parentScene, 0x2006, 0);
+					}
+				} else {
+					moveToPrevPoint();
+				}
+			} else {
+				_hasAgainDestPointIndex = true;
+				_againDestPointIndex = newPointIndex;
+			}
+		}
+		break;
+	case 0x2004:
+		// Move to the point closest to the parameter point
+		{
+			int minMatchIndex = -1;
+			int minMatchDistance, distance;
+			NPoint pt = param.asPoint();
+			if (_yMoveTotalSteps <= 0 && !_isBusy) {
+				// Check if we're already exiting (or something)
+				if ((pt.x <= 20 && _exitDirection == 1) ||
+					(pt.x >= 620 && _exitDirection == 3) ||
+					(pt.y <= 20 && _exitDirection == 2) ||
+					(pt.y >= 460 && _exitDirection == 4))
+					break;
+				_destX = pt.x;
+				_destY = pt.y;
+				minMatchDistance = calcDistance(_destX, _destY, _x, _y) + 1;
+				for (int i = _currPointIndex + 1; i < (int)_pathPoints->size(); i++) {
+					distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
+					if (distance >= minMatchDistance)
+						break;
+					minMatchDistance = distance;
+					minMatchIndex = i;
+				}
+				for (int i = _currPointIndex; i >= 0; i--) {
+					distance = calcDistance(_destX, _destY, pathPoint(i).x, pathPoint(i).y);
+					if (distance >= minMatchDistance)
+						break;
+					minMatchDistance = distance;
+					minMatchIndex = i;
+				}
+				if (minMatchIndex == -1) {
+					if (_currPointIndex == 0)
+						moveToPrevPoint();
+					else
+						SetSpriteUpdate(NULL);
+				} else {
+					if (minMatchIndex > _currPointIndex)
+						moveToNextPoint();
+					else
+						moveToPrevPoint();
+				}
+			} else {
+				_hasAgainDestPoint = true;
+				_againDestPoint = pt;
+			}
+		}
+		break;
+	case 0x2007:
+		_yMoveTotalSteps = param.asInteger();
+		_steps = 0;
+		_isBraking = false;
+		_lastDistance = 640;
+		SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
+		break;
+	case 0x2008:
+		_yMoveTotalSteps = param.asInteger();
+		_steps = 0;
+		_isBraking = false;
+		_lastDistance = 640;
+		SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
+		break;
+	case 0x2009:
+		stEnterCar();
+		break;
+	case 0x200A:
+		stLeaveCar();
+		break;
+	case 0x200E:
+		stTurnCar();
+		break;
+	case 0x200F:
+		stCarAtHome();
+		_newDeltaXType = param.asInteger();
+		break;
+	}
+	return messageResult;
+}
+
+uint32 AsCommonCar::hmAnimation(int messageNum, const MessageParam &param, Entity *sender) {
+	uint32 messageResult = AsCommonCar::handleMessage(messageNum, param, sender);
+	switch (messageNum) {
+	case 0x100D:
+		if (_isBusy && param.asInteger() == 0x025424A2)
+			gotoNextState();
+		break;
+	case 0x3002:
+		gotoNextState();
+		break;
+	}
+	return messageResult;
+}
+
+uint32 AsCommonCar::hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender) {
+	switch (messageNum) {
+	case 0x2009:
+		stEnterCar();
+		break;
+	case 0x3002:
+		sendMessage(_parentScene, 0x200A, 0);
+		SetMessageHandler(&AsCommonCar::handleMessage);
+		break;
+	}
+	return 0;
+}
+
+void AsCommonCar::stCarAtHome() {
+	bool doDeltaX = _doDeltaX;
+	SetSpriteUpdate(NULL);
+	_hasAgainDestPoint = false;
+	_hasAgainDestPointIndex = false;
+	_isBraking = false;
+	_isBusy = false;
+	_isIdle = false;
+	_isMoving = false;
+	_rectFlag = false;
+	NextState(&AsCommonCar::stLeanForwardIdle);
+	startAnimation(0x35698F78, 0, -1);
+	setDoDeltaX(doDeltaX ? 1 : 0);
+	_currMoveDirection = 0;
+	_newMoveDirection = 0;
+	_steps = 0;
+	_idleCounter = 0;
+	_idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+	SetUpdateHandler(&AsCommonCar::upIdle);
+	SetMessageHandler(&AsCommonCar::handleMessage);
+	FinalizeState(&AsCommonCar::evIdleDone);
+}
+
+void AsCommonCar::updateTurnMovement() {
+	if (_turnMoveStatus == 1) {
+		_lastDistance = 640;
+		_isIdle = false;
+		_isBraking = false;
+		SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
+	} else if (_turnMoveStatus == 2) {
+		_lastDistance = 640;
+		_isIdle = false;
+		_isBraking = false;
+		SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
+	}
+}
+
+void AsCommonCar::updateMovement() {
+	if (_isBraking && !_isIdle && !_isBusy) {
+		gotoNextState();
+		_isMoving = false;
+		_isIdle = true;
+		startAnimation(0x192ADD30, 0, -1);
+		SetUpdateHandler(&AsCommonCar::update);
+		SetMessageHandler(&AsCommonCar::hmAnimation);
+		NextState(&AsCommonCar::stLeanForwardIdle);
+	} else if (!_isBraking && _steps && _isIdle) {
+		gotoNextState();
+		_isIdle = false;
+		startAnimation(0x9966B138, 0, -1);
+		SetUpdateHandler(&AsCommonCar::update);
+		SetMessageHandler(&AsCommonCar::hmAnimation);
+		NextState(&AsCommonCar::stUpdateMoveDirection);
+	} else if (_newMoveDirection != _currMoveDirection && _isMoving && !_isBusy) {
+		gotoNextState();
+		_currMoveDirection = _newMoveDirection;
+		stUpdateMoveDirection();
+	}
+}
+
+void AsCommonCar::stEnterCar() {
+	startAnimation(0xA86A9538, 0, -1);
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	NextState(&AsCommonCar::stLeanForwardIdle);
+}
+
+void AsCommonCar::stLeaveCar() {
+	startAnimation(0xA86A9538, -1, -1);
+	_playBackwards = true;
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmLeaveCar);
+}
+
+void AsCommonCar::stLeanForwardIdle() {
+	startAnimation(0x35698F78, 0, -1);
+	_currMoveDirection = 0;
+	_newMoveDirection = 0;
+	_steps = 0;
+	_idleCounter = 0;
+	_idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+	SetUpdateHandler(&AsCommonCar::upIdle);
+	SetMessageHandler(&AsCommonCar::handleMessage);
+	FinalizeState(&AsCommonCar::evIdleDone);
+}
+
+void AsCommonCar::evIdleDone() {
+	SetUpdateHandler(&AsCommonCar::update);
+}
+
+void AsCommonCar::stIdleBlink() {
+	startAnimation(0xB579A77C, 0, -1);
+	_idleCounter = 0;
+	_idleCounterMax = _vm->_rnd->getRandomNumber(64 - 1) + 24;
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	NextState(&AsCommonCar::stLeanForwardIdle);
+}
+
+void AsCommonCar::stUpdateMoveDirection() {
+	_isMoving = true;
+	if (_currMoveDirection == 1)
+		startAnimation(0xD4AA03A4, 0, -1);
+	else if (_currMoveDirection == 3)
+		startAnimation(0xD00A1364, 0, -1);
+	else if ((_currMoveDirection == 2 && _doDeltaX) || (_currMoveDirection == 4 && !_doDeltaX))
+		stTurnCar();
+	else
+		startAnimation(0xD4220027, 0, -1);
+	setGlobalVar(V_CAR_DELTA_X, _doDeltaX ? 1 : 0);
+}
+
+void AsCommonCar::moveToNextPoint() {
+	if (_currPointIndex >= (int)_pathPoints->size() - 1) {
+		_yMoveTotalSteps = 0;
+		sendMessage(this, 0x1019, 0);
+		sendMessage(_parentScene, 0x2006, 0);
+	} else {
+		NPoint nextPt = pathPoint(_currPointIndex + 1);
+		NPoint currPt = pathPoint(_currPointIndex);
+		if (ABS(nextPt.y - currPt.y) <= ABS(nextPt.x - currPt.x) &&
+			((_currMoveDirection == 2 && nextPt.x < currPt.x) ||
+			(_currMoveDirection == 4 && nextPt.x >= currPt.x))) {
+			if (_currMoveDirection == 2)
+				_currMoveDirection = 4;
+			else if (_currMoveDirection == 4)
+				_currMoveDirection = 2;
+			if (_isIdle)
+				stTurnCarMoveToNextPoint();
+			else
+				stBrakeMoveToNextPoint();
+		} else {
+			if (_steps == 0) {
+				gotoNextState();
+				_isIdle = false;
+				startAnimation(0x9966B138, 0, -1);
+				SetMessageHandler(&AsCommonCar::hmAnimation);
+				SetUpdateHandler(&AsCommonCar::update);
+				NextState(&AsCommonCar::stUpdateMoveDirection);
+			}
+			_isBraking = false;
+			SetSpriteUpdate(&AsCommonCar::suMoveToNextPoint);
+			_lastDistance = 640;
+		}
+	}
+}
+
+void AsCommonCar::stBrakeMoveToNextPoint() {
+	gotoNextState();
+	_isBusy = true;
+	_isBraking = true;
+	startAnimation(0x192ADD30, 0, -1);
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	NextState(&AsCommonCar::stTurnCarMoveToNextPoint);
+}
+
+void AsCommonCar::stTurnCar() {
+	// Turn to left/right #1
+	gotoNextState();
+	_isBusy = true;
+	startAnimation(0xF46A0324, 0, -1);
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	FinalizeState(&AsCommonCar::evTurnCarDone);
+	_turnMoveStatus = 0;
+	updateTurnMovement();
+}
+
+void AsCommonCar::stTurnCarMoveToNextPoint() {
+	// Turn to left/right #2
+	gotoNextState();
+	_isBusy = true;
+	startAnimation(0xF46A0324, 0, -1);
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	FinalizeState(&AsCommonCar::evTurnCarDone);
+	_turnMoveStatus = 1;
+	updateTurnMovement();
+}
+
+void AsCommonCar::stTurnCarMoveToPrevPoint() {
+	// Turn to left/right #3
+	FinalizeState(NULL);
+	_isBusy = true;
+	startAnimation(0xF46A0324, 0, -1);
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	FinalizeState(&AsCommonCar::evTurnCarDone);
+	_turnMoveStatus = 2;
+	updateTurnMovement();
+}
+
+void AsCommonCar::moveToPrevPoint() {
+	if (_currPointIndex == 0 && _stepError == 0) {
+		_yMoveTotalSteps = 0;
+		sendMessage(this, 0x1019, 0);
+		sendMessage(_parentScene, 0x2005, 0);
+	} else {
+		NPoint prevPt;
+		NPoint currPt;
+		if (_stepError == 0) {
+			prevPt = pathPoint(_currPointIndex - 1);
+			currPt = pathPoint(_currPointIndex);
+		} else {
+			prevPt = pathPoint(_currPointIndex);
+			currPt = pathPoint(_currPointIndex + 1);
+		}
+		if (ABS(prevPt.y - currPt.y) <= ABS(prevPt.x - currPt.x) &&
+			((_currMoveDirection == 2 && prevPt.x < currPt.x) ||
+			(_currMoveDirection == 4 && prevPt.x >= currPt.x))) {
+			if (_currMoveDirection == 2)
+				_currMoveDirection = 4;
+			else if (_currMoveDirection == 4)
+				_currMoveDirection = 2;
+			if (_isIdle)
+				stTurnCarMoveToPrevPoint();
+			else
+				stBrakeMoveToPrevPoint();
+		} else {
+			if (_steps == 0) {
+				gotoNextState();
+				_isIdle = false;
+				startAnimation(0x9966B138, 0, -1);
+				SetMessageHandler(&AsCommonCar::hmAnimation);
+				SetUpdateHandler(&AsCommonCar::update);
+				NextState(&AsCommonCar::stUpdateMoveDirection);
+			}
+			_isBraking = false;
+			SetSpriteUpdate(&AsCommonCar::suMoveToPrevPoint);
+			_lastDistance = 640;
+		}
+	}
+}
+
+void AsCommonCar::stBrakeMoveToPrevPoint() {
+	FinalizeState(NULL);
+	_isBusy = true;
+	_isBraking = true;
+	startAnimation(0x192ADD30, 0, -1);
+	SetUpdateHandler(&AsCommonCar::update);
+	SetMessageHandler(&AsCommonCar::hmAnimation);
+	NextState(&AsCommonCar::stTurnCarMoveToPrevPoint);
+}
+
+void AsCommonCar::evTurnCarDone() {
+	_isBusy = false;
+	setDoDeltaX(2);
+	_newMoveDirection = 0;
+	stUpdateMoveDirection();
+}
+
+void AsCommonCar::suMoveToNextPoint() {
+	int16 newX = _x, newY = _y;
+
+	if (_currPointIndex >= (int)_pathPoints->size()) {
+		_yMoveTotalSteps = 0;
+		sendMessage(this, 0x1019, 0);
+		sendMessage(_parentScene, 0x2006, 0);
+		return;
+	}
+
+	if (_isBraking) {
+		if (_steps <= 0) {
+			sendMessage(this, 0x1019, 0);
+			return;
+		} else
+			_steps--;
+	} else if (_steps < 11)
+		_steps++;
+
+	bool firstTime = true;
+	_ySteps = _steps;
+	int stepsCtr = _steps;
+
+	while (stepsCtr > 0) {
+		NPoint pt1;
+		NPoint pt2 = pathPoint(_currPointIndex);
+		if (_currPointIndex + 1 >= (int)_pathPoints->size())
+			pt1 = pathPoint(0);
+		else
+			pt1 = pathPoint(_currPointIndex + 1);
+		int16 deltaX = ABS(pt1.x - pt2.x);
+		int16 deltaY = ABS(pt1.y - pt2.y);
+		if (deltaX >= deltaY) {
+			_newMoveDirection = 2;
+			if (pt1.x < pt2.x)
+				_newMoveDirection = 4;
+			if (stepsCtr + _stepError >= deltaX) {
+				stepsCtr -= deltaX;
+				stepsCtr += _stepError;
+				_stepError = 0;
+				_currPointIndex++;
+				if (_currPointIndex == (int)_pathPoints->size() - 1)
+					stepsCtr = 0;
+				newX = pathPoint(_currPointIndex).x;
+				newY = pathPoint(_currPointIndex).y;
+			} else {
+				_stepError += stepsCtr;
+				if (pt1.x >= pt2.x)
+					newX += stepsCtr;
+				else
+					newX -= stepsCtr;
+				if (pt1.y >= pt2.y)
+					newY = pt2.y + (deltaY * _stepError) / deltaX;
+				else
+					newY = pt2.y - (deltaY * _stepError) / deltaX;
+				stepsCtr = 0;
+			}
+		} else {
+			_newMoveDirection = 3;
+			if (pt1.y < pt2.y)
+				_newMoveDirection = 1;
+			if (firstTime) {
+				if (pt1.y >= pt2.y)
+					stepsCtr += 7;
+				else {
+					stepsCtr -= 4;
+					if (stepsCtr < 0)
+						stepsCtr = 0;
+				}
+				_ySteps = stepsCtr;
+			}
+			if (stepsCtr + _stepError >= deltaY) {
+				stepsCtr -= deltaY;
+				stepsCtr += _stepError;
+				_stepError = 0;
+				_currPointIndex++;
+				if (_currPointIndex == (int)_pathPoints->size() - 1)
+					stepsCtr = 0;
+				newX = pathPoint(_currPointIndex).x;
+				newY = pathPoint(_currPointIndex).y;
+			} else {
+				_stepError += stepsCtr;
+				if (pt1.x >= pt2.x)
+					newX = pt2.x + (deltaX * _stepError) / deltaY;
+				else
+					newX = pt2.x - (deltaX * _stepError) / deltaY;
+				if (pt1.y >= pt2.y)
+					newY += stepsCtr;
+				else
+					newY -= stepsCtr;
+				stepsCtr = 0;
+			}
+		}
+		firstTime = false;
+	}
+
+	if (_yMoveTotalSteps != 0) {
+		_x = newX;
+		_y = newY;
+		_yMoveTotalSteps -= _ySteps;
+		if (_yMoveTotalSteps <= 0) {
+			_isBraking = true;
+			_yMoveTotalSteps = 0;
+		}
+	} else {
+		int distance = calcDistance(_destX, _destY, _x, _y);
+		_x = newX;
+		_y = newY;
+		if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
+			_exitDirection = 0;
+			_inMainArea = true;
+		} else if (_inMainArea) {
+			_destX = pathPoint(_pathPoints->size() - 1).x;
+			_destY = pathPoint(_pathPoints->size() - 1).y;
+			_inMainArea = false;
+			if (_x <= 20)
+				_exitDirection = 1;
+			else if (_x >= 620)
+				_exitDirection = 3;
+			else if (_y <= 20)
+				_exitDirection = 2;
+			else if (_y >= 460)
+				_exitDirection = 4;
+			if (_exitDirection != 0 && _isBraking) {
+				_isBraking = false;
+				_steps = 11;
+			}
+		}
+		if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
+			(_exitDirection == 0 && _lastDistance + 20 < distance))
+			_isBraking = true;
+		if (distance < _lastDistance)
+			_lastDistance = distance;
+		if (_currPointIndex == (int)_pathPoints->size() - 1) {
+			_isBraking = true;
+			_yMoveTotalSteps = 0;
+			sendMessage(this, 0x1019, 0);
+			sendMessage(_parentScene, 0x2006, 0);
+		}
+	}
+
+}
+
+void AsCommonCar::suMoveToPrevPoint() {
+	int16 newX = _x, newY = _y;
+
+	if (_currPointIndex == 0 && _stepError == 0) {
+		_yMoveTotalSteps = 0;
+		sendMessage(this, 0x1019, 0);
+		sendMessage(_parentScene, 0x2005, 0);
+		return;
+	}
+
+	if (_isBraking) {
+		if (_steps <= 0) {
+			sendMessage(this, 0x1019, 0);
+			return;
+		} else
+			_steps--;
+	} else if (_steps < 11)
+		_steps++;
+
+	bool firstTime = true;
+	_ySteps = _steps;
+	int stepsCtr = _steps;
+
+	while (stepsCtr > 0) {
+		if (_stepError == 0)
+			_currPointIndex--;
+		NPoint pt1;
+		NPoint pt2 = pathPoint(_currPointIndex);
+		if (_currPointIndex + 1 >= (int)_pathPoints->size())
+			pt1 = pathPoint(0);
+		else
+			pt1 = pathPoint(_currPointIndex + 1);
+		int16 deltaX = ABS(pt1.x - pt2.x);
+		int16 deltaY = ABS(pt1.y - pt2.y);
+		if (deltaX >= deltaY) {
+			_newMoveDirection = 4;
+			if (pt1.x < pt2.x)
+				_newMoveDirection = 2;
+			if (_stepError == 0)
+				_stepError = deltaX;
+			if (stepsCtr > _stepError) {
+				stepsCtr -= _stepError;
+				_stepError = 0;
+				if (_currPointIndex == 0)
+					stepsCtr = 0;
+				newX = pathPoint(_currPointIndex).x;
+				newY = pathPoint(_currPointIndex).y;
+			} else {
+				_stepError -= stepsCtr;
+				if (pt1.x >= pt2.x)
+					newX -= stepsCtr;
+				else
+					newX += stepsCtr;
+				if (pt1.y >= pt2.y)
+					newY = pt2.y + (deltaY * _stepError) / deltaX;
+				else
+					newY = pt2.y - (deltaY * _stepError) / deltaX;
+				stepsCtr = 0;
+			}
+		} else {
+			_newMoveDirection = 1;
+			if (pt1.y < pt2.y)
+				_newMoveDirection = 3;
+			if (firstTime) {
+				if (pt1.y >= pt2.y) {
+					stepsCtr -= 4;
+					if (stepsCtr < 0)
+						stepsCtr = 0;
+				} else {
+					stepsCtr += 7;
+				}
+				_ySteps = stepsCtr;
+			}
+			if (_stepError == 0)
+				_stepError = deltaY;
+			if (stepsCtr > _stepError) {
+				stepsCtr -= _stepError;
+				_stepError = 0;
+				if (_currPointIndex == 0)
+					stepsCtr = 0;
+				newX = pathPoint(_currPointIndex).x;
+				newY = pathPoint(_currPointIndex).y;
+			} else {
+				_stepError -= stepsCtr;
+				if (pt1.x >= pt2.x)
+					newX = pt2.x + (deltaX * _stepError) / deltaY;
+				else
+					newX = pt2.x - (deltaX * _stepError) / deltaY;
+				if (pt1.y >= pt2.y)
+					newY -= stepsCtr;
+				else
+					newY += stepsCtr;
+				stepsCtr = 0;
+			}
+		}
+		firstTime = false;
+	}
+
+	if (_yMoveTotalSteps != 0) {
+		_x = newX;
+		_y = newY;
+		_yMoveTotalSteps -= _ySteps;
+		if (_yMoveTotalSteps <= 0) {
+			_isBraking = true;
+			_yMoveTotalSteps = 0;
+		}
+	} else {
+		int distance = calcDistance(_destX, _destY, _x, _y);
+		_x = newX;
+		_y = newY;
+		if (newX > 20 && newX < 620 && newY > 20 && newY < 460) {
+			_exitDirection = 0;
+			_inMainArea = true;
+		} else if (_inMainArea) {
+			_destX = pathPoint(0).x;
+			_destY = pathPoint(0).y;
+			_inMainArea = false;
+			if (_x <= 20)
+				_exitDirection = 1;
+			else if (_x >= 620)
+				_exitDirection = 3;
+			else if (_y <= 20)
+				_exitDirection = 2;
+			else if (_y >= 460)
+				_exitDirection = 4;
+			if (_exitDirection != 0 && _isBraking) {
+				_isBraking = false;
+				_steps = 11;
+			}
+		}
+		if ((distance < 20 && _exitDirection == 0 && _lastDistance < distance) ||
+			(_exitDirection == 0 && _lastDistance + 20 < distance))
+			_isBraking = true;
+		if (distance < _lastDistance)
+			_lastDistance = distance;
+		if (_currPointIndex == 0 && _stepError == 0) {
+			_isBraking = true;
+			_yMoveTotalSteps = 0;
+			sendMessage(this, 0x1019, 0);
+			sendMessage(_parentScene, 0x2005, 0);
+		}
+	}
+
+}
+
+void AsCommonCar::updateSound() {
+	int maxSoundCounter = 0;
+	_soundCounter++;
+	if (_steps != 0 && !_isIdle) {
+		if (_currMoveDirection == 1)
+			maxSoundCounter = 18 - _steps;
+		else if (_currMoveDirection == 3) {
+			maxSoundCounter = 5 - _steps;
+			if (maxSoundCounter < 1)
+				maxSoundCounter = 1;
+		} else
+			maxSoundCounter = 14 - _steps;
+	} else
+		maxSoundCounter = 21;
+	if (_soundCounter >= maxSoundCounter) {
+		sendMessage(_parentScene, 0x200D, 0);
+		_soundCounter = 0;
+	}
+}
+
+AsCommonIdleCarLower::AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y)
+	: AnimatedSprite(vm, 0x1209E09F, 1100, x, y) {
+
+	setDoDeltaX(1);
+	startAnimation(0x1209E09F, 1, -1);
+	_newStickFrameIndex = 1;
+}
+
+AsCommonIdleCarFull::AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y)
+	: AnimatedSprite(vm, 0x1209E09F, 100, x, y) {
+
+	setDoDeltaX(1);
+	_newStickFrameIndex = 0;
+}
+
+AsCommonCarConnector::AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar)
+	: AnimatedSprite(vm, 1100), _asCar(asCar) {
+
+	createSurface1(0x60281C10, 150);
+	startAnimation(0x60281C10, -1, -1);
+	_newStickFrameIndex = STICK_LAST_FRAME;
+	SetUpdateHandler(&AsCommonCarConnector::update);
+}
+
+void AsCommonCarConnector::update() {
+	_x = _asCar->getX();
+	_y = _asCar->getY();
+	AnimatedSprite::update();
+}
+
+void Tracks::findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
+	DataResource &dataResource) {
+	const uint trackCount = size();
+	minMatchTrackIndex = -1;
+	minMatchDistance = 640;
+	for (uint trackIndex = 0; trackIndex < trackCount; trackIndex++) {
+		NPointArray *pointList = dataResource.getPointArray((*this)[trackIndex]->trackPointsName);
+		for (uint pointIndex = 0; pointIndex < pointList->size(); pointIndex++) {
+			NPoint testPt = (*pointList)[pointIndex];
+			int distance = calcDistance(testPt.x, testPt.y, pt.x, pt.y);
+			if (distance < minMatchDistance) {
+				minMatchTrackIndex = trackIndex;
+				minMatchDistance = distance;
+			}
+		}
+	}
+}
+
+} // End of namespace Neverhood
diff --git a/engines/neverhood/modules/module1600_sprites.h b/engines/neverhood/modules/module1600_sprites.h
new file mode 100644
index 0000000..13fcf6c
--- /dev/null
+++ b/engines/neverhood/modules/module1600_sprites.h
@@ -0,0 +1,119 @@
+/* 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 NEVERHOOD_MODULES_MODULE1600_SPRITES_H
+#define NEVERHOOD_MODULES_MODULE1600_SPRITES_H
+
+#include "neverhood/neverhood.h"
+#include "neverhood/module.h"
+#include "neverhood/scene.h"
+
+namespace Neverhood {
+
+class AsCommonCar : public AnimatedSprite {
+public:
+	AsCommonCar(NeverhoodEngine *vm, Scene *parentScene, int16 x, int16 y);
+	~AsCommonCar();
+	void setPathPoints(NPointArray *pathPoints);
+protected:
+	Scene *_parentScene;
+	NPointArray *_pathPoints;
+	int _newMoveDirection;
+	int _currMoveDirection;
+	int _exitDirection;
+	int _currPointIndex;
+	bool _hasAgainDestPoint;
+	NPoint _againDestPoint;
+	bool _hasAgainDestPointIndex;
+	int _againDestPointIndex;
+	bool _inMainArea;
+	bool _isBraking;
+	bool _isBusy;
+	bool _isIdle;
+	bool _isMoving;
+	bool _rectFlag;
+	int _idleCounter;
+	int _idleCounterMax;
+	int _steps;
+	int _stepError;
+	int _lastDistance;
+	int _yMoveTotalSteps;
+	int _ySteps;
+	int _newDeltaXType;
+	int _soundCounter;
+	int _turnMoveStatus;
+	int16 _destX, _destY;
+	NPoint pathPoint(uint index) { return (*_pathPoints)[index]; }
+	void update();
+	void upIdle();
+	uint32 handleMessage(int messageNum, const MessageParam &param, Entity *sender);
+	uint32 hmAnimation(int messageNum, const MessageParam &param, Entity *sender);
+	uint32 hmLeaveCar(int messageNum, const MessageParam &param, Entity *sender);
+	void stCarAtHome();
+	void updateTurnMovement();
+	void updateMovement();
+	void stEnterCar();
+	void stLeaveCar();
+	void stLeanForwardIdle();
+	void evIdleDone();
+	void stIdleBlink();
+	void stUpdateMoveDirection();
+	void stTurnCar();
+	void moveToNextPoint();
+	void stBrakeMoveToNextPoint();
+	void stTurnCarMoveToNextPoint();
+	void moveToPrevPoint();
+	void stBrakeMoveToPrevPoint();
+	void stTurnCarMoveToPrevPoint();
+	void evTurnCarDone();
+	void suMoveToNextPoint();
+	void suMoveToPrevPoint();
+	void updateSound();
+};
+
+class AsCommonIdleCarLower : public AnimatedSprite {
+public:
+	AsCommonIdleCarLower(NeverhoodEngine *vm, int16 x, int16 y);
+};
+
+class AsCommonIdleCarFull : public AnimatedSprite {
+public:
+	AsCommonIdleCarFull(NeverhoodEngine *vm, int16 x, int16 y);
+};
+
+class AsCommonCarConnector : public AnimatedSprite {
+public:
+	AsCommonCarConnector(NeverhoodEngine *vm, AsCommonCar *asCar);
+protected:
+	AsCommonCar *_asCar;
+	void update();
+};
+
+class Tracks : public Common::Array<TrackInfo*> {
+public:
+	void findTrackPoint(NPoint pt, int &minMatchTrackIndex, int &minMatchDistance,
+		DataResource &dataResource);
+};
+
+} // End of namespace Neverhood
+
+#endif /* NEVERHOOD_MODULES_MODULE1600_SPRITES_H */
diff --git a/engines/neverhood/modules/module2500.cpp b/engines/neverhood/modules/module2500.cpp
index b606659..bda85e5 100644
--- a/engines/neverhood/modules/module2500.cpp
+++ b/engines/neverhood/modules/module2500.cpp
@@ -21,6 +21,7 @@
  */
 
 #include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module1600_sprites.h"
 #include "neverhood/modules/module2500.h"
 #include "neverhood/modules/module2500_sprites.h"
 #include "neverhood/modules/module2700.h"
diff --git a/engines/neverhood/modules/module2500.h b/engines/neverhood/modules/module2500.h
index 33464cf..de6226e 100644
--- a/engines/neverhood/modules/module2500.h
+++ b/engines/neverhood/modules/module2500.h
@@ -26,11 +26,10 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
+#include "neverhood/modules/module1600_sprites.h"	// for Tracks
 
 namespace Neverhood {
 
-// Module2500
-
 class Module2500 : public Module {
 public:
 	Module2500(NeverhoodEngine *vm, Module *parentModule, int which);
@@ -45,7 +44,6 @@ protected:
 };
 
 class AsCommonCar;
-class Tracks;
 
 class Scene2501 : public Scene {
 public:
diff --git a/engines/neverhood/modules/module2700.cpp b/engines/neverhood/modules/module2700.cpp
index 69e21dd..d05f142 100644
--- a/engines/neverhood/modules/module2700.cpp
+++ b/engines/neverhood/modules/module2700.cpp
@@ -22,7 +22,7 @@
 
 #include "neverhood/gamemodule.h"
 #include "neverhood/modules/module1000.h"
-#include "neverhood/modules/module1600.h"
+#include "neverhood/modules/module1600_sprites.h"
 #include "neverhood/modules/module2700.h"
 #include "neverhood/modules/module2700_sprites.h"
 
diff --git a/engines/neverhood/modules/module2700.h b/engines/neverhood/modules/module2700.h
index 5e42eea..97b4f1c 100644
--- a/engines/neverhood/modules/module2700.h
+++ b/engines/neverhood/modules/module2700.h
@@ -26,6 +26,7 @@
 #include "neverhood/neverhood.h"
 #include "neverhood/module.h"
 #include "neverhood/scene.h"
+#include "neverhood/modules/module1600_sprites.h"	// for Tracks
 
 namespace Neverhood {
 
@@ -49,7 +50,6 @@ protected:
 };
 
 class AsCommonCar;
-class Tracks;
 
 class Scene2701 : public Scene {
 public:






More information about the Scummvm-git-logs mailing list