[Scummvm-cvs-logs] scummvm master -> 7f5f9c9f91eb8cd52ebcffe208d0e778f8ff6448

DrMcCoy drmccoy at drmccoy.de
Sat Sep 3 18:05:59 CEST 2011


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

Summary:
eebd5a28f9 GOB: Add Util::readString()
cceaa04ef2 GOB: Make Util::setExtension() not add an extension to an empty string
44b83551aa GOB: Add the Amiga version of Geisha
2985f118b8 GOB: Add class RXYFile
37964e8e85 GOB: Add class DECFile
a4f42017d7 GOB: Add class ANIFile
220fc2b593 GOB: Add class ANIObject
dbb70e3d6f GOB: Add class Geisha::EvilFish
26dd2f5f60 GOB: Move keyPressed() to Util
7f5f9c9f91 GOB: Stub classes for Geisha's Diving and Penetration minigames


Commit: eebd5a28f9a76f3021041480fd22d218bcfa18d9
    https://github.com/scummvm/scummvm/commit/eebd5a28f9a76f3021041480fd22d218bcfa18d9
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:08-07:00

Commit Message:
GOB: Add Util::readString()

Changed paths:
    engines/gob/util.cpp
    engines/gob/util.h



diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 6d83745..1add604 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -20,6 +20,10 @@
  *
  */
 
+#include "common/stream.h"
+#include "common/events.h"
+
+#include "graphics/palette.h"
 
 #include "gob/gob.h"
 #include "gob/util.h"
@@ -31,10 +35,6 @@
 #include "gob/videoplayer.h"
 #include "gob/sound/sound.h"
 
