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

sev- sev at scummvm.org
Sat Oct 15 13:51:38 CEST 2016


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

Summary:
3596672735 CHEWY: Added engine stub
77e60faa03 CHEWY: Fix compilation with plugins enabled
9dd2e5d24e CHEWY: Implement detection for the English version
039261e731 CHEWY: Initial implementation of a resource manager, and a main loop
e60fbde1d2 CHEWY: More work on res manager, add support for RLE encoded resources
182debe908 CHEWY: Add a console, with a "dump" command to dump resources
03aae70855 CHEWY: Add a graphics class and an image drawing test
98e838275f CHEWY: Adjust comments
3a5cd65d6d CHEWY: Bugfix for drawImage()
8970473f6c CHEWY: Add a "draw" console command to draw game images
b7e4bcf3f2 CHEWY: Another bugfix for drawImage()
8ab1846f59 CHEWY: Add support for SFX and speech resources to the resource manager
078cbf0b08 CHEWY: Add a sound player class and use the proper game resolution
676fa15c19 CHEWY: Add methods for playing sound, speech and music to the debugger
c6ccd8bbe8 CHEWY: Use a specialized resource handler for each resource
a196bfff57 CHEWY: Add support for encrypted text resources
b60f5023ed CHEWY: Add a TODO for the currently unhandled resource files
f017940ca0 CHEWY: Initial work on game videos
0152b7c47f CHEWY: Add initial video (CFO) player
7331bdc6b1 VIDEO: Allow parts of the FLIC decoder to be overriden by child classes
ecc212a31a CHEWY: Properly close videos when they end
7234574370 CHEWY: Add support for sound effects in videos
1de9019665 CHEWY: Remove some unused CFO video custom sub chunks
94a942755e CHEWY: Initial support for game sprites
8767b44fe0 CHEWY: Initial work on cursor animations
93a83a6b86 CHEWY: Add an event manager, and get rid of g_engine
8c755b268c CHEWY: Add the event manager to module.mk
8c7c42d13d CHEWY: Use virtual destructors. Some cleanup
88f3fc0760 CHEWY: Implement initial sprite drawing, font loading and text drawing
832b97c1d5 CHEWY: Rename some variables
263fdb357b CHEWY: Some cleanup, and remove a seemingly unused resource
ce800ff1ce CHEWY: Fix warnings about shadowed and unused variables
b394b1b687 CHEWY: Fix compilation
891813c9e1 CHEWY: TCF resources contain error messages, not in-game text
8f9412984d CHEWY: Fix define for chewy.h
f61aee3c70 CHEWY: Mask potentially overflown palette values
9e5b745a12 CHEWY: Process events while waiting for video music to end
cec2799c64 CHEWY: Properly handle the text encryption in atds.tap (game texts)
19dab45c8c CHEWY: Initial support for in-game texts (game dialog texts)
18d6c501fc CHEWY: Add support for in-game texts
384b61a9fb CHEWY: Optimize font drawing
cf7c010d47 CHEWY: Use new instead of malloc() in the CFO video decoder
7002ede1ed CHEWY: Const correctness
c3a4950c98 CHEWY: Properly dispose audio streams after use
8df9eb5b8f CHEWY: Fix undefined behavior
339e1c1f88 CHEWY: Pass the text parameter of getLine() by reference
c1e44df357 CHEWY: Use atds.tap for detection
0a4c1eeca1 CHEWY: Move all sound functions into sound.*
bda8a9b92b CHEWY: Initial work on converting TMF music data back to MOD data
a292fcdd93 CHEWY: Fix typo
684cbfa2fd CHEWY: Add support for palette fadeout to videos
375618828f CHEWY: Move cursor related functions into a separate file
5fbf9ad171 CHEWY: Remove duplicate table
53de49a052 CHEWY: Create a scene class
af2027ddd1 Merge pull request #838 from bluegr/chewy


Commit: 3596672735c980e94dffd63d7c29e416ec98365e
    https://github.com/scummvm/scummvm/commit/3596672735c980e94dffd63d7c29e416ec98365e
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-03T00:32:32+03:00

Commit Message:
CHEWY: Added engine stub

Changed paths:
  A engines/chewy/chewy.cpp
  A engines/chewy/chewy.h
  A engines/chewy/configure.engine
  A engines/chewy/detection.cpp
  A engines/chewy/module.mk



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
new file mode 100644
index 0000000..a26a944
--- /dev/null
+++ b/engines/chewy/chewy.cpp
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/error.h"
+
+#include "engines/engine.h"
+#include "engines/util.h"
+
+#include "chewy/chewy.h"
+
+namespace Chewy {
+
+ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
+	: Engine(syst),
+	_gameDescription(gameDesc),
+	_rnd("chewy") {
+}
+
+ChewyEngine::~ChewyEngine() {
+}
+
+Common::Error ChewyEngine::run() {
+	// Initialize backend
+	initGraphics(320, 200, false);
+
+	initialize();
+
+	return Common::kNoError;
+}
+
+void ChewyEngine::initialize() {
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
new file mode 100644
index 0000000..99eafe6
--- /dev/null
+++ b/engines/chewy/chewy.h
@@ -0,0 +1,67 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_H
+#define CHEWY_H
+
+
+#include "common/scummsys.h"
+#include "common/file.h"
+#include "common/util.h"
+#include "common/str.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+#include "common/random.h"
+
+#include "engines/engine.h"
+
+namespace Chewy {
+
+struct ChewyGameDescription;
+
+class ChewyEngine : public Engine {
+
+protected:
+	// Engine APIs
+	virtual Common::Error run();
+	virtual bool hasFeature(EngineFeature f) const;
+
+	void shutdown();
+
+	void initialize();
+
+public:
+	ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc);
+	virtual ~ChewyEngine();
+
+	int getGameType() const;
+	uint32 getFeatures() const;
+	Common::Language getLanguage() const;
+	Common::Platform getPlatform() const;
+
+	const ChewyGameDescription *_gameDescription;
+	Common::RandomSource _rnd;
+};
+
+} // End of namespace Chewy
+
+#endif
diff --git a/engines/chewy/configure.engine b/engines/chewy/configure.engine
new file mode 100644
index 0000000..f9f7ffd
--- /dev/null
+++ b/engines/chewy/configure.engine
@@ -0,0 +1,3 @@
+# This file is included from the main "configure" script
+# add_engine [name] [desc] [build-by-default] [subengines] [base games] [deps]
+add_engine chewy "Chewy: Esc from F5" no
diff --git a/engines/chewy/detection.cpp b/engines/chewy/detection.cpp
new file mode 100644
index 0000000..06ba6cc
--- /dev/null
+++ b/engines/chewy/detection.cpp
@@ -0,0 +1,145 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/savefile.h"
+#include "common/system.h"
+#include "base/plugins.h"
+
+#include "engines/advancedDetector.h"
+
+#include "chewy/chewy.h"
+
+
+namespace Chewy {
+
+struct ChewyGameDescription {
+	ADGameDescription desc;
+};
+
+uint32 ChewyEngine::getFeatures() const {
+	return _gameDescription->desc.flags;
+}
+
+Common::Language ChewyEngine::getLanguage() const {
+	return _gameDescription->desc.language;
+}
+
+}
+
+static const PlainGameDescriptor chewyGames[] = {
+	{"chewy", "Chewy: Esc from F5"},
+	{0, 0}
+};
+
+
+namespace Chewy {
+
+static const ChewyGameDescription gameDescriptions[] = {
+
+	{
+		{
+			"chewy",
+			0,
+			AD_ENTRY1s("XXX", "00000000000000000", 1),
+			Common::EN_ANY,
+			Common::kPlatformDOS,
+			ADGF_NO_FLAGS,
+			GUIO1(GUIO_NONE)
+		},
+	},
+
+	{ AD_TABLE_END_MARKER }
+};
+
+} // End of namespace Chewy
+
+class ChewyMetaEngine : public AdvancedMetaEngine {
+public:
+	ChewyMetaEngine() : AdvancedMetaEngine(Chewy::gameDescriptions, sizeof(Chewy::ChewyGameDescription), chewyGames) {
+		_singleId = "chewy";
+	}
+
+	virtual const char *getName() const {
+		return "Chewy Engine";
+	}
+
+	virtual const char *getOriginalCopyright() const {
+		return "Chewy Engine New Generation Software (C) 1995";
+	}
+
+	virtual bool hasFeature(MetaEngineFeature f) const;
+	virtual bool createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const;
+	SaveStateList listSaves(const char *target) const;
+	virtual int getMaximumSaveSlot() const;
+	void removeSaveState(const char *target, int slot) const;
+	SaveStateDescriptor querySaveMetaInfos(const char *target, int slot) const;
+};
+
+bool ChewyMetaEngine::hasFeature(MetaEngineFeature f) const {
+	return
+		(f == kSupportsListSaves) ||
+		(f == kSupportsLoadingDuringStartup) ||
+		(f == kSupportsDeleteSave) ||
+		(f == kSavesSupportMetaInfo) ||
+		(f == kSavesSupportThumbnail) ||
+		(f == kSavesSupportCreationDate) ||
+		(f == kSavesSupportPlayTime);
+}
+
+bool Chewy::ChewyEngine::hasFeature(EngineFeature f) const {
+	return
+		(f == kSupportsRTL) ||
+		(f == kSupportsLoadingDuringRuntime) ||
+		(f == kSupportsSavingDuringRuntime);
+}
+
+bool ChewyMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const {
+	const Chewy::ChewyGameDescription *gd = (const Chewy::ChewyGameDescription *)desc;
+	if (gd) {
+		*engine = new Chewy::ChewyEngine(syst, gd);
+	}
+	return gd != 0;
+}
+
+SaveStateList ChewyMetaEngine::listSaves(const char *target) const {
+	SaveStateList saveList;
+
+	return saveList;
+}
+
+int ChewyMetaEngine::getMaximumSaveSlot() const {
+	return 999;
+}
+
+void ChewyMetaEngine::removeSaveState(const char *target, int slot) const {
+}
+
+SaveStateDescriptor ChewyMetaEngine::querySaveMetaInfos(const char *target, int slot) const {
+
+	return SaveStateDescriptor();
+} // End of namespace Chewy
+
+#if PLUGIN_ENABLED_DYNAMIC(Chewy)
+	REGISTER_PLUGIN_DYNAMIC(CHEWY, PLUGIN_TYPE_ENGINE, ChewyMetaEngine);
+#else
+	REGISTER_PLUGIN_STATIC(CHEWY, PLUGIN_TYPE_ENGINE, ChewyMetaEngine);
+#endif
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
new file mode 100644
index 0000000..497c101
--- /dev/null
+++ b/engines/chewy/module.mk
@@ -0,0 +1,14 @@
+MODULE := engines/chewy
+
+MODULE_OBJS = \
+	chewy.o \
+	detection.o
+
+
+# This module can be built as a plugin
+ifeq ($(ENABLE_CHEWY), DYNAMIC_PLUGIN)
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk


Commit: 77e60faa03317a874b42cdcbe54050520e015fbe
    https://github.com/scummvm/scummvm/commit/77e60faa03317a874b42cdcbe54050520e015fbe
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-03T00:32:36+03:00

Commit Message:
CHEWY: Fix compilation with plugins enabled

Changed paths:
    engines/chewy/detection.cpp



diff --git a/engines/chewy/detection.cpp b/engines/chewy/detection.cpp
index 06ba6cc..b7371b6 100644
--- a/engines/chewy/detection.cpp
+++ b/engines/chewy/detection.cpp
@@ -138,7 +138,7 @@ SaveStateDescriptor ChewyMetaEngine::querySaveMetaInfos(const char *target, int
 	return SaveStateDescriptor();
 } // End of namespace Chewy
 
-#if PLUGIN_ENABLED_DYNAMIC(Chewy)
+#if PLUGIN_ENABLED_DYNAMIC(CHEWY)
 	REGISTER_PLUGIN_DYNAMIC(CHEWY, PLUGIN_TYPE_ENGINE, ChewyMetaEngine);
 #else
 	REGISTER_PLUGIN_STATIC(CHEWY, PLUGIN_TYPE_ENGINE, ChewyMetaEngine);


Commit: 9dd2e5d24ede940ab29b4abbaf823041910a893d
    https://github.com/scummvm/scummvm/commit/9dd2e5d24ede940ab29b4abbaf823041910a893d
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:32:40+03:00

Commit Message:
CHEWY: Implement detection for the English version

Changed paths:
    engines/chewy/detection.cpp



diff --git a/engines/chewy/detection.cpp b/engines/chewy/detection.cpp
index b7371b6..57435ad 100644
--- a/engines/chewy/detection.cpp
+++ b/engines/chewy/detection.cpp
@@ -50,6 +50,10 @@ static const PlainGameDescriptor chewyGames[] = {
 	{0, 0}
 };
 
+static const char *directoryGlobs[] = {
+	"back",
+	0
+};
 
 namespace Chewy {
 
@@ -59,7 +63,7 @@ static const ChewyGameDescription gameDescriptions[] = {
 		{
 			"chewy",
 			0,
-			AD_ENTRY1s("XXX", "00000000000000000", 1),
+			AD_ENTRY1s("comic.tgp", "4f03228838663ddecebd750c04687a08", 6529814),
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,
@@ -75,6 +79,8 @@ static const ChewyGameDescription gameDescriptions[] = {
 class ChewyMetaEngine : public AdvancedMetaEngine {
 public:
 	ChewyMetaEngine() : AdvancedMetaEngine(Chewy::gameDescriptions, sizeof(Chewy::ChewyGameDescription), chewyGames) {
+		_maxScanDepth = 2;
+		_directoryGlobs = directoryGlobs;
 		_singleId = "chewy";
 	}
 


Commit: 039261e731cc7eaf290a97ef096b2d3d1ee29da7
    https://github.com/scummvm/scummvm/commit/039261e731cc7eaf290a97ef096b2d3d1ee29da7
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:32:44+03:00

Commit Message:
CHEWY: Initial implementation of a resource manager, and a main loop

Changed paths:
  A engines/chewy/resource.cpp
  A engines/chewy/resource.h
    engines/chewy/chewy.cpp
    engines/chewy/module.mk



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index a26a944..130e31b 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -20,12 +20,16 @@
  *
  */
 
+#include "common/config-manager.h"
 #include "common/error.h"
+#include "common/events.h"
+#include "common/system.h"
 
 #include "engines/engine.h"
 #include "engines/util.h"
 
 #include "chewy/chewy.h"
+#include "chewy/resource.h"
 
 namespace Chewy {
 
@@ -33,6 +37,16 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 	: Engine(syst),
 	_gameDescription(gameDesc),
 	_rnd("chewy") {
+
+	const Common::FSNode gameDataDir(ConfMan.get("path"));
+
+	SearchMan.addSubDirectoryMatching(gameDataDir, "back");
+	SearchMan.addSubDirectoryMatching(gameDataDir, "cut");
+	SearchMan.addSubDirectoryMatching(gameDataDir, "err");
+	SearchMan.addSubDirectoryMatching(gameDataDir, "misc");
+	SearchMan.addSubDirectoryMatching(gameDataDir, "room");
+	SearchMan.addSubDirectoryMatching(gameDataDir, "sound");
+	SearchMan.addSubDirectoryMatching(gameDataDir, "txt");
 }
 
 ChewyEngine::~ChewyEngine() {
@@ -44,6 +58,28 @@ Common::Error ChewyEngine::run() {
 
 	initialize();
 
+	Resource *res = new Resource("comic.tgp");
+	TBFChunk *cur = res->getChunk(1);
+	
+	debug("Chunk 1: packed %d, type %d, pos %d, mode %d, comp %d, unpacked %d, width %d, height %d",
+		cur->packedSize, cur->type, cur->pos, cur->screenMode, cur->compressionFlag, cur->unpackedSize,
+		cur->width, cur->height
+	);
+
+	delete res;
+
+	// Run a dummy loop
+	Common::Event event;
+
+	while (!shouldQuit()) {
+		while (g_system->getEventManager()->pollEvent(event)) {
+			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+				g_engine->quitGame();
+		}
+
+		g_system->delayMillis(10);
+	}
+
 	return Common::kNoError;
 }
 
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index 497c101..c9621c6 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -2,7 +2,8 @@ MODULE := engines/chewy
 
 MODULE_OBJS = \
 	chewy.o \
-	detection.o
+	detection.o \
+	resource.o
 
 
 # This module can be built as a plugin
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
new file mode 100644
index 0000000..1d8764a
--- /dev/null
+++ b/engines/chewy/resource.cpp
@@ -0,0 +1,82 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/stream.h"
+#include "common/debug.h"
+#include "common/textconsole.h"
+
+#include "chewy/chewy.h"
+#include "chewy/resource.h"
+
+namespace Chewy {
+
+Resource::Resource(Common::String filename) {
+	_stream.open(filename);
+	uint32 magicBytes = MKTAG('N', 'G', 'S', '\0');
+	if (_stream.readUint32BE() != magicBytes)
+		error("Invalid resource - %s", filename.c_str());
+	_stream.skip(2);	// type
+	_chunkCount = _stream.readUint16LE();
+
+	uint32 tbfID = MKTAG('T', 'B', 'F', '\0');
+
+	for (uint i = 0; i < _chunkCount; i++) {
+		TBFChunk cur;
+		cur.packedSize = _stream.readUint32LE();
+		cur.type = _stream.readUint16LE();
+		cur.pos = _stream.pos();
+		if (_stream.readUint32BE() != tbfID)
+			error("Corrupt resource %s", filename.c_str());
+
+		cur.screenMode = _stream.readUint16LE();
+		cur.compressionFlag = _stream.readUint16LE();
+		cur.unpackedSize = _stream.readUint32LE();
+		cur.width = _stream.readUint16LE();
+		cur.height = _stream.readUint16LE();
+		_stream.read(cur.palette, 3 * 256);
+		_stream.skip(cur.packedSize - TBF_CHUNK_HEADER_SIZE);
+
+		_tbfChunkList.push_back(cur);
+
+		/*debug("Chunk %d: packed %d, type %d, pos %d, mode %d, comp %d, unpacked %d, width %d, height %d",
+			i, cur.packedSize, cur.type, cur.pos, cur.screenMode, cur.compressionFlag, cur.unpackedSize,
+			cur.width, cur.height
+		);*/
+	}
+
+}
+
+Resource::~Resource() {
+	_tbfChunkList.clear();
+	_stream.close();
+}
+
+TBFChunk *Resource::getChunk(int num) {
+	return &_tbfChunkList[num];
+}
+
+Common::SeekableReadStream *Resource::getChunkData(int num) {
+	// TODO
+	return nullptr;
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
new file mode 100644
index 0000000..5432e3c
--- /dev/null
+++ b/engines/chewy/resource.h
@@ -0,0 +1,73 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_RESOURCE_H
+#define CHEWY_RESOURCE_H
+
+
+#include "common/scummsys.h"
+#include "common/file.h"
+#include "common/util.h"
+#include "common/str.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+#include "common/random.h"
+
+namespace Chewy {
+
+// 4 + 2 + 2 + 4 + 2 + 2 + 768 = 784 bytes
+#define TBF_CHUNK_HEADER_SIZE 784
+
+struct TBFChunk {
+	uint32 packedSize;	// includes header
+	uint16 type;
+	uint32 pos;	// extra field
+
+	// TBF chunk header
+	// ID (TBF, followed by a zero)
+	uint16 screenMode;
+	uint16 compressionFlag;
+	uint32 unpackedSize;
+	uint16 width;
+	uint16 height;
+	char palette[3 * 256];
+};
+
+typedef Common::Array<TBFChunk> TBFChunkList;
+
+class Resource {
+public:
+	Resource(Common::String filename);
+	~Resource();
+
+	TBFChunk *getChunk(int num);
+	Common::SeekableReadStream *getChunkData(int num);
+
+private:
+	Common::File _stream;
+	uint16 _chunkCount;
+	TBFChunkList _tbfChunkList;
+};
+
+} // End of namespace Chewy
+
+#endif


Commit: e60fbde1d2b736d7f44c51d27e75639837d19cfe
    https://github.com/scummvm/scummvm/commit/e60fbde1d2b736d7f44c51d27e75639837d19cfe
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:32:48+03:00

Commit Message:
CHEWY: More work on res manager, add support for RLE encoded resources

Changed paths:
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 1d8764a..40db53a 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -20,8 +20,8 @@
  *
  */
 
-#include "common/stream.h"
 #include "common/debug.h"
+#include "common/stream.h"
 #include "common/textconsole.h"
 
 #include "chewy/chewy.h"
@@ -41,9 +41,8 @@ Resource::Resource(Common::String filename) {
 
 	for (uint i = 0; i < _chunkCount; i++) {
 		TBFChunk cur;
-		cur.packedSize = _stream.readUint32LE();
+		cur.packedSize = _stream.readUint32LE() - TBF_CHUNK_HEADER_SIZE;
 		cur.type = _stream.readUint16LE();
-		cur.pos = _stream.pos();
 		if (_stream.readUint32BE() != tbfID)
 			error("Corrupt resource %s", filename.c_str());
 
@@ -52,15 +51,13 @@ Resource::Resource(Common::String filename) {
 		cur.unpackedSize = _stream.readUint32LE();
 		cur.width = _stream.readUint16LE();
 		cur.height = _stream.readUint16LE();
-		_stream.read(cur.palette, 3 * 256);
-		_stream.skip(cur.packedSize - TBF_CHUNK_HEADER_SIZE);
+		for (int j = 0; j < 3 * 256; j++)
+			cur.palette[j] = _stream.readByte() << 2;
+		cur.pos = _stream.pos();
 
-		_tbfChunkList.push_back(cur);
+		_stream.skip(cur.packedSize);
 
-		/*debug("Chunk %d: packed %d, type %d, pos %d, mode %d, comp %d, unpacked %d, width %d, height %d",
-			i, cur.packedSize, cur.type, cur.pos, cur.screenMode, cur.compressionFlag, cur.unpackedSize,
-			cur.width, cur.height
-		);*/
+		_tbfChunkList.push_back(cur);
 	}
 
 }
@@ -74,9 +71,30 @@ TBFChunk *Resource::getChunk(int num) {
 	return &_tbfChunkList[num];
 }
 
-Common::SeekableReadStream *Resource::getChunkData(int num) {
-	// TODO
-	return nullptr;
+byte *Resource::getChunkData(int num) {
+	TBFChunk *chunk = &_tbfChunkList[num];
+	byte *data = new byte[chunk->unpackedSize];
+
+	_stream.seek(chunk->pos, SEEK_SET);
+
+	if (!chunk->compressionFlag) {
+		_stream.read(data, chunk->packedSize);
+	} else {
+		// Compressed resources are packed using a very simple RLE compression
+		byte count;
+		byte value;
+		uint32 outPos = 0;
+
+		for (uint i = 0; i < (chunk->packedSize) / 2 && outPos < chunk->unpackedSize; i++) {
+			count = _stream.readByte();
+			value = _stream.readByte();
+			for (byte j = 0; j < count; j++) {
+				data[outPos++] = value;
+			}
+		}
+	}
+
+	return data;
 }
 
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 5432e3c..622ffa4 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -40,7 +40,6 @@ namespace Chewy {
 struct TBFChunk {
 	uint32 packedSize;	// includes header
 	uint16 type;
-	uint32 pos;	// extra field
 
 	// TBF chunk header
 	// ID (TBF, followed by a zero)
@@ -49,7 +48,9 @@ struct TBFChunk {
 	uint32 unpackedSize;
 	uint16 width;
 	uint16 height;
-	char palette[3 * 256];
+	byte palette[3 * 256];
+
+	uint32 pos;	// position of the actual data
 };
 
 typedef Common::Array<TBFChunk> TBFChunkList;
@@ -60,7 +61,7 @@ public:
 	~Resource();
 
 	TBFChunk *getChunk(int num);
-	Common::SeekableReadStream *getChunkData(int num);
+	byte *getChunkData(int num);
 
 private:
 	Common::File _stream;


Commit: 182debe9083a57c8f96ea5214450193feb2c6558
    https://github.com/scummvm/scummvm/commit/182debe9083a57c8f96ea5214450193feb2c6558
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:32:52+03:00

Commit Message:
CHEWY: Add a console, with a "dump" command to dump resources

Changed paths:
  A engines/chewy/console.cpp
  A engines/chewy/console.h
    engines/chewy/chewy.cpp
    engines/chewy/chewy.h
    engines/chewy/module.mk



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 130e31b..8051c87 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -38,6 +38,8 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 	_gameDescription(gameDesc),
 	_rnd("chewy") {
 
+	_console = new Console(this);
+
 	const Common::FSNode gameDataDir(ConfMan.get("path"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "back");
@@ -75,8 +77,11 @@ Common::Error ChewyEngine::run() {
 		while (g_system->getEventManager()->pollEvent(event)) {
 			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
 				g_engine->quitGame();
+			if (event.type == Common::EVENT_KEYDOWN && event.kbd.flags & Common::KBD_CTRL && event.kbd.keycode == Common::KEYCODE_d)
+				_console->attach();
 		}
 
+		_console->onFrame();
 		g_system->delayMillis(10);
 	}
 
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 99eafe6..b832144 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -33,6 +33,7 @@
 #include "common/random.h"
 
 #include "engines/engine.h"
+#include "chewy/console.h"
 
 namespace Chewy {
 
@@ -49,6 +50,8 @@ protected:
 
 	void initialize();
 
+	Console *_console;
+
 public:
 	ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc);
 	virtual ~ChewyEngine();
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
new file mode 100644
index 0000000..09f6110
--- /dev/null
+++ b/engines/chewy/console.cpp
@@ -0,0 +1,63 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "chewy/console.h"
+#include "gui/debugger.h"
+#include "chewy/chewy.h"
+#include "chewy/resource.h"
+
+namespace Chewy {
+
+	Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
+	registerCmd("dump",			WRAP_METHOD(Console, Cmd_Dump));
+}
+
+Console::~Console() {
+}
+
+bool Console::Cmd_Dump(int argc, const char **argv) {
+	if (argc < 4) {
+		debugPrintf("Usage: dump <file> <resource number> <dump file name>\n");
+		return true;
+	}
+
+	Common::String filename = argv[1];
+	int resNum = atoi(argv[2]);
+	Common::String dumpFilename = argv[3];
+
+	Resource *res = new Resource(filename);
+	TBFChunk *chunk = res->getChunk(resNum);
+	byte *data = res->getChunkData(resNum);
+
+	Common::DumpFile outFile;
+	outFile.open(dumpFilename);
+	outFile.write(data, chunk->unpackedSize);
+	outFile.flush();
+	outFile.close();
+
+	delete[] data;
+	delete res;
+
+	return true;
+}
+
+} // End of namespace Drascula
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
new file mode 100644
index 0000000..b6b32e6
--- /dev/null
+++ b/engines/chewy/console.h
@@ -0,0 +1,44 @@
+/* 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 CHEWY_CONSOLE_H
+#define CHEWY_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace Chewy {
+
+class ChewyEngine;
+
+class Console : public GUI::Debugger {
+public:
+	Console(ChewyEngine *vm);
+	virtual ~Console(void);
+
+private:
+	ChewyEngine *_vm;
+
+	bool Cmd_Dump(int argc, const char **argv);
+};
+
+} // End of namespace Drascula
+#endif
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index c9621c6..137a7fb 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/chewy
 
 MODULE_OBJS = \
 	chewy.o \
+	console.o \
 	detection.o \
 	resource.o
 


Commit: 03aae708550ce42b86656b905cd42448fa64ed2f
    https://github.com/scummvm/scummvm/commit/03aae708550ce42b86656b905cd42448fa64ed2f
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:32:56+03:00

Commit Message:
CHEWY: Add a graphics class and an image drawing test

Changed paths:
  A engines/chewy/graphics.cpp
  A engines/chewy/graphics.h
    engines/chewy/chewy.cpp
    engines/chewy/module.mk



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 8051c87..a040e16 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -24,11 +24,13 @@
 #include "common/error.h"
 #include "common/events.h"
 #include "common/system.h"
+#include "graphics/palette.h"
 
 #include "engines/engine.h"
 #include "engines/util.h"
 
 #include "chewy/chewy.h"
+#include "chewy/graphics.h"
 #include "chewy/resource.h"
 
 namespace Chewy {
@@ -56,19 +58,13 @@ ChewyEngine::~ChewyEngine() {
 
 Common::Error ChewyEngine::run() {
 	// Initialize backend
-	initGraphics(320, 200, false);
+	initGraphics(640, 480, true);
 
 	initialize();
 
-	Resource *res = new Resource("comic.tgp");
-	TBFChunk *cur = res->getChunk(1);
-	
-	debug("Chunk 1: packed %d, type %d, pos %d, mode %d, comp %d, unpacked %d, width %d, height %d",
-		cur->packedSize, cur->type, cur->pos, cur->screenMode, cur->compressionFlag, cur->unpackedSize,
-		cur->width, cur->height
-	);
-
-	delete res;
+	Graphics *g = new Graphics();
+	g->drawImage("comic.tgp", 0);
+	delete g;
 
 	// Run a dummy loop
 	Common::Event event;
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
new file mode 100644
index 0000000..5127607
--- /dev/null
+++ b/engines/chewy/graphics.cpp
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "graphics/palette.h"
+
+#include "chewy/graphics.h"
+#include "chewy/resource.h"
+
+namespace Chewy {
+
+void Graphics::drawImage(Common::String filename, int imageNum) {
+	Resource *res = new Resource("comic.tgp");
+	TBFChunk *cur = res->getChunk(0);
+	byte *buf = res->getChunkData(0);
+
+	g_system->getPaletteManager()->setPalette(cur->palette, 0, 256);
+	g_system->copyRectToScreen(buf, cur->width, 0, 0, cur->width, cur->height);
+	g_system->updateScreen();
+	delete res;
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
new file mode 100644
index 0000000..601b419
--- /dev/null
+++ b/engines/chewy/graphics.h
@@ -0,0 +1,42 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_GRAPHICS_H
+#define CHEWY_GRAPHICS_H
+
+#include "chewy/chewy.h"
+
+namespace Chewy {
+
+class Graphics {
+public:
+	Graphics() {}
+	~Graphics() {}
+
+	void drawImage(Common::String filename, int imageNum);
+private:
+
+};
+
+} // End of namespace Chewy
+
+#endif
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index 137a7fb..df932c7 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS = \
 	chewy.o \
 	console.o \
 	detection.o \
+	graphics.o \
 	resource.o
 
 


Commit: 98e838275fb6e1b122caa6b9e786db9372bfc195
    https://github.com/scummvm/scummvm/commit/98e838275fb6e1b122caa6b9e786db9372bfc195
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:00+03:00

Commit Message:
CHEWY: Adjust comments

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 09f6110..3e9c46f 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -60,4 +60,4 @@ bool Console::Cmd_Dump(int argc, const char **argv) {
 	return true;
 }
 
-} // End of namespace Drascula
+} // End of namespace Chewy
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index b6b32e6..cce736b 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -40,5 +40,5 @@ private:
 	bool Cmd_Dump(int argc, const char **argv);
 };
 
-} // End of namespace Drascula
+} // End of namespace Chewy
 #endif


Commit: 3a5cd65d6d03c2e2f17656571f8528ef6ea8f039
    https://github.com/scummvm/scummvm/commit/3a5cd65d6d03c2e2f17656571f8528ef6ea8f039
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:04+03:00

Commit Message:
CHEWY: Bugfix for drawImage()

Changed paths:
    engines/chewy/graphics.cpp



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 5127607..2369d32 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -30,8 +30,8 @@ namespace Chewy {
 
 void Graphics::drawImage(Common::String filename, int imageNum) {
 	Resource *res = new Resource("comic.tgp");
-	TBFChunk *cur = res->getChunk(0);
-	byte *buf = res->getChunkData(0);
+	TBFChunk *cur = res->getChunk(imageNum);
+	byte *buf = res->getChunkData(imageNum);
 
 	g_system->getPaletteManager()->setPalette(cur->palette, 0, 256);
 	g_system->copyRectToScreen(buf, cur->width, 0, 0, cur->width, cur->height);


Commit: 8970473f6c439496cc3c5d65539df680e1795916
    https://github.com/scummvm/scummvm/commit/8970473f6c439496cc3c5d65539df680e1795916
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:08+03:00

Commit Message:
CHEWY: Add a "draw" console command to draw game images

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 3e9c46f..dab5d5a 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -20,15 +20,18 @@
  *
  */
 
-#include "chewy/console.h"
 #include "gui/debugger.h"
+
 #include "chewy/chewy.h"
+#include "chewy/console.h"
+#include "chewy/graphics.h"
 #include "chewy/resource.h"
 
 namespace Chewy {
 
-	Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
+Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("dump",			WRAP_METHOD(Console, Cmd_Dump));
+	registerCmd("draw",			WRAP_METHOD(Console, Cmd_Draw));
 }
 
 Console::~Console() {
@@ -60,4 +63,20 @@ bool Console::Cmd_Dump(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::Cmd_Draw(int argc, const char **argv) {
+	if (argc < 3) {
+		debugPrintf("Usage: draw <file> <resource number>\n");
+		return true;
+	}
+
+	Common::String filename = argv[1];
+	int resNum = atoi(argv[2]);
+	
+	Graphics *g = new Graphics();
+	g->drawImage(filename, resNum);
+	delete g;
+
+	return false;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index cce736b..3528474 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -38,6 +38,7 @@ private:
 	ChewyEngine *_vm;
 
 	bool Cmd_Dump(int argc, const char **argv);
+	bool Cmd_Draw(int argc, const char **argv);
 };
 
 } // End of namespace Chewy


Commit: b7e4bcf3f20dc38ccd465acc07f42cb62557a2c9
    https://github.com/scummvm/scummvm/commit/b7e4bcf3f20dc38ccd465acc07f42cb62557a2c9
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:12+03:00

Commit Message:
CHEWY: Another bugfix for drawImage()

Changed paths:
    engines/chewy/graphics.cpp



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 2369d32..7f2b89c 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -29,7 +29,7 @@
 namespace Chewy {
 
 void Graphics::drawImage(Common::String filename, int imageNum) {
-	Resource *res = new Resource("comic.tgp");
+	Resource *res = new Resource(filename);
 	TBFChunk *cur = res->getChunk(imageNum);
 	byte *buf = res->getChunkData(imageNum);
 


Commit: 8ab1846f59504dc7edd8d26b7702d520e3bab631
    https://github.com/scummvm/scummvm/commit/8ab1846f59504dc7edd8d26b7702d520e3bab631
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:16+03:00

Commit Message:
CHEWY: Add support for SFX and speech resources to the resource manager

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/graphics.cpp
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index dab5d5a..386654b 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -48,12 +48,17 @@ bool Console::Cmd_Dump(int argc, const char **argv) {
 	Common::String dumpFilename = argv[3];
 
 	Resource *res = new Resource(filename);
-	TBFChunk *chunk = res->getChunk(resNum);
+	Chunk *chunk = res->getChunk(resNum);
 	byte *data = res->getChunkData(resNum);
+	uint32 size = chunk->size;
+	if (chunk->type == kResourceTBF) {
+		TBFChunk *tbf = res->getTBFChunk(resNum);
+		size = tbf->unpackedSize;
+	}
 
 	Common::DumpFile outFile;
 	outFile.open(dumpFilename);
-	outFile.write(data, chunk->unpackedSize);
+	outFile.write(data, size);
 	outFile.flush();
 	outFile.close();
 
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 7f2b89c..ba16cfb 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -30,7 +30,7 @@ namespace Chewy {
 
 void Graphics::drawImage(Common::String filename, int imageNum) {
 	Resource *res = new Resource(filename);
-	TBFChunk *cur = res->getChunk(imageNum);
+	TBFChunk *cur = res->getTBFChunk(imageNum);
 	byte *buf = res->getChunkData(imageNum);
 
 	g_system->getPaletteManager()->setPalette(cur->palette, 0, 256);
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 40db53a..233e8cd 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -34,64 +34,124 @@ Resource::Resource(Common::String filename) {
 	uint32 magicBytes = MKTAG('N', 'G', 'S', '\0');
 	if (_stream.readUint32BE() != magicBytes)
 		error("Invalid resource - %s", filename.c_str());
-	_stream.skip(2);	// type
+	_resType = (ResourceType)_stream.readUint16LE();
 	_chunkCount = _stream.readUint16LE();
 
-	uint32 tbfID = MKTAG('T', 'B', 'F', '\0');
-
 	for (uint i = 0; i < _chunkCount; i++) {
-		TBFChunk cur;
-		cur.packedSize = _stream.readUint32LE() - TBF_CHUNK_HEADER_SIZE;
-		cur.type = _stream.readUint16LE();
-		if (_stream.readUint32BE() != tbfID)
-			error("Corrupt resource %s", filename.c_str());
-
-		cur.screenMode = _stream.readUint16LE();
-		cur.compressionFlag = _stream.readUint16LE();
-		cur.unpackedSize = _stream.readUint32LE();
-		cur.width = _stream.readUint16LE();
-		cur.height = _stream.readUint16LE();
-		for (int j = 0; j < 3 * 256; j++)
-			cur.palette[j] = _stream.readByte() << 2;
+		Chunk cur;
+		cur.size = _stream.readUint32LE();
+		cur.type = (ResourceType)_stream.readUint16LE();
 		cur.pos = _stream.pos();
 
-		_stream.skip(cur.packedSize);
+		if (cur.type == kResourceTBF) {
+			cur.pos += TBF_CHUNK_HEADER_SIZE;
+			cur.size -= TBF_CHUNK_HEADER_SIZE;
+			readTBFChunk();
+		}
 
-		_tbfChunkList.push_back(cur);
+		_stream.skip(cur.size);
+		_chunkList.push_back(cur);
 	}
-
 }
 
 Resource::~Resource() {
+	_chunkList.clear();
 	_tbfChunkList.clear();
 	_stream.close();
 }
 
-TBFChunk *Resource::getChunk(int num) {
+void Resource::readTBFChunk() {
+	TBFChunk cur;
+	if (_stream.readUint32BE() != MKTAG('T', 'B', 'F', '\0'))
+		error("Corrupt TBF resource");
+
+	cur.screenMode = _stream.readUint16LE();
+	cur.compressionFlag = _stream.readUint16LE();
+	cur.unpackedSize = _stream.readUint32LE();
+	cur.width = _stream.readUint16LE();
+	cur.height = _stream.readUint16LE();
+	for (int j = 0; j < 3 * 256; j++)
+		cur.palette[j] = _stream.readByte() << 2;
+
+	_tbfChunkList.push_back(cur);
+}
+
+uint32 Resource::getChunkCount() const {
+	return _chunkList.size();
+}
+
+Chunk *Resource::getChunk(int num) {
+	return &_chunkList[num];
+}
+
+TBFChunk *Resource::getTBFChunk(int num) {
+	assert(_resType == kResourceTGP);
 	return &_tbfChunkList[num];
 }
 
 byte *Resource::getChunkData(int num) {
-	TBFChunk *chunk = &_tbfChunkList[num];
-	byte *data = new byte[chunk->unpackedSize];
+	Chunk *chunk = &_chunkList[num];
+	byte *data;
 
 	_stream.seek(chunk->pos, SEEK_SET);
 
-	if (!chunk->compressionFlag) {
-		_stream.read(data, chunk->packedSize);
-	} else {
-		// Compressed resources are packed using a very simple RLE compression
-		byte count;
-		byte value;
-		uint32 outPos = 0;
-
-		for (uint i = 0; i < (chunk->packedSize) / 2 && outPos < chunk->unpackedSize; i++) {
-			count = _stream.readByte();
-			value = _stream.readByte();
-			for (byte j = 0; j < count; j++) {
-				data[outPos++] = value;
+	if (chunk->type == kResourceTBF) {
+		TBFChunk *tbfChunk = &_tbfChunkList[num];
+		data = new byte[tbfChunk->unpackedSize];
+
+		if (!tbfChunk->compressionFlag) {
+			_stream.read(data, chunk->size);
+		} else {
+			// Compressed images are packed using a very simple RLE compression
+			byte count;
+			byte value;
+			uint32 outPos = 0;
+
+			for (uint i = 0; i < (chunk->size) / 2 && outPos < tbfChunk->unpackedSize; i++) {
+				count = _stream.readByte();
+				value = _stream.readByte();
+				for (byte j = 0; j < count; j++) {
+					data[outPos++] = value;
+				}
 			}
 		}
+	} else if (chunk->type == kResourceVOC) {
+		// Voice files are split in blocks, so reassemble them here
+		byte blocksRemaining;
+		uint32 totalLength = 0;
+		uint32 blockSize;
+		
+		// Find the total length of the voice file
+		do {
+			blocksRemaining = _stream.readByte();
+			blockSize =
+				_stream.readByte() +
+				(_stream.readByte() << 8) +
+				(_stream.readByte() << 16);
+
+			totalLength += blockSize;
+			_stream.skip(blockSize);
+		} while (blocksRemaining > 1);
+
+		// Read the voice data
+		data = new byte[totalLength];
+		byte *ptr = data;
+
+		_stream.seek(chunk->pos, SEEK_SET);
+
+		do {
+			blocksRemaining = _stream.readByte();
+			blockSize =
+				 _stream.readByte() +
+				(_stream.readByte() << 8) +
+				(_stream.readByte() << 16);
+			
+			_stream.read(ptr, blockSize);
+			ptr += blockSize;
+		} while (blocksRemaining > 1);
+	} else {
+		data = new byte[chunk->size];
+		_stream.read(data, chunk->size);
 	}
 
 	return data;
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 622ffa4..e0b4230 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -34,13 +34,46 @@
 
 namespace Chewy {
 
+enum ResourceType {
+	kResourcePCX = 0,		// unused
+	kResourceTBF = 1,		// contained in TGPs
+	kResourceTAF = 2,
+	kResourceTFF = 3,
+	kResourceVOC = 4,		// contained in TVPs
+	kResourceTPF = 5,		// unused
+	kResourceTMF = 6,		// unused
+	kResourceMOD = 7,		// unused
+	kResourceRAW = 8,		// unused
+	kResourceLBM = 9,		// unused
+	kResourceRDI = 10,
+	kResourceTXT = 11,
+	kResourceIIB = 12,
+	kResourceSIB = 13,
+	kResourceEIB = 14,
+	kResourceATS = 15,		// unused
+	kResourceSAA = 16,		// unused
+	kResourceFLC = 17,		// unused
+	kResourceAAD = 18,		// unused
+	kResourceADS = 19,		// unused
+	kResourceADH = 20,		// used in txt/diah.adh
+	kResourceTGP = 21,		// background, used in back/comic.tgp, back/episode1.tgp and back/gbook.tgp
+	kResourceTVP = 22,		// speech, used in sound/speech.tvp
+	kResourceTTP = 23,		// unused
+	kResourceTAP = 24,		// sound effects, music and cutscenes, used in sound/details.tap and cut/cut.tap
+	kResourceCFO = 25,		// unused
+	kResourceTCF = 26		// error messages, used in err/err_e.tcf (English) and err/err_d.tcf (German)
+};
+
 // 4 + 2 + 2 + 4 + 2 + 2 + 768 = 784 bytes
 #define TBF_CHUNK_HEADER_SIZE 784
 
-struct TBFChunk {
-	uint32 packedSize;	// includes header
-	uint16 type;
+struct Chunk {
+	uint32 size;
+	ResourceType type;
+	uint32 pos;	// position of the actual data
+};
 
+struct TBFChunk {
 	// TBF chunk header
 	// ID (TBF, followed by a zero)
 	uint16 screenMode;
@@ -49,10 +82,9 @@ struct TBFChunk {
 	uint16 width;
 	uint16 height;
 	byte palette[3 * 256];
-
-	uint32 pos;	// position of the actual data
 };
 
+typedef Common::Array<Chunk> ChunkList;
 typedef Common::Array<TBFChunk> TBFChunkList;
 
 class Resource {
@@ -60,12 +92,21 @@ public:
 	Resource(Common::String filename);
 	~Resource();
 
-	TBFChunk *getChunk(int num);
+	ResourceType getType() const { return _resType; }
+	uint32 getChunkCount() const;
+	Chunk *getChunk(int num);
+	TBFChunk *getTBFChunk(int num);
 	byte *getChunkData(int num);
 
-private:
+protected:
 	Common::File _stream;
 	uint16 _chunkCount;
+	ResourceType _resType;
+
+private:
+	void readTBFChunk();
+
+	ChunkList _chunkList;
 	TBFChunkList _tbfChunkList;
 };
 


Commit: 078cbf0b089588836784513a558cb7dc99b4758b
    https://github.com/scummvm/scummvm/commit/078cbf0b089588836784513a558cb7dc99b4758b
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:21+03:00

Commit Message:
CHEWY: Add a sound player class and use the proper game resolution

Currently, speech and sound effects are supported, but the current
music playing implementation is wrong, as the game's music is
encoded in custom MOD-like files. With the current music
implementation, the PCM parts of these files are played

Changed paths:
  A engines/chewy/sound.cpp
  A engines/chewy/sound.h
    engines/chewy/chewy.cpp
    engines/chewy/chewy.h
    engines/chewy/module.mk



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index a040e16..b5271d5 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -30,8 +30,10 @@
 #include "engines/util.h"
 
 #include "chewy/chewy.h"
+#include "chewy/console.h"
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
+#include "chewy/sound.h"
 
 namespace Chewy {
 
@@ -40,8 +42,6 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 	_gameDescription(gameDesc),
 	_rnd("chewy") {
 
-	_console = new Console(this);
-
 	const Common::FSNode gameDataDir(ConfMan.get("path"));
 
 	SearchMan.addSubDirectoryMatching(gameDataDir, "back");
@@ -54,17 +54,28 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 }
 
 ChewyEngine::~ChewyEngine() {
+	delete _console;
+	delete _sound;
+	delete _graphics;
+}
+
+void ChewyEngine::initialize() {
+	_console = new Console(this);
+	_graphics = new Graphics();
+	_sound = new Sound();
 }
 
 Common::Error ChewyEngine::run() {
 	// Initialize backend
-	initGraphics(640, 480, true);
+	//initGraphics(640, 480, true);
+	initGraphics(320, 200, false);
 
 	initialize();
 
-	Graphics *g = new Graphics();
-	g->drawImage("comic.tgp", 0);
-	delete g;
+	_graphics->drawImage("episode1.tgp", 0);
+	//_sound->playSpeech(1);
+	//_sound->playSound(1);
+	//_sound->playMusic(2);
 
 	// Run a dummy loop
 	Common::Event event;
@@ -84,7 +95,4 @@ Common::Error ChewyEngine::run() {
 	return Common::kNoError;
 }
 
-void ChewyEngine::initialize() {
-}
-
 } // End of namespace Chewy
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index b832144..2235d5f 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -33,11 +33,13 @@
 #include "common/random.h"
 
 #include "engines/engine.h"
-#include "chewy/console.h"
 
 namespace Chewy {
 
 struct ChewyGameDescription;
+class Console;
+class Graphics;
+class Sound;
 
 class ChewyEngine : public Engine {
 
@@ -63,6 +65,9 @@ public:
 
 	const ChewyGameDescription *_gameDescription;
 	Common::RandomSource _rnd;
+
+	Graphics *_graphics;
+	Sound *_sound;
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index df932c7..5b96ab9 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -5,8 +5,8 @@ MODULE_OBJS = \
 	console.o \
 	detection.o \
 	graphics.o \
-	resource.o
-
+	resource.o \
+	sound.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_CHEWY), DYNAMIC_PLUGIN)
diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
new file mode 100644
index 0000000..41f91d0
--- /dev/null
+++ b/engines/chewy/sound.cpp
@@ -0,0 +1,87 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
+#include "common/system.h"
+
+#include "chewy/resource.h"
+#include "chewy/sound.h"
+
+namespace Chewy {
+
+Sound::Sound() {
+	_speechRes = new Resource("speech.tvp");
+	_soundRes = new Resource("details.tap");
+}
+
+Sound::~Sound() {
+	delete _soundRes;
+	delete _speechRes;
+}
+
+void Sound::playSound(int num, bool loop) {
+	Chunk *chunk = _soundRes->getChunk(num);
+	byte *data = _soundRes->getChunkData(num);
+
+	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
+		Audio::makeRawStream(data,
+		chunk->size, 22050, Audio::FLAG_UNSIGNED,
+		DisposeAfterUse::NO),
+		loop ? 0 : 1);
+
+	g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
+}
+
+void Sound::playMusic(int num, bool loop) {
+	uint32 musicNum = _soundRes->getChunkCount() - 1 - num;
+	Chunk *chunk = _soundRes->getChunk(musicNum);
+	byte *data = _soundRes->getChunkData(musicNum);
+
+	// TODO: TMF music files are similar to MOD files. With the following
+	// incorrect implementation, the PCM parts of these files can be played
+	warning("The current music playing implementation is wrong");
+
+	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
+		Audio::makeRawStream(data,
+		chunk->size, 22050, Audio::FLAG_UNSIGNED,
+		DisposeAfterUse::NO),
+		loop ? 0 : 1);
+
+	g_engine->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream);
+}
+
+void Sound::playSpeech(int num) {
+	Chunk *chunk = _speechRes->getChunk(num);
+	byte *data = _speechRes->getChunkData(num);
+
+	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
+		Audio::makeRawStream(data,
+		chunk->size, 22050, Audio::FLAG_UNSIGNED,
+		DisposeAfterUse::NO),
+		1);
+
+	g_engine->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream);
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h
new file mode 100644
index 0000000..6537f3e
--- /dev/null
+++ b/engines/chewy/sound.h
@@ -0,0 +1,53 @@
+/* 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 CHEWY_SOUND_H
+#define CHEWY_SOUND_H
+
+#include "audio/mixer.h"
+#include "chewy/chewy.h"
+
+namespace Chewy {
+
+class Resource;
+
+class Sound {
+public:
+	Sound();
+	~Sound();
+
+	void playSound(int num, bool loop = false);
+	void playMusic(int num, bool loop = false);
+	void playSpeech(int num);
+
+private:
+	Audio::SoundHandle _soundHandle;
+	Audio::SoundHandle _musicHandle;
+	Audio::SoundHandle _speechHandle;
+
+	Resource *_speechRes;
+	Resource *_soundRes;
+};
+
+} // End of namespace Chewy
+
+#endif


Commit: 676fa15c193bbd2a7fc2962d0c2bc26e260efd6a
    https://github.com/scummvm/scummvm/commit/676fa15c193bbd2a7fc2962d0c2bc26e260efd6a
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:24+03:00

Commit Message:
CHEWY: Add methods for playing sound, speech and music to the debugger

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 386654b..b610ddd 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -26,12 +26,16 @@
 #include "chewy/console.h"
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
+#include "chewy/sound.h"
 
 namespace Chewy {
 
 Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("dump",			WRAP_METHOD(Console, Cmd_Dump));
 	registerCmd("draw",			WRAP_METHOD(Console, Cmd_Draw));
+	registerCmd("play_sound",	WRAP_METHOD(Console, Cmd_PlaySound));
+	registerCmd("play_speech",	WRAP_METHOD(Console, Cmd_PlaySpeech));
+	registerCmd("play_music",	WRAP_METHOD(Console, Cmd_PlayMusic));
 }
 
 Console::~Console() {
@@ -84,4 +88,40 @@ bool Console::Cmd_Draw(int argc, const char **argv) {
 	return false;
 }
 
+bool Console::Cmd_PlaySound(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("Usage: play_sound <number>\n");
+		return true;
+	}
+
+	int resNum = atoi(argv[1]);
+	_vm->_sound->playSound(resNum);
+
+	return true;
+}
+
+bool Console::Cmd_PlaySpeech(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("Usage: play_speech <number>\n");
+		return true;
+	}
+
+	int resNum = atoi(argv[1]);
+	_vm->_sound->playSpeech(resNum);
+
+	return true;
+}
+
+bool Console::Cmd_PlayMusic(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("Usage: play_music <number>\n");
+		return true;
+	}
+
+	int resNum = atoi(argv[1]);
+	_vm->_sound->playMusic(resNum);
+
+	return true;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index 3528474..9877824 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -39,6 +39,9 @@ private:
 
 	bool Cmd_Dump(int argc, const char **argv);
 	bool Cmd_Draw(int argc, const char **argv);
+	bool Cmd_PlaySound(int argc, const char **argv);
+	bool Cmd_PlaySpeech(int argc, const char **argv);
+	bool Cmd_PlayMusic(int argc, const char **argv);
 };
 
 } // End of namespace Chewy


Commit: c6ccd8bbe8da08534a9f1e23258dc4011a60382c
    https://github.com/scummvm/scummvm/commit/c6ccd8bbe8da08534a9f1e23258dc4011a60382c
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:29+03:00

Commit Message:
CHEWY: Use a specialized resource handler for each resource

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h
    engines/chewy/graphics.cpp
    engines/chewy/resource.cpp
    engines/chewy/resource.h
    engines/chewy/sound.cpp
    engines/chewy/sound.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index b610ddd..298e10b 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -32,6 +32,7 @@ namespace Chewy {
 
 Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("dump",			WRAP_METHOD(Console, Cmd_Dump));
+	registerCmd("dump_bg",		WRAP_METHOD(Console, Cmd_DumpBg));
 	registerCmd("draw",			WRAP_METHOD(Console, Cmd_Draw));
 	registerCmd("play_sound",	WRAP_METHOD(Console, Cmd_PlaySound));
 	registerCmd("play_speech",	WRAP_METHOD(Console, Cmd_PlaySpeech));
@@ -55,10 +56,6 @@ bool Console::Cmd_Dump(int argc, const char **argv) {
 	Chunk *chunk = res->getChunk(resNum);
 	byte *data = res->getChunkData(resNum);
 	uint32 size = chunk->size;
-	if (chunk->type == kResourceTBF) {
-		TBFChunk *tbf = res->getTBFChunk(resNum);
-		size = tbf->unpackedSize;
-	}
 
 	Common::DumpFile outFile;
 	outFile.open(dumpFilename);
@@ -72,6 +69,33 @@ bool Console::Cmd_Dump(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::Cmd_DumpBg(int argc, const char **argv) {
+	if (argc < 4) {
+		debugPrintf("Usage: dump_bg <file> <resource number> <dump file name>\n");
+		return true;
+	}
+
+	Common::String filename = argv[1];
+	int resNum = atoi(argv[2]);
+	Common::String dumpFilename = argv[3];
+
+	BackgroundResource *res = new BackgroundResource(filename);
+	TBFChunk *image = res->getImage(resNum);
+
+	Common::DumpFile outFile;
+	outFile.open(dumpFilename);
+	outFile.write(image->data, image->size);
+	outFile.flush();
+	outFile.close();
+
+	delete[] image->data;
+	delete image;
+	delete res;
+
+	return true;
+}
+
+
 bool Console::Cmd_Draw(int argc, const char **argv) {
 	if (argc < 3) {
 		debugPrintf("Usage: draw <file> <resource number>\n");
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index 9877824..873359d 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -38,6 +38,7 @@ private:
 	ChewyEngine *_vm;
 
 	bool Cmd_Dump(int argc, const char **argv);
+	bool Cmd_DumpBg(int argc, const char **argv);
 	bool Cmd_Draw(int argc, const char **argv);
 	bool Cmd_PlaySound(int argc, const char **argv);
 	bool Cmd_PlaySpeech(int argc, const char **argv);
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index ba16cfb..c3b29fe 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -29,13 +29,15 @@
 namespace Chewy {
 
 void Graphics::drawImage(Common::String filename, int imageNum) {
-	Resource *res = new Resource(filename);
-	TBFChunk *cur = res->getTBFChunk(imageNum);
-	byte *buf = res->getChunkData(imageNum);
+	BackgroundResource *res = new BackgroundResource(filename);
+	TBFChunk *image = res->getImage(imageNum);
 
-	g_system->getPaletteManager()->setPalette(cur->palette, 0, 256);
-	g_system->copyRectToScreen(buf, cur->width, 0, 0, cur->width, cur->height);
+	g_system->getPaletteManager()->setPalette(image->palette, 0, 256);
+	g_system->copyRectToScreen(image->data, image->width, 0, 0, image->width, image->height);
 	g_system->updateScreen();
+
+	delete[] image->data;
+	delete image;
 	delete res;
 }
 
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 233e8cd..1bd9583 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -43,12 +43,6 @@ Resource::Resource(Common::String filename) {
 		cur.type = (ResourceType)_stream.readUint16LE();
 		cur.pos = _stream.pos();
 
-		if (cur.type == kResourceTBF) {
-			cur.pos += TBF_CHUNK_HEADER_SIZE;
-			cur.size -= TBF_CHUNK_HEADER_SIZE;
-			readTBFChunk();
-		}
-
 		_stream.skip(cur.size);
 		_chunkList.push_back(cur);
 	}
@@ -56,26 +50,9 @@ Resource::Resource(Common::String filename) {
 
 Resource::~Resource() {
 	_chunkList.clear();
-	_tbfChunkList.clear();
 	_stream.close();
 }
 
-void Resource::readTBFChunk() {
-	TBFChunk cur;
-	if (_stream.readUint32BE() != MKTAG('T', 'B', 'F', '\0'))
-		error("Corrupt TBF resource");
-
-	cur.screenMode = _stream.readUint16LE();
-	cur.compressionFlag = _stream.readUint16LE();
-	cur.unpackedSize = _stream.readUint32LE();
-	cur.width = _stream.readUint16LE();
-	cur.height = _stream.readUint16LE();
-	for (int j = 0; j < 3 * 256; j++)
-		cur.palette[j] = _stream.readByte() << 2;
-
-	_tbfChunkList.push_back(cur);
-}
-
 uint32 Resource::getChunkCount() const {
 	return _chunkList.size();
 }
@@ -84,77 +61,98 @@ Chunk *Resource::getChunk(int num) {
 	return &_chunkList[num];
 }
 
-TBFChunk *Resource::getTBFChunk(int num) {
-	assert(_resType == kResourceTGP);
-	return &_tbfChunkList[num];
+byte *Resource::getChunkData(int num) {
+	Chunk *chunk = &_chunkList[num];
+	byte *data = new byte[chunk->size];
+
+	_stream.seek(chunk->pos, SEEK_SET);
+	_stream.read(data, chunk->size);
+
+	return data;
 }
 
-byte *Resource::getChunkData(int num) {
+TBFChunk *BackgroundResource::getImage(int num) {
 	Chunk *chunk = &_chunkList[num];
-	byte *data;
+	TBFChunk *tbf = new TBFChunk();
 
 	_stream.seek(chunk->pos, SEEK_SET);
 
-	if (chunk->type == kResourceTBF) {
-		TBFChunk *tbfChunk = &_tbfChunkList[num];
-		data = new byte[tbfChunk->unpackedSize];
-
-		if (!tbfChunk->compressionFlag) {
-			_stream.read(data, chunk->size);
-		} else {
-			// Compressed images are packed using a very simple RLE compression
-			byte count;
-			byte value;
-			uint32 outPos = 0;
-
-			for (uint i = 0; i < (chunk->size) / 2 && outPos < tbfChunk->unpackedSize; i++) {
-				count = _stream.readByte();
-				value = _stream.readByte();
-				for (byte j = 0; j < count; j++) {
-					data[outPos++] = value;
-				}
+	if (_stream.readUint32BE() != MKTAG('T', 'B', 'F', '\0'))
+		error("Corrupt TBF resource");
+
+	tbf->screenMode = _stream.readUint16LE();
+	tbf->compressionFlag = _stream.readUint16LE();
+	tbf->size = _stream.readUint32LE();
+	tbf->width = _stream.readUint16LE();
+	tbf->height = _stream.readUint16LE();
+	for (int j = 0; j < 3 * 256; j++)
+		tbf->palette[j] = _stream.readByte() << 2;
+
+	tbf->data = new byte[tbf->size];
+
+	if (!tbf->compressionFlag) {
+		_stream.read(tbf->data, chunk->size);
+	}
+	else {
+		// Compressed images are packed using a very simple RLE compression
+		byte count;
+		byte value;
+		uint32 outPos = 0;
+
+		for (uint i = 0; i < (chunk->size) / 2 && outPos < tbf->size; i++) {
+			count = _stream.readByte();
+			value = _stream.readByte();
+			for (byte j = 0; j < count; j++) {
+				tbf->data[outPos++] = value;
 			}
 		}
-	} else if (chunk->type == kResourceVOC) {
-		// Voice files are split in blocks, so reassemble them here
-		byte blocksRemaining;
-		uint32 totalLength = 0;
-		uint32 blockSize;
-		
-		// Find the total length of the voice file
-		do {
-			blocksRemaining = _stream.readByte();
-			blockSize =
-				_stream.readByte() +
-				(_stream.readByte() << 8) +
-				(_stream.readByte() << 16);
-
-			totalLength += blockSize;
-			_stream.skip(blockSize);
-		} while (blocksRemaining > 1);
-
-		// Read the voice data
-		data = new byte[totalLength];
-		byte *ptr = data;
-
-		_stream.seek(chunk->pos, SEEK_SET);
-
-		do {
-			blocksRemaining = _stream.readByte();
-			blockSize =
-				 _stream.readByte() +
-				(_stream.readByte() << 8) +
-				(_stream.readByte() << 16);
-			
-			_stream.read(ptr, blockSize);
-			ptr += blockSize;
-		} while (blocksRemaining > 1);
-	} else {
-		data = new byte[chunk->size];
-		_stream.read(data, chunk->size);
 	}
 
-	return data;
+	return tbf;
+}
+
+SoundChunk *SoundResource::getSound(int num) {
+	Chunk *chunk = &_chunkList[num];
+	SoundChunk *sound = new SoundChunk();
+
+	_stream.seek(chunk->pos, SEEK_SET);
+
+	// Voice files are split in blocks, so reassemble them here
+	byte blocksRemaining;
+	uint32 totalLength = 0;
+	uint32 blockSize;
+
+	// Find the total length of the voice file
+	do {
+		blocksRemaining = _stream.readByte();
+		blockSize =
+			_stream.readByte() +
+			(_stream.readByte() << 8) +
+			(_stream.readByte() << 16);
+
+		totalLength += blockSize;
+		_stream.skip(blockSize);
+	} while (blocksRemaining > 1);
+
+	// Read the voice data
+	sound->size = totalLength;
+	sound->data = new byte[totalLength];
+	byte *ptr = sound->data;
+
+	_stream.seek(chunk->pos, SEEK_SET);
+
+	do {
+		blocksRemaining = _stream.readByte();
+		blockSize =
+			_stream.readByte() +
+			(_stream.readByte() << 8) +
+			(_stream.readByte() << 16);
+
+		_stream.read(ptr, blockSize);
+		ptr += blockSize;
+	} while (blocksRemaining > 1);
+
+	return sound;
 }
 
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index e0b4230..50a0d1b 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -36,12 +36,12 @@ namespace Chewy {
 
 enum ResourceType {
 	kResourcePCX = 0,		// unused
-	kResourceTBF = 1,		// contained in TGPs
+	kResourceTBF = 1,		// background art, contained in TGPs
 	kResourceTAF = 2,
 	kResourceTFF = 3,
-	kResourceVOC = 4,		// contained in TVPs
+	kResourceVOC = 4,		// speech and SFX, contained in TVPs
 	kResourceTPF = 5,		// unused
-	kResourceTMF = 6,		// unused
+	kResourceTMF = 6,		// music, similar to a MOD file, contained in details.tap
 	kResourceMOD = 7,		// unused
 	kResourceRAW = 8,		// unused
 	kResourceLBM = 9,		// unused
@@ -56,10 +56,10 @@ enum ResourceType {
 	kResourceAAD = 18,		// unused
 	kResourceADS = 19,		// unused
 	kResourceADH = 20,		// used in txt/diah.adh
-	kResourceTGP = 21,		// background, used in back/comic.tgp, back/episode1.tgp and back/gbook.tgp
-	kResourceTVP = 22,		// speech, used in sound/speech.tvp
+	kResourceTGP = 21,		// container for background art, used in back/comic.tgp, back/episode1.tgp and back/gbook.tgp
+	kResourceTVP = 22,		// container for speech, used in sound/speech.tvp
 	kResourceTTP = 23,		// unused
-	kResourceTAP = 24,		// sound effects, music and cutscenes, used in sound/details.tap and cut/cut.tap
+	kResourceTAP = 24,		// container for sound effects, music and cutscenes, used in sound/details.tap and cut/cut.tap
 	kResourceCFO = 25,		// unused
 	kResourceTCF = 26		// error messages, used in err/err_e.tcf (English) and err/err_d.tcf (German)
 };
@@ -67,21 +67,30 @@ enum ResourceType {
 // 4 + 2 + 2 + 4 + 2 + 2 + 768 = 784 bytes
 #define TBF_CHUNK_HEADER_SIZE 784
 
+// Generic chunk header
 struct Chunk {
 	uint32 size;
 	ResourceType type;
 	uint32 pos;	// position of the actual data
 };
 
+// TBF (background) chunk header
 struct TBFChunk {
 	// TBF chunk header
 	// ID (TBF, followed by a zero)
 	uint16 screenMode;
 	uint16 compressionFlag;
-	uint32 unpackedSize;
+	uint32 size;
 	uint16 width;
 	uint16 height;
 	byte palette[3 * 256];
+	byte *data;
+};
+
+// Sound chunk header
+struct SoundChunk {
+	uint32 size;
+	byte *data;
 };
 
 typedef Common::Array<Chunk> ChunkList;
@@ -90,24 +99,35 @@ typedef Common::Array<TBFChunk> TBFChunkList;
 class Resource {
 public:
 	Resource(Common::String filename);
-	~Resource();
+	virtual ~Resource();
 
 	ResourceType getType() const { return _resType; }
 	uint32 getChunkCount() const;
 	Chunk *getChunk(int num);
-	TBFChunk *getTBFChunk(int num);
-	byte *getChunkData(int num);
+	virtual byte *getChunkData(int num);
 
 protected:
 	Common::File _stream;
 	uint16 _chunkCount;
 	ResourceType _resType;
 
-private:
-	void readTBFChunk();
-
 	ChunkList _chunkList;
-	TBFChunkList _tbfChunkList;
+};
+
+class BackgroundResource : public Resource {
+public:
+	BackgroundResource(Common::String filename) : Resource(filename) {}
+	~BackgroundResource() {}
+
+	TBFChunk *getImage(int num);
+};
+
+class SoundResource : public Resource {
+public:
+	SoundResource(Common::String filename) : Resource(filename) {}
+	~SoundResource() {}
+
+	SoundChunk *getSound(int num);
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
index 41f91d0..9ef4df9 100644
--- a/engines/chewy/sound.cpp
+++ b/engines/chewy/sound.cpp
@@ -31,8 +31,8 @@
 namespace Chewy {
 
 Sound::Sound() {
-	_speechRes = new Resource("speech.tvp");
-	_soundRes = new Resource("details.tap");
+	_speechRes = new SoundResource("speech.tvp");
+	_soundRes = new SoundResource("details.tap");
 }
 
 Sound::~Sound() {
@@ -41,16 +41,20 @@ Sound::~Sound() {
 }
 
 void Sound::playSound(int num, bool loop) {
-	Chunk *chunk = _soundRes->getChunk(num);
-	byte *data = _soundRes->getChunkData(num);
+	SoundChunk *sound = _soundRes->getSound(num);
+	byte *data = (byte *)malloc(sound->size);
+	memcpy(data, sound->data, sound->size);
 
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(data,
-		chunk->size, 22050, Audio::FLAG_UNSIGNED,
+		sound->size, 22050, Audio::FLAG_UNSIGNED,
 		DisposeAfterUse::NO),
 		loop ? 0 : 1);
 
 	g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
+
+	delete[] sound->data;
+	delete sound;
 }
 
 void Sound::playMusic(int num, bool loop) {
@@ -72,16 +76,20 @@ void Sound::playMusic(int num, bool loop) {
 }
 
 void Sound::playSpeech(int num) {
-	Chunk *chunk = _speechRes->getChunk(num);
-	byte *data = _speechRes->getChunkData(num);
+	SoundChunk *sound = _speechRes->getSound(num);
+	byte *data = (byte *)malloc(sound->size);
+	memcpy(data, sound->data, sound->size);
 
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(data,
-		chunk->size, 22050, Audio::FLAG_UNSIGNED,
+		sound->size, 22050, Audio::FLAG_UNSIGNED,
 		DisposeAfterUse::NO),
 		1);
 
 	g_engine->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream);
+
+	delete[] sound->data;
+	delete sound;
 }
 
 } // End of namespace Chewy
diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h
index 6537f3e..2361027 100644
--- a/engines/chewy/sound.h
+++ b/engines/chewy/sound.h
@@ -28,7 +28,7 @@
 
 namespace Chewy {
 
-class Resource;
+class SoundResource;
 
 class Sound {
 public:
@@ -44,8 +44,8 @@ private:
 	Audio::SoundHandle _musicHandle;
 	Audio::SoundHandle _speechHandle;
 
-	Resource *_speechRes;
-	Resource *_soundRes;
+	SoundResource *_speechRes;
+	SoundResource *_soundRes;
 };
 
 } // End of namespace Chewy


Commit: a196bfff57a0fb1a5cca9e242125ed2f5cbd018d
    https://github.com/scummvm/scummvm/commit/a196bfff57a0fb1a5cca9e242125ed2f5cbd018d
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:32+03:00

Commit Message:
CHEWY: Add support for encrypted text resources

These are mainly used for error messages

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 298e10b..8d55651 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -37,6 +37,7 @@ Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("play_sound",	WRAP_METHOD(Console, Cmd_PlaySound));
 	registerCmd("play_speech",	WRAP_METHOD(Console, Cmd_PlaySpeech));
 	registerCmd("play_music",	WRAP_METHOD(Console, Cmd_PlayMusic));
+	registerCmd("text",			WRAP_METHOD(Console, Cmd_Text));
 }
 
 Console::~Console() {
@@ -148,4 +149,21 @@ bool Console::Cmd_PlayMusic(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::Cmd_Text(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("Usage: <file> <text number>\n");
+		return true;
+	}
+
+	Common::String filename = argv[1];
+	int resNum = atoi(argv[2]);
+
+	TextResource *res = new TextResource(filename);
+	Common::String str = res->getText(resNum);
+	this->debugPrintf("Text: %s\n", str.c_str());
+	delete res;
+
+	return true;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index 873359d..bca8ea0 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -43,6 +43,7 @@ private:
 	bool Cmd_PlaySound(int argc, const char **argv);
 	bool Cmd_PlaySpeech(int argc, const char **argv);
 	bool Cmd_PlayMusic(int argc, const char **argv);
+	bool Cmd_Text(int argc, const char **argv);
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 1bd9583..b8fba37 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -30,17 +30,37 @@
 namespace Chewy {
 
 Resource::Resource(Common::String filename) {
+	const uint32 headerGeneric = MKTAG('N', 'G', 'S', '\0');
+	const uint32 headerTxtDec  = MKTAG('T', 'C', 'F', '\0');
+	const uint32 headerTxtEnc  = MKTAG('T', 'C', 'F', '\1');
+
 	_stream.open(filename);
-	uint32 magicBytes = MKTAG('N', 'G', 'S', '\0');
-	if (_stream.readUint32BE() != magicBytes)
+
+	uint32 header = _stream.readUint32BE();
+	bool isText = header == headerTxtDec || header == headerTxtEnc;
+
+	if (header != headerGeneric && !isText)
 		error("Invalid resource - %s", filename.c_str());
-	_resType = (ResourceType)_stream.readUint16LE();
+
+	if (isText) {
+		_resType = kResourceTCF;
+		_encrypted = (header == headerTxtEnc);
+	} else {
+		_resType = (ResourceType)_stream.readUint16LE();
+		_encrypted = false;
+	}
+
 	_chunkCount = _stream.readUint16LE();
 
 	for (uint i = 0; i < _chunkCount; i++) {
 		Chunk cur;
 		cur.size = _stream.readUint32LE();
-		cur.type = (ResourceType)_stream.readUint16LE();
+
+		if (!isText)
+			cur.type = (ResourceType)_stream.readUint16LE();
+		else
+			cur.num = _stream.readUint16LE();
+
 		cur.pos = _stream.pos();
 
 		_stream.skip(cur.size);
@@ -57,11 +77,15 @@ uint32 Resource::getChunkCount() const {
 	return _chunkList.size();
 }
 
-Chunk *Resource::getChunk(int num) {
+Chunk *Resource::getChunk(uint num) {
+	assert(num < _chunkList.size());
+
 	return &_chunkList[num];
 }
 
-byte *Resource::getChunkData(int num) {
+byte *Resource::getChunkData(uint num) {
+	assert(num < _chunkList.size());
+
 	Chunk *chunk = &_chunkList[num];
 	byte *data = new byte[chunk->size];
 
@@ -71,7 +95,9 @@ byte *Resource::getChunkData(int num) {
 	return data;
 }
 
-TBFChunk *BackgroundResource::getImage(int num) {
+TBFChunk *BackgroundResource::getImage(uint num) {
+	assert(num < _chunkList.size());
+
 	Chunk *chunk = &_chunkList[num];
 	TBFChunk *tbf = new TBFChunk();
 
@@ -111,7 +137,9 @@ TBFChunk *BackgroundResource::getImage(int num) {
 	return tbf;
 }
 
-SoundChunk *SoundResource::getSound(int num) {
+SoundChunk *SoundResource::getSound(uint num) {
+	assert(num < _chunkList.size());
+
 	Chunk *chunk = &_chunkList[num];
 	SoundChunk *sound = new SoundChunk();
 
@@ -155,4 +183,30 @@ SoundChunk *SoundResource::getSound(int num) {
 	return sound;
 }
 
+Common::String TextResource::getText(uint num) {
+	assert(num < _chunkList.size());
+
+	Chunk *chunk = &_chunkList[num];
+	Common::String str;
+	byte *data = new byte[chunk->size];
+
+	_stream.seek(chunk->pos, SEEK_SET);
+
+	_stream.read(data, chunk->size);
+
+	if (_encrypted) {
+		byte *c = data;
+
+		for (uint i = 0; i < chunk->size; i++) {
+			*c = -(*c);
+			++c;
+		}
+	}
+
+	str = (char *)data;
+	delete[] data;
+
+	return str;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 50a0d1b..cfaa802 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -70,6 +70,7 @@ enum ResourceType {
 // Generic chunk header
 struct Chunk {
 	uint32 size;
+	uint16 num;	// same as the type below, used in chunks where the type is substituted with count
 	ResourceType type;
 	uint32 pos;	// position of the actual data
 };
@@ -103,13 +104,14 @@ public:
 
 	ResourceType getType() const { return _resType; }
 	uint32 getChunkCount() const;
-	Chunk *getChunk(int num);
-	virtual byte *getChunkData(int num);
+	Chunk *getChunk(uint num);
+	virtual byte *getChunkData(uint num);
 
 protected:
 	Common::File _stream;
 	uint16 _chunkCount;
 	ResourceType _resType;
+	byte _encrypted;
 
 	ChunkList _chunkList;
 };
@@ -119,7 +121,7 @@ public:
 	BackgroundResource(Common::String filename) : Resource(filename) {}
 	~BackgroundResource() {}
 
-	TBFChunk *getImage(int num);
+	TBFChunk *getImage(uint num);
 };
 
 class SoundResource : public Resource {
@@ -127,7 +129,15 @@ public:
 	SoundResource(Common::String filename) : Resource(filename) {}
 	~SoundResource() {}
 
-	SoundChunk *getSound(int num);
+	SoundChunk *getSound(uint num);
+};
+
+class TextResource : public Resource {
+public:
+	TextResource(Common::String filename) : Resource(filename) {}
+	~TextResource() {}
+
+	Common::String getText(uint num);
 };
 
 } // End of namespace Chewy


Commit: b60f5023ed8959798b6246e227717cc0ff1e8d44
    https://github.com/scummvm/scummvm/commit/b60f5023ed8959798b6246e227717cc0ff1e8d44
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:37+03:00

Commit Message:
CHEWY: Add a TODO for the currently unhandled resource files

Changed paths:
    engines/chewy/resource.cpp



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index b8fba37..eae3896 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -29,6 +29,23 @@
 
 namespace Chewy {
 
+// Resource files - TODO:
+// ======================
+// back/episode1.gep
+// cut/blende.rnd
+// cut/cut.tap
+// misc/*.taf, room/*.taf
+// misc/exit.eib
+// misc/inventar.iib
+// misc/inventar.sib
+// room/csp.int
+// room/test.rdi
+// txt/*.tff
+// txt/*.tap
+// txt/diah.adh
+// txt/inv_st.s and txt/room_st.s
+// txt/inv_use.idx
+
 Resource::Resource(Common::String filename) {
 	const uint32 headerGeneric = MKTAG('N', 'G', 'S', '\0');
 	const uint32 headerTxtDec  = MKTAG('T', 'C', 'F', '\0');


Commit: f017940ca08e32a206982376df0bdc334acdea55
    https://github.com/scummvm/scummvm/commit/f017940ca08e32a206982376df0bdc334acdea55
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:41+03:00

Commit Message:
CHEWY: Initial work on game videos

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 8d55651..bf7e49c 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -37,6 +37,8 @@ Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("play_sound",	WRAP_METHOD(Console, Cmd_PlaySound));
 	registerCmd("play_speech",	WRAP_METHOD(Console, Cmd_PlaySpeech));
 	registerCmd("play_music",	WRAP_METHOD(Console, Cmd_PlayMusic));
+	registerCmd("play_video",	WRAP_METHOD(Console, Cmd_PlayVideo));
+	registerCmd("video_info",	WRAP_METHOD(Console, Cmd_VideoInfo));
 	registerCmd("text",			WRAP_METHOD(Console, Cmd_Text));
 }
 
@@ -149,6 +151,35 @@ bool Console::Cmd_PlayMusic(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::Cmd_PlayVideo(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("Usage: play_video <number>\n");
+		return true;
+	}
+
+	int resNum = atoi(argv[1]);
+	debugPrintf("TODO: Play video %d", resNum);
+	// TODO
+
+	return true;
+}
+
+bool Console::Cmd_VideoInfo(int argc, const char **argv) {
+	if (argc < 2) {
+		debugPrintf("Usage: video_info <number>\n");
+		return true;
+	}
+
+	int resNum = atoi(argv[1]);
+	VideoResource *res = new VideoResource("cut.tap");
+	VideoChunk *header = res->getVideoHeader(resNum);
+	debugPrintf("Size: %d, %d x %d, %d frames, %d ms frame delay, first frame at %d\n", header->size, header->width, header->height, header->frameCount, header->frameDelay, header->firstFrameOffset);
+	delete header;
+	delete res;
+
+	return true;
+}
+
 bool Console::Cmd_Text(int argc, const char **argv) {
 	if (argc < 2) {
 		debugPrintf("Usage: <file> <text number>\n");
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index bca8ea0..ab8b8de 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -43,6 +43,8 @@ private:
 	bool Cmd_PlaySound(int argc, const char **argv);
 	bool Cmd_PlaySpeech(int argc, const char **argv);
 	bool Cmd_PlayMusic(int argc, const char **argv);
+	bool Cmd_PlayVideo(int argc, const char **argv);
+	bool Cmd_VideoInfo(int argc, const char **argv);
 	bool Cmd_Text(int argc, const char **argv);
 };
 
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index eae3896..6a1b860 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -226,4 +226,25 @@ Common::String TextResource::getText(uint num) {
 	return str;
 }
 
+VideoChunk *VideoResource::getVideoHeader(uint num) {
+	assert(num < _chunkList.size());
+
+	Chunk *chunk = &_chunkList[num];
+	VideoChunk *vid = new VideoChunk();
+
+	_stream.seek(chunk->pos, SEEK_SET);
+
+	if (_stream.readUint32BE() != MKTAG('C', 'F', 'O', '\0'))
+		error("Corrupt video resource");
+
+	vid->size = _stream.readUint32LE();	// always 0
+	vid->frameCount = _stream.readUint16LE();
+	vid->width = _stream.readUint16LE();
+	vid->height = _stream.readUint16LE();
+	vid->frameDelay = _stream.readUint32LE();
+	vid->firstFrameOffset = _stream.readUint32LE();	// always 22
+
+	return vid;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index cfaa802..238f0f2 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -94,6 +94,17 @@ struct SoundChunk {
 	byte *data;
 };
 
+// Video chunk header
+struct VideoChunk {
+	// ID (CFA, followed by a zero)
+	uint32 size;
+	uint16 frameCount;
+	uint16 width;
+	uint16 height;
+	uint32 frameDelay;	// in ms
+	uint32 firstFrameOffset;
+};
+
 typedef Common::Array<Chunk> ChunkList;
 typedef Common::Array<TBFChunk> TBFChunkList;
 
@@ -111,7 +122,7 @@ protected:
 	Common::File _stream;
 	uint16 _chunkCount;
 	ResourceType _resType;
-	byte _encrypted;
+	bool _encrypted;
 
 	ChunkList _chunkList;
 };
@@ -140,6 +151,14 @@ public:
 	Common::String getText(uint num);
 };
 
+class VideoResource : public Resource {
+public:
+	VideoResource(Common::String filename) : Resource(filename) {}
+	~VideoResource() {}
+
+	VideoChunk *getVideoHeader(uint num);
+};
+
 } // End of namespace Chewy
 
 #endif


Commit: 0152b7c47f0eef04bd01ae6e1cb808d25ccdd9a0
    https://github.com/scummvm/scummvm/commit/0152b7c47f0eef04bd01ae6e1cb808d25ccdd9a0
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:45+03:00

Commit Message:
CHEWY: Add initial video (CFO) player

The game's videos are modified FLICs. There are some changes needed
to our FLIC decoder, which are included in a separate commit

Changed paths:
  A engines/chewy/video/cfo_decoder.cpp
  A engines/chewy/video/cfo_decoder.h
    engines/chewy/chewy.cpp
    engines/chewy/console.cpp
    engines/chewy/graphics.cpp
    engines/chewy/graphics.h
    engines/chewy/module.mk
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index b5271d5..b2b8cd1 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -72,6 +72,7 @@ Common::Error ChewyEngine::run() {
 
 	initialize();
 
+	//_graphics->playVideo(0);
 	_graphics->drawImage("episode1.tgp", 0);
 	//_sound->playSpeech(1);
 	//_sound->playSound(1);
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index bf7e49c..deaa1e3 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -157,11 +157,14 @@ bool Console::Cmd_PlayVideo(int argc, const char **argv) {
 		return true;
 	}
 
+	detach();	// close the console
+	
 	int resNum = atoi(argv[1]);
-	debugPrintf("TODO: Play video %d", resNum);
-	// TODO
+	Graphics *g = new Graphics();
+	g->playVideo(resNum);
+	delete g;
 
-	return true;
+	return false;
 }
 
 bool Console::Cmd_VideoInfo(int argc, const char **argv) {
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index c3b29fe..887bb75 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -21,10 +21,12 @@
  */
 
 #include "common/system.h"
+#include "common/events.h"
 #include "graphics/palette.h"
 
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
+#include "chewy/video/cfo_decoder.h"
 
 namespace Chewy {
 
@@ -41,4 +43,43 @@ void Graphics::drawImage(Common::String filename, int imageNum) {
 	delete res;
 }
 
+void Graphics::playVideo(uint num) {
+	CfoDecoder *cfoDecoder = new CfoDecoder();
+	VideoResource *videoResource = new VideoResource("cut.tap");
+	Common::SeekableReadStream *videoStream = videoResource->getVideoStream(num);
+
+	if (!cfoDecoder->loadStream(videoStream)) {
+		delete videoResource;
+		delete cfoDecoder;
+		return;
+	}
+
+	uint16 x = (g_system->getWidth() - cfoDecoder->getWidth()) / 2;
+	uint16 y = (g_system->getHeight() - cfoDecoder->getHeight()) / 2;
+	bool skipVideo = false;
+
+	cfoDecoder->start();
+
+	while (!g_engine->shouldQuit() && !cfoDecoder->endOfVideo() && !skipVideo) {
+		if (cfoDecoder->needsUpdate()) {
+			const ::Graphics::Surface *frame = cfoDecoder->decodeNextFrame();
+			if (frame) {
+				g_system->copyRectToScreen(frame->getPixels(), frame->pitch, x, y, frame->w, frame->h);
+
+				if (cfoDecoder->hasDirtyPalette())
+					g_system->getPaletteManager()->setPalette(cfoDecoder->getPalette(), 0, 256);
+
+				g_system->updateScreen();
+			}
+		}
+
+		Common::Event event;
+		while (g_system->getEventManager()->pollEvent(event)) {
+			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+				skipVideo = true;
+		}
+
+		g_system->delayMillis(10);
+	}
+}
 } // End of namespace Chewy
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index 601b419..c7d303d 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -33,6 +33,7 @@ public:
 	~Graphics() {}
 
 	void drawImage(Common::String filename, int imageNum);
+	void playVideo(uint num);
 private:
 
 };
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index 5b96ab9..2e2535f 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -6,7 +6,8 @@ MODULE_OBJS = \
 	detection.o \
 	graphics.o \
 	resource.o \
-	sound.o
+	sound.o \
+	video/cfo_decoder.o
 
 # This module can be built as a plugin
 ifeq ($(ENABLE_CHEWY), DYNAMIC_PLUGIN)
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 6a1b860..a873edf 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -22,6 +22,7 @@
 
 #include "common/debug.h"
 #include "common/stream.h"
+#include "common/substream.h"
 #include "common/textconsole.h"
 
 #include "chewy/chewy.h"
@@ -247,4 +248,11 @@ VideoChunk *VideoResource::getVideoHeader(uint num) {
 	return vid;
 }
 
+Common::SeekableReadStream *VideoResource::getVideoStream(uint num) {
+	assert(num < _chunkList.size());
+
+	Chunk *chunk = &_chunkList[num];
+	return new Common::SeekableSubReadStream(&_stream, chunk->pos, chunk->pos + chunk->size);
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 238f0f2..d9665ce 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -31,6 +31,7 @@
 #include "common/hashmap.h"
 #include "common/hash-str.h"
 #include "common/random.h"
+#include "common/stream.h"
 
 namespace Chewy {
 
@@ -105,6 +106,11 @@ struct VideoChunk {
 	uint32 firstFrameOffset;
 };
 
+enum VideoFrameType {
+	kVideoFrameNormal = 0xF1FA,
+	kVideoFrameCustom = 0xFAF1
+};
+
 typedef Common::Array<Chunk> ChunkList;
 typedef Common::Array<TBFChunk> TBFChunkList;
 
@@ -157,6 +163,7 @@ public:
 	~VideoResource() {}
 
 	VideoChunk *getVideoHeader(uint num);
+	Common::SeekableReadStream *getVideoStream(uint num);
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
new file mode 100644
index 0000000..99fd665
--- /dev/null
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -0,0 +1,261 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/stream.h"
+#include "video/flic_decoder.h"
+
+#include "chewy/video/cfo_decoder.h"
+
+namespace Chewy {
+
+enum CustomSubChunk {
+	kChunkFadeIn = 0,
+	kChunkFadeOut = 1,
+	kChunkLoadMusic = 2,
+	kChunkLoadRaw = 3,
+	kChunkLoadVoc = 4,
+	kChunkPlayMusic = 5,
+	kChunkPlaySeq = 6,
+	kChunkPlayPattern = 7,
+	kChunkStopMusic = 8,
+	kChunkWaitMusicEnd = 9,
+	kChunkSetMusicVolume = 10,
+	kChunkSetLoopMode = 11,
+	kChunkPlayRaw = 12,
+	kChunkPlayVoc = 13,
+	kChunkSetSoundVolume = 14,
+	kChunkSetChannelVolume = 15,
+	kChunkFreeSoundEffect = 16,
+	kChunkMusicFadeIn = 17,
+	kChunkMusicFadeOut = 18,
+	kChunkSetStero = 19,
+	kChunkSetSpeed = 20,
+	kChunkClearScreen = 21
+};
+
+bool CfoDecoder::loadStream(Common::SeekableReadStream *stream) {
+	close();
+
+	if (stream->readUint32BE() != MKTAG('C', 'F', 'O', '\0'))
+		error("Corrupt video resource");
+
+	stream->readUint32LE();	// always 0
+
+	uint16 frameCount = stream->readUint16LE();
+	uint16 width = stream->readUint16LE();
+	uint16 height = stream->readUint16LE();
+
+	addTrack(new CfoVideoTrack(stream, frameCount, width, height));
+	return true;
+}
+
+CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) :
+	Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) {
+	readHeader();
+}
+
+void CfoDecoder::CfoVideoTrack::readHeader() {
+	_frameDelay = _startFrameDelay = _fileStream->readUint32LE();
+	_offsetFrame1 = _fileStream->readUint32LE();
+	_offsetFrame2 = 0;	// doesn't exist, as CFO videos aren't rewindable
+
+	_fileStream->seek(_offsetFrame1);
+}
+
+#define FRAME_TYPE 0xF1FA
+#define CUSTOM_FRAME_TYPE 0xFAF1
+
+const Graphics::Surface *CfoDecoder::CfoVideoTrack::decodeNextFrame() {
+	uint16 frameType;
+
+	// Read chunk
+	/*uint32 frameSize =*/ _fileStream->readUint32LE();
+	frameType = _fileStream->readUint16LE();
+
+	switch (frameType) {
+	case FRAME_TYPE:
+		handleFrame();
+		break;
+	case CUSTOM_FRAME_TYPE:
+		handleCustomFrame();
+		break;
+	default:
+		error("CfoDecoder::decodeFrame(): unknown main chunk type (type = 0x%02X)", frameType);
+		break;
+	}
+
+	_curFrame++;
+	_nextFrameStartTime += _frameDelay;
+
+	return _surface;
+}
+
+#define FLI_SETPAL 4
+#define FLI_SS2    7
+#define FLI_BRUN   15
+#define FLI_COPY   16
+#define PSTAMP     18
+
+void CfoDecoder::CfoVideoTrack::handleFrame() {
+	uint16 chunkCount = _fileStream->readUint16LE();
+
+	// Read subchunks
+	for (uint32 i = 0; i < chunkCount; ++i) {
+		uint32 frameSize = _fileStream->readUint32LE();
+		uint16 frameType = _fileStream->readUint16LE();
+		uint8 *data = new uint8[frameSize - 6];
+		_fileStream->read(data, frameSize - 6);
+
+		switch (frameType) {
+		case FLI_SETPAL:
+			unpackPalette(data);
+			_dirtyPalette = true;
+			break;
+		case FLI_SS2:
+			decodeDeltaFLC(data);
+			break;
+		case FLI_BRUN:
+			decodeByteRun(data);
+			break;
+		case FLI_COPY:
+			copyFrame(data);
+			break;
+		case PSTAMP:
+			/* PSTAMP - skip for now */
+			break;
+		default:
+			error("FlicDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType);
+			break;
+		}
+
+		delete[] data;
+	}
+}
+
+void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
+	uint16 chunkCount = _fileStream->readUint16LE();
+
+	// Read subchunks
+	for (uint32 i = 0; i < chunkCount; ++i) {
+		uint32 frameSize = _fileStream->readUint32LE();
+		uint16 frameType = _fileStream->readUint16LE();
+		uint8 *data = new uint8[frameSize];
+		_fileStream->read(data, frameSize);
+
+		switch (frameType) {
+		case kChunkFadeIn:
+			warning("kChunkFadeIn");
+			// TODO
+			break;
+		case kChunkFadeOut:
+			warning("kChunkFadeOut");
+			// TODO
+			break;
+		case kChunkLoadMusic:
+			warning("kChunkLoadMusic");
+			// TODO
+			break;
+		case kChunkLoadRaw:
+			warning("kChunkLoadRaw");
+			// TODO
+			break;
+		case kChunkLoadVoc:
+			warning("kChunkLoadVoc");
+			// TODO
+			break;
+		case kChunkPlayMusic:
+			warning("kChunkPlayMusic");
+			break;
+		case kChunkPlaySeq:
+			warning("kChunkPlaySeq");
+			// TODO
+			break;
+		case kChunkPlayPattern:
+			warning("kChunkPlayPattern");
+			// TODO
+			break;
+		case kChunkStopMusic:
+			warning("kChunkStopMusic");
+			// TODO
+			break;
+		case kChunkWaitMusicEnd:
+			warning("kChunkWaitMusicEnd");
+			// TODO
+			break;
+		case kChunkSetMusicVolume:
+			warning("kChunkSetMusicVolume");
+			// TODO
+			break;
+		case kChunkSetLoopMode:
+			warning("kChunkSetLoopMode");
+			// TODO
+			break;
+		case kChunkPlayRaw:
+			warning("kChunkPlayRaw");
+			// TODO
+			break;
+		case kChunkPlayVoc:
+			warning("kChunkPlayVoc");
+			// TODO
+			break;
+		case kChunkSetSoundVolume:
+			warning("kChunkSetSoundVolume");
+			// TODO
+			break;
+		case kChunkSetChannelVolume:
+			warning("kChunkSetChannelVolume");
+			// TODO
+			break;
+		case kChunkFreeSoundEffect:
+			warning("kChunkFreeSoundEffect");
+			// TODO
+			break;
+		case kChunkMusicFadeIn:
+			warning("kChunkMusicFadeIn");
+			// TODO
+			break;
+		case kChunkMusicFadeOut:
+			warning("kChunkMusicFadeOut");
+			// TODO
+			break;
+		case kChunkSetStero:
+			warning("kChunkSetStero");
+			// TODO
+			break;
+		case kChunkSetSpeed:
+			warning("kChunkSetSpeed");
+			// TODO
+			break;
+		case kChunkClearScreen:
+			warning("kChunkClearScreen");
+			// TODO
+			break;
+		default:
+			error("Unknown subchunk: %d", frameType);
+			break;
+		}
+
+		delete[] data;
+	}
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h
new file mode 100644
index 0000000..57c0838
--- /dev/null
+++ b/engines/chewy/video/cfo_decoder.h
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_VIDEO_CFO_DECODER_H
+#define CHEWY_VIDEO_CFO_DECODER_H
+
+
+#include "graphics/surface.h"
+#include "video/flic_decoder.h"
+
+namespace Chewy {
+
+// A FLIC decoder, with a modified header and additional custom frames
+class CfoDecoder : public Video::FlicDecoder {
+public:
+	CfoDecoder() : Video::FlicDecoder() {}
+	virtual ~CfoDecoder() {}
+
+	bool loadStream(Common::SeekableReadStream *stream);
+
+protected:
+	class CfoVideoTrack : public Video::FlicDecoder::FlicVideoTrack {
+	public:
+		CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height);
+		~CfoVideoTrack() {}
+
+		void readHeader();
+
+		bool isRewindable() const { return false; }
+		bool rewind() { return false; }
+
+		const ::Graphics::Surface *decodeNextFrame();
+		void handleFrame();
+		void handleCustomFrame();
+	};
+};
+
+} // End of namespace Chewy
+
+#endif


Commit: 7331bdc6b1f15bc9f5c8e186d4f19923c1c723a4
    https://github.com/scummvm/scummvm/commit/7331bdc6b1f15bc9f5c8e186d4f19923c1c723a4
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:49+03:00

Commit Message:
VIDEO: Allow parts of the FLIC decoder to be overriden by child classes

This is needed by the specialized FLIC video decoder used in the chewy
engine

Changed paths:
    video/flic_decoder.cpp
    video/flic_decoder.h



diff --git a/video/flic_decoder.cpp b/video/flic_decoder.cpp
index 994f47c..a1976e2 100644
--- a/video/flic_decoder.cpp
+++ b/video/flic_decoder.cpp
@@ -85,19 +85,10 @@ void FlicDecoder::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) {
 		((FlicVideoTrack *)track)->copyDirtyRectsToBuffer(dst, pitch);
 }
 
-FlicDecoder::FlicVideoTrack::FlicVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) {
+FlicDecoder::FlicVideoTrack::FlicVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, bool skipHeader) {
 	_fileStream = stream;
 	_frameCount = frameCount;
 
-	_fileStream->readUint16LE();	// flags
-	// Note: The normal delay is a 32-bit integer (dword), whereas the overridden delay is a 16-bit integer (word)
-	// the frame delay is the FLIC "speed", in milliseconds.
-	_frameDelay = _startFrameDelay = _fileStream->readUint32LE();
-
-	_fileStream->seek(80);
-	_offsetFrame1 = _fileStream->readUint32LE();
-	_offsetFrame2 = _fileStream->readUint32LE();
-
 	_surface = new Graphics::Surface();
 	_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
 	_palette = new byte[3 * 256];
@@ -108,8 +99,8 @@ FlicDecoder::FlicVideoTrack::FlicVideoTrack(Common::SeekableReadStream *stream,
 	_nextFrameStartTime = 0;
 	_atRingFrame = false;
 
-	// Seek to the first frame
-	_fileStream->seek(_offsetFrame1);
+	if (!skipHeader)
+		readHeader();
 }
 
 FlicDecoder::FlicVideoTrack::~FlicVideoTrack() {
@@ -120,6 +111,20 @@ FlicDecoder::FlicVideoTrack::~FlicVideoTrack() {
 	delete _surface;
 }
 
+void FlicDecoder::FlicVideoTrack::readHeader() {
+	_fileStream->readUint16LE();	// flags
+	// Note: The normal delay is a 32-bit integer (dword), whereas the overridden delay is a 16-bit integer (word)
+	// the frame delay is the FLIC "speed", in milliseconds.
+	_frameDelay = _startFrameDelay = _fileStream->readUint32LE();
+
+	_fileStream->seek(80);
+	_offsetFrame1 = _fileStream->readUint32LE();
+	_offsetFrame2 = _fileStream->readUint32LE();
+
+	// Seek to the first frame
+	_fileStream->seek(_offsetFrame1);
+}
+
 bool FlicDecoder::FlicVideoTrack::endOfTrack() const {
 	return getCurFrame() >= getFrameCount() - 1;
 }
@@ -158,76 +163,18 @@ Graphics::PixelFormat FlicDecoder::FlicVideoTrack::getPixelFormat() const {
 
 const Graphics::Surface *FlicDecoder::FlicVideoTrack::decodeNextFrame() {
 	// Read chunk
-	uint32 frameSize = _fileStream->readUint32LE();
+	/*uint32 frameSize = */ _fileStream->readUint32LE();
 	uint16 frameType = _fileStream->readUint16LE();
-	uint16 chunkCount = 0;
 
 	switch (frameType) {
 	case FRAME_TYPE:
-		{
-			chunkCount = _fileStream->readUint16LE();
-			// Note: The overridden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
-			// the frame delay is the FLIC "speed", in milliseconds.
-			uint16 newFrameDelay = _fileStream->readUint16LE();	// "speed", in milliseconds
-			if (newFrameDelay > 0)
-				_frameDelay = newFrameDelay;
-
-			_fileStream->readUint16LE();	// reserved, always 0
-			uint16 newWidth = _fileStream->readUint16LE();
-			uint16 newHeight = _fileStream->readUint16LE();
-
-			if ((newWidth != 0) || (newHeight != 0)) {
-				if (newWidth == 0)
-					newWidth = _surface->w;
-				if (newHeight == 0)
-					newHeight = _surface->h;
-
-				_surface->free();
-				delete _surface;
-				_surface = new Graphics::Surface();
-				_surface->create(newWidth, newHeight, Graphics::PixelFormat::createFormatCLUT8());
-			}
-		}
+		handleFrame();
 		break;
 	default:
 		error("FlicDecoder::decodeFrame(): unknown main chunk type (type = 0x%02X)", frameType);
 		break;
 	 }
 
-	// Read subchunks
-	if (frameType == FRAME_TYPE) {
-		for (uint32 i = 0; i < chunkCount; ++i) {
-			frameSize = _fileStream->readUint32LE();
-			frameType = _fileStream->readUint16LE();
-			uint8 *data = new uint8[frameSize - 6];
-			_fileStream->read(data, frameSize - 6);
-
-			switch (frameType) {
-			case FLI_SETPAL:
-				unpackPalette(data);
-				_dirtyPalette = true;
-				break;
-			case FLI_SS2:
-				decodeDeltaFLC(data);
-				break;
-			case FLI_BRUN:
-				decodeByteRun(data);
-				break;
-			case FLI_COPY:
-				copyFrame(data);
-				break;
-			case PSTAMP:
-				/* PSTAMP - skip for now */
-				break;
-			default:
-				error("FlicDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType);
-				break;
-			 }
-
-			delete[] data;
-		}
-	}
-
 	_curFrame++;
 	_nextFrameStartTime += _frameDelay;
 
@@ -240,6 +187,63 @@ const Graphics::Surface *FlicDecoder::FlicVideoTrack::decodeNextFrame() {
 	return _surface;
 }
 
+void FlicDecoder::FlicVideoTrack::handleFrame() {
+	uint16 chunkCount = _fileStream->readUint16LE();
+	// Note: The overridden delay is a 16-bit integer (word), whereas the normal delay is a 32-bit integer (dword)
+	// the frame delay is the FLIC "speed", in milliseconds.
+	uint16 newFrameDelay = _fileStream->readUint16LE();	// "speed", in milliseconds
+	if (newFrameDelay > 0)
+		_frameDelay = newFrameDelay;
+
+	_fileStream->readUint16LE();	// reserved, always 0
+	uint16 newWidth = _fileStream->readUint16LE();
+	uint16 newHeight = _fileStream->readUint16LE();
+
+	if ((newWidth != 0) || (newHeight != 0)) {
+		if (newWidth == 0)
+			newWidth = _surface->w;
+		if (newHeight == 0)
+			newHeight = _surface->h;
+
+		_surface->free();
+		delete _surface;
+		_surface = new Graphics::Surface();
+		_surface->create(newWidth, newHeight, Graphics::PixelFormat::createFormatCLUT8());
+	}
+
+	// Read subchunks
+	for (uint32 i = 0; i < chunkCount; ++i) {
+		uint32 frameSize = _fileStream->readUint32LE();
+		uint16 frameType = _fileStream->readUint16LE();
+		uint8 *data = new uint8[frameSize - 6];
+		_fileStream->read(data, frameSize - 6);
+
+		switch (frameType) {
+		case FLI_SETPAL:
+			unpackPalette(data);
+			_dirtyPalette = true;
+			break;
+		case FLI_SS2:
+			decodeDeltaFLC(data);
+			break;
+		case FLI_BRUN:
+			decodeByteRun(data);
+			break;
+		case FLI_COPY:
+			copyFrame(data);
+			break;
+		case PSTAMP:
+			/* PSTAMP - skip for now */
+			break;
+		default:
+			error("FlicDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType);
+			break;
+		}
+
+		delete[] data;
+	}
+}
+
 void FlicDecoder::FlicVideoTrack::copyDirtyRectsToBuffer(uint8 *dst, uint pitch) {
 	for (Common::List<Common::Rect>::const_iterator it = _dirtyRects.begin(); it != _dirtyRects.end(); ++it) {
 		for (int y = (*it).top; y < (*it).bottom; ++y) {
diff --git a/video/flic_decoder.h b/video/flic_decoder.h
index 1769e1e..445e474 100644
--- a/video/flic_decoder.h
+++ b/video/flic_decoder.h
@@ -42,6 +42,7 @@ namespace Video {
  * Decoder for FLIC videos.
  *
  * Video decoder used in engines:
+ *  - chewy
  *  - tucker
  */
 class FlicDecoder : public VideoDecoder {
@@ -49,21 +50,23 @@ public:
 	FlicDecoder();
 	virtual ~FlicDecoder();
 
-	bool loadStream(Common::SeekableReadStream *stream);
+	virtual bool loadStream(Common::SeekableReadStream *stream);
 
 	const Common::List<Common::Rect> *getDirtyRects() const;
 	void clearDirtyRects();
 	void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
 
-private:
+protected:
 	class FlicVideoTrack : public VideoTrack {
 	public:
-		FlicVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height);
+		FlicVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, bool skipHeader = false);
 		~FlicVideoTrack();
 
+		virtual void readHeader();
+
 		bool endOfTrack() const;
-		bool isRewindable() const { return true; }
-		bool rewind();
+		virtual bool isRewindable() const { return true; }
+		virtual bool rewind();
 
 		uint16 getWidth() const;
 		uint16 getHeight() const;
@@ -71,7 +74,8 @@ private:
 		int getCurFrame() const { return _curFrame; }
 		int getFrameCount() const { return _frameCount; }
 		uint32 getNextFrameStartTime() const { return _nextFrameStartTime; }
-		const Graphics::Surface *decodeNextFrame();
+		virtual const Graphics::Surface *decodeNextFrame();
+		virtual void handleFrame();
 		const byte *getPalette() const { _dirtyPalette = false; return _palette; }
 		bool hasDirtyPalette() const { return _dirtyPalette; }
 
@@ -79,7 +83,7 @@ private:
 		void clearDirtyRects() { _dirtyRects.clear(); }
 		void copyDirtyRectsToBuffer(uint8 *dst, uint pitch);
 
-	private:
+	protected:
 		Common::SeekableReadStream *_fileStream;
 		Graphics::Surface *_surface;
 


Commit: ecc212a31ab94e1abda628217eacff9ac6f39948
    https://github.com/scummvm/scummvm/commit/ecc212a31ab94e1abda628217eacff9ac6f39948
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:53+03:00

Commit Message:
CHEWY: Properly close videos when they end

Changed paths:
    engines/chewy/graphics.cpp



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 887bb75..fda46a3 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -81,5 +81,8 @@ void Graphics::playVideo(uint num) {
 
 		g_system->delayMillis(10);
 	}
+
+	cfoDecoder->close();
 }
+
 } // End of namespace Chewy


Commit: 7234574370d20684263e5e4f635348d161b8ce3a
    https://github.com/scummvm/scummvm/commit/7234574370d20684263e5e4f635348d161b8ce3a
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:33:57+03:00

Commit Message:
CHEWY: Add support for sound effects in videos

Changed paths:
    engines/chewy/resource.cpp
    engines/chewy/video/cfo_decoder.cpp
    engines/chewy/video/cfo_decoder.h



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index a873edf..23ac5c2 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -34,7 +34,6 @@ namespace Chewy {
 // ======================
 // back/episode1.gep
 // cut/blende.rnd
-// cut/cut.tap
 // misc/*.taf, room/*.taf
 // misc/exit.eib
 // misc/inventar.iib
diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 99fd665..bfdf065 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -20,7 +20,12 @@
  *
  */
 
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/raw.h"
 #include "common/stream.h"
+#include "common/system.h"
+#include "engines/engine.h"
 #include "video/flic_decoder.h"
 
 #include "chewy/video/cfo_decoder.h"
@@ -47,7 +52,7 @@ enum CustomSubChunk {
 	kChunkFreeSoundEffect = 16,
 	kChunkMusicFadeIn = 17,
 	kChunkMusicFadeOut = 18,
-	kChunkSetStero = 19,
+	kChunkSetBalance = 19,
 	kChunkSetSpeed = 20,
 	kChunkClearScreen = 21
 };
@@ -71,6 +76,19 @@ bool CfoDecoder::loadStream(Common::SeekableReadStream *stream) {
 CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) :
 	Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) {
 	readHeader();
+
+	for (int i = 0; i < MAX_SOUND_EFFECTS; i++) {
+		_soundEffects[i] = nullptr;
+		_soundEffectSize[i] = 0;
+	}
+}
+
+CfoDecoder::CfoVideoTrack::~CfoVideoTrack() {
+	g_engine->_mixer->stopAll();
+
+	for (int i = 0; i < MAX_SOUND_EFFECTS; i++) {
+		delete[] _soundEffects[i];
+	}
 }
 
 void CfoDecoder::CfoVideoTrack::readHeader() {
@@ -154,107 +172,145 @@ void CfoDecoder::CfoVideoTrack::handleFrame() {
 void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 	uint16 chunkCount = _fileStream->readUint16LE();
 
+	uint16 delay, number, channel, volume, repeat, balance;
+	Audio::AudioStream *stream;
+
 	// Read subchunks
 	for (uint32 i = 0; i < chunkCount; ++i) {
 		uint32 frameSize = _fileStream->readUint32LE();
 		uint16 frameType = _fileStream->readUint16LE();
-		uint8 *data = new uint8[frameSize];
-		_fileStream->read(data, frameSize);
 
 		switch (frameType) {
 		case kChunkFadeIn:
-			warning("kChunkFadeIn");
+			delay = _fileStream->readUint16LE();
+
+			warning("kChunkFadeIn, delay %d", delay);
 			// TODO
 			break;
 		case kChunkFadeOut:
-			warning("kChunkFadeOut");
+			delay = _fileStream->readUint16LE();
+
+			warning("kChunkFadeOut, delay %d", delay);
 			// TODO
 			break;
 		case kChunkLoadMusic:
 			warning("kChunkLoadMusic");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkLoadRaw:
-			warning("kChunkLoadRaw");
-			// TODO
+			error("Unused chunk kChunkLoadRaw found");
 			break;
 		case kChunkLoadVoc:
-			warning("kChunkLoadVoc");
-			// TODO
+			number = _fileStream->readUint16LE();
+			assert(number < MAX_SOUND_EFFECTS);
+			delete[] _soundEffects[number];
+
+			_soundEffectSize[number] = frameSize - 2;
+			_soundEffects[number] = (byte *)malloc(frameSize - 2);
+			_fileStream->read(_soundEffects[number], frameSize - 2);
 			break;
 		case kChunkPlayMusic:
 			warning("kChunkPlayMusic");
+			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkPlaySeq:
 			warning("kChunkPlaySeq");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkPlayPattern:
 			warning("kChunkPlayPattern");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkStopMusic:
-			warning("kChunkStopMusic");
-			// TODO
+			g_engine->_mixer->stopHandle(_musicHandle);
 			break;
 		case kChunkWaitMusicEnd:
-			warning("kChunkWaitMusicEnd");
-			// TODO
+			do {
+				g_system->delayMillis(10);
+			} while (g_engine->_mixer->isSoundHandleActive(_musicHandle));
 			break;
 		case kChunkSetMusicVolume:
-			warning("kChunkSetMusicVolume");
-			// TODO
+			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
+
+			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType, volume);
 			break;
 		case kChunkSetLoopMode:
 			warning("kChunkSetLoopMode");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkPlayRaw:
-			warning("kChunkPlayRaw");
-			// TODO
+			error("Unused chunk kChunkPlayRaw found");
 			break;
 		case kChunkPlayVoc:
-			warning("kChunkPlayVoc");
-			// TODO
+			number = _fileStream->readUint16LE();
+			channel = _fileStream->readUint16LE();
+			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
+			repeat = _fileStream->readUint16LE();
+			assert(number < MAX_SOUND_EFFECTS);
+			assert(channel < MAX_SOUND_EFFECTS);
+
+			stream = Audio::makeLoopingAudioStream(
+				Audio::makeRawStream(_soundEffects[number],
+				_soundEffectSize[number], 22050, Audio::FLAG_UNSIGNED,
+				DisposeAfterUse::NO),
+				(repeat == 0) ? 1 : repeat);
+
+			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
+			g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream);
 			break;
 		case kChunkSetSoundVolume:
-			warning("kChunkSetSoundVolume");
-			// TODO
+			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
+
+			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
 			break;
 		case kChunkSetChannelVolume:
-			warning("kChunkSetChannelVolume");
-			// TODO
+			channel = _fileStream->readUint16LE();
+			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
+			assert(channel < MAX_SOUND_EFFECTS);
+
+			g_engine->_mixer->setChannelVolume(_soundHandle[channel], volume);
 			break;
 		case kChunkFreeSoundEffect:
-			warning("kChunkFreeSoundEffect");
-			// TODO
+			number = _fileStream->readUint16LE();
+			assert(number < MAX_SOUND_EFFECTS);
+
+			delete[] _soundEffects[number];
+			_soundEffects[number] = nullptr;
 			break;
 		case kChunkMusicFadeIn:
 			warning("kChunkMusicFadeIn");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkMusicFadeOut:
 			warning("kChunkMusicFadeOut");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
-		case kChunkSetStero:
-			warning("kChunkSetStero");
-			// TODO
+		case kChunkSetBalance:
+			channel = _fileStream->readUint16LE();
+			balance = (_fileStream->readUint16LE() * 2) - 127;
+			assert(channel < MAX_SOUND_EFFECTS);
+
+			g_engine->_mixer->setChannelBalance(_soundHandle[channel], balance);
 			break;
 		case kChunkSetSpeed:
 			warning("kChunkSetSpeed");
 			// TODO
+			_fileStream->skip(frameSize);
 			break;
 		case kChunkClearScreen:
-			warning("kChunkClearScreen");
-			// TODO
+			g_system->fillScreen(0);
 			break;
 		default:
 			error("Unknown subchunk: %d", frameType);
 			break;
 		}
-
-		delete[] data;
 	}
 }
 
diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h
index 57c0838..9150d68 100644
--- a/engines/chewy/video/cfo_decoder.h
+++ b/engines/chewy/video/cfo_decoder.h
@@ -23,12 +23,14 @@
 #ifndef CHEWY_VIDEO_CFO_DECODER_H
 #define CHEWY_VIDEO_CFO_DECODER_H
 
-
+#include "audio/mixer.h"
 #include "graphics/surface.h"
 #include "video/flic_decoder.h"
 
 namespace Chewy {
 
+#define MAX_SOUND_EFFECTS 10
+
 // A FLIC decoder, with a modified header and additional custom frames
 class CfoDecoder : public Video::FlicDecoder {
 public:
@@ -37,11 +39,11 @@ public:
 
 	bool loadStream(Common::SeekableReadStream *stream);
 
-protected:
+private:
 	class CfoVideoTrack : public Video::FlicDecoder::FlicVideoTrack {
 	public:
 		CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height);
-		~CfoVideoTrack() {}
+		virtual ~CfoVideoTrack();
 
 		void readHeader();
 
@@ -49,8 +51,15 @@ protected:
 		bool rewind() { return false; }
 
 		const ::Graphics::Surface *decodeNextFrame();
+
+	private:
 		void handleFrame();
 		void handleCustomFrame();
+
+		Audio::SoundHandle _musicHandle;
+		Audio::SoundHandle _soundHandle[MAX_SOUND_EFFECTS];
+		byte *_soundEffects[MAX_SOUND_EFFECTS];
+		uint32 _soundEffectSize[MAX_SOUND_EFFECTS];
 	};
 };
 


Commit: 1de9019665d8e1d2791684ae84d4ca45f652bb38
    https://github.com/scummvm/scummvm/commit/1de9019665d8e1d2791684ae84d4ca45f652bb38
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:01+03:00

Commit Message:
CHEWY: Remove some unused CFO video custom sub chunks

Changed paths:
    engines/chewy/chewy.cpp
    engines/chewy/video/cfo_decoder.cpp
    engines/chewy/video/cfo_decoder.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index b2b8cd1..e5dd7ec 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -72,6 +72,11 @@ Common::Error ChewyEngine::run() {
 
 	initialize();
 
+	/*for (uint i = 0; i < 161; i++) {
+		debug("Video %d", i);
+		_graphics->playVideo(i);
+	}*/
+
 	//_graphics->playVideo(0);
 	_graphics->drawImage("episode1.tgp", 0);
 	//_sound->playSpeech(1);
diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index bfdf065..9ec11cc 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -33,27 +33,27 @@
 namespace Chewy {
 
 enum CustomSubChunk {
-	kChunkFadeIn = 0,
+	kChunkFadeIn = 0,				// unused
 	kChunkFadeOut = 1,
 	kChunkLoadMusic = 2,
-	kChunkLoadRaw = 3,
+	kChunkLoadRaw = 3,				// unused
 	kChunkLoadVoc = 4,
 	kChunkPlayMusic = 5,
-	kChunkPlaySeq = 6,
-	kChunkPlayPattern = 7,
+	kChunkPlaySeq = 6,				// unused
+	kChunkPlayPattern = 7,			// unused
 	kChunkStopMusic = 8,
 	kChunkWaitMusicEnd = 9,
 	kChunkSetMusicVolume = 10,
-	kChunkSetLoopMode = 11,
-	kChunkPlayRaw = 12,
+	kChunkSetLoopMode = 11,			// unused
+	kChunkPlayRaw = 12,				// unused
 	kChunkPlayVoc = 13,
 	kChunkSetSoundVolume = 14,
 	kChunkSetChannelVolume = 15,
 	kChunkFreeSoundEffect = 16,
-	kChunkMusicFadeIn = 17,
+	kChunkMusicFadeIn = 17,			// unused
 	kChunkMusicFadeOut = 18,
 	kChunkSetBalance = 19,
-	kChunkSetSpeed = 20,
+	kChunkSetSpeed = 20,			// unused
 	kChunkClearScreen = 21
 };
 
@@ -182,18 +182,17 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 
 		switch (frameType) {
 		case kChunkFadeIn:
-			delay = _fileStream->readUint16LE();
-
-			warning("kChunkFadeIn, delay %d", delay);
-			// TODO
+			error("Unused chunk kChunkFadeIn found");
 			break;
 		case kChunkFadeOut:
+			// Used in video 0
 			delay = _fileStream->readUint16LE();
 
 			warning("kChunkFadeOut, delay %d", delay);
 			// TODO
 			break;
 		case kChunkLoadMusic:
+			// Used in videos 0, 18, 34, 71
 			warning("kChunkLoadMusic");
 			// TODO
 			_fileStream->skip(frameSize);
@@ -211,19 +210,16 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			_fileStream->read(_soundEffects[number], frameSize - 2);
 			break;
 		case kChunkPlayMusic:
+			// Used in videos 0, 18, 34, 71
 			warning("kChunkPlayMusic");
 			// TODO
 			_fileStream->skip(frameSize);
 			break;
 		case kChunkPlaySeq:
-			warning("kChunkPlaySeq");
-			// TODO
-			_fileStream->skip(frameSize);
+			error("Unused chunk kChunkPlaySeq found");
 			break;
 		case kChunkPlayPattern:
-			warning("kChunkPlayPattern");
-			// TODO
-			_fileStream->skip(frameSize);
+			error("Unused chunk kChunkPlayPattern found");
 			break;
 		case kChunkStopMusic:
 			g_engine->_mixer->stopHandle(_musicHandle);
@@ -239,9 +235,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType, volume);
 			break;
 		case kChunkSetLoopMode:
-			warning("kChunkSetLoopMode");
-			// TODO
-			_fileStream->skip(frameSize);
+			error("Unused chunk kChunkSetLoopMode found");
 			break;
 		case kChunkPlayRaw:
 			error("Unused chunk kChunkPlayRaw found");
@@ -283,11 +277,10 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			_soundEffects[number] = nullptr;
 			break;
 		case kChunkMusicFadeIn:
-			warning("kChunkMusicFadeIn");
-			// TODO
-			_fileStream->skip(frameSize);
+			error("Unused chunk kChunkMusicFadeIn found");
 			break;
 		case kChunkMusicFadeOut:
+			// Used in videos 0, 71
 			warning("kChunkMusicFadeOut");
 			// TODO
 			_fileStream->skip(frameSize);
@@ -300,9 +293,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			g_engine->_mixer->setChannelBalance(_soundHandle[channel], balance);
 			break;
 		case kChunkSetSpeed:
-			warning("kChunkSetSpeed");
-			// TODO
-			_fileStream->skip(frameSize);
+			error("Unused chunk kChunkSetSpeed found");
 			break;
 		case kChunkClearScreen:
 			g_system->fillScreen(0);
diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h
index 9150d68..4396205 100644
--- a/engines/chewy/video/cfo_decoder.h
+++ b/engines/chewy/video/cfo_decoder.h
@@ -29,7 +29,7 @@
 
 namespace Chewy {
 
-#define MAX_SOUND_EFFECTS 10
+#define MAX_SOUND_EFFECTS 14
 
 // A FLIC decoder, with a modified header and additional custom frames
 class CfoDecoder : public Video::FlicDecoder {


Commit: 94a942755e745bc3553b3d8cc83e533688d867fa
    https://github.com/scummvm/scummvm/commit/94a942755e745bc3553b3d8cc83e533688d867fa
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:05+03:00

Commit Message:
CHEWY: Initial support for game sprites

Changed paths:
    engines/chewy/chewy.cpp
    engines/chewy/graphics.cpp
    engines/chewy/graphics.h
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index e5dd7ec..94cbee4 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -79,22 +79,35 @@ Common::Error ChewyEngine::run() {
 
 	//_graphics->playVideo(0);
 	_graphics->drawImage("episode1.tgp", 0);
+	_graphics->showCursor();
+	_graphics->setCursor(0);
 	//_sound->playSpeech(1);
 	//_sound->playSound(1);
 	//_sound->playMusic(2);
 
 	// Run a dummy loop
 	Common::Event event;
+	uint curCursor = 0;
+	const uint maxCursors = 41;
 
 	while (!shouldQuit()) {
 		while (g_system->getEventManager()->pollEvent(event)) {
 			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
 				g_engine->quitGame();
+			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_SPACE) || event.type == Common::EVENT_RBUTTONUP) {
+				curCursor++;
+				if (curCursor == maxCursors)
+					curCursor = 0;
+				_graphics->setCursor(curCursor);
+			}
+
 			if (event.type == Common::EVENT_KEYDOWN && event.kbd.flags & Common::KBD_CTRL && event.kbd.keycode == Common::KEYCODE_d)
 				_console->attach();
 		}
 
 		_console->onFrame();
+
+		g_system->updateScreen();
 		g_system->delayMillis(10);
 	}
 
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index fda46a3..84e6002 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -22,6 +22,7 @@
 
 #include "common/system.h"
 #include "common/events.h"
+#include "graphics/cursorman.h"
 #include "graphics/palette.h"
 
 #include "chewy/graphics.h"
@@ -85,4 +86,23 @@ void Graphics::playVideo(uint num) {
 	cfoDecoder->close();
 }
 
+void Graphics::setCursor(uint num) {
+	SpriteResource *res = new SpriteResource("cursor.taf");
+	TAFChunk *cursor = res->getSprite(num);
+
+	CursorMan.replaceCursor(cursor->data, cursor->width, cursor->height, 0, 0, 0);
+
+	delete[] cursor->data;
+	delete cursor;
+	delete res;
+}
+
+void Graphics::showCursor() {
+	CursorMan.showMouse(true);
+}
+
+void Graphics::hideCursor() {
+	CursorMan.showMouse(false);
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index c7d303d..64c4255 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -34,6 +34,9 @@ public:
 
 	void drawImage(Common::String filename, int imageNum);
 	void playVideo(uint num);
+	void setCursor(uint num);
+	void showCursor();
+	void hideCursor();
 private:
 
 };
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 23ac5c2..13bd9d2 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -50,18 +50,23 @@ Resource::Resource(Common::String filename) {
 	const uint32 headerGeneric = MKTAG('N', 'G', 'S', '\0');
 	const uint32 headerTxtDec  = MKTAG('T', 'C', 'F', '\0');
 	const uint32 headerTxtEnc  = MKTAG('T', 'C', 'F', '\1');
+	const uint32 headerSprite  = MKTAG('T', 'A', 'F', '\0');
 
 	_stream.open(filename);
 
 	uint32 header = _stream.readUint32BE();
-	bool isText = header == headerTxtDec || header == headerTxtEnc;
+	bool isText = (header == headerTxtDec || header == headerTxtEnc);
+	bool isSprite = (header == headerSprite);
 
-	if (header != headerGeneric && !isText)
+	if (header != headerGeneric && !isSprite && !isText)
 		error("Invalid resource - %s", filename.c_str());
 
 	if (isText) {
 		_resType = kResourceTCF;
 		_encrypted = (header == headerTxtEnc);
+	} else if (isSprite) {
+		initSprite(filename);
+		return;
 	} else {
 		_resType = (ResourceType)_stream.readUint16LE();
 		_encrypted = false;
@@ -112,6 +117,83 @@ byte *Resource::getChunkData(uint num) {
 	return data;
 }
 
+void Resource::initSprite(Common::String filename) {
+	uint16 screenMode;;
+	uint32 nextSpriteOffset;
+
+	// TAF (sprite) resources are much different than the rest, so we have a
+	// separate initializer for them here
+
+	_resType = kResourceTAF;
+	_encrypted = false;
+	screenMode = _stream.readUint16LE();
+	_chunkCount = _stream.readUint16LE();
+	_stream.skip(4);		// total size of all sprites
+	_stream.skip(3 * 256);	// palette
+	nextSpriteOffset = _stream.readUint32LE();
+	_stream.skip(2 + 1);	// correction table, padding
+	if ((int32)nextSpriteOffset != _stream.pos())
+		error("Invalid sprite resource - %s", filename.c_str());
+
+	for (uint i = 0; i < _chunkCount; i++) {
+		Chunk cur;
+
+		cur.pos = _stream.pos();
+		cur.type = kResourceTAF;
+
+		_stream.skip(2 + 2 + 2);	// compression flag, width, height
+		uint32 nextSpriteOffset = _stream.readUint32LE();
+		uint32 spriteImageOffset = _stream.readUint32LE();
+		_stream.skip(1);	// padding
+
+		if ((int32)spriteImageOffset != _stream.pos())
+			error("Invalid sprite resource - %s", filename.c_str());
+
+		cur.size = nextSpriteOffset - cur.pos - 15; // 15 = sizeof(TAFChunk)
+
+		_stream.skip(cur.size);
+		_chunkList.push_back(cur);
+	}
+}
+
+void Resource::unpackRLE(byte *buffer, uint32 compressedSize, uint32 uncompressedSize) {
+	// Compressed images are packed using a very simple RLE compression
+	byte count;
+	byte value;
+	uint32 outPos = 0;
+
+	for (uint i = 0; i < (compressedSize) / 2 && outPos < uncompressedSize; i++) {
+		count = _stream.readByte();
+		value = _stream.readByte();
+		for (byte j = 0; j < count; j++) {
+			buffer[outPos++] = value;
+		}
+	}
+}
+
+TAFChunk *SpriteResource::getSprite(uint num) {
+	assert(num < _chunkList.size());
+
+	Chunk *chunk = &_chunkList[num];
+	TAFChunk *taf = new TAFChunk();
+
+	_stream.seek(chunk->pos, SEEK_SET);
+
+	taf->compressionFlag = _stream.readUint16LE();
+	taf->width = _stream.readUint16LE();
+	taf->height = _stream.readUint16LE();
+	_stream.skip(4 + 4 + 1);	// nextSpriteOffset, spriteImageOffset, padding
+
+	taf->data = new byte[taf->width * taf->height];
+
+	if (!taf->compressionFlag)
+		_stream.read(taf->data, chunk->size);
+	else
+		unpackRLE(taf->data, chunk->size, taf->width * taf->height);
+
+	return taf;
+}
+
 TBFChunk *BackgroundResource::getImage(uint num) {
 	assert(num < _chunkList.size());
 
@@ -133,23 +215,10 @@ TBFChunk *BackgroundResource::getImage(uint num) {
 
 	tbf->data = new byte[tbf->size];
 
-	if (!tbf->compressionFlag) {
+	if (!tbf->compressionFlag)
 		_stream.read(tbf->data, chunk->size);
-	}
-	else {
-		// Compressed images are packed using a very simple RLE compression
-		byte count;
-		byte value;
-		uint32 outPos = 0;
-
-		for (uint i = 0; i < (chunk->size) / 2 && outPos < tbf->size; i++) {
-			count = _stream.readByte();
-			value = _stream.readByte();
-			for (byte j = 0; j < count; j++) {
-				tbf->data[outPos++] = value;
-			}
-		}
-	}
+	else
+		unpackRLE(tbf->data, chunk->size, tbf->size);
 
 	return tbf;
 }
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index d9665ce..b869840 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -65,9 +65,6 @@ enum ResourceType {
 	kResourceTCF = 26		// error messages, used in err/err_e.tcf (English) and err/err_d.tcf (German)
 };
 
-// 4 + 2 + 2 + 4 + 2 + 2 + 768 = 784 bytes
-#define TBF_CHUNK_HEADER_SIZE 784
-
 // Generic chunk header
 struct Chunk {
 	uint32 size;
@@ -89,6 +86,30 @@ struct TBFChunk {
 	byte *data;
 };
 
+// TAF (sprite) chunk header
+/*struct TAFHeader {
+	// TAF chunk header
+	// ID (TAF, followed by a zero)
+	uint16 screenMode;
+	uint16 spriteCount;
+	uint32 size;	// total size (width * height) of all sprites
+	byte palette[3 * 256];
+	uint32 nextSpriteOffset;
+	uint16 correctionTable;
+	// 1 byte padding
+};*/
+
+// TAF (sprite) image data chunk header - 15 bytes
+struct TAFChunk {
+	uint16 compressionFlag;
+	uint16 width;
+	uint16 height;
+	// 4 bytes next sprite offset
+	// 4 bytes sprite image offset
+	// 1 byte padding
+	byte *data;
+};
+
 // Sound chunk header
 struct SoundChunk {
 	uint32 size;
@@ -125,6 +146,9 @@ public:
 	virtual byte *getChunkData(uint num);
 
 protected:
+	void initSprite(Common::String filename);
+	void unpackRLE(byte *buffer, uint32 compressedSize, uint32 uncompressedSize);
+
 	Common::File _stream;
 	uint16 _chunkCount;
 	ResourceType _resType;
@@ -133,6 +157,14 @@ protected:
 	ChunkList _chunkList;
 };
 
+class SpriteResource : public Resource {
+public:
+	SpriteResource(Common::String filename) : Resource(filename) {}
+	~SpriteResource() {}
+
+	TAFChunk *getSprite(uint num);
+};
+
 class BackgroundResource : public Resource {
 public:
 	BackgroundResource(Common::String filename) : Resource(filename) {}


Commit: 8767b44fe0e216145e6f4218966b604e158f912e
    https://github.com/scummvm/scummvm/commit/8767b44fe0e216145e6f4218966b604e158f912e
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:09+03:00

Commit Message:
CHEWY: Initial work on cursor animations

Changed paths:
    engines/chewy/chewy.cpp
    engines/chewy/chewy.h
    engines/chewy/graphics.cpp
    engines/chewy/graphics.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 94cbee4..35575e1 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -63,6 +63,9 @@ void ChewyEngine::initialize() {
 	_console = new Console(this);
 	_graphics = new Graphics();
 	_sound = new Sound();
+
+	_curCursor = 0;
+	_elapsedFrames = 0;
 }
 
 Common::Error ChewyEngine::run() {
@@ -86,29 +89,26 @@ Common::Error ChewyEngine::run() {
 	//_sound->playMusic(2);
 
 	// Run a dummy loop
-	Common::Event event;
-	uint curCursor = 0;
-	const uint maxCursors = 41;
-
 	while (!shouldQuit()) {
-		while (g_system->getEventManager()->pollEvent(event)) {
-			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP)
+		while (g_system->getEventManager()->pollEvent(_event)) {
+			if (_event.type == Common::EVENT_KEYDOWN && _event.kbd.keycode == Common::KEYCODE_ESCAPE)
 				g_engine->quitGame();
-			if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_SPACE) || event.type == Common::EVENT_RBUTTONUP) {
-				curCursor++;
-				if (curCursor == maxCursors)
-					curCursor = 0;
-				_graphics->setCursor(curCursor);
-			}
-
-			if (event.type == Common::EVENT_KEYDOWN && event.kbd.flags & Common::KBD_CTRL && event.kbd.keycode == Common::KEYCODE_d)
+			if ((_event.type == Common::EVENT_KEYDOWN && _event.kbd.keycode == Common::KEYCODE_SPACE) || _event.type == Common::EVENT_RBUTTONUP)
+				_graphics->nextCursor();
+			if (_event.type == Common::EVENT_KEYDOWN && _event.kbd.flags & Common::KBD_CTRL && _event.kbd.keycode == Common::KEYCODE_d)
 				_console->attach();
 		}
 
 		_console->onFrame();
 
+		// Cursor animation
+		if (_elapsedFrames % 30 == 0)
+			_graphics->animateCursor();
+
 		g_system->updateScreen();
 		g_system->delayMillis(10);
+
+		_elapsedFrames++;
 	}
 
 	return Common::kNoError;
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 2235d5f..a3f5f92 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -25,6 +25,7 @@
 
 
 #include "common/scummsys.h"
+#include "common/events.h"
 #include "common/file.h"
 #include "common/util.h"
 #include "common/str.h"
@@ -42,18 +43,6 @@ class Graphics;
 class Sound;
 
 class ChewyEngine : public Engine {
-
-protected:
-	// Engine APIs
-	virtual Common::Error run();
-	virtual bool hasFeature(EngineFeature f) const;
-
-	void shutdown();
-
-	void initialize();
-
-	Console *_console;
-
 public:
 	ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc);
 	virtual ~ChewyEngine();
@@ -68,6 +57,20 @@ public:
 
 	Graphics *_graphics;
 	Sound *_sound;
+
+protected:
+	// Engine APIs
+	virtual Common::Error run();
+	virtual bool hasFeature(EngineFeature f) const;
+
+	void initialize();
+	void shutdown();
+
+	Console *_console;
+
+	Common::Event _event;
+	uint _curCursor;
+	uint _elapsedFrames;
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 84e6002..2b90ab7 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -31,6 +31,34 @@
 
 namespace Chewy {
 
+const byte _cursorFrames[] = {
+	4, 1, 1, 1,		// walk
+	4, 1, 1, 1,		// pick up / use
+	1, 1, 1, 1, 1,
+	4, 1, 1, 1,		// look
+	4, 1, 1, 1,		// talk
+	4, 1, 1, 1,		// open
+	1,
+	1, 1, 1, 1,		// left, right, up, down
+	1,				// save
+	1,
+	5, 1, 1, 1, 1,
+	1,
+	1,				// use (inventory)
+	1,				// look (inventory)
+	1				// gun
+};
+
+Graphics::Graphics() {
+	_curCursor = 0;
+	_curCursorFrame = 0;
+	_cursorSprites = new SpriteResource("cursor.taf");
+}
+
+Graphics::~Graphics() {
+	delete _cursorSprites;
+}
+
 void Graphics::drawImage(Common::String filename, int imageNum) {
 	BackgroundResource *res = new BackgroundResource(filename);
 	TBFChunk *image = res->getImage(imageNum);
@@ -86,15 +114,15 @@ void Graphics::playVideo(uint num) {
 	cfoDecoder->close();
 }
 
-void Graphics::setCursor(uint num) {
-	SpriteResource *res = new SpriteResource("cursor.taf");
-	TAFChunk *cursor = res->getSprite(num);
+void Graphics::setCursor(uint num, bool newCursor) {
+	TAFChunk *cursor = _cursorSprites->getSprite(num);
+	if (newCursor)
+		_curCursor = num;
 
 	CursorMan.replaceCursor(cursor->data, cursor->width, cursor->height, 0, 0, 0);
 
 	delete[] cursor->data;
 	delete cursor;
-	delete res;
 }
 
 void Graphics::showCursor() {
@@ -105,4 +133,30 @@ void Graphics::hideCursor() {
 	CursorMan.showMouse(false);
 }
 
+void Graphics::animateCursor() {
+	if (_cursorFrames[_curCursor] > 1) {
+		_curCursorFrame++;
+
+		if (_curCursorFrame >= _cursorFrames[_curCursor])
+			_curCursorFrame = 0;
+
+		setCursor(_curCursor + _curCursorFrame, false);
+	}
+}
+
+void Graphics::nextCursor() {
+	uint maxCursors = ARRAYSIZE(_cursorFrames);
+
+	if (_cursorFrames[_curCursor] > 0)
+		_curCursor += _cursorFrames[_curCursor];
+	else
+		_curCursor++;
+
+	if (_curCursor >= maxCursors)
+		_curCursor = 0;
+
+	_curCursorFrame = 0;
+	setCursor(_curCursor);
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index 64c4255..381e8f5 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -27,18 +27,24 @@
 
 namespace Chewy {
 
+class SpriteResource;
+
 class Graphics {
 public:
-	Graphics() {}
-	~Graphics() {}
+	Graphics();
+	~Graphics();
 
 	void drawImage(Common::String filename, int imageNum);
 	void playVideo(uint num);
-	void setCursor(uint num);
+	void setCursor(uint num, bool newCursor = true);
 	void showCursor();
 	void hideCursor();
+	void animateCursor();
+	void nextCursor();
 private:
-
+	uint _curCursor;
+	uint _curCursorFrame;
+	SpriteResource *_cursorSprites;
 };
 
 } // End of namespace Chewy


Commit: 93a83a6b86116dabc058c4d799615d7e6c496a0c
    https://github.com/scummvm/scummvm/commit/93a83a6b86116dabc058c4d799615d7e6c496a0c
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:14+03:00

Commit Message:
CHEWY: Add an event manager, and get rid of g_engine

Changed paths:
  A engines/chewy/events.cpp
  A engines/chewy/events.h
    engines/chewy/chewy.cpp
    engines/chewy/chewy.h
    engines/chewy/console.cpp
    engines/chewy/graphics.cpp
    engines/chewy/graphics.h
    engines/chewy/sound.cpp
    engines/chewy/sound.h
    engines/chewy/video/cfo_decoder.cpp
    engines/chewy/video/cfo_decoder.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 35575e1..a91bd2f 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -31,6 +31,7 @@
 
 #include "chewy/chewy.h"
 #include "chewy/console.h"
+#include "chewy/events.h"
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
 #include "chewy/sound.h"
@@ -54,18 +55,21 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 }
 
 ChewyEngine::~ChewyEngine() {
-	delete _console;
+	delete _events;
 	delete _sound;
 	delete _graphics;
+	delete _console;
 }
 
 void ChewyEngine::initialize() {
 	_console = new Console(this);
-	_graphics = new Graphics();
-	_sound = new Sound();
+	_graphics = new Graphics(this);
+	_sound = new Sound(_mixer);
+	_events = new Events(this, _graphics, _console);
 
 	_curCursor = 0;
 	_elapsedFrames = 0;
+	_videoNum = -1;
 }
 
 Common::Error ChewyEngine::run() {
@@ -90,14 +94,7 @@ Common::Error ChewyEngine::run() {
 
 	// Run a dummy loop
 	while (!shouldQuit()) {
-		while (g_system->getEventManager()->pollEvent(_event)) {
-			if (_event.type == Common::EVENT_KEYDOWN && _event.kbd.keycode == Common::KEYCODE_ESCAPE)
-				g_engine->quitGame();
-			if ((_event.type == Common::EVENT_KEYDOWN && _event.kbd.keycode == Common::KEYCODE_SPACE) || _event.type == Common::EVENT_RBUTTONUP)
-				_graphics->nextCursor();
-			if (_event.type == Common::EVENT_KEYDOWN && _event.kbd.flags & Common::KBD_CTRL && _event.kbd.keycode == Common::KEYCODE_d)
-				_console->attach();
-		}
+		_events->processEvents();
 
 		_console->onFrame();
 
@@ -105,6 +102,11 @@ Common::Error ChewyEngine::run() {
 		if (_elapsedFrames % 30 == 0)
 			_graphics->animateCursor();
 
+		if (_videoNum >= 0) {
+			_graphics->playVideo(_videoNum);
+			_videoNum = -1;
+		}
+
 		g_system->updateScreen();
 		g_system->delayMillis(10);
 
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index a3f5f92..6bb9df5 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -25,7 +25,6 @@
 
 
 #include "common/scummsys.h"
-#include "common/events.h"
 #include "common/file.h"
 #include "common/util.h"
 #include "common/str.h"
@@ -39,6 +38,7 @@ namespace Chewy {
 
 struct ChewyGameDescription;
 class Console;
+class Events;
 class Graphics;
 class Sound;
 
@@ -55,6 +55,8 @@ public:
 	const ChewyGameDescription *_gameDescription;
 	Common::RandomSource _rnd;
 
+	void setPlayVideo(uint num) { _videoNum = num; }
+
 	Graphics *_graphics;
 	Sound *_sound;
 
@@ -67,10 +69,11 @@ protected:
 	void shutdown();
 
 	Console *_console;
+	Events *_events;
 
-	Common::Event _event;
 	uint _curCursor;
 	uint _elapsedFrames;
+	int _videoNum;
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index deaa1e3..f982cad 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -108,9 +108,7 @@ bool Console::Cmd_Draw(int argc, const char **argv) {
 	Common::String filename = argv[1];
 	int resNum = atoi(argv[2]);
 	
-	Graphics *g = new Graphics();
-	g->drawImage(filename, resNum);
-	delete g;
+	_vm->_graphics->drawImage(filename, resNum);
 
 	return false;
 }
@@ -157,12 +155,8 @@ bool Console::Cmd_PlayVideo(int argc, const char **argv) {
 		return true;
 	}
 
-	detach();	// close the console
-	
 	int resNum = atoi(argv[1]);
-	Graphics *g = new Graphics();
-	g->playVideo(resNum);
-	delete g;
+	_vm->setPlayVideo(resNum);
 
 	return false;
 }
diff --git a/engines/chewy/events.cpp b/engines/chewy/events.cpp
new file mode 100644
index 0000000..cfbcb8b
--- /dev/null
+++ b/engines/chewy/events.cpp
@@ -0,0 +1,62 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "common/events.h"
+
+#include "chewy/chewy.h"
+#include "chewy/console.h"
+#include "chewy/events.h"
+#include "chewy/graphics.h"
+
+namespace Chewy {
+
+Events::Events(ChewyEngine *vm, Graphics *graphics, Console *console) :
+	_vm(vm), _graphics(graphics), _console(console) {
+
+	_eventManager = g_system->getEventManager();
+}
+
+void Events::processEvents() {
+	while (_eventManager->pollEvent(_event)) {
+		if (_event.type == Common::EVENT_KEYDOWN) {
+			switch (_event.kbd.keycode) {
+			case Common::KEYCODE_ESCAPE:
+				_vm->quitGame();
+				break;
+			case Common::KEYCODE_SPACE:
+				_graphics->nextCursor();
+				break;
+			case Common::KEYCODE_d:
+				if (_event.kbd.flags & Common::KBD_CTRL)
+					_console->attach();
+				break;
+			default:
+				break;
+			}
+		} else if (_event.type == Common::EVENT_RBUTTONUP) {
+			_graphics->nextCursor();
+		}
+	}
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/events.h b/engines/chewy/events.h
new file mode 100644
index 0000000..c202b27
--- /dev/null
+++ b/engines/chewy/events.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_EVENTS_H
+#define CHEWY_EVENTS_H
+
+#include "common/events.h"
+
+namespace Chewy {
+
+class ChewyEngine;
+class Graphics;
+class Console;
+
+class Events {
+public:
+	Events(ChewyEngine *vm, Graphics *graphics, Console *console);
+	~Events() {}
+
+	void processEvents();
+
+private:
+	Common::Event _event;
+	Common::EventManager *_eventManager;
+	ChewyEngine *_vm;
+	Graphics *_graphics;
+	Console *_console;
+};
+
+} // End of namespace Chewy
+
+#endif
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 2b90ab7..612551d 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -49,7 +49,7 @@ const byte _cursorFrames[] = {
 	1				// gun
 };
 
-Graphics::Graphics() {
+Graphics::Graphics(ChewyEngine *vm) : _vm(vm) {
 	_curCursor = 0;
 	_curCursorFrame = 0;
 	_cursorSprites = new SpriteResource("cursor.taf");
@@ -73,7 +73,7 @@ void Graphics::drawImage(Common::String filename, int imageNum) {
 }
 
 void Graphics::playVideo(uint num) {
-	CfoDecoder *cfoDecoder = new CfoDecoder();
+	CfoDecoder *cfoDecoder = new CfoDecoder(_vm->_mixer);
 	VideoResource *videoResource = new VideoResource("cut.tap");
 	Common::SeekableReadStream *videoStream = videoResource->getVideoStream(num);
 
@@ -87,9 +87,11 @@ void Graphics::playVideo(uint num) {
 	uint16 y = (g_system->getHeight() - cfoDecoder->getHeight()) / 2;
 	bool skipVideo = false;
 
+	hideCursor();
+
 	cfoDecoder->start();
 
-	while (!g_engine->shouldQuit() && !cfoDecoder->endOfVideo() && !skipVideo) {
+	while (!_vm->shouldQuit() && !cfoDecoder->endOfVideo() && !skipVideo) {
 		if (cfoDecoder->needsUpdate()) {
 			const ::Graphics::Surface *frame = cfoDecoder->decodeNextFrame();
 			if (frame) {
@@ -112,6 +114,8 @@ void Graphics::playVideo(uint num) {
 	}
 
 	cfoDecoder->close();
+
+	showCursor();
 }
 
 void Graphics::setCursor(uint num, bool newCursor) {
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index 381e8f5..90315e3 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -31,7 +31,7 @@ class SpriteResource;
 
 class Graphics {
 public:
-	Graphics();
+	Graphics(ChewyEngine *vm);
 	~Graphics();
 
 	void drawImage(Common::String filename, int imageNum);
@@ -41,7 +41,10 @@ public:
 	void hideCursor();
 	void animateCursor();
 	void nextCursor();
+
 private:
+	ChewyEngine *_vm;
+
 	uint _curCursor;
 	uint _curCursorFrame;
 	SpriteResource *_cursorSprites;
diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
index 9ef4df9..fc27f63 100644
--- a/engines/chewy/sound.cpp
+++ b/engines/chewy/sound.cpp
@@ -30,7 +30,8 @@
 
 namespace Chewy {
 
-Sound::Sound() {
+Sound::Sound(Audio::Mixer *mixer) {
+	_mixer = mixer;
 	_speechRes = new SoundResource("speech.tvp");
 	_soundRes = new SoundResource("details.tap");
 }
@@ -51,7 +52,7 @@ void Sound::playSound(int num, bool loop) {
 		DisposeAfterUse::NO),
 		loop ? 0 : 1);
 
-	g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
+	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
 
 	delete[] sound->data;
 	delete sound;
@@ -72,7 +73,7 @@ void Sound::playMusic(int num, bool loop) {
 		DisposeAfterUse::NO),
 		loop ? 0 : 1);
 
-	g_engine->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream);
+	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream);
 }
 
 void Sound::playSpeech(int num) {
@@ -86,7 +87,7 @@ void Sound::playSpeech(int num) {
 		DisposeAfterUse::NO),
 		1);
 
-	g_engine->_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream);
+	_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream);
 
 	delete[] sound->data;
 	delete sound;
diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h
index 2361027..9dc9536 100644
--- a/engines/chewy/sound.h
+++ b/engines/chewy/sound.h
@@ -32,7 +32,7 @@ class SoundResource;
 
 class Sound {
 public:
-	Sound();
+	Sound(Audio::Mixer *mixer);
 	~Sound();
 
 	void playSound(int num, bool loop = false);
@@ -40,6 +40,7 @@ public:
 	void playSpeech(int num);
 
 private:
+	Audio::Mixer *_mixer;
 	Audio::SoundHandle _soundHandle;
 	Audio::SoundHandle _musicHandle;
 	Audio::SoundHandle _speechHandle;
diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 9ec11cc..09d264a 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -69,11 +69,11 @@ bool CfoDecoder::loadStream(Common::SeekableReadStream *stream) {
 	uint16 width = stream->readUint16LE();
 	uint16 height = stream->readUint16LE();
 
-	addTrack(new CfoVideoTrack(stream, frameCount, width, height));
+	addTrack(new CfoVideoTrack(stream, frameCount, width, height, _mixer));
 	return true;
 }
 
-CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height) :
+CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, Audio::Mixer *mixer) :
 	Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) {
 	readHeader();
 
@@ -81,10 +81,12 @@ CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uin
 		_soundEffects[i] = nullptr;
 		_soundEffectSize[i] = 0;
 	}
+
+	_mixer = mixer;
 }
 
 CfoDecoder::CfoVideoTrack::~CfoVideoTrack() {
-	g_engine->_mixer->stopAll();
+	_mixer->stopAll();
 
 	for (int i = 0; i < MAX_SOUND_EFFECTS; i++) {
 		delete[] _soundEffects[i];
@@ -222,17 +224,17 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			error("Unused chunk kChunkPlayPattern found");
 			break;
 		case kChunkStopMusic:
-			g_engine->_mixer->stopHandle(_musicHandle);
+			_mixer->stopHandle(_musicHandle);
 			break;
 		case kChunkWaitMusicEnd:
 			do {
 				g_system->delayMillis(10);
-			} while (g_engine->_mixer->isSoundHandleActive(_musicHandle));
+			} while (_mixer->isSoundHandleActive(_musicHandle));
 			break;
 		case kChunkSetMusicVolume:
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
 
-			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType, volume);
+			_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType, volume);
 			break;
 		case kChunkSetLoopMode:
 			error("Unused chunk kChunkSetLoopMode found");
@@ -254,20 +256,20 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 				DisposeAfterUse::NO),
 				(repeat == 0) ? 1 : repeat);
 
-			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
-			g_engine->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream);
+			_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
+			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream);
 			break;
 		case kChunkSetSoundVolume:
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
 
-			g_engine->_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
+			_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
 			break;
 		case kChunkSetChannelVolume:
 			channel = _fileStream->readUint16LE();
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
 			assert(channel < MAX_SOUND_EFFECTS);
 
-			g_engine->_mixer->setChannelVolume(_soundHandle[channel], volume);
+			_mixer->setChannelVolume(_soundHandle[channel], volume);
 			break;
 		case kChunkFreeSoundEffect:
 			number = _fileStream->readUint16LE();
@@ -290,7 +292,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			balance = (_fileStream->readUint16LE() * 2) - 127;
 			assert(channel < MAX_SOUND_EFFECTS);
 
-			g_engine->_mixer->setChannelBalance(_soundHandle[channel], balance);
+			_mixer->setChannelBalance(_soundHandle[channel], balance);
 			break;
 		case kChunkSetSpeed:
 			error("Unused chunk kChunkSetSpeed found");
diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h
index 4396205..b15b00e 100644
--- a/engines/chewy/video/cfo_decoder.h
+++ b/engines/chewy/video/cfo_decoder.h
@@ -34,15 +34,17 @@ namespace Chewy {
 // A FLIC decoder, with a modified header and additional custom frames
 class CfoDecoder : public Video::FlicDecoder {
 public:
-	CfoDecoder() : Video::FlicDecoder() {}
+	CfoDecoder(Audio::Mixer *mixer) : Video::FlicDecoder() { _mixer = mixer; }
 	virtual ~CfoDecoder() {}
 
 	bool loadStream(Common::SeekableReadStream *stream);
 
 private:
+	Audio::Mixer *_mixer;
+
 	class CfoVideoTrack : public Video::FlicDecoder::FlicVideoTrack {
 	public:
-		CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height);
+		CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, Audio::Mixer *mixer);
 		virtual ~CfoVideoTrack();
 
 		void readHeader();
@@ -56,6 +58,7 @@ private:
 		void handleFrame();
 		void handleCustomFrame();
 
+		Audio::Mixer *_mixer;
 		Audio::SoundHandle _musicHandle;
 		Audio::SoundHandle _soundHandle[MAX_SOUND_EFFECTS];
 		byte *_soundEffects[MAX_SOUND_EFFECTS];


Commit: 8c755b268c41be8d1ecc688c83c8904c41f7419e
    https://github.com/scummvm/scummvm/commit/8c755b268c41be8d1ecc688c83c8904c41f7419e
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:23+03:00

Commit Message:
CHEWY: Add the event manager to module.mk

Changed paths:
    engines/chewy/module.mk



diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index 2e2535f..bc82a3f 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -4,6 +4,7 @@ MODULE_OBJS = \
 	chewy.o \
 	console.o \
 	detection.o \
+	events.o \
 	graphics.o \
 	resource.o \
 	sound.o \


Commit: 8c7c42d13d652abd8e7982fb402cc70150e15491
    https://github.com/scummvm/scummvm/commit/8c7c42d13d652abd8e7982fb402cc70150e15491
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:32+03:00

Commit Message:
CHEWY: Use virtual destructors. Some cleanup

Changed paths:
    engines/chewy/events.h
    engines/chewy/graphics.h
    engines/chewy/resource.h
    engines/chewy/sound.h



diff --git a/engines/chewy/events.h b/engines/chewy/events.h
index c202b27..fb2ab40 100644
--- a/engines/chewy/events.h
+++ b/engines/chewy/events.h
@@ -34,7 +34,7 @@ class Console;
 class Events {
 public:
 	Events(ChewyEngine *vm, Graphics *graphics, Console *console);
-	~Events() {}
+	virtual ~Events() {}
 
 	void processEvents();
 
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index 90315e3..28af8fe 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -32,7 +32,7 @@ class SpriteResource;
 class Graphics {
 public:
 	Graphics(ChewyEngine *vm);
-	~Graphics();
+	virtual ~Graphics();
 
 	void drawImage(Common::String filename, int imageNum);
 	void playVideo(uint num);
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index b869840..04a0598 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -86,19 +86,6 @@ struct TBFChunk {
 	byte *data;
 };
 
-// TAF (sprite) chunk header
-/*struct TAFHeader {
-	// TAF chunk header
-	// ID (TAF, followed by a zero)
-	uint16 screenMode;
-	uint16 spriteCount;
-	uint32 size;	// total size (width * height) of all sprites
-	byte palette[3 * 256];
-	uint32 nextSpriteOffset;
-	uint16 correctionTable;
-	// 1 byte padding
-};*/
-
 // TAF (sprite) image data chunk header - 15 bytes
 struct TAFChunk {
 	uint16 compressionFlag;
@@ -160,7 +147,7 @@ protected:
 class SpriteResource : public Resource {
 public:
 	SpriteResource(Common::String filename) : Resource(filename) {}
-	~SpriteResource() {}
+	virtual ~SpriteResource() {}
 
 	TAFChunk *getSprite(uint num);
 };
@@ -168,7 +155,7 @@ public:
 class BackgroundResource : public Resource {
 public:
 	BackgroundResource(Common::String filename) : Resource(filename) {}
-	~BackgroundResource() {}
+	virtual ~BackgroundResource() {}
 
 	TBFChunk *getImage(uint num);
 };
@@ -176,7 +163,7 @@ public:
 class SoundResource : public Resource {
 public:
 	SoundResource(Common::String filename) : Resource(filename) {}
-	~SoundResource() {}
+	virtual ~SoundResource() {}
 
 	SoundChunk *getSound(uint num);
 };
@@ -184,7 +171,7 @@ public:
 class TextResource : public Resource {
 public:
 	TextResource(Common::String filename) : Resource(filename) {}
-	~TextResource() {}
+	virtual ~TextResource() {}
 
 	Common::String getText(uint num);
 };
@@ -192,7 +179,7 @@ public:
 class VideoResource : public Resource {
 public:
 	VideoResource(Common::String filename) : Resource(filename) {}
-	~VideoResource() {}
+	virtual ~VideoResource() {}
 
 	VideoChunk *getVideoHeader(uint num);
 	Common::SeekableReadStream *getVideoStream(uint num);
diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h
index 9dc9536..7884ead 100644
--- a/engines/chewy/sound.h
+++ b/engines/chewy/sound.h
@@ -33,7 +33,7 @@ class SoundResource;
 class Sound {
 public:
 	Sound(Audio::Mixer *mixer);
-	~Sound();
+	virtual ~Sound();
 
 	void playSound(int num, bool loop = false);
 	void playMusic(int num, bool loop = false);


Commit: 88f3fc07603d132b12d366509e547e4367787700
    https://github.com/scummvm/scummvm/commit/88f3fc07603d132b12d366509e547e4367787700
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:36+03:00

Commit Message:
CHEWY: Implement initial sprite drawing, font loading and text drawing

Changed paths:
    engines/chewy/chewy.cpp
    engines/chewy/graphics.cpp
    engines/chewy/graphics.h
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index a91bd2f..0f2e9c3 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -86,6 +86,9 @@ Common::Error ChewyEngine::run() {
 
 	//_graphics->playVideo(0);
 	_graphics->drawImage("episode1.tgp", 0);
+	_graphics->drawSprite("det1.taf", 0, 200, 100);
+	_graphics->loadFont("6x8.tff");
+	_graphics->drawText("This is a test", 200, 80);
 	_graphics->showCursor();
 	_graphics->setCursor(0);
 	//_sound->playSpeech(1);
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 612551d..db3b094 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -24,6 +24,7 @@
 #include "common/events.h"
 #include "graphics/cursorman.h"
 #include "graphics/palette.h"
+#include "graphics/surface.h"
 
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
@@ -53,12 +54,26 @@ Graphics::Graphics(ChewyEngine *vm) : _vm(vm) {
 	_curCursor = 0;
 	_curCursorFrame = 0;
 	_cursorSprites = new SpriteResource("cursor.taf");
+	_font = nullptr;
 }
 
 Graphics::~Graphics() {
+	delete _font;
 	delete _cursorSprites;
 }
 
+void Graphics::drawSprite(Common::String filename, int spriteNum, uint x, uint y) {
+	SpriteResource *res = new SpriteResource(filename);
+	TAFChunk *sprite = res->getSprite(spriteNum);
+
+	drawTransparent(x, y, sprite->data, sprite->width, sprite->height, 0);
+	g_system->updateScreen();
+
+	delete[] sprite->data;
+	delete sprite;
+	delete res;
+}
+
 void Graphics::drawImage(Common::String filename, int imageNum) {
 	BackgroundResource *res = new BackgroundResource(filename);
 	TBFChunk *image = res->getImage(imageNum);
@@ -72,6 +87,32 @@ void Graphics::drawImage(Common::String filename, int imageNum) {
 	delete res;
 }
 
+void Graphics::loadFont(Common::String filename) {
+	_font = new Font(filename);
+}
+
+void Graphics::drawTransparent(uint16 x, uint16 y, byte *data, uint16 width, uint16 height, byte transparentColor) {
+	::Graphics::Surface *screen = g_system->lockScreen();
+	for (uint textX = 0; textX < width; textX++) {
+		for (uint textY = 0; textY < height; textY++) {
+			byte *src = data + (textY * width) + textX;
+			byte *dst = (byte *)screen->getBasePtr(textX + x, textY + y);
+			if (*src != transparentColor)
+				*dst = *src;
+		}
+	}
+	g_system->unlockScreen();
+}
+
+void Graphics::drawText(Common::String text, uint x, uint y) {
+	::Graphics::Surface *textSurface = _font->getLine(text);
+
+	drawTransparent(x, y, (byte *)textSurface->getPixels(), textSurface->pitch, textSurface->h, 0xFF);
+
+	textSurface->free();
+	delete textSurface;
+}
+
 void Graphics::playVideo(uint num) {
 	CfoDecoder *cfoDecoder = new CfoDecoder(_vm->_mixer);
 	VideoResource *videoResource = new VideoResource("cut.tap");
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index 28af8fe..a3f6005 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -28,6 +28,7 @@
 namespace Chewy {
 
 class SpriteResource;
+class Font;
 
 class Graphics {
 public:
@@ -35,7 +36,11 @@ public:
 	virtual ~Graphics();
 
 	void drawImage(Common::String filename, int imageNum);
+	void drawSprite(Common::String filename, int spriteNum, uint x, uint y);
 	void playVideo(uint num);
+	void loadFont(Common::String filename);
+	void drawText(Common::String text, uint x, uint y);
+
 	void setCursor(uint num, bool newCursor = true);
 	void showCursor();
 	void hideCursor();
@@ -43,11 +48,14 @@ public:
 	void nextCursor();
 
 private:
+	void drawTransparent(uint16 x, uint16 y, byte *data, uint16 width, uint16 height, byte transparentColor);
+
 	ChewyEngine *_vm;
 
 	uint _curCursor;
 	uint _curCursorFrame;
 	SpriteResource *_cursorSprites;
+	Font *_font;
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 13bd9d2..368f589 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -21,9 +21,12 @@
  */
 
 #include "common/debug.h"
+#include "common/rect.h"
 #include "common/stream.h"
 #include "common/substream.h"
 #include "common/textconsole.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
 
 #include "chewy/chewy.h"
 #include "chewy/resource.h"
@@ -34,13 +37,11 @@ namespace Chewy {
 // ======================
 // back/episode1.gep
 // cut/blende.rnd
-// misc/*.taf, room/*.taf
 // misc/exit.eib
 // misc/inventar.iib
 // misc/inventar.sib
 // room/csp.int
 // room/test.rdi
-// txt/*.tff
 // txt/*.tap
 // txt/diah.adh
 // txt/inv_st.s and txt/room_st.s
@@ -323,4 +324,62 @@ Common::SeekableReadStream *VideoResource::getVideoStream(uint num) {
 	return new Common::SeekableSubReadStream(&_stream, chunk->pos, chunk->pos + chunk->size);
 }
 
+Font::Font(Common::String filename) {
+	const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
+	Common::File stream;
+
+	stream.open(filename);
+
+	uint32 header = stream.readUint32BE();
+
+	if (header != headerFont)
+		error("Invalid resource - %s", filename.c_str());
+
+	stream.skip(4);	// total memory
+	_count = stream.readUint16LE();
+	_first = stream.readUint16LE();
+	_last = stream.readUint16LE();
+	_width = stream.readUint16LE();
+	_height = stream.readUint16LE();
+
+	_fontSurface.create(_width * _count, _height, ::Graphics::PixelFormat::createFormatCLUT8());
+
+	byte cur;
+	int bitIndex = 7;
+	byte *p;
+
+	cur = stream.readByte();
+
+	for (uint n = 0; n < _count; n++) {
+		for (uint y = 0; y < _height; y++) {
+			for (uint x = n * _width; x < n * _width + _width; x++) {
+				p = (byte *)_fontSurface.getBasePtr(x, y);
+				*p = (cur & (1 << bitIndex)) ? 0 : 0xFF;
+
+				bitIndex--;
+				if (bitIndex < 0) {
+					bitIndex = 7;
+					cur = stream.readByte();
+				}
+			}
+		}
+	}
+}
+
+Font::~Font() {
+	_fontSurface.free();
+}
+
+::Graphics::Surface *Font::getLine(Common::String text) {
+	::Graphics::Surface *line = new ::Graphics::Surface();
+	line->create(text.size() * _width, _height, ::Graphics::PixelFormat::createFormatCLUT8());
+
+	for (uint i = 0; i < text.size(); i++) {
+		int c = text[i];
+		line->copyRectToSurface(_fontSurface, i * _width, 0, Common::Rect((c - _first) * _width, 0, (c - _first) * _width + _width, _height));
+	}
+
+	return line;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 04a0598..6d2126c 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -32,6 +32,7 @@
 #include "common/hash-str.h"
 #include "common/random.h"
 #include "common/stream.h"
+#include "graphics/surface.h"
 
 namespace Chewy {
 
@@ -185,6 +186,19 @@ public:
 	Common::SeekableReadStream *getVideoStream(uint num);
 };
 
+class Font {
+public:
+	Font(Common::String filename);
+	virtual ~Font();
+
+	::Graphics::Surface *getLine(Common::String text);
+
+private:
+	uint16 _count, _first, _last, _width, _height;
+
+	::Graphics::Surface _fontSurface;
+};
+
 } // End of namespace Chewy
 
 #endif


Commit: 832b97c1d5f3bf8f7c1ae451beea1e6ac1b33834
    https://github.com/scummvm/scummvm/commit/832b97c1d5f3bf8f7c1ae451beea1e6ac1b33834
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:50+03:00

Commit Message:
CHEWY: Rename some variables

Changed paths:
    engines/chewy/graphics.cpp



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index db3b094..6f72d04 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -93,10 +93,10 @@ void Graphics::loadFont(Common::String filename) {
 
 void Graphics::drawTransparent(uint16 x, uint16 y, byte *data, uint16 width, uint16 height, byte transparentColor) {
 	::Graphics::Surface *screen = g_system->lockScreen();
-	for (uint textX = 0; textX < width; textX++) {
-		for (uint textY = 0; textY < height; textY++) {
-			byte *src = data + (textY * width) + textX;
-			byte *dst = (byte *)screen->getBasePtr(textX + x, textY + y);
+	for (uint curX = 0; curX < width; curX++) {
+		for (uint curY = 0; curY < height; curY++) {
+			byte *src = data + (curY * width) + curX;
+			byte *dst = (byte *)screen->getBasePtr(curX + x, curY + y);
 			if (*src != transparentColor)
 				*dst = *src;
 		}


Commit: 263fdb357bc7fd01283c016f34a24f45ac13257e
    https://github.com/scummvm/scummvm/commit/263fdb357bc7fd01283c016f34a24f45ac13257e
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T00:34:59+03:00

Commit Message:
CHEWY: Some cleanup, and remove a seemingly unused resource

Changed paths:
    engines/chewy/resource.cpp



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 368f589..365bcbb 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -40,7 +40,6 @@ namespace Chewy {
 // misc/exit.eib
 // misc/inventar.iib
 // misc/inventar.sib
-// room/csp.int
 // room/test.rdi
 // txt/*.tap
 // txt/diah.adh
@@ -375,8 +374,8 @@ Font::~Font() {
 	line->create(text.size() * _width, _height, ::Graphics::PixelFormat::createFormatCLUT8());
 
 	for (uint i = 0; i < text.size(); i++) {
-		int c = text[i];
-		line->copyRectToSurface(_fontSurface, i * _width, 0, Common::Rect((c - _first) * _width, 0, (c - _first) * _width + _width, _height));
+		uint x = (text[i] - _first) * _width;
+		line->copyRectToSurface(_fontSurface, i * _width, 0, Common::Rect(x, 0, x + _width, _height));
 	}
 
 	return line;


Commit: ce800ff1ceff73cb89272f6cc11912396565f812
    https://github.com/scummvm/scummvm/commit/ce800ff1ceff73cb89272f6cc11912396565f812
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T01:10:34+03:00

Commit Message:
CHEWY: Fix warnings about shadowed and unused variables

Changed paths:
    engines/chewy/resource.cpp



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 365bcbb..c5f0a19 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -118,7 +118,6 @@ byte *Resource::getChunkData(uint num) {
 }
 
 void Resource::initSprite(Common::String filename) {
-	uint16 screenMode;;
 	uint32 nextSpriteOffset;
 
 	// TAF (sprite) resources are much different than the rest, so we have a
@@ -126,7 +125,7 @@ void Resource::initSprite(Common::String filename) {
 
 	_resType = kResourceTAF;
 	_encrypted = false;
-	screenMode = _stream.readUint16LE();
+	/*screenMode = */_stream.readUint16LE();
 	_chunkCount = _stream.readUint16LE();
 	_stream.skip(4);		// total size of all sprites
 	_stream.skip(3 * 256);	// palette
@@ -142,7 +141,7 @@ void Resource::initSprite(Common::String filename) {
 		cur.type = kResourceTAF;
 
 		_stream.skip(2 + 2 + 2);	// compression flag, width, height
-		uint32 nextSpriteOffset = _stream.readUint32LE();
+		nextSpriteOffset = _stream.readUint32LE();
 		uint32 spriteImageOffset = _stream.readUint32LE();
 		_stream.skip(1);	// padding
 


Commit: b394b1b687a037369db6f4242329cf370d4d1c85
    https://github.com/scummvm/scummvm/commit/b394b1b687a037369db6f4242329cf370d4d1c85
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T01:10:49+03:00

Commit Message:
CHEWY: Fix compilation

Changed paths:
    engines/chewy/video/cfo_decoder.cpp



diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 09d264a..9cd0479 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -234,7 +234,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 		case kChunkSetMusicVolume:
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
 
-			_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kMusicSoundType, volume);
+			_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
 			break;
 		case kChunkSetLoopMode:
 			error("Unused chunk kChunkSetLoopMode found");
@@ -256,13 +256,13 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 				DisposeAfterUse::NO),
 				(repeat == 0) ? 1 : repeat);
 
-			_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
+			_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
 			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream);
 			break;
 		case kChunkSetSoundVolume:
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
 
-			_mixer->setVolumeForSoundType(Audio::Mixer::SoundType::kSFXSoundType, volume);
+			_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
 			break;
 		case kChunkSetChannelVolume:
 			channel = _fileStream->readUint16LE();


Commit: 891813c9e1ec96971a61ede016e3b7872977549e
    https://github.com/scummvm/scummvm/commit/891813c9e1ec96971a61ede016e3b7872977549e
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T01:38:48+03:00

Commit Message:
CHEWY: TCF resources contain error messages, not in-game text

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index f982cad..a681c89 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -31,15 +31,15 @@
 namespace Chewy {
 
 Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
-	registerCmd("dump",			WRAP_METHOD(Console, Cmd_Dump));
-	registerCmd("dump_bg",		WRAP_METHOD(Console, Cmd_DumpBg));
-	registerCmd("draw",			WRAP_METHOD(Console, Cmd_Draw));
-	registerCmd("play_sound",	WRAP_METHOD(Console, Cmd_PlaySound));
-	registerCmd("play_speech",	WRAP_METHOD(Console, Cmd_PlaySpeech));
-	registerCmd("play_music",	WRAP_METHOD(Console, Cmd_PlayMusic));
-	registerCmd("play_video",	WRAP_METHOD(Console, Cmd_PlayVideo));
-	registerCmd("video_info",	WRAP_METHOD(Console, Cmd_VideoInfo));
-	registerCmd("text",			WRAP_METHOD(Console, Cmd_Text));
+	registerCmd("dump",			 WRAP_METHOD(Console, Cmd_Dump));
+	registerCmd("dump_bg",		 WRAP_METHOD(Console, Cmd_DumpBg));
+	registerCmd("draw",			 WRAP_METHOD(Console, Cmd_Draw));
+	registerCmd("play_sound",	 WRAP_METHOD(Console, Cmd_PlaySound));
+	registerCmd("play_speech",	 WRAP_METHOD(Console, Cmd_PlaySpeech));
+	registerCmd("play_music",	 WRAP_METHOD(Console, Cmd_PlayMusic));
+	registerCmd("play_video",	 WRAP_METHOD(Console, Cmd_PlayVideo));
+	registerCmd("video_info",	 WRAP_METHOD(Console, Cmd_VideoInfo));
+	registerCmd("error_message", WRAP_METHOD(Console, Cmd_ErrorMessage));
 }
 
 Console::~Console() {
@@ -177,18 +177,18 @@ bool Console::Cmd_VideoInfo(int argc, const char **argv) {
 	return true;
 }
 
-bool Console::Cmd_Text(int argc, const char **argv) {
+bool Console::Cmd_ErrorMessage(int argc, const char **argv) {
 	if (argc < 2) {
-		debugPrintf("Usage: <file> <text number>\n");
+		debugPrintf("Usage: error_message <file> <message number>\n");
 		return true;
 	}
 
 	Common::String filename = argv[1];
 	int resNum = atoi(argv[2]);
 
-	TextResource *res = new TextResource(filename);
-	Common::String str = res->getText(resNum);
-	this->debugPrintf("Text: %s\n", str.c_str());
+	ErrorMessage *res = new ErrorMessage(filename);
+	Common::String str = res->getErrorMessage(resNum);
+	this->debugPrintf("Error message: %s\n", str.c_str());
 	delete res;
 
 	return true;
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index ab8b8de..a4ffbe8 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -45,7 +45,7 @@ private:
 	bool Cmd_PlayMusic(int argc, const char **argv);
 	bool Cmd_PlayVideo(int argc, const char **argv);
 	bool Cmd_VideoInfo(int argc, const char **argv);
-	bool Cmd_Text(int argc, const char **argv);
+	bool Cmd_ErrorMessage(int argc, const char **argv);
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index c5f0a19..a30548c 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -268,7 +268,7 @@ SoundChunk *SoundResource::getSound(uint num) {
 	return sound;
 }
 
-Common::String TextResource::getText(uint num) {
+Common::String ErrorMessage::getErrorMessage(uint num) {
 	assert(num < _chunkList.size());
 
 	Chunk *chunk = &_chunkList[num];
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 6d2126c..8685cc6 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -169,12 +169,12 @@ public:
 	SoundChunk *getSound(uint num);
 };
 
-class TextResource : public Resource {
+class ErrorMessage : public Resource {
 public:
-	TextResource(Common::String filename) : Resource(filename) {}
-	virtual ~TextResource() {}
+	ErrorMessage(Common::String filename) : Resource(filename) {}
+	virtual ~ErrorMessage() {}
 
-	Common::String getText(uint num);
+	Common::String getErrorMessage(uint num);
 };
 
 class VideoResource : public Resource {


Commit: 8f9412984db5b647d159fe33abf122fb0d2d7060
    https://github.com/scummvm/scummvm/commit/8f9412984db5b647d159fe33abf122fb0d2d7060
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T01:40:07+03:00

Commit Message:
CHEWY: Fix define for chewy.h

Changed paths:
    engines/chewy/chewy.h



diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 6bb9df5..34a3d5f 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -20,8 +20,8 @@
  *
  */
 
-#ifndef CHEWY_H
-#define CHEWY_H
+#ifndef CHEWY_CHEWY_H
+#define CHEWY_CHEWY_H
 
 
 #include "common/scummsys.h"


Commit: f61aee3c70a97152550814d2035189fad192b2d4
    https://github.com/scummvm/scummvm/commit/f61aee3c70a97152550814d2035189fad192b2d4
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T01:44:09+03:00

Commit Message:
CHEWY: Mask potentially overflown palette values

Changed paths:
    engines/chewy/resource.cpp



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index a30548c..90849cd 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -210,7 +210,7 @@ TBFChunk *BackgroundResource::getImage(uint num) {
 	tbf->width = _stream.readUint16LE();
 	tbf->height = _stream.readUint16LE();
 	for (int j = 0; j < 3 * 256; j++)
-		tbf->palette[j] = _stream.readByte() << 2;
+		tbf->palette[j] = (_stream.readByte() << 2) & 0xff;
 
 	tbf->data = new byte[tbf->size];
 


Commit: 9e5b745a123f0cc9b696eed6946edc31ef702dd8
    https://github.com/scummvm/scummvm/commit/9e5b745a123f0cc9b696eed6946edc31ef702dd8
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T01:44:46+03:00

Commit Message:
CHEWY: Process events while waiting for video music to end

Changed paths:
    engines/chewy/video/cfo_decoder.cpp



diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 9cd0479..18fc6ea 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -23,6 +23,7 @@
 #include "audio/audiostream.h"
 #include "audio/mixer.h"
 #include "audio/decoders/raw.h"
+#include "common/events.h"
 #include "common/stream.h"
 #include "common/system.h"
 #include "engines/engine.h"
@@ -228,6 +229,9 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			break;
 		case kChunkWaitMusicEnd:
 			do {
+				Common::Event event;
+				while (g_system->getEventManager()->pollEvent(event)) {}	// ignore events
+				g_system->updateScreen();
 				g_system->delayMillis(10);
 			} while (_mixer->isSoundHandleActive(_musicHandle));
 			break;


Commit: cec2799c64d996dba247669c6eedfbffacc5f384
    https://github.com/scummvm/scummvm/commit/cec2799c64d996dba247669c6eedfbffacc5f384
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-03T05:29:58+03:00

Commit Message:
CHEWY: Properly handle the text encryption in atds.tap (game texts)

Changed paths:
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 90849cd..352e2f1 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -41,9 +41,9 @@ namespace Chewy {
 // misc/inventar.iib
 // misc/inventar.sib
 // room/test.rdi
-// txt/*.tap
+// txt/atds.tap (game texts)
 // txt/diah.adh
-// txt/inv_st.s and txt/room_st.s
+// txt/inv_st.s and txt/room_st.s (inventory/room control bytes)
 // txt/inv_use.idx
 
 Resource::Resource(Common::String filename) {
@@ -52,6 +52,7 @@ Resource::Resource(Common::String filename) {
 	const uint32 headerTxtEnc  = MKTAG('T', 'C', 'F', '\1');
 	const uint32 headerSprite  = MKTAG('T', 'A', 'F', '\0');
 
+	filename.toLowercase();
 	_stream.open(filename);
 
 	uint32 header = _stream.readUint32BE();
@@ -72,6 +73,9 @@ Resource::Resource(Common::String filename) {
 		_encrypted = false;
 	}
 
+	if (filename == "atds.tap")
+		_encrypted = true;
+
 	_chunkCount = _stream.readUint16LE();
 
 	for (uint i = 0; i < _chunkCount; i++) {
@@ -113,6 +117,8 @@ byte *Resource::getChunkData(uint num) {
 
 	_stream.seek(chunk->pos, SEEK_SET);
 	_stream.read(data, chunk->size);
+	if (_encrypted)
+		decrypt(data, chunk->size);
 
 	return data;
 }
@@ -170,6 +176,15 @@ void Resource::unpackRLE(byte *buffer, uint32 compressedSize, uint32 uncompresse
 	}
 }
 
+void Resource::decrypt(byte *data, uint32 size) {
+	byte *c = data;
+
+	for (uint i = 0; i < size; i++) {
+		*c = -(*c);
+		++c;
+	}
+}
+
 TAFChunk *SpriteResource::getSprite(uint num) {
 	assert(num < _chunkList.size());
 
@@ -276,17 +291,9 @@ Common::String ErrorMessage::getErrorMessage(uint num) {
 	byte *data = new byte[chunk->size];
 
 	_stream.seek(chunk->pos, SEEK_SET);
-
 	_stream.read(data, chunk->size);
-
-	if (_encrypted) {
-		byte *c = data;
-
-		for (uint i = 0; i < chunk->size; i++) {
-			*c = -(*c);
-			++c;
-		}
-	}
+	if (_encrypted)
+		decrypt(data, chunk->size);
 
 	str = (char *)data;
 	delete[] data;
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 8685cc6..7a79beb 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -136,6 +136,7 @@ public:
 protected:
 	void initSprite(Common::String filename);
 	void unpackRLE(byte *buffer, uint32 compressedSize, uint32 uncompressedSize);
+	void decrypt(byte *data, uint32 size);
 
 	Common::File _stream;
 	uint16 _chunkCount;


Commit: 19dab45c8c8bbca6aedce0574ffa44ab27715172
    https://github.com/scummvm/scummvm/commit/19dab45c8c8bbca6aedce0574ffa44ab27715172
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-04T02:27:22+03:00

Commit Message:
CHEWY: Initial support for in-game texts (game dialog texts)

Changed paths:
  A engines/chewy/text.cpp
  A engines/chewy/text.h
    engines/chewy/chewy.cpp
    engines/chewy/chewy.h
    engines/chewy/console.cpp
    engines/chewy/console.h
    engines/chewy/graphics.cpp
    engines/chewy/module.mk
    engines/chewy/resource.cpp
    engines/chewy/resource.h



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 0f2e9c3..3845bfd 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -35,6 +35,7 @@
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
 #include "chewy/sound.h"
+#include "chewy/text.h"
 
 namespace Chewy {
 
@@ -56,6 +57,7 @@ ChewyEngine::ChewyEngine(OSystem *syst, const ChewyGameDescription *gameDesc)
 
 ChewyEngine::~ChewyEngine() {
 	delete _events;
+	delete _text;
 	delete _sound;
 	delete _graphics;
 	delete _console;
@@ -65,6 +67,7 @@ void ChewyEngine::initialize() {
 	_console = new Console(this);
 	_graphics = new Graphics(this);
 	_sound = new Sound(_mixer);
+	_text = new Text();
 	_events = new Events(this, _graphics, _console);
 
 	_curCursor = 0;
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 34a3d5f..7caed6e 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -41,6 +41,7 @@ class Console;
 class Events;
 class Graphics;
 class Sound;
+class Text;
 
 class ChewyEngine : public Engine {
 public:
@@ -59,6 +60,7 @@ public:
 
 	Graphics *_graphics;
 	Sound *_sound;
+	Text *_text;
 
 protected:
 	// Engine APIs
diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index a681c89..7fefe45 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -27,19 +27,21 @@
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
 #include "chewy/sound.h"
+#include "chewy/text.h"
 
 namespace Chewy {
 
 Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
-	registerCmd("dump",			 WRAP_METHOD(Console, Cmd_Dump));
-	registerCmd("dump_bg",		 WRAP_METHOD(Console, Cmd_DumpBg));
-	registerCmd("draw",			 WRAP_METHOD(Console, Cmd_Draw));
-	registerCmd("play_sound",	 WRAP_METHOD(Console, Cmd_PlaySound));
-	registerCmd("play_speech",	 WRAP_METHOD(Console, Cmd_PlaySpeech));
-	registerCmd("play_music",	 WRAP_METHOD(Console, Cmd_PlayMusic));
-	registerCmd("play_video",	 WRAP_METHOD(Console, Cmd_PlayVideo));
-	registerCmd("video_info",	 WRAP_METHOD(Console, Cmd_VideoInfo));
+	registerCmd("dump",          WRAP_METHOD(Console, Cmd_Dump));
+	registerCmd("dump_bg",       WRAP_METHOD(Console, Cmd_DumpBg));
+	registerCmd("draw",          WRAP_METHOD(Console, Cmd_Draw));
+	registerCmd("play_sound",    WRAP_METHOD(Console, Cmd_PlaySound));
+	registerCmd("play_speech",   WRAP_METHOD(Console, Cmd_PlaySpeech));
+	registerCmd("play_music",    WRAP_METHOD(Console, Cmd_PlayMusic));
+	registerCmd("play_video",    WRAP_METHOD(Console, Cmd_PlayVideo));
+	registerCmd("video_info",    WRAP_METHOD(Console, Cmd_VideoInfo));
 	registerCmd("error_message", WRAP_METHOD(Console, Cmd_ErrorMessage));
+	registerCmd("dialog",        WRAP_METHOD(Console, Cmd_Dialog));
 }
 
 Console::~Console() {
@@ -178,7 +180,7 @@ bool Console::Cmd_VideoInfo(int argc, const char **argv) {
 }
 
 bool Console::Cmd_ErrorMessage(int argc, const char **argv) {
-	if (argc < 2) {
+	if (argc < 3) {
 		debugPrintf("Usage: error_message <file> <message number>\n");
 		return true;
 	}
@@ -194,4 +196,25 @@ bool Console::Cmd_ErrorMessage(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::Cmd_Dialog(int argc, const char **argv) {
+	if (argc < 3) {
+		debugPrintf("Usage: dialog <dialog> <entry>\n");
+		return true;
+	}
+
+	int dialogNum = atoi(argv[1]);
+	int entryNum  = atoi(argv[2]);
+	uint cur = 0;
+	DialogList *d = _vm->_text->getDialog(dialogNum, entryNum);
+
+	for (DialogList::iterator it = d->begin(); it != d->end(); ++it) {
+		this->debugPrintf("Entry %d: speech %d, text '%s'\n", cur, (*it).speechId, (*it).text.c_str());
+	}
+
+	d->clear();
+	delete d;
+
+	return true;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index a4ffbe8..122f79c 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -46,6 +46,7 @@ private:
 	bool Cmd_PlayVideo(int argc, const char **argv);
 	bool Cmd_VideoInfo(int argc, const char **argv);
 	bool Cmd_ErrorMessage(int argc, const char **argv);
+	bool Cmd_Dialog(int argc, const char **argv);
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 6f72d04..de95b11 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -28,6 +28,7 @@
 
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
+#include "chewy/text.h"
 #include "chewy/video/cfo_decoder.h"
 
 namespace Chewy {
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index bc82a3f..38b4265 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS = \
 	graphics.o \
 	resource.o \
 	sound.o \
+	text.o \
 	video/cfo_decoder.o
 
 # This module can be built as a plugin
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 352e2f1..07af798 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -21,7 +21,6 @@
  */
 
 #include "common/debug.h"
-#include "common/rect.h"
 #include "common/stream.h"
 #include "common/substream.h"
 #include "common/textconsole.h"
@@ -283,24 +282,6 @@ SoundChunk *SoundResource::getSound(uint num) {
 	return sound;
 }
 
-Common::String ErrorMessage::getErrorMessage(uint num) {
-	assert(num < _chunkList.size());
-
-	Chunk *chunk = &_chunkList[num];
-	Common::String str;
-	byte *data = new byte[chunk->size];
-
-	_stream.seek(chunk->pos, SEEK_SET);
-	_stream.read(data, chunk->size);
-	if (_encrypted)
-		decrypt(data, chunk->size);
-
-	str = (char *)data;
-	delete[] data;
-
-	return str;
-}
-
 VideoChunk *VideoResource::getVideoHeader(uint num) {
 	assert(num < _chunkList.size());
 
@@ -329,62 +310,4 @@ Common::SeekableReadStream *VideoResource::getVideoStream(uint num) {
 	return new Common::SeekableSubReadStream(&_stream, chunk->pos, chunk->pos + chunk->size);
 }
 
-Font::Font(Common::String filename) {
-	const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
-	Common::File stream;
-
-	stream.open(filename);
-
-	uint32 header = stream.readUint32BE();
-
-	if (header != headerFont)
-		error("Invalid resource - %s", filename.c_str());
-
-	stream.skip(4);	// total memory
-	_count = stream.readUint16LE();
-	_first = stream.readUint16LE();
-	_last = stream.readUint16LE();
-	_width = stream.readUint16LE();
-	_height = stream.readUint16LE();
-
-	_fontSurface.create(_width * _count, _height, ::Graphics::PixelFormat::createFormatCLUT8());
-
-	byte cur;
-	int bitIndex = 7;
-	byte *p;
-
-	cur = stream.readByte();
-
-	for (uint n = 0; n < _count; n++) {
-		for (uint y = 0; y < _height; y++) {
-			for (uint x = n * _width; x < n * _width + _width; x++) {
-				p = (byte *)_fontSurface.getBasePtr(x, y);
-				*p = (cur & (1 << bitIndex)) ? 0 : 0xFF;
-
-				bitIndex--;
-				if (bitIndex < 0) {
-					bitIndex = 7;
-					cur = stream.readByte();
-				}
-			}
-		}
-	}
-}
-
-Font::~Font() {
-	_fontSurface.free();
-}
-
-::Graphics::Surface *Font::getLine(Common::String text) {
-	::Graphics::Surface *line = new ::Graphics::Surface();
-	line->create(text.size() * _width, _height, ::Graphics::PixelFormat::createFormatCLUT8());
-
-	for (uint i = 0; i < text.size(); i++) {
-		uint x = (text[i] - _first) * _width;
-		line->copyRectToSurface(_fontSurface, i * _width, 0, Common::Rect(x, 0, x + _width, _height));
-	}
-
-	return line;
-}
-
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.h b/engines/chewy/resource.h
index 7a79beb..abccc96 100644
--- a/engines/chewy/resource.h
+++ b/engines/chewy/resource.h
@@ -170,14 +170,6 @@ public:
 	SoundChunk *getSound(uint num);
 };
 
-class ErrorMessage : public Resource {
-public:
-	ErrorMessage(Common::String filename) : Resource(filename) {}
-	virtual ~ErrorMessage() {}
-
-	Common::String getErrorMessage(uint num);
-};
-
 class VideoResource : public Resource {
 public:
 	VideoResource(Common::String filename) : Resource(filename) {}
@@ -187,19 +179,6 @@ public:
 	Common::SeekableReadStream *getVideoStream(uint num);
 };
 
-class Font {
-public:
-	Font(Common::String filename);
-	virtual ~Font();
-
-	::Graphics::Surface *getLine(Common::String text);
-
-private:
-	uint16 _count, _first, _last, _width, _height;
-
-	::Graphics::Surface _fontSurface;
-};
-
 } // End of namespace Chewy
 
 #endif
diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp
new file mode 100644
index 0000000..da7b227
--- /dev/null
+++ b/engines/chewy/text.cpp
@@ -0,0 +1,160 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/rect.h"
+#include "common/system.h"
+
+#include "chewy/resource.h"
+#include "chewy/text.h"
+
+namespace Chewy {
+
+Text::Text() : Resource("atds.tap") {
+}
+
+Text::~Text() {
+}
+
+DialogList *Text::getDialog(uint dialogNum, uint entryNum) {
+	DialogList *l = new DialogList();
+
+	if (dialogNum >= kADSTextMax)
+		error("getDialog(): Invalid entry number requested, %d (max %d)", dialogNum, kADSTextMax);
+
+	byte *data = getChunkData(dialogNum);
+	byte *ptr = data;
+
+	ptr += 2;	// entry number
+	ptr += 2;	// number of persons
+	ptr += 2;	// automove count
+	ptr += 2;	// cursor number
+	ptr += 13;	// misc data
+
+	for (uint i = 0; i <= entryNum; i++) {
+		do {
+			Dialog curDialog;
+			ptr++;	// current entry
+			ptr += 2;
+			curDialog.speechId = READ_LE_UINT16(ptr) - VOICE_OFFSET;	ptr += 2;
+
+			do {
+				curDialog.text += *ptr++;
+
+				if (*ptr == 0 && *(ptr + 1) != kEndText) {
+					// TODO: Split lines
+					*ptr = ' ';
+				}
+			} while (*ptr != kEndText);
+
+			if (i == entryNum)
+				l->push_back(curDialog);
+
+		} while (*(ptr + 1) != kEndEntry);
+
+		ptr += 2;	// kEndText, kEndEntry
+
+		if (*ptr == kEndBlock)	// not found
+			break;
+	}
+
+	delete[] data;
+
+	return l;
+}
+
+Font::Font(Common::String filename) {
+	const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
+	Common::File stream;
+
+	stream.open(filename);
+
+	uint32 header = stream.readUint32BE();
+
+	if (header != headerFont)
+		error("Invalid resource - %s", filename.c_str());
+
+	stream.skip(4);	// total memory
+	_count = stream.readUint16LE();
+	_first = stream.readUint16LE();
+	_last = stream.readUint16LE();
+	_width = stream.readUint16LE();
+	_height = stream.readUint16LE();
+
+	_fontSurface.create(_width * _count, _height, ::Graphics::PixelFormat::createFormatCLUT8());
+
+	byte cur;
+	int bitIndex = 7;
+	byte *p;
+
+	cur = stream.readByte();
+
+	for (uint n = 0; n < _count; n++) {
+		for (uint y = 0; y < _height; y++) {
+			for (uint x = n * _width; x < n * _width + _width; x++) {
+				p = (byte *)_fontSurface.getBasePtr(x, y);
+				*p = (cur & (1 << bitIndex)) ? 0 : 0xFF;
+
+				bitIndex--;
+				if (bitIndex < 0) {
+					bitIndex = 7;
+					cur = stream.readByte();
+				}
+			}
+		}
+	}
+}
+
+Font::~Font() {
+	_fontSurface.free();
+}
+
+::Graphics::Surface *Font::getLine(Common::String text) {
+	::Graphics::Surface *line = new ::Graphics::Surface();
+	line->create(text.size() * _width, _height, ::Graphics::PixelFormat::createFormatCLUT8());
+
+	for (uint i = 0; i < text.size(); i++) {
+		uint x = (text[i] - _first) * _width;
+		line->copyRectToSurface(_fontSurface, i * _width, 0, Common::Rect(x, 0, x + _width, _height));
+	}
+
+	return line;
+}
+
+Common::String ErrorMessage::getErrorMessage(uint num) {
+	assert(num < _chunkList.size());
+
+	Chunk *chunk = &_chunkList[num];
+	Common::String str;
+	byte *data = new byte[chunk->size];
+
+	_stream.seek(chunk->pos, SEEK_SET);
+	_stream.read(data, chunk->size);
+	if (_encrypted)
+		decrypt(data, chunk->size);
+
+	str = (char *)data;
+	delete[] data;
+
+	return str;
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/text.h b/engines/chewy/text.h
new file mode 100644
index 0000000..fe3e1da
--- /dev/null
+++ b/engines/chewy/text.h
@@ -0,0 +1,105 @@
+/* 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 CHEWY_TEXT_H
+#define CHEWY_TEXT_H
+
+#include "common/list.h"
+#include "chewy/chewy.h"
+#include "chewy/resource.h"
+
+namespace Chewy {
+
+/**
+ * Game texts are contained in txt/atds.tap, and contain the following (in that order):
+ * ADS (Adventure Dialog System) - dialogs, 500 entries max
+ * ATS (Adventure Text System) - text descriptions, 100 entries max
+ * AAD (Adventure Auto Dialog System) - automatic dialogs, 100 entries max
+ * INV - inventory text descriptions, 100 entries max
+ * USE - use action texts, 100 entries max
+ */
+enum MaxTextTypes {
+	kADSTextMax = 500,
+	kATSTextMax = 100,
+	kAADTextMax = 100,
+	kINVTextMax = 100,
+	kUSETextMax = 100
+};
+
+/**
+ * Markers for text entries
+ */
+enum TextEntryMarkers {
+	kEndRow = 0x00,
+	kEndBlock = 0x0b,
+	kEndEntry = 0x0c,
+	kEndText = 0x0d,
+	kEndChunk = 0x0e
+	// There's also 0x0f, block end, which we don't use
+};
+
+#define VOICE_OFFSET 20
+
+struct Dialog {
+	uint16 speechId;
+	Common::String text;
+};
+
+typedef Common::List<Dialog> DialogList;
+
+
+class Text : public Resource {
+public:
+	Text();
+	virtual ~Text();
+
+	DialogList *getDialog(uint dialogNum, uint entryNum);
+	// TODO: getText()
+	// TODO: getAutoDialog()
+	// TODO: getInvDesc()
+	// TODO: getUseText()
+};
+
+class ErrorMessage : public Resource {
+public:
+	ErrorMessage(Common::String filename) : Resource(filename) {}
+	virtual ~ErrorMessage() {}
+
+	Common::String getErrorMessage(uint num);
+};
+
+class Font {
+public:
+	Font(Common::String filename);
+	virtual ~Font();
+
+	::Graphics::Surface *getLine(Common::String text);
+
+private:
+	uint16 _count, _first, _last, _width, _height;
+
+	::Graphics::Surface _fontSurface;
+};
+
+} // End of namespace Chewy
+
+#endif


Commit: 18d6c501fc8f1af50e0e945406233af7ae94a75a
    https://github.com/scummvm/scummvm/commit/18d6c501fc8f1af50e0e945406233af7ae94a75a
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-05T10:47:22+03:00

Commit Message:
CHEWY: Add support for in-game texts

Changed paths:
    engines/chewy/console.cpp
    engines/chewy/console.h
    engines/chewy/resource.cpp
    engines/chewy/text.cpp
    engines/chewy/text.h



diff --git a/engines/chewy/console.cpp b/engines/chewy/console.cpp
index 7fefe45..cb2d5e2 100644
--- a/engines/chewy/console.cpp
+++ b/engines/chewy/console.cpp
@@ -42,6 +42,7 @@ Console::Console(ChewyEngine *vm) : GUI::Debugger(), _vm(vm) {
 	registerCmd("video_info",    WRAP_METHOD(Console, Cmd_VideoInfo));
 	registerCmd("error_message", WRAP_METHOD(Console, Cmd_ErrorMessage));
 	registerCmd("dialog",        WRAP_METHOD(Console, Cmd_Dialog));
+	registerCmd("text",          WRAP_METHOD(Console, Cmd_Text));
 }
 
 Console::~Console() {
@@ -205,9 +206,9 @@ bool Console::Cmd_Dialog(int argc, const char **argv) {
 	int dialogNum = atoi(argv[1]);
 	int entryNum  = atoi(argv[2]);
 	uint cur = 0;
-	DialogList *d = _vm->_text->getDialog(dialogNum, entryNum);
+	TextEntryList *d = _vm->_text->getDialog(dialogNum, entryNum);
 
-	for (DialogList::iterator it = d->begin(); it != d->end(); ++it) {
+	for (TextEntryList::iterator it = d->begin(); it != d->end(); ++it) {
 		this->debugPrintf("Entry %d: speech %d, text '%s'\n", cur, (*it).speechId, (*it).text.c_str());
 	}
 
@@ -217,4 +218,21 @@ bool Console::Cmd_Dialog(int argc, const char **argv) {
 	return true;
 }
 
+bool Console::Cmd_Text(int argc, const char **argv) {
+	if (argc < 3) {
+		debugPrintf("Usage: text <dialog> <entry>\n");
+		return true;
+	}
+
+	int dialogNum = atoi(argv[1]);
+	int entryNum = atoi(argv[2]);
+	TextEntry *d = _vm->_text->getText(dialogNum, entryNum);
+
+	debugPrintf("Speech %d, text '%s'\n", d->speechId, d->text.c_str());
+
+	delete d;
+
+	return true;
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/console.h b/engines/chewy/console.h
index 122f79c..4953480 100644
--- a/engines/chewy/console.h
+++ b/engines/chewy/console.h
@@ -47,6 +47,7 @@ private:
 	bool Cmd_VideoInfo(int argc, const char **argv);
 	bool Cmd_ErrorMessage(int argc, const char **argv);
 	bool Cmd_Dialog(int argc, const char **argv);
+	bool Cmd_Text(int argc, const char **argv);
 };
 
 } // End of namespace Chewy
diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index 07af798..c1164f1 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -40,7 +40,6 @@ namespace Chewy {
 // misc/inventar.iib
 // misc/inventar.sib
 // room/test.rdi
-// txt/atds.tap (game texts)
 // txt/diah.adh
 // txt/inv_st.s and txt/room_st.s (inventory/room control bytes)
 // txt/inv_use.idx
diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp
index da7b227..e877b99 100644
--- a/engines/chewy/text.cpp
+++ b/engines/chewy/text.cpp
@@ -34,11 +34,11 @@ Text::Text() : Resource("atds.tap") {
 Text::~Text() {
 }
 
-DialogList *Text::getDialog(uint dialogNum, uint entryNum) {
-	DialogList *l = new DialogList();
-
+TextEntryList *Text::getDialog(uint dialogNum, uint entryNum) {
 	if (dialogNum >= kADSTextMax)
-		error("getDialog(): Invalid entry number requested, %d (max %d)", dialogNum, kADSTextMax);
+		error("getDialog(): Invalid entry number requested, %d (max %d)", dialogNum, kADSTextMax - 1);
+
+	TextEntryList *l = new TextEntryList();
 
 	byte *data = getChunkData(dialogNum);
 	byte *ptr = data;
@@ -51,7 +51,7 @@ DialogList *Text::getDialog(uint dialogNum, uint entryNum) {
 
 	for (uint i = 0; i <= entryNum; i++) {
 		do {
-			Dialog curDialog;
+			TextEntry curDialog;
 			ptr++;	// current entry
 			ptr += 2;
 			curDialog.speechId = READ_LE_UINT16(ptr) - VOICE_OFFSET;	ptr += 2;
@@ -81,6 +81,59 @@ DialogList *Text::getDialog(uint dialogNum, uint entryNum) {
 	return l;
 }
 
+TextEntry *Text::getText(uint dialogNum, uint entryNum) {
+	if (dialogNum < kADSTextMax)
+		error("getText(): Invalid entry number requested, %d (min %d)", dialogNum, kADSTextMax);
+
+	TextEntry *d = new TextEntry();
+	bool isText = (dialogNum >= kADSTextMax && dialogNum < kADSTextMax + kATSTextMax);
+	bool isAutoDialog = (dialogNum >= kADSTextMax + kATSTextMax && dialogNum < kADSTextMax + kATSTextMax + kAADTextMax);
+	//bool isInvText = (dialogNum >= kADSTextMax + kATSTextMax + kAADTextMax && dialogNum < kADSTextMax + kATSTextMax + kAADTextMax + kINVTextMax);
+
+	byte *data = getChunkData(dialogNum);
+	byte *ptr = data;
+
+	if (isAutoDialog)
+		ptr += 3;
+
+	for (uint i = 0; i <= entryNum; i++) {
+		ptr += 13;
+		d->speechId = READ_LE_UINT16(ptr) - VOICE_OFFSET;	ptr += 2;
+
+		do {
+			if (i == entryNum)
+				d->text += *ptr++;
+			else
+				ptr++;
+
+			if (*ptr == 0 && *(ptr + 1) != kEndText) {
+				// TODO: Split lines
+				*ptr = ' ';
+			}
+		} while (*ptr);
+
+		if (*(ptr + 1) != kEndText || *(ptr + 2) != kEndChunk)
+			error("Invalid text resource - %d", dialogNum);
+
+		if (!isText)
+			ptr += 3;	// 0, kEndText, kEndChunk
+		if (isAutoDialog)
+			ptr += 3;
+
+		if (i == entryNum) {
+			// Found
+			delete[] data;
+			return d;
+		}
+	}
+
+	// Not found
+	delete[] data;
+	delete d;
+
+	return nullptr;
+}
+
 Font::Font(Common::String filename) {
 	const uint32 headerFont = MKTAG('T', 'F', 'F', '\0');
 	Common::File stream;
diff --git a/engines/chewy/text.h b/engines/chewy/text.h
index fe3e1da..f729205 100644
--- a/engines/chewy/text.h
+++ b/engines/chewy/text.h
@@ -38,11 +38,11 @@ namespace Chewy {
  * USE - use action texts, 100 entries max
  */
 enum MaxTextTypes {
-	kADSTextMax = 500,
-	kATSTextMax = 100,
-	kAADTextMax = 100,
-	kINVTextMax = 100,
-	kUSETextMax = 100
+	kADSTextMax = 500,	//   0 - 499
+	kATSTextMax = 100,	// 500 - 599
+	kAADTextMax = 100,	// 600 - 699
+	kINVTextMax = 100,	// 700 - 799
+	kUSETextMax = 100	// 800 - 899
 };
 
 /**
@@ -59,12 +59,12 @@ enum TextEntryMarkers {
 
 #define VOICE_OFFSET 20
 
-struct Dialog {
+struct TextEntry {
 	uint16 speechId;
 	Common::String text;
 };
 
-typedef Common::List<Dialog> DialogList;
+typedef Common::List<TextEntry> TextEntryList;
 
 
 class Text : public Resource {
@@ -72,11 +72,19 @@ public:
 	Text();
 	virtual ~Text();
 
-	DialogList *getDialog(uint dialogNum, uint entryNum);
-	// TODO: getText()
-	// TODO: getAutoDialog()
-	// TODO: getInvDesc()
-	// TODO: getUseText()
+	/**
+	 * Gets a list of lines for a specific dialog entry
+	 */
+	TextEntryList *getDialog(uint dialogNum, uint entryNum);
+
+	/**
+	* Gets a line of text of the following types:
+	* - text (ATS) - 500 - 599
+	* - auto dialog (AAD) - 600 - 699
+	* - inventory text (INV) - 700 - 799
+	* - use text (USE) - 800 - 899
+	*/
+	TextEntry *getText(uint dialogNum, uint entryNum);
 };
 
 class ErrorMessage : public Resource {


Commit: 384b61a9fbf71eeee093fc47168650b1f4bee283
    https://github.com/scummvm/scummvm/commit/384b61a9fbf71eeee093fc47168650b1f4bee283
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-05T10:47:56+03:00

Commit Message:
CHEWY: Optimize font drawing

Thanks to _sev for the suggestion

Changed paths:
    engines/chewy/text.cpp



diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp
index e877b99..5a4a526 100644
--- a/engines/chewy/text.cpp
+++ b/engines/chewy/text.cpp
@@ -162,9 +162,10 @@ Font::Font(Common::String filename) {
 
 	for (uint n = 0; n < _count; n++) {
 		for (uint y = 0; y < _height; y++) {
+			p = (byte *)_fontSurface.getBasePtr(n * _width, y);
+
 			for (uint x = n * _width; x < n * _width + _width; x++) {
-				p = (byte *)_fontSurface.getBasePtr(x, y);
-				*p = (cur & (1 << bitIndex)) ? 0 : 0xFF;
+				*p++ = (cur & (1 << bitIndex)) ? 0 : 0xFF;
 
 				bitIndex--;
 				if (bitIndex < 0) {


Commit: cf7c010d47e8d2babdd051aaccc4b26e42468bb4
    https://github.com/scummvm/scummvm/commit/cf7c010d47e8d2babdd051aaccc4b26e42468bb4
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-07T03:12:00+03:00

Commit Message:
CHEWY: Use new instead of malloc() in the CFO video decoder

Thanks to wjp for noticing this

Changed paths:
    engines/chewy/video/cfo_decoder.cpp



diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 18fc6ea..94363dc 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -209,7 +209,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			delete[] _soundEffects[number];
 
 			_soundEffectSize[number] = frameSize - 2;
-			_soundEffects[number] = (byte *)malloc(frameSize - 2);
+			_soundEffects[number] = new byte[frameSize - 2];
 			_fileStream->read(_soundEffects[number], frameSize - 2);
 			break;
 		case kChunkPlayMusic:


Commit: 7002ede1ed03b1588e18ff41129e000a63081792
    https://github.com/scummvm/scummvm/commit/7002ede1ed03b1588e18ff41129e000a63081792
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-07T03:13:16+03:00

Commit Message:
CHEWY: Const correctness

Changed paths:
    engines/chewy/text.cpp
    engines/chewy/text.h



diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp
index 5a4a526..d56246f 100644
--- a/engines/chewy/text.cpp
+++ b/engines/chewy/text.cpp
@@ -181,7 +181,7 @@ Font::~Font() {
 	_fontSurface.free();
 }
 
-::Graphics::Surface *Font::getLine(Common::String text) {
+::Graphics::Surface *Font::getLine(const Common::String text) {
 	::Graphics::Surface *line = new ::Graphics::Surface();
 	line->create(text.size() * _width, _height, ::Graphics::PixelFormat::createFormatCLUT8());
 
diff --git a/engines/chewy/text.h b/engines/chewy/text.h
index f729205..564f601 100644
--- a/engines/chewy/text.h
+++ b/engines/chewy/text.h
@@ -100,7 +100,7 @@ public:
 	Font(Common::String filename);
 	virtual ~Font();
 
-	::Graphics::Surface *getLine(Common::String text);
+	::Graphics::Surface *getLine(const Common::String text);
 
 private:
 	uint16 _count, _first, _last, _width, _height;


Commit: c3a4950c983235ce566e6fc96856b5848c4a38f5
    https://github.com/scummvm/scummvm/commit/c3a4950c983235ce566e6fc96856b5848c4a38f5
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-07T09:31:16+03:00

Commit Message:
CHEWY: Properly dispose audio streams after use

Changed paths:
    engines/chewy/sound.cpp



diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
index fc27f63..e0e84e2 100644
--- a/engines/chewy/sound.cpp
+++ b/engines/chewy/sound.cpp
@@ -49,7 +49,7 @@ void Sound::playSound(int num, bool loop) {
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(data,
 		sound->size, 22050, Audio::FLAG_UNSIGNED,
-		DisposeAfterUse::NO),
+		DisposeAfterUse::YES),
 		loop ? 0 : 1);
 
 	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
@@ -70,7 +70,7 @@ void Sound::playMusic(int num, bool loop) {
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(data,
 		chunk->size, 22050, Audio::FLAG_UNSIGNED,
-		DisposeAfterUse::NO),
+		DisposeAfterUse::YES),
 		loop ? 0 : 1);
 
 	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream);
@@ -84,7 +84,7 @@ void Sound::playSpeech(int num) {
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(data,
 		sound->size, 22050, Audio::FLAG_UNSIGNED,
-		DisposeAfterUse::NO),
+		DisposeAfterUse::YES),
 		1);
 
 	_mixer->playStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, stream);


Commit: 8df9eb5b8fd5a88a1158f9a6253bd0b18fc52362
    https://github.com/scummvm/scummvm/commit/8df9eb5b8fd5a88a1158f9a6253bd0b18fc52362
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-07T12:29:14+03:00

Commit Message:
CHEWY: Fix undefined behavior

Changed paths:
    engines/chewy/resource.cpp



diff --git a/engines/chewy/resource.cpp b/engines/chewy/resource.cpp
index c1164f1..e112d98 100644
--- a/engines/chewy/resource.cpp
+++ b/engines/chewy/resource.cpp
@@ -251,10 +251,11 @@ SoundChunk *SoundResource::getSound(uint num) {
 	// Find the total length of the voice file
 	do {
 		blocksRemaining = _stream.readByte();
-		blockSize =
-			_stream.readByte() +
-			(_stream.readByte() << 8) +
-			(_stream.readByte() << 16);
+
+		byte b1 = _stream.readByte();
+		byte b2 = _stream.readByte();
+		byte b3 = _stream.readByte();
+		blockSize = b1 + (b2 << 8) + (b3 << 16);
 
 		totalLength += blockSize;
 		_stream.skip(blockSize);
@@ -269,10 +270,11 @@ SoundChunk *SoundResource::getSound(uint num) {
 
 	do {
 		blocksRemaining = _stream.readByte();
-		blockSize =
-			_stream.readByte() +
-			(_stream.readByte() << 8) +
-			(_stream.readByte() << 16);
+
+		byte b1 = _stream.readByte();
+		byte b2 = _stream.readByte();
+		byte b3 = _stream.readByte();
+		blockSize = b1 + (b2 << 8) + (b3 << 16);
 
 		_stream.read(ptr, blockSize);
 		ptr += blockSize;


Commit: 339e1c1f8878509e1f983b7cdc2c3218a8760ebd
    https://github.com/scummvm/scummvm/commit/339e1c1f8878509e1f983b7cdc2c3218a8760ebd
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-09T23:33:19+03:00

Commit Message:
CHEWY: Pass the text parameter of getLine() by reference

Saves an unneeded copy

Changed paths:
    engines/chewy/text.cpp
    engines/chewy/text.h



diff --git a/engines/chewy/text.cpp b/engines/chewy/text.cpp
index d56246f..fcf07a6 100644
--- a/engines/chewy/text.cpp
+++ b/engines/chewy/text.cpp
@@ -181,7 +181,7 @@ Font::~Font() {
 	_fontSurface.free();
 }
 
-::Graphics::Surface *Font::getLine(const Common::String text) {
+::Graphics::Surface *Font::getLine(const Common::String &text) {
 	::Graphics::Surface *line = new ::Graphics::Surface();
 	line->create(text.size() * _width, _height, ::Graphics::PixelFormat::createFormatCLUT8());
 
diff --git a/engines/chewy/text.h b/engines/chewy/text.h
index 564f601..a082de6 100644
--- a/engines/chewy/text.h
+++ b/engines/chewy/text.h
@@ -100,7 +100,7 @@ public:
 	Font(Common::String filename);
 	virtual ~Font();
 
-	::Graphics::Surface *getLine(const Common::String text);
+	::Graphics::Surface *getLine(const Common::String &text);
 
 private:
 	uint16 _count, _first, _last, _width, _height;


Commit: c1e44df357a310a6020e472881e0d1ed29c8ab37
    https://github.com/scummvm/scummvm/commit/c1e44df357a310a6020e472881e0d1ed29c8ab37
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-09T23:34:51+03:00

Commit Message:
CHEWY: Use atds.tap for detection

Now that a lot of the game's resources have been figured out, it turns
out that using comic.tgp was a bad idea, as it's the same in both the
English and German versions. atds.tap contains all of the game's texts,
so it is probably the best candidate for detection

Changed paths:
    engines/chewy/detection.cpp



diff --git a/engines/chewy/detection.cpp b/engines/chewy/detection.cpp
index 57435ad..835a435 100644
--- a/engines/chewy/detection.cpp
+++ b/engines/chewy/detection.cpp
@@ -51,7 +51,7 @@ static const PlainGameDescriptor chewyGames[] = {
 };
 
 static const char *directoryGlobs[] = {
-	"back",
+	"txt",
 	0
 };
 
@@ -63,7 +63,7 @@ static const ChewyGameDescription gameDescriptions[] = {
 		{
 			"chewy",
 			0,
-			AD_ENTRY1s("comic.tgp", "4f03228838663ddecebd750c04687a08", 6529814),
+			AD_ENTRY1s("atds.tap", "e6050c144dd4f23d79ea4f89a8ef306e", 218857),
 			Common::EN_ANY,
 			Common::kPlatformDOS,
 			ADGF_NO_FLAGS,


Commit: 0a4c1eeca1ebd67cb0dcd891aba9a3c05e8e8a80
    https://github.com/scummvm/scummvm/commit/0a4c1eeca1ebd67cb0dcd891aba9a3c05e8e8a80
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-09T23:38:39+03:00

Commit Message:
CHEWY: Move all sound functions into sound.*

Changed paths:
    engines/chewy/graphics.cpp
    engines/chewy/sound.cpp
    engines/chewy/sound.h
    engines/chewy/video/cfo_decoder.cpp
    engines/chewy/video/cfo_decoder.h



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index de95b11..5db2a76 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -115,7 +115,7 @@ void Graphics::drawText(Common::String text, uint x, uint y) {
 }
 
 void Graphics::playVideo(uint num) {
-	CfoDecoder *cfoDecoder = new CfoDecoder(_vm->_mixer);
+	CfoDecoder *cfoDecoder = new CfoDecoder(_vm->_sound);
 	VideoResource *videoResource = new VideoResource("cut.tap");
 	Common::SeekableReadStream *videoStream = videoResource->getVideoStream(num);
 
diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
index e0e84e2..5e519f4 100644
--- a/engines/chewy/sound.cpp
+++ b/engines/chewy/sound.cpp
@@ -41,41 +41,112 @@ Sound::~Sound() {
 	delete _speechRes;
 }
 
-void Sound::playSound(int num, bool loop) {
+void Sound::playSound(int num, bool loop, uint channel) {
 	SoundChunk *sound = _soundRes->getSound(num);
 	byte *data = (byte *)malloc(sound->size);
 	memcpy(data, sound->data, sound->size);
 
+	playSound(data, sound->size, loop, channel);
+
+	delete[] sound->data;
+	delete sound;
+}
+
+void Sound::playSound(byte *data, uint32 size, bool loop, uint channel, DisposeAfterUse::Flag dispose) {
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(data,
-		sound->size, 22050, Audio::FLAG_UNSIGNED,
-		DisposeAfterUse::YES),
+		size, 22050, Audio::FLAG_UNSIGNED,
+		dispose),
 		loop ? 0 : 1);
 
-	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle, stream);
+	_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream);
+}
 
-	delete[] sound->data;
-	delete sound;
+void Sound::pauseSound(uint channel) {
+	assert(channel < MAX_SOUND_EFFECTS);
+	_mixer->pauseHandle(_soundHandle[channel], true);
+}
+
+void Sound::resumeSound(uint channel) {
+	assert(channel < MAX_SOUND_EFFECTS);
+	_mixer->pauseHandle(_soundHandle[channel], false);
+}
+
+void Sound::stopSound(uint channel) {
+	assert(channel < MAX_SOUND_EFFECTS);
+	_mixer->stopHandle(_soundHandle[channel]);
+}
+
+bool Sound::isSoundActive(uint channel) {
+	assert(channel < MAX_SOUND_EFFECTS);
+	return _mixer->isSoundHandleActive(_soundHandle[channel]);
+}
+
+void Sound::setSoundVolume(uint volume) {
+	_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
+}
+
+void Sound::setSoundChannelVolume(uint channel, uint volume) {
+	assert(channel < MAX_SOUND_EFFECTS);
+	_mixer->setChannelVolume(_soundHandle[channel], volume);
+}
+
+void Sound::setSoundChannelBalance(uint channel, uint balance) {
+	assert(channel < MAX_SOUND_EFFECTS);
+	_mixer->setChannelBalance(_soundHandle[channel], balance);
 }
 
 void Sound::playMusic(int num, bool loop) {
 	uint32 musicNum = _soundRes->getChunkCount() - 1 - num;
 	Chunk *chunk = _soundRes->getChunk(musicNum);
 	byte *data = _soundRes->getChunkData(musicNum);
+	
+	playMusic(data, chunk->size, loop);
+
+	delete[] data;
+	delete chunk;
+}
+
+void Sound::playMusic(byte *data, uint32 size, bool loop, DisposeAfterUse::Flag dispose) {
+	byte *modData = nullptr;
+	uint32 modSize;
 
 	// TODO: TMF music files are similar to MOD files. With the following
 	// incorrect implementation, the PCM parts of these files can be played
 	warning("The current music playing implementation is wrong");
+	modSize = size;
+	modData = (byte *)malloc(modSize);
+	memcpy(modData, data, size);
 
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
-		Audio::makeRawStream(data,
-		chunk->size, 22050, Audio::FLAG_UNSIGNED,
-		DisposeAfterUse::YES),
+		Audio::makeRawStream(modData,
+		modSize, 22050, Audio::FLAG_UNSIGNED,
+		dispose),
 		loop ? 0 : 1);
 
 	_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, stream);
 }
 
+void Sound::pauseMusic() {
+	_mixer->pauseHandle(_musicHandle, true);
+}
+
+void Sound::resumeMusic() {
+	_mixer->pauseHandle(_musicHandle, false);
+}
+
+void Sound::stopMusic() {
+	_mixer->stopHandle(_musicHandle);
+}
+
+bool Sound::isMusicActive() {
+	return _mixer->isSoundHandleActive(_musicHandle);
+}
+
+void Sound::setMusicVolume(uint volume) {
+	_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
+}
+
 void Sound::playSpeech(int num) {
 	SoundChunk *sound = _speechRes->getSound(num);
 	byte *data = (byte *)malloc(sound->size);
@@ -93,4 +164,28 @@ void Sound::playSpeech(int num) {
 	delete sound;
 }
 
+void Sound::pauseSpeech() {
+	_mixer->pauseHandle(_speechHandle, true);
+}
+
+void Sound::resumeSpeech() {
+	_mixer->pauseHandle(_speechHandle, false);
+}
+
+void Sound::stopSpeech() {
+	_mixer->stopHandle(_speechHandle);
+}
+
+bool Sound::isSpeechActive() {
+	return _mixer->isSoundHandleActive(_speechHandle);
+}
+
+void Sound::setSpeechVolume(uint volume) {
+	_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume);
+}
+
+void Sound::stopAll() {
+	_mixer->stopAll();
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h
index 7884ead..9b7acab 100644
--- a/engines/chewy/sound.h
+++ b/engines/chewy/sound.h
@@ -30,18 +30,43 @@ namespace Chewy {
 
 class SoundResource;
 
+#define MAX_SOUND_EFFECTS 14
+
 class Sound {
 public:
 	Sound(Audio::Mixer *mixer);
 	virtual ~Sound();
 
-	void playSound(int num, bool loop = false);
+	void playSound(int num, bool loop = false, uint channel = 0);
+	void playSound(byte *data, uint32 size, bool loop = false, uint channel = 0, DisposeAfterUse::Flag dispose = DisposeAfterUse::YES);
+	void pauseSound(uint channel);
+	void resumeSound(uint channel);
+	void stopSound(uint channel);
+	bool isSoundActive(uint channel);
+	void setSoundVolume(uint volume);
+	void setSoundChannelVolume(uint channel, uint volume);
+	void setSoundChannelBalance(uint channel, uint balance);
+
 	void playMusic(int num, bool loop = false);
+	void playMusic(byte *data, uint32 size, bool loop = false, DisposeAfterUse::Flag dispose = DisposeAfterUse::YES);
+	void pauseMusic();
+	void resumeMusic();
+	void stopMusic();
+	bool isMusicActive();
+	void setMusicVolume(uint volume);
+
 	void playSpeech(int num);
+	void pauseSpeech();
+	void resumeSpeech();
+	void stopSpeech();
+	bool isSpeechActive();
+	void setSpeechVolume(uint volume);
+
+	void stopAll();
 
 private:
 	Audio::Mixer *_mixer;
-	Audio::SoundHandle _soundHandle;
+	Audio::SoundHandle _soundHandle[MAX_SOUND_EFFECTS];
 	Audio::SoundHandle _musicHandle;
 	Audio::SoundHandle _speechHandle;
 
diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 94363dc..30f48d2 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -20,15 +20,12 @@
  *
  */
 
-#include "audio/audiostream.h"
-#include "audio/mixer.h"
-#include "audio/decoders/raw.h"
 #include "common/events.h"
-#include "common/stream.h"
 #include "common/system.h"
 #include "engines/engine.h"
 #include "video/flic_decoder.h"
 
+#include "chewy/sound.h"
 #include "chewy/video/cfo_decoder.h"
 
 namespace Chewy {
@@ -70,12 +67,12 @@ bool CfoDecoder::loadStream(Common::SeekableReadStream *stream) {
 	uint16 width = stream->readUint16LE();
 	uint16 height = stream->readUint16LE();
 
-	addTrack(new CfoVideoTrack(stream, frameCount, width, height, _mixer));
+	addTrack(new CfoVideoTrack(stream, frameCount, width, height, _sound));
 	return true;
 }
 
-CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, Audio::Mixer *mixer) :
-	Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true) {
+CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, Sound *sound) :
+	Video::FlicDecoder::FlicVideoTrack(stream, frameCount, width, height, true), _sound(sound) {
 	readHeader();
 
 	for (int i = 0; i < MAX_SOUND_EFFECTS; i++) {
@@ -83,15 +80,18 @@ CfoDecoder::CfoVideoTrack::CfoVideoTrack(Common::SeekableReadStream *stream, uin
 		_soundEffectSize[i] = 0;
 	}
 
-	_mixer = mixer;
+	_musicData = nullptr;
+	_musicSize = 0;
 }
 
 CfoDecoder::CfoVideoTrack::~CfoVideoTrack() {
-	_mixer->stopAll();
+	_sound->stopAll();
 
 	for (int i = 0; i < MAX_SOUND_EFFECTS; i++) {
 		delete[] _soundEffects[i];
 	}
+
+	delete[] _musicData;
 }
 
 void CfoDecoder::CfoVideoTrack::readHeader() {
@@ -105,7 +105,7 @@ void CfoDecoder::CfoVideoTrack::readHeader() {
 #define FRAME_TYPE 0xF1FA
 #define CUSTOM_FRAME_TYPE 0xFAF1
 
-const Graphics::Surface *CfoDecoder::CfoVideoTrack::decodeNextFrame() {
+const ::Graphics::Surface *CfoDecoder::CfoVideoTrack::decodeNextFrame() {
 	uint16 frameType;
 
 	// Read chunk
@@ -164,7 +164,7 @@ void CfoDecoder::CfoVideoTrack::handleFrame() {
 			/* PSTAMP - skip for now */
 			break;
 		default:
-			error("FlicDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType);
+			error("CfoDecoder::decodeNextFrame(): unknown subchunk type (type = 0x%02X)", frameType);
 			break;
 		}
 
@@ -176,7 +176,6 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 	uint16 chunkCount = _fileStream->readUint16LE();
 
 	uint16 delay, number, channel, volume, repeat, balance;
-	Audio::AudioStream *stream;
 
 	// Read subchunks
 	for (uint32 i = 0; i < chunkCount; ++i) {
@@ -196,9 +195,9 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			break;
 		case kChunkLoadMusic:
 			// Used in videos 0, 18, 34, 71
-			warning("kChunkLoadMusic");
-			// TODO
-			_fileStream->skip(frameSize);
+			_musicSize = frameSize;
+			_musicData = new byte[frameSize];
+			_fileStream->read(_musicData, frameSize);
 			break;
 		case kChunkLoadRaw:
 			error("Unused chunk kChunkLoadRaw found");
@@ -214,9 +213,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			break;
 		case kChunkPlayMusic:
 			// Used in videos 0, 18, 34, 71
-			warning("kChunkPlayMusic");
-			// TODO
-			_fileStream->skip(frameSize);
+			_sound->playMusic(_musicData, _musicSize, false, DisposeAfterUse::NO);
 			break;
 		case kChunkPlaySeq:
 			error("Unused chunk kChunkPlaySeq found");
@@ -225,7 +222,11 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			error("Unused chunk kChunkPlayPattern found");
 			break;
 		case kChunkStopMusic:
-			_mixer->stopHandle(_musicHandle);
+			_sound->stopMusic();
+
+			// Game videos do not restart music after stopping it
+			delete[] _musicData;
+			_musicSize = 0;
 			break;
 		case kChunkWaitMusicEnd:
 			do {
@@ -233,12 +234,11 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 				while (g_system->getEventManager()->pollEvent(event)) {}	// ignore events
 				g_system->updateScreen();
 				g_system->delayMillis(10);
-			} while (_mixer->isSoundHandleActive(_musicHandle));
+			} while (_sound->isMusicActive());
 			break;
 		case kChunkSetMusicVolume:
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
-
-			_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
+			_sound->setMusicVolume(volume);
 			break;
 		case kChunkSetLoopMode:
 			error("Unused chunk kChunkSetLoopMode found");
@@ -252,28 +252,19 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
 			repeat = _fileStream->readUint16LE();
 			assert(number < MAX_SOUND_EFFECTS);
-			assert(channel < MAX_SOUND_EFFECTS);
-
-			stream = Audio::makeLoopingAudioStream(
-				Audio::makeRawStream(_soundEffects[number],
-				_soundEffectSize[number], 22050, Audio::FLAG_UNSIGNED,
-				DisposeAfterUse::NO),
-				(repeat == 0) ? 1 : repeat);
 
-			_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
-			_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundHandle[channel], stream);
+			_sound->setSoundVolume(volume);
+			_sound->playSound(_soundEffects[number], _soundEffectSize[number], repeat, channel, DisposeAfterUse::NO);
 			break;
 		case kChunkSetSoundVolume:
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
-
-			_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, volume);
+			_sound->setSoundVolume(volume);
 			break;
 		case kChunkSetChannelVolume:
 			channel = _fileStream->readUint16LE();
 			volume = _fileStream->readUint16LE() * Audio::Mixer::kMaxChannelVolume / 63;
-			assert(channel < MAX_SOUND_EFFECTS);
 
-			_mixer->setChannelVolume(_soundHandle[channel], volume);
+			_sound->setSoundChannelVolume(channel, volume);
 			break;
 		case kChunkFreeSoundEffect:
 			number = _fileStream->readUint16LE();
@@ -294,9 +285,7 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 		case kChunkSetBalance:
 			channel = _fileStream->readUint16LE();
 			balance = (_fileStream->readUint16LE() * 2) - 127;
-			assert(channel < MAX_SOUND_EFFECTS);
-
-			_mixer->setChannelBalance(_soundHandle[channel], balance);
+			_sound->setSoundChannelBalance(channel, balance);
 			break;
 		case kChunkSetSpeed:
 			error("Unused chunk kChunkSetSpeed found");
diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h
index b15b00e..26b97ec 100644
--- a/engines/chewy/video/cfo_decoder.h
+++ b/engines/chewy/video/cfo_decoder.h
@@ -23,7 +23,6 @@
 #ifndef CHEWY_VIDEO_CFO_DECODER_H
 #define CHEWY_VIDEO_CFO_DECODER_H
 
-#include "audio/mixer.h"
 #include "graphics/surface.h"
 #include "video/flic_decoder.h"
 
@@ -31,20 +30,22 @@ namespace Chewy {
 
 #define MAX_SOUND_EFFECTS 14
 
+class Sound;
+
 // A FLIC decoder, with a modified header and additional custom frames
 class CfoDecoder : public Video::FlicDecoder {
 public:
-	CfoDecoder(Audio::Mixer *mixer) : Video::FlicDecoder() { _mixer = mixer; }
+	CfoDecoder(Sound *sound) : Video::FlicDecoder(), _sound(sound) {}
 	virtual ~CfoDecoder() {}
 
 	bool loadStream(Common::SeekableReadStream *stream);
 
 private:
-	Audio::Mixer *_mixer;
+	Sound *_sound;
 
 	class CfoVideoTrack : public Video::FlicDecoder::FlicVideoTrack {
 	public:
-		CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, Audio::Mixer *mixer);
+		CfoVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, Sound *sound);
 		virtual ~CfoVideoTrack();
 
 		void readHeader();
@@ -58,11 +59,12 @@ private:
 		void handleFrame();
 		void handleCustomFrame();
 
-		Audio::Mixer *_mixer;
-		Audio::SoundHandle _musicHandle;
-		Audio::SoundHandle _soundHandle[MAX_SOUND_EFFECTS];
+		Sound *_sound;
+
 		byte *_soundEffects[MAX_SOUND_EFFECTS];
 		uint32 _soundEffectSize[MAX_SOUND_EFFECTS];
+		byte *_musicData;
+		uint32 _musicSize;
 	};
 };
 


Commit: bda8a9b92b50656f28e6745a3e48af108c17b920
    https://github.com/scummvm/scummvm/commit/bda8a9b92b50656f28e6745a3e48af108c17b920
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-09T23:39:41+03:00

Commit Message:
CHEWY: Initial work on converting TMF music data back to MOD data

This way, we can use our regular Protracker MOD player

Changed paths:
    engines/chewy/sound.cpp
    engines/chewy/sound.h



diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
index 5e519f4..b11079a 100644
--- a/engines/chewy/sound.cpp
+++ b/engines/chewy/sound.cpp
@@ -117,6 +117,7 @@ void Sound::playMusic(byte *data, uint32 size, bool loop, DisposeAfterUse::Flag
 	modSize = size;
 	modData = (byte *)malloc(modSize);
 	memcpy(modData, data, size);
+	//convertTMFToMod(data, size, modData, modSize);
 
 	Audio::AudioStream *stream = Audio::makeLoopingAudioStream(
 		Audio::makeRawStream(modData,
@@ -188,4 +189,69 @@ void Sound::stopAll() {
 	_mixer->stopAll();
 }
 
+void Sound::convertTMFToMod(byte *tmfData, uint32 tmfSize, byte *modData, uint32 &modSize) {
+	// Convert the TMF stream back to a regular Protracker MOD stream
+	const int maxInstruments = 31;
+	// Extra bytes needed: 20 bytes song name, 31 * 22 instrument names, 4 magic bytes "M.K."
+	modSize = tmfSize + 20 + maxInstruments * 22 + 4;
+	modData = (byte *)malloc(modSize);
+	byte *tmfPtr = tmfData;
+	byte *modPtr = modData;
+
+	const byte songName[20] = {
+		'S', 'C', 'U', 'M', 'M',
+		'V', 'M', ' ', 'M', 'O',
+		'D', 'U', 'L', 'E', '\0',
+		'\0', '\0', '\0', '\0', '\0'
+	};
+	const byte instrumentName[22] = {
+		'S', 'C', 'U', 'M', 'M',
+		'V', 'M', ' ', 'I', 'N',
+		'S', 'T', 'R', 'U', 'M',
+		'E', 'N', 'T', '\0', '\0',
+		'\0', '\0'
+	};
+
+	if (READ_BE_UINT32(tmfPtr) != MKTAG('T', 'M', 'F', '\0'))
+		error("Corrupt TBF resource");
+	tmfPtr += 4;
+
+	memcpy(modPtr, songName, 20);
+	modPtr += 20;
+
+	byte fineTune, instVolume;
+	uint16 repeatPoint, repeatLength, sampleLength;
+
+	for (int i = 0; i < maxInstruments; i++) {
+		fineTune = *tmfPtr++;
+		instVolume = *tmfPtr++;
+		repeatPoint = READ_BE_UINT16(tmfPtr);	tmfPtr += 2;
+		repeatLength = READ_BE_UINT16(tmfPtr);	tmfPtr += 2;
+		sampleLength = READ_BE_UINT16(tmfPtr);	tmfPtr += 2;
+
+		// Instrument name
+		memcpy(modPtr, instrumentName, 18);	modPtr += 18;
+		*modPtr++ = ' ';
+		*modPtr++ = i / 10;
+		*modPtr++ = i % 10;
+		*modPtr++ = '\0';
+
+		WRITE_BE_UINT16(modPtr, sampleLength / 2);	modPtr += 2;
+		*modPtr++ = fineTune;
+		*modPtr++ = instVolume;
+		WRITE_BE_UINT16(modPtr, repeatPoint / 2);	modPtr += 2;
+		WRITE_BE_UINT16(modPtr, repeatLength / 2);	modPtr += 2;
+	}
+
+	*modPtr++ = *tmfPtr++;	// song length
+	*modPtr++ = *tmfPtr++;	// undef
+	memcpy(modPtr, tmfPtr, 128);
+	modPtr += 128;
+	tmfPtr += 128;
+	WRITE_BE_UINT32(modPtr, MKTAG('M', '.', 'K', '.'));	modPtr += 4;
+	// TODO: 31 bytes instrument positions
+
+	// TODO: notes
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/sound.h b/engines/chewy/sound.h
index 9b7acab..a39cf5d 100644
--- a/engines/chewy/sound.h
+++ b/engines/chewy/sound.h
@@ -72,6 +72,8 @@ private:
 
 	SoundResource *_speechRes;
 	SoundResource *_soundRes;
+
+	void convertTMFToMod(byte *tmfData, uint32 tmfSize, byte *modData, uint32 &modSize);
 };
 
 } // End of namespace Chewy


Commit: a292fcdd93bb41b11ac1a22849b44150362795ab
    https://github.com/scummvm/scummvm/commit/a292fcdd93bb41b11ac1a22849b44150362795ab
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-10T04:41:31+03:00

Commit Message:
CHEWY: Fix typo

Changed paths:
    engines/chewy/sound.cpp



diff --git a/engines/chewy/sound.cpp b/engines/chewy/sound.cpp
index b11079a..36f2d63 100644
--- a/engines/chewy/sound.cpp
+++ b/engines/chewy/sound.cpp
@@ -213,7 +213,7 @@ void Sound::convertTMFToMod(byte *tmfData, uint32 tmfSize, byte *modData, uint32
 	};
 
 	if (READ_BE_UINT32(tmfPtr) != MKTAG('T', 'M', 'F', '\0'))
-		error("Corrupt TBF resource");
+		error("Corrupt TMF resource");
 	tmfPtr += 4;
 
 	memcpy(modPtr, songName, 20);


Commit: 684cbfa2fdee6d2927409670a22ecc571ef31a02
    https://github.com/scummvm/scummvm/commit/684cbfa2fdee6d2927409670a22ecc571ef31a02
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-10T04:42:06+03:00

Commit Message:
CHEWY: Add support for palette fadeout to videos

Changed paths:
    engines/chewy/graphics.cpp
    engines/chewy/video/cfo_decoder.cpp
    engines/chewy/video/cfo_decoder.h



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 5db2a76..0861a34 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -128,7 +128,9 @@ void Graphics::playVideo(uint num) {
 	uint16 x = (g_system->getWidth() - cfoDecoder->getWidth()) / 2;
 	uint16 y = (g_system->getHeight() - cfoDecoder->getHeight()) / 2;
 	bool skipVideo = false;
+	byte curPalette[256 * 3];
 
+	g_system->getPaletteManager()->grabPalette(curPalette, 0, 256);
 	hideCursor();
 
 	cfoDecoder->start();
@@ -157,6 +159,7 @@ void Graphics::playVideo(uint num) {
 
 	cfoDecoder->close();
 
+	g_system->getPaletteManager()->setPalette(curPalette, 0, 256);
 	showCursor();
 }
 
diff --git a/engines/chewy/video/cfo_decoder.cpp b/engines/chewy/video/cfo_decoder.cpp
index 30f48d2..0d8fcd7 100644
--- a/engines/chewy/video/cfo_decoder.cpp
+++ b/engines/chewy/video/cfo_decoder.cpp
@@ -23,6 +23,7 @@
 #include "common/events.h"
 #include "common/system.h"
 #include "engines/engine.h"
+#include "graphics/palette.h"
 #include "video/flic_decoder.h"
 
 #include "chewy/sound.h"
@@ -175,7 +176,7 @@ void CfoDecoder::CfoVideoTrack::handleFrame() {
 void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 	uint16 chunkCount = _fileStream->readUint16LE();
 
-	uint16 delay, number, channel, volume, repeat, balance;
+	uint16 number, channel, volume, repeat, balance;
 
 	// Read subchunks
 	for (uint32 i = 0; i < chunkCount; ++i) {
@@ -188,10 +189,8 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 			break;
 		case kChunkFadeOut:
 			// Used in video 0
-			delay = _fileStream->readUint16LE();
-
-			warning("kChunkFadeOut, delay %d", delay);
-			// TODO
+			_fileStream->skip(2);	// delay, unused
+			fadeOut();
 			break;
 		case kChunkLoadMusic:
 			// Used in videos 0, 18, 34, 71
@@ -300,4 +299,21 @@ void CfoDecoder::CfoVideoTrack::handleCustomFrame() {
 	}
 }
 
+void CfoDecoder::CfoVideoTrack::fadeOut() {
+	for (int j = 0; j < 64; j++) {
+		for (int i = 0; i < 256; i++) {
+			if (_palette[i * 3 + 0] > 0)
+				--_palette[i * 3 + 0];
+			if (_palette[i * 3 + 1] > 0)
+				--_palette[i * 3 + 1];
+			if (_palette[i * 3 + 2] > 0)
+				--_palette[i * 3 + 2];
+		}
+
+		g_system->getPaletteManager()->setPalette(_palette, 0, 256);
+		g_system->updateScreen();
+		g_system->delayMillis(10);
+	}
+}
+
 } // End of namespace Chewy
diff --git a/engines/chewy/video/cfo_decoder.h b/engines/chewy/video/cfo_decoder.h
index 26b97ec..1495821 100644
--- a/engines/chewy/video/cfo_decoder.h
+++ b/engines/chewy/video/cfo_decoder.h
@@ -58,6 +58,7 @@ private:
 	private:
 		void handleFrame();
 		void handleCustomFrame();
+		void fadeOut();
 
 		Sound *_sound;
 


Commit: 375618828f5131dc3a838b51ffca7f7a6973b8f2
    https://github.com/scummvm/scummvm/commit/375618828f5131dc3a838b51ffca7f7a6973b8f2
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-10T04:50:35+03:00

Commit Message:
CHEWY: Move cursor related functions into a separate file

Changed paths:
  A engines/chewy/cursor.cpp
  A engines/chewy/cursor.h
    engines/chewy/chewy.cpp
    engines/chewy/chewy.h
    engines/chewy/events.cpp
    engines/chewy/graphics.cpp
    engines/chewy/graphics.h
    engines/chewy/module.mk



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 3845bfd..1172728 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -31,6 +31,7 @@
 
 #include "chewy/chewy.h"
 #include "chewy/console.h"
+#include "chewy/cursor.h"
 #include "chewy/events.h"
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
@@ -59,12 +60,14 @@ ChewyEngine::~ChewyEngine() {
 	delete _events;
 	delete _text;
 	delete _sound;
+	delete _cursor;
 	delete _graphics;
 	delete _console;
 }
 
 void ChewyEngine::initialize() {
 	_console = new Console(this);
+	_cursor = new Cursor(this);
 	_graphics = new Graphics(this);
 	_sound = new Sound(_mixer);
 	_text = new Text();
@@ -92,8 +95,8 @@ Common::Error ChewyEngine::run() {
 	_graphics->drawSprite("det1.taf", 0, 200, 100);
 	_graphics->loadFont("6x8.tff");
 	_graphics->drawText("This is a test", 200, 80);
-	_graphics->showCursor();
-	_graphics->setCursor(0);
+	_cursor->showCursor();
+	_cursor->setCursor(0);
 	//_sound->playSpeech(1);
 	//_sound->playSound(1);
 	//_sound->playMusic(2);
@@ -106,7 +109,7 @@ Common::Error ChewyEngine::run() {
 
 		// Cursor animation
 		if (_elapsedFrames % 30 == 0)
-			_graphics->animateCursor();
+			_cursor->animateCursor();
 
 		if (_videoNum >= 0) {
 			_graphics->playVideo(_videoNum);
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 7caed6e..64ec3a4 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -38,6 +38,7 @@ namespace Chewy {
 
 struct ChewyGameDescription;
 class Console;
+class Cursor;
 class Events;
 class Graphics;
 class Sound;
@@ -59,6 +60,7 @@ public:
 	void setPlayVideo(uint num) { _videoNum = num; }
 
 	Graphics *_graphics;
+	Cursor *_cursor;
 	Sound *_sound;
 	Text *_text;
 
diff --git a/engines/chewy/cursor.cpp b/engines/chewy/cursor.cpp
new file mode 100644
index 0000000..18e001f
--- /dev/null
+++ b/engines/chewy/cursor.cpp
@@ -0,0 +1,107 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "common/events.h"
+#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+#include "chewy/cursor.h"
+#include "chewy/resource.h"
+
+namespace Chewy {
+
+const byte _cursorFrames[] = {
+	4, 1, 1, 1,		// walk
+	4, 1, 1, 1,		// pick up / use
+	1, 1, 1, 1, 1,
+	4, 1, 1, 1,		// look
+	4, 1, 1, 1,		// talk
+	4, 1, 1, 1,		// open
+	1,
+	1, 1, 1, 1,		// left, right, up, down
+	1,				// save
+	1,
+	5, 1, 1, 1, 1,
+	1,
+	1,				// use (inventory)
+	1,				// look (inventory)
+	1				// gun
+};
+
+Cursor::Cursor(ChewyEngine *vm) : _vm(vm) {
+	_curCursor = 0;
+	_curCursorFrame = 0;
+	_cursorSprites = new SpriteResource("cursor.taf");
+}
+
+Cursor::~Cursor() {
+	delete _cursorSprites;
+}
+
+void Cursor::setCursor(uint num, bool newCursor) {
+	TAFChunk *cursor = _cursorSprites->getSprite(num);
+	if (newCursor)
+		_curCursor = num;
+
+	CursorMan.replaceCursor(cursor->data, cursor->width, cursor->height, 0, 0, 0);
+
+	delete[] cursor->data;
+	delete cursor;
+}
+
+void Cursor::showCursor() {
+	CursorMan.showMouse(true);
+}
+
+void Cursor::hideCursor() {
+	CursorMan.showMouse(false);
+}
+
+void Cursor::animateCursor() {
+	if (_cursorFrames[_curCursor] > 1) {
+		_curCursorFrame++;
+
+		if (_curCursorFrame >= _cursorFrames[_curCursor])
+			_curCursorFrame = 0;
+
+		setCursor(_curCursor + _curCursorFrame, false);
+	}
+}
+
+void Cursor::nextCursor() {
+	uint maxCursors = ARRAYSIZE(_cursorFrames);
+
+	if (_cursorFrames[_curCursor] > 0)
+		_curCursor += _cursorFrames[_curCursor];
+	else
+		_curCursor++;
+
+	if (_curCursor >= maxCursors)
+		_curCursor = 0;
+
+	_curCursorFrame = 0;
+	setCursor(_curCursor);
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/cursor.h b/engines/chewy/cursor.h
new file mode 100644
index 0000000..1ab75d0
--- /dev/null
+++ b/engines/chewy/cursor.h
@@ -0,0 +1,54 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_CURSOR_H
+#define CHEWY_CURSOR_H
+
+#include "chewy/chewy.h"
+
+namespace Chewy {
+
+class SpriteResource;
+class Font;
+
+class Cursor {
+public:
+	Cursor(ChewyEngine *vm);
+	virtual ~Cursor();
+
+	void setCursor(uint num, bool newCursor = true);
+	void showCursor();
+	void hideCursor();
+	void animateCursor();
+	void nextCursor();
+
+private:
+	ChewyEngine *_vm;
+
+	uint _curCursor;
+	uint _curCursorFrame;
+	SpriteResource *_cursorSprites;
+};
+
+} // End of namespace Chewy
+
+#endif
diff --git a/engines/chewy/events.cpp b/engines/chewy/events.cpp
index cfbcb8b..6675fea 100644
--- a/engines/chewy/events.cpp
+++ b/engines/chewy/events.cpp
@@ -25,6 +25,7 @@
 
 #include "chewy/chewy.h"
 #include "chewy/console.h"
+#include "chewy/cursor.h"
 #include "chewy/events.h"
 #include "chewy/graphics.h"
 
@@ -44,7 +45,7 @@ void Events::processEvents() {
 				_vm->quitGame();
 				break;
 			case Common::KEYCODE_SPACE:
-				_graphics->nextCursor();
+				_vm->_cursor->nextCursor();
 				break;
 			case Common::KEYCODE_d:
 				if (_event.kbd.flags & Common::KBD_CTRL)
@@ -54,7 +55,7 @@ void Events::processEvents() {
 				break;
 			}
 		} else if (_event.type == Common::EVENT_RBUTTONUP) {
-			_graphics->nextCursor();
+			_vm->_cursor->nextCursor();
 		}
 	}
 }
diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 0861a34..427d4fa 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -26,6 +26,7 @@
 #include "graphics/palette.h"
 #include "graphics/surface.h"
 
+#include "chewy/cursor.h"
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
 #include "chewy/text.h"
@@ -52,15 +53,11 @@ const byte _cursorFrames[] = {
 };
 
 Graphics::Graphics(ChewyEngine *vm) : _vm(vm) {
-	_curCursor = 0;
-	_curCursorFrame = 0;
-	_cursorSprites = new SpriteResource("cursor.taf");
 	_font = nullptr;
 }
 
 Graphics::~Graphics() {
 	delete _font;
-	delete _cursorSprites;
 }
 
 void Graphics::drawSprite(Common::String filename, int spriteNum, uint x, uint y) {
@@ -131,7 +128,7 @@ void Graphics::playVideo(uint num) {
 	byte curPalette[256 * 3];
 
 	g_system->getPaletteManager()->grabPalette(curPalette, 0, 256);
-	hideCursor();
+	_vm->_cursor->hideCursor();
 
 	cfoDecoder->start();
 
@@ -160,52 +157,7 @@ void Graphics::playVideo(uint num) {
 	cfoDecoder->close();
 
 	g_system->getPaletteManager()->setPalette(curPalette, 0, 256);
-	showCursor();
-}
-
-void Graphics::setCursor(uint num, bool newCursor) {
-	TAFChunk *cursor = _cursorSprites->getSprite(num);
-	if (newCursor)
-		_curCursor = num;
-
-	CursorMan.replaceCursor(cursor->data, cursor->width, cursor->height, 0, 0, 0);
-
-	delete[] cursor->data;
-	delete cursor;
-}
-
-void Graphics::showCursor() {
-	CursorMan.showMouse(true);
-}
-
-void Graphics::hideCursor() {
-	CursorMan.showMouse(false);
-}
-
-void Graphics::animateCursor() {
-	if (_cursorFrames[_curCursor] > 1) {
-		_curCursorFrame++;
-
-		if (_curCursorFrame >= _cursorFrames[_curCursor])
-			_curCursorFrame = 0;
-
-		setCursor(_curCursor + _curCursorFrame, false);
-	}
-}
-
-void Graphics::nextCursor() {
-	uint maxCursors = ARRAYSIZE(_cursorFrames);
-
-	if (_cursorFrames[_curCursor] > 0)
-		_curCursor += _cursorFrames[_curCursor];
-	else
-		_curCursor++;
-
-	if (_curCursor >= maxCursors)
-		_curCursor = 0;
-
-	_curCursorFrame = 0;
-	setCursor(_curCursor);
+	_vm->_cursor->showCursor();
 }
 
 } // End of namespace Chewy
diff --git a/engines/chewy/graphics.h b/engines/chewy/graphics.h
index a3f6005..a260311 100644
--- a/engines/chewy/graphics.h
+++ b/engines/chewy/graphics.h
@@ -41,20 +41,10 @@ public:
 	void loadFont(Common::String filename);
 	void drawText(Common::String text, uint x, uint y);
 
-	void setCursor(uint num, bool newCursor = true);
-	void showCursor();
-	void hideCursor();
-	void animateCursor();
-	void nextCursor();
-
 private:
 	void drawTransparent(uint16 x, uint16 y, byte *data, uint16 width, uint16 height, byte transparentColor);
 
 	ChewyEngine *_vm;
-
-	uint _curCursor;
-	uint _curCursorFrame;
-	SpriteResource *_cursorSprites;
 	Font *_font;
 };
 
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index 38b4265..e13a69a 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/chewy
 
 MODULE_OBJS = \
 	chewy.o \
+	cursor.o \
 	console.o \
 	detection.o \
 	events.o \


Commit: 5fbf9ad17168fead64ccd71d3493b9271b55bac5
    https://github.com/scummvm/scummvm/commit/5fbf9ad17168fead64ccd71d3493b9271b55bac5
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-10T05:05:19+03:00

Commit Message:
CHEWY: Remove duplicate table

Changed paths:
    engines/chewy/graphics.cpp



diff --git a/engines/chewy/graphics.cpp b/engines/chewy/graphics.cpp
index 427d4fa..07a3abe 100644
--- a/engines/chewy/graphics.cpp
+++ b/engines/chewy/graphics.cpp
@@ -34,24 +34,6 @@
 
 namespace Chewy {
 
-const byte _cursorFrames[] = {
-	4, 1, 1, 1,		// walk
-	4, 1, 1, 1,		// pick up / use
-	1, 1, 1, 1, 1,
-	4, 1, 1, 1,		// look
-	4, 1, 1, 1,		// talk
-	4, 1, 1, 1,		// open
-	1,
-	1, 1, 1, 1,		// left, right, up, down
-	1,				// save
-	1,
-	5, 1, 1, 1, 1,
-	1,
-	1,				// use (inventory)
-	1,				// look (inventory)
-	1				// gun
-};
-
 Graphics::Graphics(ChewyEngine *vm) : _vm(vm) {
 	_font = nullptr;
 }


Commit: 53de49a052426151a1afb1de0b6843d1b8127b9b
    https://github.com/scummvm/scummvm/commit/53de49a052426151a1afb1de0b6843d1b8127b9b
Author: Filippos Karapetis (bluegr at gmail.com)
Date: 2016-10-10T05:05:42+03:00

Commit Message:
CHEWY: Create a scene class

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



diff --git a/engines/chewy/chewy.cpp b/engines/chewy/chewy.cpp
index 1172728..75243cc 100644
--- a/engines/chewy/chewy.cpp
+++ b/engines/chewy/chewy.cpp
@@ -35,6 +35,7 @@
 #include "chewy/events.h"
 #include "chewy/graphics.h"
 #include "chewy/resource.h"
+#include "chewy/scene.h"
 #include "chewy/sound.h"
 #include "chewy/text.h"
 
@@ -61,6 +62,7 @@ ChewyEngine::~ChewyEngine() {
 	delete _text;
 	delete _sound;
 	delete _cursor;
+	delete _scene;
 	delete _graphics;
 	delete _console;
 }
@@ -69,6 +71,7 @@ void ChewyEngine::initialize() {
 	_console = new Console(this);
 	_cursor = new Cursor(this);
 	_graphics = new Graphics(this);
+	_scene = new Scene(this);
 	_sound = new Sound(_mixer);
 	_text = new Text();
 	_events = new Events(this, _graphics, _console);
@@ -91,12 +94,8 @@ Common::Error ChewyEngine::run() {
 	}*/
 
 	//_graphics->playVideo(0);
-	_graphics->drawImage("episode1.tgp", 0);
-	_graphics->drawSprite("det1.taf", 0, 200, 100);
-	_graphics->loadFont("6x8.tff");
-	_graphics->drawText("This is a test", 200, 80);
-	_cursor->showCursor();
-	_cursor->setCursor(0);
+	
+	_scene->change(0);
 	//_sound->playSpeech(1);
 	//_sound->playSound(1);
 	//_sound->playMusic(2);
@@ -113,6 +112,7 @@ Common::Error ChewyEngine::run() {
 
 		if (_videoNum >= 0) {
 			_graphics->playVideo(_videoNum);
+			_scene->draw();
 			_videoNum = -1;
 		}
 
diff --git a/engines/chewy/chewy.h b/engines/chewy/chewy.h
index 64ec3a4..6ebeff8 100644
--- a/engines/chewy/chewy.h
+++ b/engines/chewy/chewy.h
@@ -41,6 +41,7 @@ class Console;
 class Cursor;
 class Events;
 class Graphics;
+class Scene;
 class Sound;
 class Text;
 
@@ -61,6 +62,7 @@ public:
 
 	Graphics *_graphics;
 	Cursor *_cursor;
+	Scene *_scene;
 	Sound *_sound;
 	Text *_text;
 
diff --git a/engines/chewy/module.mk b/engines/chewy/module.mk
index e13a69a..5752e28 100644
--- a/engines/chewy/module.mk
+++ b/engines/chewy/module.mk
@@ -8,6 +8,7 @@ MODULE_OBJS = \
 	events.o \
 	graphics.o \
 	resource.o \
+	scene.o \
 	sound.o \
 	text.o \
 	video/cfo_decoder.o
diff --git a/engines/chewy/scene.cpp b/engines/chewy/scene.cpp
new file mode 100644
index 0000000..03e4332
--- /dev/null
+++ b/engines/chewy/scene.cpp
@@ -0,0 +1,59 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/system.h"
+#include "common/events.h"
+#include "graphics/cursorman.h"
+#include "graphics/palette.h"
+#include "graphics/surface.h"
+
+#include "chewy/cursor.h"
+#include "chewy/graphics.h"
+#include "chewy/scene.h"
+#include "chewy/resource.h"
+#include "chewy/text.h"
+#include "chewy/video/cfo_decoder.h"
+
+namespace Chewy {
+
+Scene::Scene(ChewyEngine *vm) : _vm(vm) {
+}
+
+Scene::~Scene() {
+}
+
+void Scene::change(uint scene) {
+	_curScene = scene;
+	_vm->_cursor->setCursor(0);
+	_vm->_cursor->showCursor();
+	
+	draw();
+}
+
+void Scene::draw() {
+	_vm->_graphics->drawImage("episode1.tgp", _curScene);
+	_vm->_graphics->drawSprite("det1.taf", 0, 200, 100);
+	_vm->_graphics->loadFont("6x8.tff");
+	_vm->_graphics->drawText("This is a test", 200, 80);
+}
+
+} // End of namespace Chewy
diff --git a/engines/chewy/scene.h b/engines/chewy/scene.h
new file mode 100644
index 0000000..37601d0
--- /dev/null
+++ b/engines/chewy/scene.h
@@ -0,0 +1,45 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef CHEWY_SCENE_H
+#define CHEWY_SCENE_H
+
+#include "chewy/chewy.h"
+
+namespace Chewy {
+
+class Scene {
+public:
+	Scene(ChewyEngine *vm);
+	virtual ~Scene();
+
+	void change(uint scene);
+	void draw();
+
+private:
+	ChewyEngine *_vm;
+	uint _curScene;
+};
+
+} // End of namespace Chewy
+
+#endif


Commit: af2027ddd19b7ac14b3671e80fd6eca1a2a6b12d
    https://github.com/scummvm/scummvm/commit/af2027ddd19b7ac14b3671e80fd6eca1a2a6b12d
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2016-10-15T13:51:00+02:00

Commit Message:
Merge pull request #838 from bluegr/chewy

Chewy: Esc from F5. New WIP engine.

Changed paths:
  A engines/chewy/chewy.cpp
  A engines/chewy/chewy.h
  A engines/chewy/configure.engine
  A engines/chewy/console.cpp
  A engines/chewy/console.h
  A engines/chewy/cursor.cpp
  A engines/chewy/cursor.h
  A engines/chewy/detection.cpp
  A engines/chewy/events.cpp
  A engines/chewy/events.h
  A engines/chewy/graphics.cpp
  A engines/chewy/graphics.h
  A engines/chewy/module.mk
  A engines/chewy/resource.cpp
  A engines/chewy/resource.h
  A engines/chewy/scene.cpp
  A engines/chewy/scene.h
  A engines/chewy/sound.cpp
  A engines/chewy/sound.h
  A engines/chewy/text.cpp
  A engines/chewy/text.h
  A engines/chewy/video/cfo_decoder.cpp
  A engines/chewy/video/cfo_decoder.h
    video/flic_decoder.cpp
    video/flic_decoder.h








More information about the Scummvm-git-logs mailing list