-#include "common/events.h"
-
-#include "graphics/palette.h"
-
 namespace Gob {
 
 Util::Util(GobEngine *vm) : _vm(vm) {
@@ -534,6 +534,23 @@ Common::String Util::setExtension(const Common::String &str, const Common::Strin
 	return str + ext;
 }
 
+Common::String Util::readString(Common::SeekableReadStream &stream, int n) {
+	Common::String str;
+
+	char c;
+	while (n-- > 0) {
+		if ((c = stream.readByte()) == '\0')
+			break;
+
+		str += c;
+	}
+
+	if (n > 0)
+		stream.skip(n);
+
+	return str;
+}
+
 /* NOT IMPLEMENTED */
 void Util::checkJoystick() {
 	_vm->_global->_useJoystick = 0;
diff --git a/engines/gob/util.h b/engines/gob/util.h
index a6a689c..7c1e44c 100644
--- a/engines/gob/util.h
+++ b/engines/gob/util.h
@@ -23,8 +23,13 @@
 #ifndef GOB_UTIL_H
 #define GOB_UTIL_H
 
+#include "common/str.h"
 #include "common/keyboard.h"
 
+namespace Common {
+	class SeekableReadStream;
+}
+
 namespace Gob {
 
 class GobEngine;
@@ -131,6 +136,9 @@ public:
 	static char *setExtension(char *str, const char *ext);
 	static Common::String setExtension(const Common::String &str, const Common::String &ext);
 
+	/** Read a constant-length string out of a stream. */
+	static Common::String readString(Common::SeekableReadStream &stream, int n);
+
 	Util(GobEngine *vm);
 
 protected:


Commit: cceaa04ef23d766bc666324e69b8fa6fbfa1e39a
    https://github.com/scummvm/scummvm/commit/cceaa04ef23d766bc666324e69b8fa6fbfa1e39a
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:08-07:00

Commit Message:
GOB: Make Util::setExtension() not add an extension to an empty string

Changed paths:
    engines/gob/util.cpp



diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 1add604..58dfc9c 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -518,6 +518,11 @@ void Util::deleteList(List *list) {
 }
 
 char *Util::setExtension(char *str, const char *ext) {
+	assert(str && ext);
+
+	if (str[0] == '\0')
+		return str;
+
 	char *dot = strrchr(str, '.');
 	if (dot)
 		*dot = '\0';
@@ -527,6 +532,9 @@ char *Util::setExtension(char *str, const char *ext) {
 }
 
 Common::String Util::setExtension(const Common::String &str, const Common::String &ext) {
+	if (str.empty())
+		return str;
+
 	const char *dot = strrchr(str.c_str(), '.');
 	if (dot)
 		return Common::String(str.c_str(), dot - str.c_str()) + ext;


Commit: 44b83551aa1d6aee8e6e9a643bfade93d1aa5fef
    https://github.com/scummvm/scummvm/commit/44b83551aa1d6aee8e6e9a643bfade93d1aa5fef
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:08-07:00

Commit Message:
GOB: Add the Amiga version of Geisha

Changed paths:
    engines/gob/detection_tables.h



diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h
index 4c1ff9a..9c13b4f 100644
--- a/engines/gob/detection_tables.h
+++ b/engines/gob/detection_tables.h
@@ -2515,6 +2515,20 @@ static const GOBGameDescription gameDescriptions[] = {
 	},
 	{
 		{
+			"geisha",
+			"",
+			AD_ENTRY1s("disk1.stk", "e5892f00917c62423e93f5fd9920cf47", 208120),
+			UNK_LANG,
+			kPlatformAmiga,
+			ADGF_NO_FLAGS,
+			GUIO_NOSUBTITLES | GUIO_NOSPEECH
+		},
+		kGameTypeGeisha,
+		kFeaturesEGA,
+		"disk1.stk", "intro.tot", 0
+	},
+	{
+		{
 			"gob3",
 			"",
 			AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084),


Commit: 2985f118b802d231aa5ec328c8b61e1419c14e48
    https://github.com/scummvm/scummvm/commit/2985f118b802d231aa5ec328c8b61e1419c14e48
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Add class RXYFile

Handles RXY files, containing relative sprite coordinates.
Used in hardcoded "actiony" parts of gob games, like
Geisha's minigames.

Changed paths:
  A engines/gob/rxyfile.cpp
  A engines/gob/rxyfile.h
    engines/gob/module.mk



diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 0300bcc..a026964 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -53,6 +53,7 @@ MODULE_OBJS := \
 	mult_v2.o \
 	palanim.o \
 	resources.o \
+	rxyfile.o \
 	scenery.o \
 	scenery_v1.o \
 	scenery_v2.o \
diff --git a/engines/gob/rxyfile.cpp b/engines/gob/rxyfile.cpp
new file mode 100644
index 0000000..5311eec
--- /dev/null
+++ b/engines/gob/rxyfile.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 "gob/rxyfile.h"
+
+namespace Gob {
+
+RXYFile::RXYFile(Common::SeekableReadStream &rxy) : _width(0), _height(0) {
+	load(rxy);
+}
+
+RXYFile::~RXYFile() {
+}
+
+uint RXYFile::size() const {
+	return _coords.size();
+}
+
+uint16 RXYFile::getWidth() const {
+	return _width;
+}
+
+uint16 RXYFile::getHeight() const {
+	return _height;
+}
+
+uint16 RXYFile::getRealCount() const {
+	return _realCount;
+}
+
+const RXYFile::Coordinates &RXYFile::operator[](uint i) const {
+	assert(i < _coords.size());
+
+	return _coords[i];
+}
+
+void RXYFile::load(Common::SeekableReadStream &rxy) {
+	if (rxy.size() < 2)
+		return;
+
+	rxy.seek(0);
+
+	_realCount = rxy.readUint16LE();
+
+	uint16 count = (rxy.size() - 2) / 8;
+
+	_coords.resize(count);
+	for (CoordArray::iterator c = _coords.begin(); c != _coords.end(); ++c) {
+		c->left   = rxy.readUint16LE();
+		c->right  = rxy.readUint16LE();
+		c->top    = rxy.readUint16LE();
+		c->bottom = rxy.readUint16LE();
+
+		if (c->left != 0xFFFF) {
+			_width  = MAX<uint16>(_width , c->right  + 1);
+			_height = MAX<uint16>(_height, c->bottom + 1);
+		}
+	}
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/rxyfile.h b/engines/gob/rxyfile.h
new file mode 100644
index 0000000..828f8b7
--- /dev/null
+++ b/engines/gob/rxyfile.h
@@ -0,0 +1,76 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_RXYFILE_H
+#define GOB_RXYFILE_H
+
+#include "common/system.h"
+#include "common/array.h"
+
+namespace Common {
+	class SeekableReadStream;
+}
+
+namespace Gob {
+
+/** A RXY file, containing relative sprite coordinates.
+ *
+ *  Used in hardcoded "actiony" parts of gob games.
+ */
+class RXYFile {
+public:
+	struct Coordinates {
+		uint16 left;
+		uint16 top;
+		uint16 right;
+		uint16 bottom;
+	};
+
+	RXYFile(Common::SeekableReadStream &rxy);
+	~RXYFile();
+
+	uint size() const;
+
+	uint16 getWidth () const;
+	uint16 getHeight() const;
+
+	uint16 getRealCount() const;
+
+	const Coordinates &operator[](uint i) const;
+
+private:
+	typedef Common::Array<Coordinates> CoordArray;
+
+	CoordArray _coords;
+
+	uint16 _realCount;
+
+	uint16 _width;
+	uint16 _height;
+
+
+	void load(Common::SeekableReadStream &rxy);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_RXYFILE_H


Commit: 37964e8e85137ff7cb3a317c34b6a6210b7564d4
    https://github.com/scummvm/scummvm/commit/37964e8e85137ff7cb3a317c34b6a6210b7564d4
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Add class DECFile

Handles DEC files, describing "decals" (backgrounds).
Used in hardcoded "actiony" parts of gob games, like
Geisha's minigames.

Changed paths:
  A engines/gob/decfile.cpp
  A engines/gob/decfile.h
    engines/gob/module.mk



diff --git a/engines/gob/decfile.cpp b/engines/gob/decfile.cpp
new file mode 100644
index 0000000..f5910f0
--- /dev/null
+++ b/engines/gob/decfile.cpp
@@ -0,0 +1,214 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/str.h"
+#include "common/stream.h"
+#include "common/substream.h"
+
+#include "gob/gob.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/surface.h"
+#include "gob/video.h"
+#include "gob/rxyfile.h"
+#include "gob/decfile.h"
+
+namespace Gob {
+
+DECFile::Layer::Layer() : surface(0), coordinates(0) {
+}
+
+DECFile::Layer::~Layer() {
+	delete coordinates;
+	delete surface;
+}
+
+
+DECFile::DECFile(GobEngine *vm, const Common::String &fileName,
+                 uint16 width, uint16 height, uint8 bpp) : _vm(vm),
+	_width(width), _height(height), _bpp(bpp), _hasPadding(false) {
+
+	_backdrop = new Surface(_width, _height, _bpp);
+
+	Common::SeekableReadStream *dec = _vm->_dataIO->getFile(fileName);
+	if (dec) {
+		Common::SeekableSubReadStreamEndian sub(dec, 0, dec->size(), false, DisposeAfterUse::YES);
+
+		load(sub, fileName);
+		return;
+	}
+
+	// File doesn't exist, try to open the big-endian'd alternate file
+	Common::String alternateFileName = fileName;
+	alternateFileName.setChar('_', 0);
+
+	dec = _vm->_dataIO->getFile(alternateFileName);
+	if (dec) {
+		Common::SeekableSubReadStreamEndian sub(dec, 0, dec->size(), true, DisposeAfterUse::YES);
+
+		// The big endian version pads a few fields to even size
+		_hasPadding = true;
+
+		load(sub, fileName);
+		return;
+	}
+
+	warning("DECFile::DECFile(): No such file \"%s\"", fileName.c_str());
+}
+
+DECFile::~DECFile() {
+	delete _backdrop;
+}
+
+void DECFile::load(Common::SeekableSubReadStreamEndian &dec, const Common::String &fileName) {
+	dec.skip(2); // Unused
+
+	int16 backdropCount = dec.readUint16();
+	int16 layerCount    = dec.readUint16();
+
+	// Sanity checks
+	if (backdropCount > 1)
+		warning("DECFile::load(): More than one backdrop (%d) in file \"%s\"",
+		        backdropCount, fileName.c_str());
+	if (layerCount < 1)
+		warning("DECFile::load(): Less than one layer (%d) in file \"%s\"",
+		        layerCount, fileName.c_str());
+
+	// Load the backdrop
+	if (backdropCount > 0) {
+		loadBackdrop(dec);
+
+		// We only support one backdrop, skip the rest
+		dec.skip((backdropCount - 1) * (13 + (_hasPadding ? 1 : 0)));
+	}
+
+	// Load the layers
+	_layers.resize(MAX(0, layerCount - 1));
+	for (LayerArray::iterator l = _layers.begin(); l != _layers.end(); ++l)
+		loadLayer(*l, dec);
+
+	// Load the backdrop parts
+	if (backdropCount > 0)
+		loadParts(dec);
+}
+
+void DECFile::loadBackdrop(Common::SeekableSubReadStreamEndian &dec) {
+	// Interestingly, DEC files reference "FOO.LBM" instead of "FOO.CMP"
+	Common::String file = Util::setExtension(Util::readString(dec, 13), ".CMP");
+	if (_hasPadding)
+		dec.skip(1);
+
+	if (file.empty() || !_vm->_dataIO->hasFile(file))
+		return;
+
+	_vm->_video->drawPackedSprite(file.c_str(), *_backdrop);
+}
+
+void DECFile::loadLayer(Layer &layer, Common::SeekableSubReadStreamEndian &dec) {
+	Common::String file = Util::readString(dec, 13);
+	if (_hasPadding)
+		dec.skip(1);
+
+	if (file.empty())
+		return;
+
+	Common::String fileRXY = Util::setExtension(file, ".RXY");
+	Common::String fileCMP = Util::setExtension(file, ".CMP");
+	if (!_vm->_dataIO->hasFile(fileRXY) || !_vm->_dataIO->hasFile(fileCMP))
+		return;
+
+	loadLayer(layer, fileRXY, fileCMP);
+}
+
+void DECFile::loadLayer(Layer &layer, const Common::String &fileRXY,
+                                      const Common::String &fileCMP) {
+
+	Common::SeekableReadStream *dataRXY = _vm->_dataIO->getFile(fileRXY);
+	if (!dataRXY)
+		return;
+
+	layer.coordinates = new RXYFile(*dataRXY);
+	layer.surface     = new Surface(_width, layer.coordinates->getHeight(), _bpp);
+
+	_vm->_video->drawPackedSprite(fileCMP.c_str(), *layer.surface);
+}
+
+void DECFile::loadParts(Common::SeekableSubReadStreamEndian &dec) {
+	dec.skip(13); // Name
+	if (_hasPadding)
+		dec.skip(1);
+
+	dec.skip(13); // File?
+	if (_hasPadding)
+		dec.skip(1);
+
+	uint16 partCount = dec.readUint16();
+
+	_parts.resize(partCount);
+	for (PartArray::iterator p = _parts.begin(); p != _parts.end(); ++p)
+		loadPart(*p, dec);
+}
+
+void DECFile::loadPart(Part &part, Common::SeekableSubReadStreamEndian &dec) {
+	part.layer = dec.readByte() - 1;
+	part.part  = dec.readByte();
+
+	dec.skip(1); // Unknown
+
+	part.x = dec.readUint16();
+	part.y = dec.readUint16();
+
+	part.transp = dec.readByte() != 0;
+}
+
+void DECFile::draw(Surface &dest) const {
+	drawBackdrop(dest);
+
+	for (PartArray::const_iterator p = _parts.begin(); p != _parts.end(); ++p)
+		drawLayer(dest, p->layer, p->part, p->x, p->y, p->transp ? 0 : -1);
+}
+
+void DECFile::drawBackdrop(Surface &dest) const {
+	dest.blit(*_backdrop);
+}
+
+void DECFile::drawLayer(Surface &dest, uint16 layer, uint16 part,
+                        uint16 x, uint16 y, int32 transp) const {
+
+	if (layer >= _layers.size())
+		return;
+
+	const Layer &l = _layers[layer];
+	if (!l.surface || !l.coordinates)
+		return;
+
+	if (part >= l.coordinates->size())
+		return;
+
+	const RXYFile::Coordinates &c = (*l.coordinates)[part];
+	if (c.left == 0xFFFF)
+		return;
+
+	dest.blit(*l.surface, c.left, c.top, c.right, c.bottom, x, y, transp);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/decfile.h b/engines/gob/decfile.h
new file mode 100644
index 0000000..31d9018
--- /dev/null
+++ b/engines/gob/decfile.h
@@ -0,0 +1,111 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_DECFILE_H
+#define GOB_DECFILE_H
+
+#include "common/system.h"
+
+namespace Common {
+	class String;
+	class SeekableSubReadStreamEndian;
+}
+
+namespace Gob {
+
+class GobEngine;
+class Surface;
+class RXYFile;
+
+/** A DEC file, describing a "decal" (background).
+ *
+ *  Used in hardcoded "actiony" parts of gob games.
+ *  The principle is similar to a Static in Scenery (see scenery.cpp), but
+ *  instead of referencing indices in the sprites array, DECs reference sprites
+ *  directly by filename.
+ */
+class DECFile {
+public:
+	DECFile(GobEngine *vm, const Common::String &fileName,
+	        uint16 width, uint16 height, uint8 bpp = 1);
+	~DECFile();
+
+	/** Draw the background, including all default layer parts. */
+	void draw(Surface &dest) const;
+
+	/** Explicitly draw the backdrop. */
+	void drawBackdrop(Surface &dest) const;
+
+	/** Explicitly draw a layer part. */
+	void drawLayer(Surface &dest, uint16 layer, uint16 part,
+	               uint16 x, uint16 y, int32 transp = -1) const;
+
+private:
+	struct Layer {
+		Surface *surface;     ///< The surface containing the layer sprite.
+		RXYFile *coordinates; ///< The coordinates describing the layer sprite parts.
+
+		Layer();
+		~Layer();
+	};
+
+	struct Part {
+		uint8 layer;
+		uint8 part;
+
+		uint16 x;
+		uint16 y;
+		bool transp;
+	};
+
+	typedef Common::Array<Layer> LayerArray;
+	typedef Common::Array<Part>  PartArray;
+
+	GobEngine *_vm;
+
+	uint16 _width;
+	uint16 _height;
+	uint8  _bpp;
+
+	byte _hasPadding;
+
+	Surface *_backdrop;
+
+	LayerArray _layers;
+	PartArray  _parts;
+
+
+	void load(Common::SeekableSubReadStreamEndian &dec, const Common::String &fileName);
+
+	void loadBackdrop(Common::SeekableSubReadStreamEndian &dec);
+
+	void loadLayer(Layer &layer, Common::SeekableSubReadStreamEndian &dec);
+	void loadLayer(Layer &layer, const Common::String &fileRXY,
+	                             const Common::String &fileCMP);
+
+	void loadParts(Common::SeekableSubReadStreamEndian &dec);
+	void loadPart(Part &part, Common::SeekableSubReadStreamEndian &dec);
+};
+
+} // End of namespace Gob
+
+#endif // GOB_DECFILE_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index a026964..0fdbdf9 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -5,6 +5,7 @@ MODULE_OBJS := \
 	dataio.o \
 	databases.o \
 	dbase.o \
+	decfile.o \
 	detection.o \
 	draw.o \
 	draw_v1.o \


Commit: a4f42017d7a43ae0e8cd7c61d6af746a19c410f5
    https://github.com/scummvm/scummvm/commit/a4f42017d7a43ae0e8cd7c61d6af746a19c410f5
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Add class ANIFile

Handles ANI files, describing animations.
Used in hardcoded "actiony" parts of gob games, like
Geisha's minigames.

Changed paths:
  A engines/gob/anifile.cpp
  A engines/gob/anifile.h
    engines/gob/module.mk



diff --git a/engines/gob/anifile.cpp b/engines/gob/anifile.cpp
new file mode 100644
index 0000000..1a905f1
--- /dev/null
+++ b/engines/gob/anifile.cpp
@@ -0,0 +1,326 @@
+/* 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/substream.h"
+
+#include "gob/gob.h"
+#include "gob/util.h"
+#include "gob/dataio.h"
+#include "gob/surface.h"
+#include "gob/video.h"
+#include "gob/anifile.h"
+
+namespace Gob {
+
+ANIFile::Layer::Layer() : surface(0), coordinates(0) {
+}
+
+ANIFile::Layer::~Layer() {
+	delete coordinates;
+	delete surface;
+}
+
+
+ANIFile::ANIFile(GobEngine *vm, const Common::String &fileName,
+                 uint16 width, uint8 bpp) : _vm(vm),
+	_width(width), _bpp(bpp), _hasPadding(false) {
+
+	Common::SeekableReadStream *ani = _vm->_dataIO->getFile(fileName);
+	if (ani) {
+		Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), false, DisposeAfterUse::YES);
+
+		load(sub, fileName);
+		return;
+	}
+
+	// File doesn't exist, try to open the big-endian'd alternate file
+	Common::String alternateFileName = fileName;
+	alternateFileName.setChar('_', 0);
+
+	ani = _vm->_dataIO->getFile(alternateFileName);
+	if (ani) {
+		Common::SeekableSubReadStreamEndian sub(ani, 0, ani->size(), true, DisposeAfterUse::YES);
+
+		// The big endian version pads a few fields to even size
+		_hasPadding = true;
+
+		load(sub, fileName);
+		return;
+	}
+
+	warning("ANIFile::ANIFile(): No such file \"%s\"", fileName.c_str());
+}
+
+ANIFile::~ANIFile() {
+}
+
+void ANIFile::load(Common::SeekableSubReadStreamEndian &ani, const Common::String &fileName) {
+	ani.skip(2); // Unused
+
+	uint16 animationCount = ani.readUint16();
+	uint16 layerCount     = ani.readUint16();
+
+	if (layerCount < 1)
+		warning("ANIFile::load(): Less than one layer (%d) in file \"%s\"",
+		        layerCount, fileName.c_str());
+
+		// Load the layers
+	if (layerCount > 0) {
+		ani.skip(13); // The first layer is ignored?
+		if (_hasPadding)
+			ani.skip(1);
+
+		_layers.resize(layerCount - 1);
+		for (LayerArray::iterator l = _layers.begin(); l != _layers.end(); ++l)
+			loadLayer(*l, ani);
+	}
+
+	_maxWidth  = 0;
+	_maxHeight = 0;
+
+	// Load the animations
+	_animations.resize(animationCount);
+	_frames.resize(animationCount);
+
+	for (uint16 animation = 0; animation < animationCount; animation++) {
+		loadAnimation(_animations[animation], _frames[animation], ani);
+
+		_maxWidth  = MAX<uint16>(_maxWidth , _animations[animation].width);
+		_maxHeight = MAX<uint16>(_maxHeight, _animations[animation].height);
+	}
+}
+
+void ANIFile::loadAnimation(Animation &animation, FrameArray &frames,
+                            Common::SeekableSubReadStreamEndian &ani) {
+
+	// Animation properties
+
+	animation.name = Util::readString(ani, 13);
+	if (_hasPadding)
+		ani.skip(1);
+
+	ani.skip(13); // The name a second time?!?
+	if (_hasPadding)
+		ani.skip(1);
+
+	ani.skip(2);  // Unknown
+
+	animation.x      = (int16) ani.readUint16();
+	animation.y      = (int16) ani.readUint16();
+	animation.deltaX = (int16) ani.readUint16();
+	animation.deltaY = (int16) ani.readUint16();
+
+	animation.transp = ani.readByte() != 0;
+
+	if (_hasPadding)
+		ani.skip(1);
+
+	uint16 frameCount = ani.readUint16();
+
+	// Load the frames
+
+	frames.resize(MAX<uint16>(1, frameCount));
+	loadFrames(frames, ani);
+
+	animation.frameCount = frames.size();
+
+	animation.width  = 0;
+	animation.height = 0;
+
+	// Calculate the areas of each frame
+
+	animation.frameAreas.resize(animation.frameCount);
+	for (uint16 i = 0; i < animation.frameCount; i++) {
+		const ChunkList &frame = frames[i];
+		FrameArea &area = animation.frameAreas[i];
+
+		area.left  = area.top    =  0x7FFF;
+		area.right = area.bottom = -0x7FFF;
+
+		for (ChunkList::const_iterator c = frame.begin(); c != frame.end(); c++) {
+			const Layer *layer;
+			const RXYFile::Coordinates *coords;
+
+			if (!getPart(c->layer, c->part, layer, coords))
+				continue;
+
+			const uint16 width  = coords->right  - coords->left + 1;
+			const uint16 height = coords->bottom - coords->top  + 1;
+
+			const uint16 l = c->x;
+			const uint16 t = c->y;
+			const uint16 r = l + width  - 1;
+			const uint16 b = t + height - 1;
+
+			area.left   = MIN<int16>(area.left  , l);
+			area.top    = MIN<int16>(area.top   , t);
+			area.right  = MAX<int16>(area.right , r);
+			area.bottom = MAX<int16>(area.bottom, b);
+		}
+
+		if ((area.left <= area.right) && (area.top <= area.bottom)) {
+			animation.width  = MAX<uint16>(animation.width , area.right  - area.left + 1);
+			animation.height = MAX<uint16>(animation.height, area.bottom - area.top  + 1);
+		}
+	}
+}
+
+void ANIFile::loadFrames(FrameArray &frames, Common::SeekableSubReadStreamEndian &ani) {
+	uint32 curFrame = 0;
+
+	bool end = false;
+	while (!end) {
+		frames[curFrame].push_back(AnimationChunk());
+		AnimationChunk &chunk = frames[curFrame].back();
+
+		uint8 layerFlags = ani.readByte();
+
+		// Chunk properties
+		chunk.layer = (layerFlags & 0x0F) - 1;
+		chunk.part  = ani.readByte();
+		chunk.x     = (int8) ani.readByte();
+		chunk.y     = (int8) ani.readByte();
+
+		// X multiplier/offset
+		int16 xOff = ((layerFlags & 0xC0) >> 6) << 7;
+		if (chunk.x >= 0)
+			chunk.x += xOff;
+		else
+			chunk.x -= xOff;
+
+		// Y multiplier/offset
+		int16 yOff = ((layerFlags & 0x30) >> 4) << 7;
+		if (chunk.y >= 0)
+			chunk.y += yOff;
+		else
+			chunk.y -= yOff;
+
+		uint8 multiPart = ani.readByte();
+		if      (multiPart == 0xFF) // No more frames in this animation
+			end = true;
+		else if (multiPart != 0x01) // No more chunks in this frame
+			curFrame++;
+
+		// Shouldn't happen, but just to be safe
+		if (curFrame >= frames.size())
+			frames.resize(curFrame + 1);
+
+		if (_hasPadding)
+			ani.skip(1);
+
+		if (ani.eos() || ani.err())
+			error("ANIFile::loadFrames(): Read error");
+	}
+}
+
+void ANIFile::loadLayer(Layer &layer, Common::SeekableSubReadStreamEndian &ani) {
+	Common::String file = Util::readString(ani, 13);
+	if (_hasPadding)
+		ani.skip(1);
+
+	if (file.empty())
+		return;
+
+	Common::String fileRXY = Util::setExtension(file, ".RXY");
+	Common::String fileCMP = Util::setExtension(file, ".CMP");
+	if (!_vm->_dataIO->hasFile(fileRXY) || !_vm->_dataIO->hasFile(fileCMP))
+		return;
+
+	loadLayer(layer, fileRXY, fileCMP);
+}
+
+void ANIFile::loadLayer(Layer &layer, const Common::String &fileRXY,
+                                      const Common::String &fileCMP) {
+
+	Common::SeekableReadStream *dataRXY = _vm->_dataIO->getFile(fileRXY);
+	if (!dataRXY)
+		return;
+
+	layer.coordinates = new RXYFile(*dataRXY);
+	layer.surface     = new Surface(_width, layer.coordinates->getHeight(), _bpp);
+
+	_vm->_video->drawPackedSprite(fileCMP.c_str(), *layer.surface);
+}
+
+uint16 ANIFile::getAnimationCount() const {
+	return _animations.size();
+}
+
+void ANIFile::getMaxSize(uint16 &width, uint16 &height) const {
+	width  = _maxWidth;
+	height = _maxHeight;
+}
+
+const ANIFile::Animation &ANIFile::getAnimationInfo(uint16 animation) const {
+	assert(animation < _animations.size());
+
+	return _animations[animation];
+}
+
+bool ANIFile::getPart(uint16 layer, uint16 part,
+                      const Layer *&l, const RXYFile::Coordinates *&c) const {
+
+	if (layer >= _layers.size())
+		return false;
+
+	l = &_layers[layer];
+	if (!l->surface || !l->coordinates)
+		return false;
+
+	if (part >= l->coordinates->size())
+		return false;
+
+	c = &(*l->coordinates)[part];
+	if (c->left == 0xFFFF)
+		return false;
+
+	return true;
+}
+
+void ANIFile::draw(Surface &dest, uint16 animation, uint16 frame, int16 x, int16 y) const {
+	if (animation >= _animations.size())
+		return;
+
+	const Animation &anim = _animations[animation];
+	if (frame >= anim.frameCount)
+		return;
+
+	const ChunkList &chunks = _frames[animation][frame];
+
+	for (ChunkList::const_iterator c = chunks.begin(); c != chunks.end(); ++c)
+		drawLayer(dest, c->layer, c->part, x + c->x, y + c->y, anim.transp ? 0 : -1);
+}
+
+void ANIFile::drawLayer(Surface &dest, uint16 layer, uint16 part,
+                        int16 x, int16 y, int32 transp) const {
+
+	const Layer *l;
+	const RXYFile::Coordinates *c;
+
+	if (!getPart(layer, part, l, c))
+		return;
+
+	dest.blit(*l->surface, c->left, c->top, c->right, c->bottom, x, y, transp);
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/anifile.h b/engines/gob/anifile.h
new file mode 100644
index 0000000..1e10da6
--- /dev/null
+++ b/engines/gob/anifile.h
@@ -0,0 +1,161 @@
+/* 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 GOB_ANIFILE_H
+#define GOB_ANIFILE_H
+
+#include "common/system.h"
+#include "common/str.h"
+#include "common/array.h"
+#include "common/list.h"
+
+#include "gob/rxyfile.h"
+
+namespace Common {
+	class SeekableSubReadStreamEndian;
+}
+
+namespace Gob {
+
+class GobEngine;
+class Surface;
+
+/** An ANI file, describing an animation.
+ *
+ *  Used in hardcoded "actiony" parts of gob games.
+ *  The principle is similar to an Anim in Scenery (see scenery.cpp), but
+ *  instead of referencing indices in the sprites array, ANIs reference sprites
+ *  directly by filename.
+ */
+class ANIFile {
+public:
+	/** The relative area a frame sprite occupies. */
+	struct FrameArea {
+		int16 left;
+		int16 top;
+		int16 right;
+		int16 bottom;
+	};
+
+	/** An animation within an ANI file. */
+	struct Animation {
+		Common::String name; ///< The name of the animation.
+
+		uint16 frameCount; ///< The number of frames in this animation.
+
+		int16 x;     ///< The default x position for this animation.
+		int16 y;     ///< The default y position for this animation.
+		bool transp; ///< Should the animation frames be drawn with transparency?
+
+		int16 deltaX; ///< # of pixels to advance in X direction after each cycle.
+		int16 deltaY; ///< # of pixels to advance in Y direction after each cycle.
+
+		/** The relative area each frame sprite occupies. */
+		Common::Array<FrameArea> frameAreas;
+
+		uint16 width;  ///< The maximum width of this animation's frames.
+		uint16 height; ///< The maximum height of this animation's frames.
+	};
+
+
+	ANIFile(GobEngine *vm, const Common::String &fileName,
+	        uint16 width = 320, uint8 bpp = 1);
+	~ANIFile();
+
+	/** Return the number of animations in this ANI file. */
+	uint16 getAnimationCount() const;
+
+	/** Return the maximum size of all animation frames. */
+	void getMaxSize(uint16 &width, uint16 &height) const;
+
+	/** Get this animation's properties. */
+	const Animation &getAnimationInfo(uint16 animation) const;
+
+	/** Draw an animation frame. */
+	void draw(Surface &dest, uint16 animation, uint16 frame, int16 x, int16 y) const;
+
+private:
+	/** A sprite layer. */
+	struct Layer {
+		Surface *surface;     ///< The surface containing the layer sprite.
+		RXYFile *coordinates; ///< The coordinates describing the layer sprite parts.
+
+		Layer();
+		~Layer();
+	};
+
+	typedef Common::Array<Layer> LayerArray;
+	typedef Common::Array<Animation> AnimationArray;
+
+	/** A "chunk" of an animation frame. */
+	struct AnimationChunk {
+		int16 x; ///< The relative x offset of this chunk.
+		int16 y; ///< The relative y offset of this chunk.
+
+		uint16 layer; ///< The layer the chunk's sprite is on.
+		uint16 part;  ///< The layer part the chunk's sprite is.
+	};
+
+	typedef Common::List<AnimationChunk> ChunkList;
+	typedef Common::Array<ChunkList>     FrameArray;
+	typedef Common::Array<FrameArray>    AnimationFrameArray;
+
+
+	GobEngine *_vm;
+
+	uint16 _width; ///< The width of a sprite layer.
+	uint8  _bpp;   ///< Number of bytes per pixel in a sprite layer.
+
+	byte _hasPadding;
+
+	LayerArray          _layers;     ///< The animation sprite layers.
+	AnimationArray      _animations; ///< The animations.
+	AnimationFrameArray _frames;     ///< The animation frames.
+
+	uint16 _maxWidth;
+	uint16 _maxHeight;
+
+
+	// Loading helpers
+
+	void load(Common::SeekableSubReadStreamEndian &ani, const Common::String &fileName);
+
+	void loadLayer(Layer &layer, Common::SeekableSubReadStreamEndian &ani);
+	void loadLayer(Layer &layer, const Common::String &fileRXY,
+	                             const Common::String &fileCMP);
+
+	void loadAnimation(Animation &animation, FrameArray &frames,
+	                   Common::SeekableSubReadStreamEndian &ani);
+	void loadFrames(FrameArray &frames, Common::SeekableSubReadStreamEndian &ani);
+
+	// Drawing helpers
+
+	bool getPart(uint16 layer, uint16 part,
+	             const Layer *&l, const RXYFile::Coordinates *&c) const;
+
+	void drawLayer(Surface &dest, uint16 layer, uint16 part,
+	              int16 x, int16 y, int32 transp) const;
+};
+
+} // End of namespace Gob
+
+#endif // GOB_ANIFILE_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 0fdbdf9..a2a78bc 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -1,6 +1,7 @@
 MODULE := engines/gob
 
 MODULE_OBJS := \
+	anifile.o \
 	console.o \
 	dataio.o \
 	databases.o \


Commit: 220fc2b59307734a26057fa6446ed13fa2c543a1
    https://github.com/scummvm/scummvm/commit/220fc2b59307734a26057fa6446ed13fa2c543a1
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Add class ANIObject

Controls an animation stored within an ANI file.

Changed paths:
  A engines/gob/aniobject.cpp
  A engines/gob/aniobject.h
    engines/gob/module.mk



diff --git a/engines/gob/aniobject.cpp b/engines/gob/aniobject.cpp
new file mode 100644
index 0000000..c6a9234
--- /dev/null
+++ b/engines/gob/aniobject.cpp
@@ -0,0 +1,185 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/surface.h"
+#include "gob/anifile.h"
+#include "gob/aniobject.h"
+
+namespace Gob {
+
+ANIObject::ANIObject(const ANIFile &ani) : _ani(&ani), _visible(false),
+	_x(0), _y(0), _background(0), _drawn(false) {
+
+	setAnimation(0);
+	setPosition();
+}
+
+ANIObject::~ANIObject() {
+	delete _background;
+}
+
+void ANIObject::setVisible(bool visible) {
+	_visible = visible;
+}
+
+bool ANIObject::isVisible() const {
+	return _visible;
+}
+
+void ANIObject::setAnimation(uint16 animation) {
+	_animation = animation;
+	_frame     = 0;
+}
+
+void ANIObject::setPosition() {
+	if (_animation >= _ani->getAnimationCount())
+		return;
+
+	const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
+
+	_x = animation.x;
+	_y = animation.y;
+}
+
+void ANIObject::setPosition(int16 x, int16 y) {
+	_x = x;
+	_y = y;
+}
+
+void ANIObject::getPosition(int16 &x, int16 &y) const {
+	x = _x;
+	y = _y;
+}
+
+void ANIObject::getFramePosition(int16 &x, int16 &y) const {
+	if (_animation >= _ani->getAnimationCount())
+		return;
+
+	const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
+	if (_frame >= animation.frameCount)
+		return;
+
+	x = _x + animation.frameAreas[_frame].left;
+	y = _y + animation.frameAreas[_frame].top;
+}
+
+void ANIObject::getFrameSize(int16 &width, int16 &height) const {
+	if (_animation >= _ani->getAnimationCount())
+		return;
+
+	const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
+	if (_frame >= animation.frameCount)
+		return;
+
+	width  = animation.frameAreas[_frame].right  - animation.frameAreas[_frame].left + 1;
+	height = animation.frameAreas[_frame].bottom - animation.frameAreas[_frame].top  + 1;
+}
+
+void ANIObject::draw(Surface &dest, int16 &left, int16 &top,
+                                    int16 &right, int16 &bottom) {
+
+	if (!_visible)
+		return;
+
+	if (!_background) {
+		uint16 width, height;
+
+		_ani->getMaxSize(width, height);
+
+		_background = new Surface(width, height, dest.getBPP());
+	}
+
+	const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
+	if (_frame >= animation.frameCount)
+		return;
+
+	const ANIFile::FrameArea &area = animation.frameAreas[_frame];
+
+	_backgroundLeft   = CLIP<int16>(area.left   + _x, 0, dest.getWidth () - 1);
+	_backgroundTop    = CLIP<int16>(area.top    + _y, 0, dest.getHeight() - 1);
+	_backgroundRight  = CLIP<int16>(area.right  + _x, 0, dest.getWidth () - 1);
+	_backgroundBottom = CLIP<int16>(area.bottom + _y, 0, dest.getHeight() - 1);
+
+	_background->blit(dest, _backgroundLeft , _backgroundTop,
+	                        _backgroundRight, _backgroundBottom, 0, 0);
+
+	_ani->draw(dest, _animation, _frame, _x, _y);
+
+	_drawn = true;
+
+	left   = _backgroundLeft;
+	top    = _backgroundTop;
+	right  = _backgroundRight;
+	bottom = _backgroundBottom;
+}
+
+void ANIObject::clear(Surface &dest, int16 &left, int16 &top,
+                                     int16 &right, int16 &bottom) {
+
+	if (!_drawn)
+		return;
+
+	const int16 bgRight  = _backgroundRight  - _backgroundLeft;
+	const int16 bgBottom = _backgroundBottom - _backgroundTop;
+
+	dest.blit(*_background, 0, 0, bgRight, bgBottom, _backgroundLeft, _backgroundTop);
+
+	_drawn = false;
+
+	left   = _backgroundLeft;
+	top    = _backgroundTop;
+	right  = _backgroundRight;
+	bottom = _backgroundBottom;
+}
+
+void ANIObject::advance() {
+	if (_animation >= _ani->getAnimationCount())
+		return;
+
+	const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
+
+	_frame = (_frame + 1) % animation.frameCount;
+
+	if (_frame == 0) {
+		_x += animation.deltaX;
+		_y += animation.deltaY;
+	}
+}
+
+uint16 ANIObject::getAnimation() const {
+	return _animation;
+}
+
+uint16 ANIObject::getFrame() const {
+	return _frame;
+}
+
+bool ANIObject::lastFrame() const {
+	if (_animation >= _ani->getAnimationCount())
+		return true;
+
+	const ANIFile::Animation &animation = _ani->getAnimationInfo(_animation);
+
+	return (_frame + 1) >= animation.frameCount;
+}
+
+} // End of namespace Gob
diff --git a/engines/gob/aniobject.h b/engines/gob/aniobject.h
new file mode 100644
index 0000000..357c2a9
--- /dev/null
+++ b/engines/gob/aniobject.h
@@ -0,0 +1,99 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_ANIOBJECT_H
+#define GOB_ANIOBJECT_H
+
+#include "common/system.h"
+
+namespace Gob {
+
+class ANIFile;
+class Surface;
+
+/** An ANI object, controlling an animation within an ANI file. */
+class ANIObject {
+public:
+	ANIObject(const ANIFile &ani);
+	virtual ~ANIObject();
+
+	/** Make the object visible/invisible. */
+	void setVisible(bool visible);
+
+	/** Is the object currently visible? */
+	bool isVisible() const;
+
+	/** Set the current position to the animation's default. */
+	void setPosition();
+	/** Set the current position. */
+	void setPosition(int16 x, int16 y);
+
+	/** Return the current position. */
+	void getPosition(int16 &x, int16 &y) const;
+
+	/** Return the current frame position. */
+	void getFramePosition(int16 &x, int16 &y) const;
+	/** Return the current frame size. */
+	void getFrameSize(int16 &width, int16 &height) const;
+
+	/** Set the animation number. */
+	void setAnimation(uint16 animation);
+
+	/** Return the current animation number. */
+	uint16 getAnimation() const;
+	/** Return the current frame number. */
+	uint16 getFrame() const;
+
+	/** Is this the last frame within this animation cycle? */
+	bool lastFrame() const;
+
+	/** Draw the current frame onto the surface and return the affected rectangle. */
+	void draw(Surface &dest, int16 &left, int16 &top, int16 &right, int16 &bottom);
+	/** Draw the current frame from the surface and return the affected rectangle. */
+	void clear(Surface &dest, int16 &left , int16 &top, int16 &right, int16 &bottom);
+
+	/** Advance the animation to the next frame. */
+	virtual void advance();
+
+private:
+	const ANIFile *_ani; ///< The managed ANI file.
+
+	uint16 _animation; ///< The current animation number
+	uint16 _frame;     ///< The current frame.
+
+	bool _visible; ///< Is the object currently visible?
+
+	int16 _x; ///< The current X position.
+	int16 _y; ///< The current Y position.
+
+	Surface *_background; ///< The saved background.
+	bool _drawn;          ///< Was the animation drawn?
+
+	int16 _backgroundLeft;   ///< The left position of the saved background.
+	int16 _backgroundTop;    ///< The top of the saved background.
+	int16 _backgroundRight;  ///< The right position of the saved background.
+	int16 _backgroundBottom; ///< The bottom position of the saved background.
+};
+
+} // End of namespace Gob
+
+#endif // GOB_ANIOBJECT_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index a2a78bc..d451e25 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/gob
 
 MODULE_OBJS := \
 	anifile.o \
+	aniobject.o \
 	console.o \
 	dataio.o \
 	databases.o \


Commit: dbb70e3d6f3b6ce5ff0497dbded420783edb3256
    https://github.com/scummvm/scummvm/commit/dbb70e3d6f3b6ce5ff0497dbded420783edb3256
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Add class Geisha::EvilFish

An "evil" fish in Geisha's "Diving" minigame.

Changed paths:
  A engines/gob/minigames/geisha/evilfish.cpp
  A engines/gob/minigames/geisha/evilfish.h
    engines/gob/module.mk



diff --git a/engines/gob/minigames/geisha/evilfish.cpp b/engines/gob/minigames/geisha/evilfish.cpp
new file mode 100644
index 0000000..e2672d7
--- /dev/null
+++ b/engines/gob/minigames/geisha/evilfish.cpp
@@ -0,0 +1,163 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/minigames/geisha/evilfish.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+EvilFish::EvilFish(const ANIFile &ani, uint16 screenWidth,
+                   uint16 animSwimLeft, uint16 animSwimRight,
+                   uint16 animTurnLeft, uint16 animTurnRight, uint16 animDie) :
+	ANIObject(ani), _screenWidth(screenWidth),
+	_animSwimLeft(animSwimLeft), _animSwimRight(animSwimRight),
+	_animTurnLeft(animTurnLeft), _animTurnRight(animTurnRight), _animDie(animDie),
+	_shouldLeave(false), _state(kStateNone) {
+
+}
+
+EvilFish::~EvilFish() {
+}
+
+bool EvilFish::isIn(int16 x, int16 y) const {
+	int16 frameX, frameY, frameWidth, frameHeight;
+	getFramePosition(frameX, frameY);
+	getFrameSize(frameWidth, frameHeight);
+
+	if ((x < frameX) || (y < frameY))
+		return false;
+	if ((x > (frameX + frameWidth)) || (y > (frameY + frameHeight)))
+		return false;
+
+	return true;
+}
+
+void EvilFish::enter(Direction from, int16 y) {
+	_shouldLeave = false;
+
+	bool left = from == kDirectionLeft;
+
+	setAnimation(left ? _animSwimLeft : _animSwimRight);
+
+	int16 width, height;
+	getFrameSize(width, height);
+
+	setPosition(left ? -width : _screenWidth, y);
+	setVisible(true);
+
+	_state = left ? kStateSwimLeft : kStateSwimRight;
+}
+
+void EvilFish::leave() {
+	if (_state == kStateNone)
+		return;
+
+	_shouldLeave = true;
+}
+
+void EvilFish::die() {
+	if ((_state == kStateNone) || (_state == kStateDie))
+		return;
+
+	int16 x, y;
+	getFramePosition(x, y);
+
+	setAnimation(_animDie);
+	setPosition(x, y);
+
+	_state = kStateDie;
+}
+
+void EvilFish::advance() {
+	if (_state == kStateNone)
+		return;
+
+	bool wasLastFrame = lastFrame();
+
+	ANIObject::advance();
+
+	int16 x, y, width, height;
+	getFramePosition(x, y);
+	getFrameSize(width, height);
+
+	switch (_state) {
+	case kStateNone:
+		break;
+
+	case kStateSwimLeft:
+		if (!_shouldLeave && (x >= _screenWidth - width)) {
+			setAnimation(_animTurnRight);
+			setPosition(x, y);
+			_state = kStateTurnRight;
+		}
+
+		if (_shouldLeave && (x >= _screenWidth)) {
+			setVisible(false);
+
+			_shouldLeave = false;
+			_state       = kStateNone;
+		}
+		break;
+
+	case kStateSwimRight:
+		if (!_shouldLeave && (x <= 0)) {
+			setAnimation(_animTurnLeft);
+			setPosition(x, y);
+			_state = kStateTurnLeft;
+		}
+
+		if (_shouldLeave && (x < -width)) {
+			setVisible(false);
+
+			_shouldLeave = false;
+			_state       = kStateNone;
+		}
+		break;
+
+	case kStateTurnLeft:
+		if (wasLastFrame) {
+			setAnimation(_animSwimLeft);
+			_state = kStateSwimLeft;
+		}
+		break;
+
+	case kStateTurnRight:
+		if (wasLastFrame) {
+			setAnimation(_animSwimRight);
+			_state = kStateSwimRight;
+		}
+		break;
+
+	case kStateDie:
+		if (wasLastFrame) {
+			setVisible(false);
+
+			_state = kStateNone;
+		}
+		break;
+	}
+}
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/evilfish.h b/engines/gob/minigames/geisha/evilfish.h
new file mode 100644
index 0000000..9144cef
--- /dev/null
+++ b/engines/gob/minigames/geisha/evilfish.h
@@ -0,0 +1,86 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_MINIGAMES_GEISHA_EVILFISH_H
+#define GOB_MINIGAMES_GEISHA_EVILFISH_H
+
+#include "gob/aniobject.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+/** An "evil" fish in Geisha's "Diving" minigame. */
+class EvilFish : public ANIObject {
+public:
+	enum Direction {
+		kDirectionLeft,
+		kDirectionRight
+	};
+
+	EvilFish(const ANIFile &ani, uint16 screenWidth,
+	         uint16 animSwimLeft, uint16 animSwimRight,
+	         uint16 animTurnLeft, uint16 animTurnRight, uint16 animDie);
+	~EvilFish();
+
+	/** Are there coordinates within the fish's sprite? */
+	bool isIn(int16 x, int16 y) const;
+
+	/** Enter from this direction / screen edge. */
+	void enter(Direction from, int16 y);
+	/** Leave the screen in the current direction. */
+	void leave();
+
+	/** Kill the fish. */
+	void die();
+
+	/** Advance the animation to the next frame. */
+	void advance();
+
+private:
+	enum State {
+		kStateNone,
+		kStateSwimLeft,
+		kStateSwimRight,
+		kStateTurnLeft,
+		kStateTurnRight,
+		kStateDie
+	};
+
+	uint16 _screenWidth;
+
+	uint16 _animSwimLeft;
+	uint16 _animSwimRight;
+	uint16 _animTurnLeft;
+	uint16 _animTurnRight;
+	uint16 _animDie;
+
+	bool _shouldLeave;
+
+	State _state;
+};
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
+
+#endif // GOB_MINIGAMES_GEISHA_EVILFISH_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index d451e25..0ea4f26 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -73,6 +73,7 @@ MODULE_OBJS := \
 	demos/demoplayer.o \
 	demos/scnplayer.o \
 	demos/batplayer.o \
+	minigames/geisha/evilfish.o \
 	save/savefile.o \
 	save/savehandler.o \
 	save/saveload.o \


Commit: 26dd2f5f603b10b3b54664b6589c8feb6c4f7b82
    https://github.com/scummvm/scummvm/commit/26dd2f5f603b10b3b54664b6589c8feb6c4f7b82
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Move keyPressed() to Util

Changed paths:
    engines/gob/inter.h
    engines/gob/inter_geisha.cpp
    engines/gob/util.cpp
    engines/gob/util.h



diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index c84cc38..d1c28fc 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -362,8 +362,6 @@ protected:
 	void oGeisha_caress2(OpGobParams &params);
 
 	int16 loadSound(int16 slot);
-
-	bool keyPressed();
 };
 
 class Inter_v2 : public Inter_v1 {
diff --git a/engines/gob/inter_geisha.cpp b/engines/gob/inter_geisha.cpp
index 6c3e97c..d72dd79 100644
--- a/engines/gob/inter_geisha.cpp
+++ b/engines/gob/inter_geisha.cpp
@@ -82,18 +82,6 @@ void Inter_Geisha::oGeisha_loadCursor(OpFuncParams &params) {
 	o1_loadCursor(params);
 }
 
-bool Inter_Geisha::keyPressed() {
-	int16 key = _vm->_util->checkKey();
-	if (key)
-		return true;
-
-	int16 x, y;
-	MouseButtons buttons;
-
-	_vm->_util->getMouseState(&x, &y, &buttons);
-	return buttons != kMouseButtonsNone;
-}
-
 struct TOTTransition {
 	const char *to;
 	const char *from;
@@ -134,7 +122,7 @@ void Inter_Geisha::oGeisha_loadTot(OpFuncParams &params) {
 		}
 
 	if (needWait)
-		while (!keyPressed())
+		while (!_vm->_util->keyPressed())
 			_vm->_util->longDelay(1);
 }
 
diff --git a/engines/gob/util.cpp b/engines/gob/util.cpp
index 58dfc9c..7f9c613 100644
--- a/engines/gob/util.cpp
+++ b/engines/gob/util.cpp
@@ -257,6 +257,18 @@ bool Util::checkKey(int16 &key) {
 	return true;
 }
 
+bool Util::keyPressed() {
+	int16 key = checkKey();
+	if (key)
+		return true;
+
+	int16 x, y;
+	MouseButtons buttons;
+
+	getMouseState(&x, &y, &buttons);
+	return buttons != kMouseButtonsNone;
+}
+
 void Util::getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons) {
 	Common::Point mouse = g_system->getEventManager()->getMousePos();
 	*pX = mouse.x + _vm->_video->_scrollOffsetX - _vm->_video->_screenDeltaX;
diff --git a/engines/gob/util.h b/engines/gob/util.h
index 7c1e44c..4228dac 100644
--- a/engines/gob/util.h
+++ b/engines/gob/util.h
@@ -108,6 +108,7 @@ public:
 	int16 getKey();
 	int16 checkKey();
 	bool checkKey(int16 &key);
+	bool keyPressed();
 
 	void getMouseState(int16 *pX, int16 *pY, MouseButtons *pButtons);
 	void setMousePos(int16 x, int16 y);


Commit: 7f5f9c9f91eb8cd52ebcffe208d0e778f8ff6448
    https://github.com/scummvm/scummvm/commit/7f5f9c9f91eb8cd52ebcffe208d0e778f8ff6448
Author: Sven Hesse (drmccoy at users.sourceforge.net)
Date: 2011-09-03T09:00:09-07:00

Commit Message:
GOB: Stub classes for Geisha's Diving and Penetration minigames

Changed paths:
  A engines/gob/minigames/geisha/diving.cpp
  A engines/gob/minigames/geisha/diving.h
  A engines/gob/minigames/geisha/penetration.cpp
  A engines/gob/minigames/geisha/penetration.h
    engines/gob/inter.h
    engines/gob/inter_geisha.cpp
    engines/gob/module.mk



diff --git a/engines/gob/inter.h b/engines/gob/inter.h
index d1c28fc..6fd4dc2 100644
--- a/engines/gob/inter.h
+++ b/engines/gob/inter.h
@@ -33,6 +33,11 @@
 
 namespace Gob {
 
+namespace Geisha {
+	class Diving;
+	class Penetration;
+}
+
 // This is to help devices with small memory (PDA, smartphones, ...)
 // to save a bit of memory used by opcode names in the Gob engine.
 #ifndef REDUCE_MEMORY_USAGE
@@ -337,7 +342,7 @@ protected:
 class Inter_Geisha : public Inter_v1 {
 public:
 	Inter_Geisha(GobEngine *vm);
-	virtual ~Inter_Geisha() {}
+	virtual ~Inter_Geisha();
 
 protected:
 	virtual void setupOpcodesDraw();
@@ -362,6 +367,10 @@ protected:
 	void oGeisha_caress2(OpGobParams &params);
 
 	int16 loadSound(int16 slot);
+
+private:
+	Geisha::Diving      *_diving;
+	Geisha::Penetration *_penetration;
 };
 
 class Inter_v2 : public Inter_v1 {
diff --git a/engines/gob/inter_geisha.cpp b/engines/gob/inter_geisha.cpp
index d72dd79..c5b91a4 100644
--- a/engines/gob/inter_geisha.cpp
+++ b/engines/gob/inter_geisha.cpp
@@ -38,6 +38,9 @@
 #include "gob/sound/sound.h"
 #include "gob/sound/sounddesc.h"
 
+#include "gob/minigames/geisha/diving.h"
+#include "gob/minigames/geisha/penetration.h"
+
 namespace Gob {
 
 #define OPCODEVER Inter_Geisha
@@ -45,7 +48,16 @@ namespace Gob {
 #define OPCODEFUNC(i, x)  _opcodesFunc[i]._OPCODEFUNC(OPCODEVER, x)
 #define OPCODEGOB(i, x)   _opcodesGob[i]._OPCODEGOB(OPCODEVER, x)
 
-Inter_Geisha::Inter_Geisha(GobEngine *vm) : Inter_v1(vm) {
+Inter_Geisha::Inter_Geisha(GobEngine *vm) : Inter_v1(vm),
+	_diving(0), _penetration(0) {
+
+	_diving      = new Geisha::Diving(vm);
+	_penetration = new Geisha::Penetration(vm);
+}
+
+Inter_Geisha::~Inter_Geisha() {
+	delete _penetration;
+	delete _diving;
 }
 
 void Inter_Geisha::setupOpcodesDraw() {
@@ -251,30 +263,24 @@ void Inter_Geisha::oGeisha_writeData(OpFuncParams &params) {
 }
 
 void Inter_Geisha::oGeisha_gamePenetration(OpGobParams &params) {
-	uint16 var1 = _vm->_game->_script->readUint16();
-	uint16 var2 = _vm->_game->_script->readUint16();
-	uint16 var3 = _vm->_game->_script->readUint16();
-	uint16 var4 = _vm->_game->_script->readUint16();
-
-	WRITE_VAR_UINT32(var4, 0);
+	uint16 var1      = _vm->_game->_script->readUint16();
+	uint16 var2      = _vm->_game->_script->readUint16();
+	uint16 var3      = _vm->_game->_script->readUint16();
+	uint16 resultVar = _vm->_game->_script->readUint16();
 
-	warning("Geisha Stub: Minigame \"Penetration\": %d, %d, %d, %d", var1, var2, var3, var4);
+	bool result = _penetration->play(var1, var2, var3);
 
-	// Fudge a win for now
-	WRITE_VAR_UINT32(var4, 1);
+	WRITE_VAR_UINT32(resultVar, result ? 1 : 0);
 }
 
 void Inter_Geisha::oGeisha_gameDiving(OpGobParams &params) {
-	uint16 var1 = _vm->_game->_script->readUint16();
-	uint16 var2 = _vm->_game->_script->readUint16();
-	uint16 var3 = _vm->_game->_script->readUint16();
-
-	WRITE_VAR_UINT32(var3, 1);
+	uint16 playerCount      = _vm->_game->_script->readUint16();
+	uint16 hasPearlLocation = _vm->_game->_script->readUint16();
+	uint16 resultVar        = _vm->_game->_script->readUint16();
 
-	warning("Geisha Stub: Minigame \"Diving\": %d, %d, %d", var1, var2, var3);
+	bool result = _diving->play(playerCount, hasPearlLocation);
 
-	// Fudge a win for now
-	WRITE_VAR_UINT32(var3, 0);
+	WRITE_VAR_UINT32(resultVar, result ? 1 : 0);
 }
 
 void Inter_Geisha::oGeisha_loadTitleMusic(OpGobParams &params) {
diff --git a/engines/gob/minigames/geisha/diving.cpp b/engines/gob/minigames/geisha/diving.cpp
new file mode 100644
index 0000000..0d216ab
--- /dev/null
+++ b/engines/gob/minigames/geisha/diving.cpp
@@ -0,0 +1,155 @@
+/* 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/list.h"
+
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+#include "gob/decfile.h"
+#include "gob/anifile.h"
+
+#include "gob/minigames/geisha/evilfish.h"
+#include "gob/minigames/geisha/diving.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+Diving::Diving(GobEngine *vm) : _vm(vm), _background(0),
+	_objects(0), _gui(0), _oko(0), _lungs(0), _heart(0) {
+
+}
+
+Diving::~Diving() {
+	deinit();
+}
+
+bool Diving::play(uint16 playerCount, bool hasPearlLocation) {
+	init();
+	initScreen();
+
+	_vm->_draw->blitInvalidated();
+	_vm->_video->retrace();
+
+	EvilFish shark(*_objects, 320, 0, 14, 8, 9, 3);
+
+	Common::List<ANIObject *> objects;
+
+	objects.push_back(_water);
+	objects.push_back(&shark);
+
+	shark.enter(EvilFish::kDirectionLeft, 90);
+
+	while (!_vm->_util->keyPressed() && !_vm->shouldQuit()) {
+		int16 left, top, right, bottom;
+
+		// Clear the previous animation frames
+		for (Common::List<ANIObject *>::iterator o = objects.reverse_begin();
+		     o != objects.end(); --o) {
+
+			(*o)->clear(*_vm->_draw->_backSurface, left, top, right, bottom);
+			_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+		}
+
+		// Draw the current animation frames
+		for (Common::List<ANIObject *>::iterator o = objects.begin();
+		     o != objects.end(); ++o) {
+
+			(*o)->draw(*_vm->_draw->_backSurface, left, top, right, bottom);
+			_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, left, top, right, bottom);
+
+			(*o)->advance();
+		}
+
+		_vm->_draw->blitInvalidated();
+
+		_vm->_util->waitEndFrame();
+		_vm->_util->processInput();
+	}
+
+	deinit();
+	return true;
+}
+
+void Diving::init() {
+	_background = new DECFile(_vm, "tperle.dec"  , 320, 200);
+	_objects    = new ANIFile(_vm, "tperle.ani"  , 320);
+	_gui        = new ANIFile(_vm, "tperlcpt.ani", 320);
+	_oko        = new ANIFile(_vm, "tplonge.ani" , 320);
+
+	_water = new ANIObject(*_objects);
+	_lungs = new ANIObject(*_gui);
+	_heart = new ANIObject(*_gui);
+
+	_water->setAnimation(7);
+	_water->setPosition();
+	_water->setVisible(true);
+
+	_lungs->setAnimation(0);
+	_lungs->setPosition();
+	_lungs->setVisible(true);
+
+	_heart->setAnimation(1);
+	_heart->setPosition();
+	_heart->setVisible(true);
+}
+
+void Diving::deinit() {
+	delete _heart;
+	delete _lungs;
+	delete _water;
+
+	delete _oko;
+	delete _gui;
+	delete _objects;
+	delete _background;
+
+	_water = 0;
+	_heart = 0;
+	_lungs = 0;
+
+	_oko        = 0;
+	_gui        = 0;
+	_objects    = 0;
+	_background = 0;
+}
+
+void Diving::initScreen() {
+	_vm->_util->setFrameRate(15);
+
+	_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+	_vm->_draw->_backSurface->clear();
+	_background->draw(*_vm->_draw->_backSurface);
+
+	int16 left, top, right, bottom;
+	_lungs->draw(*_vm->_draw->_backSurface, left, top, right, bottom);
+	_heart->draw(*_vm->_draw->_backSurface, left, top, right, bottom);
+
+	_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
+}
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/diving.h b/engines/gob/minigames/geisha/diving.h
new file mode 100644
index 0000000..238a1ad
--- /dev/null
+++ b/engines/gob/minigames/geisha/diving.h
@@ -0,0 +1,68 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_MINIGAMES_GEISHA_DIVING_H
+#define GOB_MINIGAMES_GEISHA_DIVING_H
+
+#include "common/system.h"
+
+namespace Gob {
+
+class GobEngine;
+class DECFile;
+class ANIFile;
+class ANIObject;
+
+namespace Geisha {
+
+/** Geisha's "Diving" minigame. */
+class Diving {
+public:
+	Diving(GobEngine *vm);
+	~Diving();
+
+	bool play(uint16 playerCount, bool hasPearlLocation);
+
+private:
+	GobEngine *_vm;
+
+	DECFile *_background;
+	ANIFile *_objects;
+	ANIFile *_gui;
+	ANIFile *_oko;
+
+	ANIObject *_water;
+	ANIObject *_lungs;
+	ANIObject *_heart;
+
+
+	void init();
+	void deinit();
+
+	void initScreen();
+};
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
+
+#endif // GOB_MINIGAMES_GEISHA_DIVING_H
diff --git a/engines/gob/minigames/geisha/penetration.cpp b/engines/gob/minigames/geisha/penetration.cpp
new file mode 100644
index 0000000..4334cae
--- /dev/null
+++ b/engines/gob/minigames/geisha/penetration.cpp
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "gob/global.h"
+#include "gob/util.h"
+#include "gob/draw.h"
+#include "gob/video.h"
+#include "gob/decfile.h"
+#include "gob/anifile.h"
+
+#include "gob/minigames/geisha/penetration.h"
+
+namespace Gob {
+
+namespace Geisha {
+
+static byte kPalette[48] = {
+	0x16,  0x16,  0x16,
+	0x12,  0x14,  0x16,
+	0x34,  0x00,  0x25,
+	0x1D,  0x1F,  0x22,
+	0x24,  0x27,  0x2A,
+	0x2C,  0x0D,  0x22,
+	0x2B,  0x2E,  0x32,
+	0x12,  0x09,  0x20,
+	0x3D,  0x3F,  0x00,
+	0x3F,  0x3F,  0x3F,
+	0x00,  0x00,  0x00,
+	0x15,  0x15,  0x3F,
+	0x25,  0x22,  0x2F,
+	0x1A,  0x14,  0x28,
+	0x3F,  0x00,  0x00,
+	0x15,  0x3F,  0x15
+};
+
+Penetration::Penetration(GobEngine *vm) : _vm(vm), _background(0), _objects(0) {
+	_background = new Surface(320, 200, 1);
+}
+
+Penetration::~Penetration() {
+	deinit();
+
+	delete _background;
+}
+
+bool Penetration::play(uint16 var1, uint16 var2, uint16 var3) {
+	init();
+	initScreen();
+
+	_vm->_draw->blitInvalidated();
+	_vm->_video->retrace();
+	while (!_vm->_util->keyPressed() && !_vm->shouldQuit())
+		_vm->_util->longDelay(1);
+
+	deinit();
+	return true;
+}
+
+void Penetration::init() {
+	_background->clear();
+
+	_vm->_video->drawPackedSprite("hyprmef2.cmp", *_background);
+
+	_objects = new ANIFile(_vm, "tcite.ani", 320);
+}
+
+void Penetration::deinit() {
+	delete _objects;
+
+	_objects = 0;
+}
+
+void Penetration::initScreen() {
+	_vm->_util->setFrameRate(15);
+
+	memcpy(_vm->_draw->_vgaPalette     , kPalette, 48);
+	memcpy(_vm->_draw->_vgaSmallPalette, kPalette, 48);
+
+	_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
+
+	_vm->_draw->_backSurface->blit(*_background);
+	_vm->_draw->dirtiedRect(_vm->_draw->_backSurface, 0, 0, 319, 199);
+}
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
diff --git a/engines/gob/minigames/geisha/penetration.h b/engines/gob/minigames/geisha/penetration.h
new file mode 100644
index 0000000..c346a7b
--- /dev/null
+++ b/engines/gob/minigames/geisha/penetration.h
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GOB_MINIGAMES_GEISHA_PENETRATION_H
+#define GOB_MINIGAMES_GEISHA_PENETRATION_H
+
+#include "common/system.h"
+
+namespace Gob {
+
+class GobEngine;
+class Surface;
+class ANIFile;
+
+namespace Geisha {
+
+/** Geisha's "Penetration" minigame. */
+class Penetration {
+public:
+	Penetration(GobEngine *vm);
+	~Penetration();
+
+	bool play(uint16 var1, uint16 var2, uint16 var3);
+
+private:
+	GobEngine *_vm;
+
+	Surface *_background;
+	ANIFile *_objects;
+
+
+	void init();
+	void deinit();
+
+	void initScreen();
+};
+
+} // End of namespace Geisha
+
+} // End of namespace Gob
+
+#endif // GOB_MINIGAMES_GEISHA_PENETRATION_H
diff --git a/engines/gob/module.mk b/engines/gob/module.mk
index 0ea4f26..bf040c5 100644
--- a/engines/gob/module.mk
+++ b/engines/gob/module.mk
@@ -74,6 +74,8 @@ MODULE_OBJS := \
 	demos/scnplayer.o \
 	demos/batplayer.o \
 	minigames/geisha/evilfish.o \
+	minigames/geisha/diving.o \
+	minigames/geisha/penetration.o \
 	save/savefile.o \
 	save/savehandler.o \
 	save/saveload.o \






More information about the Scummvm-git-logs mailing list