aboutsummaryrefslogtreecommitdiff
path: root/engines/made
diff options
context:
space:
mode:
Diffstat (limited to 'engines/made')
-rw-r--r--engines/made/database.cpp393
-rw-r--r--engines/made/database.h105
-rw-r--r--engines/made/detection.cpp172
-rw-r--r--engines/made/graphics.cpp152
-rw-r--r--engines/made/graphics.h40
-rw-r--r--engines/made/made.cpp155
-rw-r--r--engines/made/made.h106
-rw-r--r--engines/made/module.mk22
-rw-r--r--engines/made/pmvplayer.cpp152
-rw-r--r--engines/made/pmvplayer.h39
-rw-r--r--engines/made/resource.cpp333
-rw-r--r--engines/made/resource.h178
-rw-r--r--engines/made/screen.cpp459
-rw-r--r--engines/made/screen.h123
-rw-r--r--engines/made/script.cpp738
-rw-r--r--engines/made/script.h154
-rw-r--r--engines/made/scriptfuncs.cpp718
-rw-r--r--engines/made/scriptfuncs.h188
-rw-r--r--engines/made/sound.cpp131
-rw-r--r--engines/made/sound.h39
20 files changed, 4397 insertions, 0 deletions
diff --git a/engines/made/database.cpp b/engines/made/database.cpp
new file mode 100644
index 0000000000..1c2ddf0a8a
--- /dev/null
+++ b/engines/made/database.cpp
@@ -0,0 +1,393 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/util.h"
+
+#include "made/database.h"
+
+namespace Made {
+
+/*
+ Class types:
+ 0x7FFF byte array
+ 0x7FFE word array
+ < 0x7FFE object
+*/
+
+Object::Object() {
+}
+
+Object::~Object() {
+ if (_freeData && _objData)
+ delete[] _objData;
+}
+
+void Object::load(Common::SeekableReadStream &source) {
+
+ _freeData = true;
+
+ source.readUint16LE(); // skip flags
+ uint16 type = source.readUint16LE();
+
+ /*
+ if (type < 0x7FFE) {
+ byte count1 = source.readByte();
+ byte count2 = source.readByte();
+ _objSize = (count1 + count2) * 2;
+ } else {
+ _objSize = source.readUint16LE();
+ }
+ */
+
+ if (type == 0x7FFF) {
+ _objSize = source.readUint16LE();
+ } else if (type == 0x7FFE) {
+ _objSize = source.readUint16LE() * 2;
+ } else if (type < 0x7FFE) {
+ byte count1 = source.readByte();
+ byte count2 = source.readByte();
+ _objSize = (count1 + count2) * 2;
+ }
+
+ source.seek(-6, SEEK_CUR);
+
+ _objSize += 6;
+
+ _objData = new byte[_objSize];
+ source.read(_objData, _objSize);
+
+ /*
+ debug(2, "Object::load(con): flags = %04X; type = %04X; _objSize = %04X\n", getFlags(), getClass(), _objSize);
+ fflush(stdout);
+ */
+}
+
+void Object::load(byte *source) {
+
+ _objData = source;
+ _freeData = false;
+
+ if (getClass() < 0x7FFE) {
+ _objSize = (getCount1() + getCount2()) * 2;
+ } else {
+ _objSize = getSize();
+ }
+
+ _objSize += 6;
+
+ /*
+ debug(2, "Object::load(var): flags = %04X; type = %04X; _objSize = %04X\n", getFlags(), getClass(), _objSize);
+ fflush(stdout);
+ */
+
+}
+
+uint16 Object::getFlags() const {
+ return READ_LE_UINT16(_objData);
+}
+
+uint16 Object::getClass() const {
+ return READ_LE_UINT16(_objData + 2);
+}
+
+uint16 Object::getSize() const {
+ return READ_LE_UINT16(_objData + 4);
+}
+
+byte Object::getCount1() const {
+ return _objData[4];
+}
+
+byte Object::getCount2() const {
+ return _objData[5];
+}
+
+byte *Object::getData() {
+ return _objData + 6;
+}
+
+const char *Object::getString() {
+ if (getClass() == 0x7FFF)
+ return (const char*)getData();
+ else
+ return NULL;
+}
+
+bool Object::isObject() {
+ return getClass() < 0x7FFE;
+}
+
+bool Object::isVector() {
+ return getClass() == 0x7FFF;
+}
+
+int16 Object::getVectorSize() {
+ if (getClass() == 0x7FFF || getClass() == 0x7FFE) {
+ return getSize();
+ } else if (getClass() < 0x7FFE) {
+ return getCount1() + getCount2();
+ } else {
+ return 0; // FIXME
+ }
+}
+
+int16 Object::getVectorItem(int16 index) {
+ if (getClass() == 0x7FFF) {
+ byte *vector = (byte*)getData();
+ return vector[index];
+ } else if (getClass() == 0x7FFE) {
+ int16 *vector = (int16*)getData();
+ return vector[index];
+ } else if (getClass() < 0x7FFE) {
+ int16 *vector = (int16*)getData();
+ return vector[index];
+ } else {
+ return 0; // FIXME
+ }
+}
+
+void Object::setVectorItem(int16 index, int16 value) {
+ if (getClass() == 0x7FFF) {
+ byte *vector = (byte*)getData();
+ vector[index] = value;
+ } else if (getClass() <= 0x7FFE) {
+ int16 *vector = (int16*)getData();
+ vector[index] = value;
+ }
+}
+
+void Object::dump(const char *filename) {
+ /*
+ FILE *o = fopen(filename, "wb");
+ fwrite(_objData, _objSize, 1, o);
+ fclose(o);
+ */
+}
+
+GameDatabase::GameDatabase() {
+}
+
+GameDatabase::~GameDatabase() {
+ if (_gameState)
+ delete[] _gameState;
+}
+
+void GameDatabase::open(const char *filename) {
+ _fd.open(filename);
+
+ // TODO: Read/verifiy header
+
+ _fd.seek(0x1E);
+
+ uint32 objectIndexOffs = _fd.readUint32LE();
+ uint16 objectCount = _fd.readUint16LE();
+ uint32 gameStateOffs = _fd.readUint32LE();
+ _gameStateSize = _fd.readUint32LE();
+ uint32 objectsOffs = _fd.readUint32LE();
+ uint32 objectsSize = _fd.readUint32LE();
+ _mainCodeObjectIndex = _fd.readUint16LE();
+
+ debug(2, "objectIndexOffs = %08X; objectCount = %d; gameStateOffs = %08X; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n",
+ objectIndexOffs, objectCount, gameStateOffs, _gameStateSize, objectsOffs, objectsSize);
+
+ _gameState = new byte[_gameStateSize];
+ _fd.seek(gameStateOffs);
+ _fd.read(_gameState, _gameStateSize);
+
+ Common::Array<uint32> objectOffsets;
+ _fd.seek(objectIndexOffs);
+ for (uint32 i = 0; i < objectCount; i++)
+ objectOffsets.push_back(_fd.readUint32LE());
+
+ for (uint32 i = 0; i < objectCount; i++) {
+ Object *obj = new Object();
+ // The LSB indicates if it's a constant or variable object
+
+ debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]);
+
+ if (objectOffsets[i] & 1) {
+ debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1);
+ _fd.seek(objectsOffs + objectOffsets[i] - 1);
+ obj->load(_fd);
+ } else {
+ debug(2, "-> var\n");
+ obj->load(_gameState + objectOffsets[i]);
+ }
+ _objects.push_back(obj);
+ }
+
+}
+
+int16 GameDatabase::getVar(int16 index) {
+ return (int16)READ_LE_UINT16(_gameState + index * 2);
+}
+
+void GameDatabase::setVar(int16 index, int16 value) {
+ WRITE_LE_UINT16(_gameState + index * 2, value);
+}
+
+int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
+ Object *obj = getObject(objectIndex);
+
+ //dumpObject(objectIndex);
+
+ int16 *prop = (int16*)obj->getData();
+ byte count1 = obj->getCount1();
+ byte count2 = obj->getCount2();
+
+ int16 *propPtr1 = prop + count1;
+ int16 *propPtr2 = prop + count2;
+
+ debug(2, "# propertyId = %04X\n", propertyId);
+
+ // First see if the property exists in the given object
+ while (count2-- > 0) {
+ if ((*prop & 0x3FFF) == propertyId) {
+ if (*prop & 0x4000) {
+ debug(2, "! L1.1\n");
+ propertyFlag = 1;
+ return (int16*)_gameState + *propPtr1;
+ } else {
+ debug(2, "! L1.2\n");
+ propertyFlag = obj->getFlags() & 1;
+ return propPtr1;
+ }
+ }
+ prop++;
+ propPtr1++;
+ }
+
+ // Now check in the object hierarchy of the given object
+ int16 parentObjectIndex = obj->getClass();
+ if (parentObjectIndex == 0) {
+ debug(2, "! NULL(np)\n");
+ return NULL;
+ }
+
+ while (parentObjectIndex != 0) {
+
+ debug(2, "parentObjectIndex = %04X\n", parentObjectIndex);
+
+ //dumpObject(parentObjectIndex);
+
+ obj = getObject(parentObjectIndex);
+
+ prop = (int16*)obj->getData();
+ count1 = obj->getCount1();
+ count2 = obj->getCount2();
+
+ propPtr1 = propPtr2 + count1 - count2;
+ int16 *propertyPtr = prop + count1;
+
+ while (count2-- > 0) {
+ if (!(*prop & 0x8000)) {
+ if ((*prop & 0x3FFF) == propertyId) {
+ if (*prop & 0x4000) {
+ debug(2, "! L2.1\n");
+ propertyFlag = 1;
+ return (int16*)_gameState + *propPtr1;
+ } else {
+ debug(2, "! L2.2\n");
+ propertyFlag = obj->getFlags() & 1;
+ return propPtr1;
+ }
+ } else {
+ propPtr1++;
+ }
+ } else {
+ if ((*prop & 0x3FFF) == propertyId) {
+ if (*prop & 0x4000) {
+ debug(2, "! L3.1\n");
+ propertyFlag = 1;
+ return (int16*)_gameState + *propertyPtr;
+ } else {
+ debug(2, "! L3.2\n");
+ propertyFlag = obj->getFlags() & 1;
+ return propertyPtr;
+ }
+ }
+ }
+ prop++;
+ propertyPtr++;
+ }
+
+ parentObjectIndex = obj->getClass();
+
+ }
+
+ debug(2, "! NULL(nf)\n");
+ return NULL;
+
+ fflush(stdout);
+
+}
+
+int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) {
+
+ if (objectIndex == 0)
+ return 0;
+
+ int16 propertyFlag;
+ int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag);
+
+ if (property) {
+ return *property;
+ } else {
+ return 0;
+ }
+
+}
+
+int16 GameDatabase::setObjectProperty(int16 objectIndex, int16 propertyId, int16 value) {
+
+ if (objectIndex == 0)
+ return 0;
+
+ int16 propertyFlag;
+ int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag);
+
+ if (property) {
+ if (propertyFlag == 1) {
+ *property = value;
+ } else {
+ debug(2, "GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n",
+ objectIndex, propertyId, value);
+ }
+ return value;
+ } else {
+ return 0;
+ }
+
+}
+
+void GameDatabase::dumpObject(int16 index) {
+ Object *obj = getObject(index);
+ char fn[512];
+ sprintf(fn, "obj%04X.0", index);
+ obj->dump(fn);
+}
+
+} // End of namespace Made
diff --git a/engines/made/database.h b/engines/made/database.h
new file mode 100644
index 0000000000..d5468db607
--- /dev/null
+++ b/engines/made/database.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_DATABASE_H
+#define MADE_DATABASE_H
+
+#include "common/array.h"
+#include "common/util.h"
+#include "common/file.h"
+#include "common/stream.h"
+
+namespace Made {
+
+class Object {
+public:
+ Object();
+ ~Object();
+ void load(Common::SeekableReadStream &source);
+ void load(byte *source);
+
+ uint16 getFlags() const;
+ uint16 getClass() const;
+ uint16 getSize() const;
+
+ byte getCount1() const;
+ byte getCount2() const;
+
+ byte *getData();
+ const char *getString();
+
+ bool isObject();
+ bool isVector();
+ bool isConstant() const { return !(getFlags() & 1); }
+
+ int16 getVectorSize();
+ int16 getVectorItem(int16 index);
+ void setVectorItem(int16 index, int16 value);
+
+ void dump(const char *filename);
+
+protected:
+ bool _freeData;
+ uint16 _objSize;
+ byte *_objData;
+};
+
+class GameDatabase {
+public:
+
+ GameDatabase();
+ ~GameDatabase();
+
+ void open(const char *filename);
+
+ Object *getObject(int16 index) const {
+ if (index >= 1)
+ return _objects[index - 1];
+ else
+ return NULL;
+ }
+
+ int16 getMainCodeObjectIndex() const { return _mainCodeObjectIndex; }
+
+ int16 getVar(int16 index);
+ void setVar(int16 index, int16 value);
+
+ int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag);
+ int16 getObjectProperty(int16 objectIndex, int16 propertyId);
+ int16 setObjectProperty(int16 objectIndex, int16 propertyId, int16 value);
+
+ void dumpObject(int16 index);
+
+protected:
+ Common::File _fd;
+ Common::Array<Object*> _objects;
+ byte *_gameState;
+ uint32 _gameStateSize;
+ int16 _mainCodeObjectIndex;
+};
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp
new file mode 100644
index 0000000000..5f96ff5e8b
--- /dev/null
+++ b/engines/made/detection.cpp
@@ -0,0 +1,172 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "base/plugins.h"
+
+#include "common/advancedDetector.h"
+#include "common/file.h"
+
+#include "made/made.h"
+
+
+namespace Made {
+
+struct MadeGameDescription {
+ Common::ADGameDescription desc;
+
+ int gameID;
+ int gameType;
+ uint32 features;
+ uint16 version;
+};
+
+uint32 MadeEngine::getGameID() const {
+ return _gameDescription->gameID;
+}
+
+uint32 MadeEngine::getFeatures() const {
+ return _gameDescription->features;
+}
+
+Common::Platform MadeEngine::getPlatform() const {
+ return _gameDescription->desc.platform;
+}
+
+uint16 MadeEngine::getVersion() const {
+ return _gameDescription->version;
+}
+
+}
+
+static const PlainGameDescriptor madeGames[] = {
+ {"made", "Return to Zork"},
+ {0, 0}
+};
+
+
+namespace Made {
+
+static const MadeGameDescription gameDescriptions[] = {
+
+ {
+ // Made English version
+ {
+ "made",
+ "CD",
+ AD_ENTRY1("rtzcd.dat", "a1db8c97a78dae10f91d356f16ad07b8"),
+ Common::EN_ANY,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ 0,
+ 0,
+ 0,
+ 0,
+ },
+
+ { AD_TABLE_END_MARKER, 0, 0, 0, 0 }
+};
+
+/**
+ * The fallback game descriptor used by the Made engine's fallbackDetector.
+ * Contents of this struct are to be overwritten by the fallbackDetector.
+ */
+static MadeGameDescription g_fallbackDesc = {
+ {
+ "",
+ "",
+ AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor
+ Common::UNK_LANG,
+ Common::kPlatformPC,
+ Common::ADGF_NO_FLAGS
+ },
+ 0,
+ 0,
+ 0,
+ 0,
+};
+
+} // End of namespace Made
+
+static const Common::ADParams detectionParams = {
+ // Pointer to ADGameDescription or its superset structure
+ (const byte *)Made::gameDescriptions,
+ // Size of that superset structure
+ sizeof(Made::MadeGameDescription),
+ // Number of bytes to compute MD5 sum for
+ 5000,
+ // List of all engine targets
+ madeGames,
+ // Structure for autoupgrading obsolete targets
+ 0,
+ // Name of single gameid (optional)
+ "made",
+ // List of files for file-based fallback detection (optional)
+ 0,
+ // Flags
+ 0
+};
+
+class MadeMetaEngine : public Common::AdvancedMetaEngine {
+public:
+ MadeMetaEngine() : Common::AdvancedMetaEngine(detectionParams) {}
+
+ virtual const char *getName() const {
+ return "MADE Engine";
+ }
+
+ virtual const char *getCopyright() const {
+ return "MADE Engine";
+ }
+
+ virtual bool createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const;
+
+ const Common::ADGameDescription *fallbackDetect(const FSList *fslist) const;
+
+};
+
+bool MadeMetaEngine::createInstance(OSystem *syst, Engine **engine, const Common::ADGameDescription *desc) const {
+ const Made::MadeGameDescription *gd = (const Made::MadeGameDescription *)desc;
+ if (gd) {
+ *engine = new Made::MadeEngine(syst, gd);
+ }
+ return gd != 0;
+}
+
+const Common::ADGameDescription *MadeMetaEngine::fallbackDetect(const FSList *fslist) const {
+ // Set the default values for the fallback descriptor's ADGameDescription part.
+ Made::g_fallbackDesc.desc.language = Common::UNK_LANG;
+ Made::g_fallbackDesc.desc.platform = Common::kPlatformPC;
+ Made::g_fallbackDesc.desc.flags = Common::ADGF_NO_FLAGS;
+
+ // Set default values for the fallback descriptor's MadeGameDescription part.
+ Made::g_fallbackDesc.gameID = 0;
+ Made::g_fallbackDesc.features = 0;
+ Made::g_fallbackDesc.version = 0;
+
+ return (const Common::ADGameDescription *)&Made::g_fallbackDesc;
+}
+
+REGISTER_PLUGIN(MADE, PLUGIN_TYPE_ENGINE, MadeMetaEngine);
diff --git a/engines/made/graphics.cpp b/engines/made/graphics.cpp
new file mode 100644
index 0000000000..76c10d97cc
--- /dev/null
+++ b/engines/made/graphics.cpp
@@ -0,0 +1,152 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "made/graphics.h"
+
+namespace Made {
+
+void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame) {
+
+ const int offsets[] = {
+ 0, 1, 2, 3,
+ 320, 321, 322, 323,
+ 640, 641, 642, 643,
+ 960, 961, 962, 963
+ };
+
+ uint16 width = surface.w;
+ uint16 height = surface.h;
+
+ byte *cmdBuffer = source + cmdOffs;
+ byte *maskBuffer = source + maskOffs;
+ byte *pixelBuffer = source + pixelOffs;
+
+ byte *destPtr = (byte*)surface.getBasePtr(0, 0);
+
+ //byte lineBuf[320 * 4];
+ byte lineBuf[640 * 4];
+ byte bitBuf[40];
+
+ int bitBufLastOfs = (((lineSize + 1) >> 1) << 1) - 2;
+ int bitBufLastCount = ((width + 3) >> 2) & 7;
+ if (bitBufLastCount == 0)
+ bitBufLastCount = 8;
+
+ while (height > 0) {
+
+ int drawDestOfs = 0;
+
+ memset(lineBuf, 0, sizeof(lineBuf));
+
+ memcpy(bitBuf, cmdBuffer, lineSize);
+ cmdBuffer += lineSize;
+
+ for (uint16 bitBufOfs = 0; bitBufOfs < lineSize; bitBufOfs += 2) {
+
+ uint16 bits = READ_LE_UINT16(&bitBuf[bitBufOfs]);
+
+ int bitCount;
+ if (bitBufOfs == bitBufLastOfs)
+ bitCount = bitBufLastCount;
+ else
+ bitCount = 8;
+
+ for (int curCmd = 0; curCmd < bitCount; curCmd++) {
+ int cmd = bits & 3;
+ bits >>= 2;
+
+ byte pixels[4];
+ uint32 mask;
+
+ switch (cmd) {
+
+ case 0:
+ pixels[0] = *pixelBuffer++;
+ for (int i = 0; i < 16; i++)
+ lineBuf[drawDestOfs + offsets[i]] = pixels[0];
+ break;
+
+ case 1:
+ pixels[0] = *pixelBuffer++;
+ pixels[1] = *pixelBuffer++;
+ mask = READ_LE_UINT16(maskBuffer);
+ maskBuffer += 2;
+ for (int i = 0; i < 16; i++) {
+ lineBuf[drawDestOfs + offsets[i]] = pixels[mask & 1];
+ mask >>= 1;
+ }
+ break;
+
+ case 2:
+ pixels[0] = *pixelBuffer++;
+ pixels[1] = *pixelBuffer++;
+ pixels[2] = *pixelBuffer++;
+ pixels[3] = *pixelBuffer++;
+ mask = READ_LE_UINT32(maskBuffer);
+ maskBuffer += 4;
+ for (int i = 0; i < 16; i++) {
+ lineBuf[drawDestOfs + offsets[i]] = pixels[mask & 3];
+ mask >>= 2;
+ }
+ break;
+
+ case 3:
+ if (!deltaFrame) {
+ // Yes, it reads from maskBuffer here
+ for (int i = 0; i < 16; i++)
+ lineBuf[drawDestOfs + offsets[i]] = *maskBuffer++;
+ }
+ break;
+
+ }
+
+ drawDestOfs += 4;
+
+ }
+
+ }
+
+ if (deltaFrame) {
+ for (int y = 0; y < 4 && height > 0; y++, height--) {
+ for (int x = 0; x < width; x++) {
+ if (lineBuf[x + y * 320] != 0)
+ *destPtr = lineBuf[x + y * 320];
+ destPtr++;
+ }
+ }
+ } else {
+ for (int y = 0; y < 4 && height > 0; y++, height--) {
+ memcpy(destPtr, &lineBuf[y * 320], width);
+ destPtr += width;
+ }
+ }
+
+ }
+
+}
+
+} // End of namespace Made
diff --git a/engines/made/graphics.h b/engines/made/graphics.h
new file mode 100644
index 0000000000..3c56bb4231
--- /dev/null
+++ b/engines/made/graphics.h
@@ -0,0 +1,40 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_GRAPHICS_H
+#define MADE_GRAPHICS_H
+
+#include "common/util.h"
+#include "common/file.h"
+#include "common/stream.h"
+#include "graphics/surface.h"
+
+namespace Made {
+
+void decompressImage(byte *source, Graphics::Surface &surface, uint16 cmdOffs, uint16 pixelOffs, uint16 maskOffs, uint16 lineSize, bool deltaFrame = false);
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/made.cpp b/engines/made/made.cpp
new file mode 100644
index 0000000000..e8b0f1b1e1
--- /dev/null
+++ b/engines/made/made.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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/events.h"
+#include "common/keyboard.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/config-manager.h"
+
+#include "graphics/cursorman.h"
+
+#include "base/plugins.h"
+#include "base/version.h"
+
+#include "sound/mixer.h"
+
+#include "made/made.h"
+#include "made/database.h"
+#include "made/pmvplayer.h"
+#include "made/resource.h"
+#include "made/screen.h"
+#include "made/script.h"
+#include "made/sound.h"
+
+namespace Made {
+
+struct GameSettings {
+ const char *gameid;
+ const char *description;
+ byte id;
+ uint32 features;
+ const char *detectname;
+};
+
+static const GameSettings madeSettings[] = {
+ {"made", "Made game", 0, 0, 0},
+
+ {NULL, NULL, 0, 0, NULL}
+};
+
+MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {
+
+ // Setup mixer
+ _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
+ _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume"));
+
+ const GameSettings *g;
+
+ const char *gameid = ConfMan.get("gameid").c_str();
+ for (g = madeSettings; g->gameid; ++g)
+ if (!scumm_stricmp(g->gameid, gameid))
+ _gameId = g->id;
+
+ _rnd = new Common::RandomSource();
+ syst->getEventManager()->registerRandomSource(*_rnd, "made");
+
+ int cd_num = ConfMan.getInt("cdrom");
+ if (cd_num >= 0)
+ _system->openCD(cd_num);
+
+ _pmvPlayer = new PmvPlayer(_system, _mixer);
+ _res = new ProjectReader();
+ _screen = new Screen(this);
+ _dat = new GameDatabase();
+ _script = new ScriptInterpreter(this);
+
+}
+
+MadeEngine::~MadeEngine() {
+ delete _rnd;
+ delete _pmvPlayer;
+ delete _res;
+ delete _screen;
+ delete _dat;
+ delete _script;
+}
+
+int MadeEngine::init() {
+ // Initialize backend
+ _system->beginGFXTransaction();
+ initCommonGFX(false);
+ _system->initSize(320, 200);
+ _system->endGFXTransaction();
+
+ return 0;
+}
+
+int16 MadeEngine::getTimer(int16 timerNum) {
+ return (_system->getMillis() - _timers[timerNum]) / 60;
+}
+
+void MadeEngine::setTimer(int16 timerNum, int16 value) {
+ _timers[timerNum] = value * 60;
+}
+
+void MadeEngine::resetTimer(int16 timerNum) {
+ _timers[timerNum] = _system->getMillis();
+}
+
+int16 MadeEngine::allocTimer() {
+ for (int i = 0; i < ARRAYSIZE(_timers); i++) {
+ if (_timers[i] == -1) {
+ resetTimer(i);
+ return i + 1;
+ }
+ }
+ return 0;
+}
+
+void MadeEngine::freeTimer(int16 timerNum) {
+ _timers[timerNum] = -1;
+}
+
+int MadeEngine::go() {
+
+ for (int i = 0; i < ARRAYSIZE(_timers); i++)
+ _timers[i] = -1;
+
+ _dat->open("rtzcd.dat");
+ _res->open("rtzcd.prj");
+
+ PictureResource *flex1 = _res->getPicture(78);
+ Graphics::Surface *surf = flex1->getPicture();
+ CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, 0, 0, 0);
+ CursorMan.showMouse(true);
+ _res->freeResource(flex1);
+ _eventMouseX = _eventMouseY = 0;
+ _script->runScript(_dat->getMainCodeObjectIndex());
+
+ return 0;
+}
+
+} // End of namespace Made
diff --git a/engines/made/made.h b/engines/made/made.h
new file mode 100644
index 0000000000..6753b391cd
--- /dev/null
+++ b/engines/made/made.h
@@ -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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_H
+#define MADE_H
+
+#include "common/scummsys.h"
+#include "common/endian.h"
+#include "common/util.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/system.h"
+#include "common/hash-str.h"
+#include "common/events.h"
+#include "common/keyboard.h"
+
+#include "graphics/surface.h"
+
+#include "sound/audiostream.h"
+#include "sound/mixer.h"
+#include "sound/voc.h"
+#include "sound/audiocd.h"
+
+#include "engines/engine.h"
+
+namespace Made {
+
+enum MadeGameFeatures {
+};
+
+struct MadeGameDescription;
+
+class ProjectReader;
+class PmvPlayer;
+class Screen;
+class ScriptInterpreter;
+class GameDatabase;
+
+class MadeEngine : public ::Engine {
+ int _gameId;
+ Common::KeyState _keyPressed;
+
+protected:
+
+ int init();
+ int go();
+
+public:
+ MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc);
+ virtual ~MadeEngine();
+ int getGameId() {
+ return _gameId;
+ }
+
+ Common::RandomSource *_rnd;
+ const MadeGameDescription *_gameDescription;
+ uint32 getGameID() const;
+ uint32 getFeatures() const;
+ uint16 getVersion() const;
+ Common::Platform getPlatform() const;
+ void update_events();
+
+private:
+public:
+ PmvPlayer *_pmvPlayer;
+ ProjectReader *_res;
+ Screen *_screen;
+ GameDatabase *_dat;
+ ScriptInterpreter *_script;
+
+ int _eventMouseX, _eventMouseY;
+
+ int32 _timers[50];
+ int16 getTimer(int16 timerNum);
+ void setTimer(int16 timerNum, int16 value);
+ void resetTimer(int16 timerNum);
+ int16 allocTimer();
+ void freeTimer(int16 timerNum);
+
+};
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/module.mk b/engines/made/module.mk
new file mode 100644
index 0000000000..727a785dbc
--- /dev/null
+++ b/engines/made/module.mk
@@ -0,0 +1,22 @@
+MODULE := engines/made
+
+MODULE_OBJS = \
+ database.o \
+ detection.o \
+ graphics.o \
+ made.o \
+ pmvplayer.o \
+ resource.o \
+ screen.o \
+ script.o \
+ scriptfuncs.o \
+ sound.o
+
+
+# This module can be built as a plugin
+ifdef BUILD_PLUGINS
+PLUGIN := 1
+endif
+
+# Include common rules
+include $(srcdir)/rules.mk
diff --git a/engines/made/pmvplayer.cpp b/engines/made/pmvplayer.cpp
new file mode 100644
index 0000000000..704947132e
--- /dev/null
+++ b/engines/made/pmvplayer.cpp
@@ -0,0 +1,152 @@
+#include "made/pmvplayer.h"
+
+namespace Made {
+
+PmvPlayer::PmvPlayer(OSystem *system, Audio::Mixer *mixer) : _fd(NULL), _system(system), _mixer(mixer) {
+}
+
+PmvPlayer::~PmvPlayer() {
+}
+
+void PmvPlayer::play(const char *filename) {
+
+ _abort = false;
+ _surface = NULL;
+
+ _fd = new Common::File();
+ _fd->open(filename);
+
+ uint32 chunkType, chunkSize;
+
+ readChunk(chunkType, chunkSize); // "MOVE"
+ readChunk(chunkType, chunkSize); // "MHED"
+
+ // TODO: Evaluate header
+ //_fd->skip(0x3A);
+
+ uint frameDelay = _fd->readUint16LE();
+ _fd->skip(10);
+ uint soundFreq = _fd->readUint16LE();
+ // FIXME: weird frequencies... (11127 or 22254)
+ //if (soundFreq == 11127) soundFreq = 11025;
+ //if (soundFreq == 22254) soundFreq = 22050;
+
+ int unk;
+
+ for (int i = 0; i < 22; i++) {
+ unk = _fd->readUint16LE();
+ debug(2, "%i ", unk);
+ }
+ debug(2, "\n");
+
+ _mixer->stopAll();
+
+ _audioStream = Audio::makeAppendableAudioStream(soundFreq, Audio::Mixer::FLAG_UNSIGNED);
+ _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &_audioStreamHandle, _audioStream);
+
+ // Read palette
+ _fd->read(_palette, 768);
+ updatePalette();
+
+ //FILE *raw = fopen("track.raw", "wb");
+
+ while (!_abort && !_fd->eof()) {
+
+ readChunk(chunkType, chunkSize);
+
+ if (_fd->eof())
+ break;
+
+ byte *frameData = new byte[chunkSize];
+ _fd->read(frameData, chunkSize);
+
+ byte *audioData = frameData + READ_LE_UINT32(frameData + 8) - 8;
+ uint16 chunkSize = READ_LE_UINT16(audioData + 4);
+ uint16 chunkCount = READ_LE_UINT16(audioData + 6);
+
+ if (chunkCount > 50) break; // FIXME: this is a hack
+
+ debug(2, "chunkCount = %d; chunkSize = %d\n", chunkCount, chunkSize);
+
+ uint32 soundSize = chunkCount * chunkSize;
+ byte *soundData = new byte[soundSize];
+ decompressSound(audioData + 8, soundData, chunkSize, chunkCount);
+ _audioStream->queueBuffer(soundData, soundSize);
+
+ //fwrite(soundData, soundSize, 1, raw);
+
+ byte *imageData = frameData + READ_LE_UINT32(frameData + 12) - 8;
+
+ uint32 frameNum = READ_LE_UINT32(frameData);
+ uint16 width = READ_LE_UINT16(imageData + 8);
+ uint16 height = READ_LE_UINT16(imageData + 10);
+ uint16 cmdOffs = READ_LE_UINT16(imageData + 12);
+ uint16 pixelOffs = READ_LE_UINT16(imageData + 16);
+ uint16 maskOffs = READ_LE_UINT16(imageData + 20);
+ uint16 lineSize = READ_LE_UINT16(imageData + 24);
+
+ debug(2, "width = %d; height = %d; cmdOffs = %04X; pixelOffs = %04X; maskOffs = %04X; lineSize = %d\n",
+ width, height, cmdOffs, pixelOffs, maskOffs, lineSize);
+
+ if (!_surface) {
+ _surface = new Graphics::Surface();
+ _surface->create(width, height, 1);
+ }
+
+ decompressImage(imageData, *_surface, cmdOffs, pixelOffs, maskOffs, lineSize, frameNum > 0);
+
+ handleEvents();
+ updateScreen();
+
+ delete[] frameData;
+
+ _system->delayMillis(frameDelay);
+ }
+
+ _audioStream->finish();
+ _mixer->stopAll();
+
+ //delete _audioStream;
+ delete _fd;
+ delete _surface;
+
+ //fclose(raw);
+
+}
+
+void PmvPlayer::readChunk(uint32 &chunkType, uint32 &chunkSize) {
+ chunkType = _fd->readUint32BE();
+ chunkSize = _fd->readUint32LE();
+
+ debug(2, "chunkType = %c%c%c%c; chunkSize = %d\n",
+ (chunkType >> 24) & 0xFF, (chunkType >> 16) & 0xFF, (chunkType >> 8) & 0xFF, chunkType & 0xFF,
+ chunkSize);
+
+}
+
+void PmvPlayer::handleEvents() {
+ Common::Event event;
+ while (_system->getEventManager()->pollEvent(event)) {
+ if (event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) {
+ _abort = true;
+ }
+ }
+}
+
+void PmvPlayer::updatePalette() {
+ byte colors[1024];
+ for (int i = 0; i < 256; i++) {
+ colors[i * 4 + 0] = _palette[i * 3 + 0];
+ colors[i * 4 + 1] = _palette[i * 3 + 1];
+ colors[i * 4 + 2] = _palette[i * 3 + 2];
+ colors[i * 4 + 3] = 0;
+ }
+ _system->setPalette(colors, 0, 256);
+}
+
+void PmvPlayer::updateScreen() {
+ _system->copyRectToScreen((const byte*)_surface->pixels, _surface->pitch, 0, 0, _surface->w, _surface->h);
+ _system->updateScreen();
+}
+
+}
diff --git a/engines/made/pmvplayer.h b/engines/made/pmvplayer.h
new file mode 100644
index 0000000000..51f5a36734
--- /dev/null
+++ b/engines/made/pmvplayer.h
@@ -0,0 +1,39 @@
+#ifndef MADE_PMVPLAYER_H
+#define MADE_PMVPLAYER_H
+
+#include "common/system.h"
+#include "common/events.h"
+#include "common/file.h"
+#include "common/endian.h"
+#include "graphics/surface.h"
+#include "sound/mixer.h"
+#include "sound/audiostream.h"
+
+#include "made/graphics.h"
+#include "made/sound.h"
+
+namespace Made {
+
+class PmvPlayer {
+public:
+ PmvPlayer(OSystem *system, Audio::Mixer *mixer);
+ ~PmvPlayer();
+ void play(const char *filename);
+protected:
+ OSystem *_system;
+ Audio::Mixer *_mixer;
+ Common::File *_fd;
+ Audio::AppendableAudioStream *_audioStream;
+ Audio::SoundHandle _audioStreamHandle;
+ byte _palette[768];
+ Graphics::Surface *_surface;
+ bool _abort;
+ void readChunk(uint32 &chunkType, uint32 &chunkSize);
+ void handleEvents();
+ void updatePalette();
+ void updateScreen();
+};
+
+}
+
+#endif
diff --git a/engines/made/resource.cpp b/engines/made/resource.cpp
new file mode 100644
index 0000000000..ea1e16b3a2
--- /dev/null
+++ b/engines/made/resource.cpp
@@ -0,0 +1,333 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+
+#include "made/resource.h"
+#include "made/graphics.h"
+#include "made/sound.h"
+
+namespace Made {
+
+/* Resource */
+
+Resource::~Resource() {
+}
+
+/* PictureResource */
+
+PictureResource::PictureResource() : _picture(NULL), _palette(NULL) {
+}
+
+PictureResource::~PictureResource() {
+ if (_picture)
+ delete _picture;
+ if (_palette)
+ delete[] _palette;
+}
+
+void PictureResource::load(byte *source, int size) {
+
+ Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
+
+ bool hasPalette = sourceS->readByte() == 1;
+ sourceS->readByte();
+ sourceS->readByte();
+ sourceS->readByte();
+ uint16 cmdOffs = sourceS->readUint16LE();
+ uint16 pixelOffs = sourceS->readUint16LE();
+ uint16 maskOffs = sourceS->readUint16LE();
+ uint16 lineSize = sourceS->readUint16LE();
+ uint16 u = sourceS->readUint16LE();
+ uint16 width = sourceS->readUint16LE();
+ uint16 height = sourceS->readUint16LE();
+
+ debug(2, "width = %d; height = %d\n", width, height);
+
+ if (hasPalette) {
+ _palette = new byte[768];
+ sourceS->read(_palette, 768);
+ }
+
+ _picture = new Graphics::Surface();
+ _picture->create(width, height, 1);
+
+ decompressImage(source, *_picture, cmdOffs, pixelOffs, maskOffs, lineSize);
+
+ delete sourceS;
+
+}
+
+/* AnimationResource */
+
+AnimationResource::AnimationResource() {
+}
+
+AnimationResource::~AnimationResource() {
+ // TODO: Free anim frames
+}
+
+void AnimationResource::load(byte *source, int size) {
+
+ Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
+
+ sourceS->readUint32LE();
+ sourceS->readUint32LE();
+ sourceS->readUint16LE();
+
+ _flags = sourceS->readUint16LE();
+ _width = sourceS->readUint16LE();
+ _height = sourceS->readUint16LE();
+ sourceS->readUint32LE();
+ uint16 frameCount = sourceS->readUint16LE();
+ sourceS->readUint16LE();
+ sourceS->readUint16LE();
+
+ for (uint16 i = 0; i < frameCount; i++) {
+
+ sourceS->seek(26 + i * 4);
+
+ uint32 frameOffs = sourceS->readUint32LE();
+
+ sourceS->seek(frameOffs);
+ sourceS->readUint32LE();
+ sourceS->readUint32LE();
+
+ uint16 frameWidth = sourceS->readUint16LE();
+ uint16 frameHeight = sourceS->readUint16LE();
+ uint16 cmdOffs = sourceS->readUint16LE();
+ sourceS->readUint16LE();
+ uint16 pixelOffs = sourceS->readUint16LE();
+ sourceS->readUint16LE();
+ uint16 maskOffs = sourceS->readUint16LE();
+ sourceS->readUint16LE();
+ uint16 lineSize = sourceS->readUint16LE();
+
+ Graphics::Surface *frame = new Graphics::Surface();
+ frame->create(frameWidth, frameHeight, 1);
+
+ decompressImage(source + frameOffs, *frame, cmdOffs, pixelOffs, maskOffs, lineSize, _flags & 1);
+
+ _frames.push_back(frame);
+
+ }
+
+ delete sourceS;
+
+}
+
+/* SoundResource */
+
+SoundResource::SoundResource() : _soundSize(0), _soundData(NULL) {
+}
+
+SoundResource::~SoundResource() {
+ if (_soundData)
+ delete[] _soundData;
+}
+
+void SoundResource::load(byte *source, int size) {
+
+ uint16 chunkCount = READ_LE_UINT16(source + 8);
+ uint16 chunkSize = READ_LE_UINT16(source + 12);
+
+ _soundSize = chunkCount * chunkSize;
+ _soundData = new byte[_soundSize];
+
+ decompressSound(source + 14, _soundData, chunkSize, chunkCount);
+
+}
+
+Audio::AudioStream *SoundResource::getAudioStream() {
+ return Audio::makeLinearInputStream(_soundData, _soundSize, 22050, 0, 0, 0);
+}
+
+/* MenuResource */
+
+MenuResource::MenuResource() {
+}
+
+MenuResource::~MenuResource() {
+}
+
+void MenuResource::load(byte *source, int size) {
+ _strings.clear();
+ Common::MemoryReadStream *sourceS = new Common::MemoryReadStream(source, size);
+ sourceS->skip(4); // skip "MENU"
+ uint16 count = sourceS->readUint16LE();
+ for (uint16 i = 0; i < count; i++) {
+ uint16 offs = sourceS->readUint16LE();
+ const char *string = (const char*)(source + offs);
+ _strings.push_back(string);
+ debug(2, "%02d: %s\n", i, string);
+ }
+ fflush(stdout);
+ delete sourceS;
+}
+
+/* ProjectReader */
+
+ProjectReader::ProjectReader() {
+}
+
+ProjectReader::~ProjectReader() {
+}
+
+void ProjectReader::open(const char *filename) {
+
+ _fd = new Common::File();
+ _fd->open(filename);
+
+ _fd->skip(0x18); // skip header for now
+
+ uint16 indexCount = _fd->readUint16LE();
+
+ for (uint16 i = 0; i < indexCount; i++) {
+
+ uint32 resType = _fd->readUint32BE();
+ uint32 indexOffs = _fd->readUint32LE();
+ _fd->readUint32LE();
+ _fd->readUint32LE();
+ _fd->readUint32LE();
+ _fd->readUint16LE();
+ _fd->readUint16LE();
+
+ // We don't need ARCH, FREE and OMNI resources
+ if (resType == kResARCH || resType == kResFREE || resType == kResOMNI)
+ continue;
+
+ //debug(2, "resType = %08X; indexOffs = %d\n", resType, indexOffs);
+
+ uint32 oldOffs = _fd->pos();
+
+ ResourceSlots *resSlots = new ResourceSlots();
+ _fd->seek(indexOffs);
+ loadIndex(resSlots);
+ _resSlots[resType] = resSlots;
+
+ _fd->seek(oldOffs);
+
+ }
+
+ _cacheCount = 0;
+
+}
+
+PictureResource *ProjectReader::getPicture(int index) {
+ return createResource<PictureResource>(kResFLEX, index);
+}
+
+AnimationResource *ProjectReader::getAnimation(int index) {
+ return createResource<AnimationResource>(kResANIM, index);
+}
+
+SoundResource *ProjectReader::getSound(int index) {
+ return createResource<SoundResource>(kResSNDS, index);
+}
+
+MenuResource *ProjectReader::getMenu(int index) {
+ return createResource<MenuResource>(kResMENU, index);
+}
+
+void ProjectReader::loadIndex(ResourceSlots *slots) {
+ _fd->readUint32LE(); // skip INDX
+ _fd->readUint32LE(); // skip index size
+ _fd->readUint32LE(); // skip unknown
+ _fd->readUint32LE(); // skip res type
+ uint16 count = _fd->readUint16LE();
+ _fd->readUint16LE(); // skip unknown count
+ _fd->readUint16LE(); // skip unknown count
+ for (uint16 i = 0; i < count; i++) {
+ uint32 offs = _fd->readUint32LE();
+ uint32 size = _fd->readUint32LE();
+ slots->push_back(ResourceSlot(offs, size));
+ }
+}
+
+void ProjectReader::freeResource(Resource *resource) {
+ tossResourceFromCache(resource->slot);
+}
+
+bool ProjectReader::loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size) {
+ if (slot && slot->size > 0) {
+ size = slot->size - 62;
+ buffer = new byte[size];
+ debug(2, "ProjectReader::loadResource() %08X\n", slot->offs + 62); fflush(stdout);
+ _fd->seek(slot->offs + 62);
+ _fd->read(buffer, size);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+ResourceSlot *ProjectReader::getResourceSlot(uint32 resType, uint index) {
+ ResourceSlots *slots = _resSlots[resType];
+ if (index >= 1 && index < slots->size()) {
+ ResourceSlot *slot = &slots->operator[](index);
+ return slot;
+ } else {
+ return NULL;
+ }
+}
+
+Resource *ProjectReader::getResourceFromCache(ResourceSlot *slot) {
+ if (slot->res)
+ slot->refCount++;
+ return slot->res;
+}
+
+void ProjectReader::addResourceToCache(ResourceSlot *slot, Resource *res) {
+ if (_cacheCount >= kMaxResourceCacheCount) {
+ purgeCache();
+ }
+ slot->res = res;
+ slot->refCount = 0;
+ _cacheCount++;
+}
+
+void ProjectReader::tossResourceFromCache(ResourceSlot *slot) {
+ if (slot->res) {
+ slot->refCount--;
+ }
+}
+
+void ProjectReader::purgeCache() {
+ printf("ProjectReader::purgeCache()\n");
+ for (ResMap::const_iterator resTypeIter = _resSlots.begin(); resTypeIter != _resSlots.end(); ++resTypeIter) {
+ ResourceSlots *slots = (*resTypeIter)._value;
+ for (ResourceSlots::iterator slotIter = slots->begin(); slotIter != slots->end(); ++slotIter) {
+ ResourceSlot *slot = &(*slotIter);
+ if (slot->refCount <= 0 && slot->res) {
+ delete slot->res;
+ slot->res = NULL;
+ slot->refCount = 0;
+ _cacheCount--;
+ }
+ }
+ }
+}
+
+} // End of namespace Made
diff --git a/engines/made/resource.h b/engines/made/resource.h
new file mode 100644
index 0000000000..9b672a1c5d
--- /dev/null
+++ b/engines/made/resource.h
@@ -0,0 +1,178 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_RESOURCE_H
+#define MADE_RESOURCE_H
+
+#include "common/util.h"
+#include "common/file.h"
+#include "common/stream.h"
+#include "common/hashmap.h"
+#include "graphics/surface.h"
+#include "sound/audiostream.h"
+
+namespace Made {
+
+const int kMaxResourceCacheCount = 100;
+
+enum ResourceType {
+ kResARCH = MKID_BE('ARCH'),
+ kResFREE = MKID_BE('FREE'),
+ kResOMNI = MKID_BE('OMNI'),
+ kResFLEX = MKID_BE('FLEX'),
+ kResSNDS = MKID_BE('SNDS'),
+ kResANIM = MKID_BE('ANIM'),
+ kResMENU = MKID_BE('MENU')
+};
+
+struct ResourceSlot;
+
+class Resource {
+public:
+ ResourceSlot *slot;
+ virtual ~Resource();
+ virtual void load(byte *buffer, int size) = 0;
+};
+
+class PictureResource : public Resource {
+public:
+ PictureResource();
+ ~PictureResource();
+ void load(byte *source, int size);
+ Graphics::Surface *getPicture() const { return _picture; }
+ byte *getPalette() const { return _palette; }
+protected:
+ Graphics::Surface *_picture;
+ byte *_palette;
+};
+
+class AnimationResource : public Resource {
+public:
+ AnimationResource();
+ ~AnimationResource();
+ void load(byte *source, int size);
+ int getCount() const { return _frames.size(); }
+ Graphics::Surface *getFrame(int index) const { return _frames[index]; }
+ uint16 getFlags() const { return _flags; }
+ int16 getWidth() const { return _width; }
+ int16 getHeight() const { return _height; }
+protected:
+ Common::Array<Graphics::Surface*> _frames;
+ uint16 _flags;
+ int16 _width, _height;
+};
+
+class SoundResource : public Resource {
+public:
+ SoundResource();
+ ~SoundResource();
+ void load(byte *source, int size);
+ Audio::AudioStream *getAudioStream();
+protected:
+ byte *_soundData;
+ int _soundSize;
+};
+
+class MenuResource : public Resource {
+public:
+ MenuResource();
+ ~MenuResource();
+ void load(byte *source, int size);
+ int getCount() const { return _strings.size(); }
+ Common::String getString(int index) const { return _strings[index]; }
+protected:
+ Common::Array<Common::String> _strings;
+};
+
+struct ResourceSlot {
+ uint32 offs;
+ uint32 size;
+ Resource *res;
+ int refCount;
+ ResourceSlot() : offs(0), size(0), res(NULL), refCount(0) {
+ }
+ ResourceSlot(uint32 roffs, uint32 rsize) : offs(roffs), size(rsize), res(NULL), refCount(0) {
+ }
+};
+
+class ProjectReader {
+public:
+
+ ProjectReader();
+ ~ProjectReader();
+
+ void open(const char *filename);
+
+ PictureResource *getPicture(int index);
+ AnimationResource *getAnimation(int index);
+ SoundResource *getSound(int index);
+ MenuResource *getMenu(int index);
+
+ void freeResource(Resource *resource);
+
+protected:
+
+ Common::File *_fd;
+
+ typedef Common::Array<ResourceSlot> ResourceSlots;
+ typedef Common::HashMap<uint32, ResourceSlots*> ResMap;
+
+ ResMap _resSlots;
+ int _cacheCount;
+
+ void loadIndex(ResourceSlots *slots);
+
+ template <class T>
+ T *createResource(uint32 resType, int index) {
+ ResourceSlot *slot = getResourceSlot(resType, index);
+ if (!slot)
+ return NULL;
+ T *res = (T*)getResourceFromCache(slot);
+ if (!res) {
+ byte *buffer;
+ uint32 size;
+ if (loadResource(slot, buffer, size)) {
+ res = new T();
+ res->slot = slot;
+ res->load(buffer, size);
+ addResourceToCache(slot, res);
+ delete[] buffer;
+ }
+ }
+ return res;
+ }
+
+ bool loadResource(ResourceSlot *slot, byte *&buffer, uint32 &size);
+ ResourceSlot *getResourceSlot(uint32 resType, uint index);
+ Resource *getResourceFromCache(ResourceSlot *slot);
+ void addResourceToCache(ResourceSlot *slot, Resource *res);
+ void tossResourceFromCache(ResourceSlot *slot);
+ void purgeCache();
+
+};
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/screen.cpp b/engines/made/screen.cpp
new file mode 100644
index 0000000000..90688929ae
--- /dev/null
+++ b/engines/made/screen.cpp
@@ -0,0 +1,459 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "made/made.h"
+#include "made/screen.h"
+#include "made/resource.h"
+
+namespace Made {
+
+Screen::Screen(MadeEngine *vm) : _vm(vm) {
+
+ _screen1 = new Graphics::Surface();
+ _screen1->create(320, 200, 1);
+ _clipInfo1.x = 0;
+ _clipInfo1.y = 0;
+ _clipInfo1.w = 320;
+ _clipInfo1.h = 200;
+ _clipInfo1.destSurface = _screen1;
+
+ _screen2 = new Graphics::Surface();
+ _screen2->create(320, 200, 1);
+ _clipInfo2.x = 0;
+ _clipInfo2.y = 0;
+ _clipInfo2.w = 320;
+ _clipInfo2.h = 200;
+ _clipInfo2.destSurface = _screen2;
+
+ _clipArea.destSurface = _screen2;
+
+ _excludeClipAreaEnabled[0] = false;
+ _excludeClipAreaEnabled[1] = false;
+ _excludeClipAreaEnabled[2] = false;
+ _excludeClipAreaEnabled[3] = false;
+
+ clearChannels();
+
+}
+
+Screen::~Screen() {
+ delete _screen1;
+ delete _screen2;
+}
+
+void Screen::clearScreen() {
+ _screen1->fillRect(Common::Rect(0, 0, 320, 200), 0);
+ _screen2->fillRect(Common::Rect(0, 0, 320, 200), 0);
+ //_vm->_system->clearScreen();
+}
+
+void Screen::drawSurface(Graphics::Surface *source, int x, int y) {
+
+}
+
+void Screen::setPalette(byte *palette, int start, int count) {
+}
+
+uint16 Screen::updateChannel(uint16 channelIndex) {
+ return 0;
+}
+
+void Screen::deleteChannel(uint16 channelIndex) {
+ if (channelIndex < 1 || channelIndex >= 100)
+ return;
+ _channels[channelIndex - 1].type = 0;
+ _channels[channelIndex - 1].state = 0;
+ _channels[channelIndex - 1].index = 0;
+}
+
+int16 Screen::getChannelType(uint16 channelIndex) {
+ if (channelIndex < 1 || channelIndex >= 100)
+ return -1;
+ return _channels[channelIndex - 1].type;
+}
+
+int16 Screen::getChannelState(uint16 channelIndex) {
+ if (channelIndex < 1 || channelIndex >= 100)
+ return -1;
+ return _channels[channelIndex - 1].state;
+}
+
+void Screen::setChannelState(uint16 channelIndex, int16 state) {
+ if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
+ return;
+ _channels[channelIndex - 1].state = state;
+}
+
+uint16 Screen::setChannelLocation(uint16 channelIndex, int16 x, int16 y) {
+ if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
+ return 0;
+ _channels[channelIndex - 1].x = x;
+ _channels[channelIndex - 1].y = y;
+ return updateChannel(channelIndex - 1) + 1;
+}
+
+uint16 Screen::setChannelContent(uint16 channelIndex, uint16 index) {
+ if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
+ return 0;
+ //debug(2, "setChannelContent(%d, %04X)\n", channelIndex, index); fflush(stdout); g_system->delayMillis(5000);
+ _channels[channelIndex - 1].index = index;
+ return updateChannel(channelIndex - 1) + 1;
+}
+
+void Screen::drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask) {
+
+ _excludeClipArea[0].destSurface = clipInfo.destSurface;
+ _excludeClipArea[1].destSurface = clipInfo.destSurface;
+ _excludeClipArea[2].destSurface = clipInfo.destSurface;
+ _excludeClipArea[3].destSurface = clipInfo.destSurface;
+ _clipArea.destSurface = clipInfo.destSurface;
+
+ for (uint16 i = 0; i < _channelsUsedCount; i++) {
+
+ debug(2, "drawSpriteChannels() i = %d\n", i);
+
+ if (((_channels[i].state & includeStateMask) == includeStateMask) && (_channels[i].state & excludeStateMask) == 0)
+ {
+
+ uint16 flag1 = _channels[i].state & 0x10;
+ uint16 flag2 = _channels[i].state & 0x20;
+
+ debug(2, "drawSpriteChannels() type = %d; index = %04X\n", _channels[i].type, _channels[i].index);
+
+ switch (_channels[i].type) {
+
+ case 1: // drawFlex
+ if (_channels[i].state & 4) {
+ drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _clipArea);
+ } else if (_channels[i].state & 8) {
+ for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) {
+ if (_excludeClipAreaEnabled[excludeIndex]) {
+ drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, _excludeClipArea[excludeIndex]);
+ }
+ }
+ } else {
+ drawFlex(_channels[i].index, _channels[i].x, _channels[i].y, flag1, flag2, clipInfo);
+ }
+ break;
+
+ case 2: // drawObjectText
+ // TODO
+ break;
+
+ case 3: // drawAnimFrame
+ if (_channels[i].state & 4) {
+ drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _clipArea);
+ } else if (_channels[i].state & 8) {
+ for (int excludeIndex = 0; excludeIndex < 4; excludeIndex++) {
+ if (_excludeClipAreaEnabled[excludeIndex]) {
+ drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, _excludeClipArea[excludeIndex]);
+ }
+ }
+ } else {
+ drawAnimFrame(_channels[i].index, _channels[i].x, _channels[i].y, _channels[i].frameNum, flag1, flag2, clipInfo);
+ }
+ break;
+
+ case 4: // drawMenuText
+ // TODO
+ break;
+
+ default:
+ break;
+
+ }
+
+ }
+
+ }
+
+}
+
+void Screen::updateSprites() {
+
+ // TODO: This needs some more work, I don't use dirty rectangles for now
+
+ memcpy(_screen2->pixels, _screen1->pixels, 64000);
+
+ //drawSpriteChannels(_clipInfo1, 3, 0x40);//CHECKME
+
+ drawSpriteChannels(_clipInfo1, 3, 0);//CHECKME
+ drawSpriteChannels(_clipInfo2, 1, 2);//CHECKME
+
+ _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h);
+
+}
+
+void Screen::clearChannels() {
+ for (uint16 i = 0; i < ARRAYSIZE(_channels); i++) {
+ _channels[i].type = 0;
+ _channels[i].index = 0;
+ }
+ _channelsUsedCount = 0;
+}
+
+uint16 Screen::drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) {
+
+ if (flexIndex == 0)
+ return 0;
+
+ PictureResource *flex = _vm->_res->getPicture(flexIndex);
+ Graphics::Surface *sourceSurface = flex->getPicture();
+ byte *source = (byte*)sourceSurface->getBasePtr(0, 0);
+ byte *dest = (byte*)clipInfo.destSurface->getBasePtr(x, y);
+
+
+ if (x + sourceSurface->w > clipInfo.destSurface->w || y + sourceSurface->h > clipInfo.destSurface->h) {
+ debug(2, "CLIPPING PROBLEM: x = %d; y = %d; w = %d; h = %d; x+w = %d; y+h = %d\n",
+ x, y, sourceSurface->w, sourceSurface->h, x + sourceSurface->w, y + sourceSurface->h);
+ //fflush(stdout); g_system->delayMillis(5000);
+ return 0;
+ }
+
+ for (int16 yc = 0; yc < sourceSurface->h; yc++) {
+ for (int16 xc = 0; xc < sourceSurface->w; xc++) {
+ if (source[xc])
+ dest[xc] = source[xc];
+ }
+ source += sourceSurface->pitch;
+ dest += clipInfo.destSurface->pitch;
+ }
+
+ // TODO: Palette stuff; palette should be set in showPage
+ byte *pal = flex->getPalette();
+ if (pal) {
+ for (int i = 0; i < 256; i++) {
+ _palette[i * 4 + 0] = pal[i * 3 + 0];
+ _palette[i * 4 + 1] = pal[i * 3 + 1];
+ _palette[i * 4 + 2] = pal[i * 3 + 2];
+ }
+ _vm->_system->setPalette(_palette, 0, 256);
+ }
+
+ _vm->_res->freeResource(flex);
+
+ return 0;
+}
+
+void Screen::drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo) {
+
+ AnimationResource *anim = _vm->_res->getAnimation(animIndex);
+ Graphics::Surface *sourceSurface = anim->getFrame(frameNum);
+ byte *source = (byte*)sourceSurface->getBasePtr(0, 0);
+ byte *dest = (byte*)clipInfo.destSurface->getBasePtr(x, y);
+
+ for (int16 yc = 0; yc < sourceSurface->h; yc++) {
+ for (int16 xc = 0; xc < sourceSurface->w; xc++) {
+ if (source[xc])
+ dest[xc] = source[xc];
+ }
+ source += sourceSurface->pitch;
+ dest += clipInfo.destSurface->pitch;
+ }
+
+ _vm->_res->freeResource(anim);
+
+}
+
+uint16 Screen::drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2) {
+
+ //DEBUG
+ if (y > 200) y = 0;
+
+ drawFlex(index, x, y, flag1, flag2, _clipInfo1);
+ return 0;
+}
+
+uint16 Screen::drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2) {
+ drawAnimFrame(animIndex, x, y, frameNum, flag1, flag2, _clipInfo1);
+ return 0;
+}
+
+uint16 Screen::addSprite(uint16 spriteIndex) {
+ bool oldScreenLock = _screenLock;
+ drawFlex(spriteIndex, 0, 0, 0, 0, _clipInfo1);
+ _screenLock = oldScreenLock;
+ return 0;
+}
+
+uint16 Screen::drawSprite(uint16 flexIndex, int16 x, int16 y) {
+ return placeSprite(_channelsUsedCount + 1, flexIndex, x, y);
+}
+
+uint16 Screen::placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 y) {
+
+ debug(2, "placeSprite(%d, %04X, %d, %d)\n", channelIndex, flexIndex, x, y); fflush(stdout);
+ //g_system->delayMillis(5000);
+
+ if (channelIndex < 1 || channelIndex >= 100)
+ return 0;
+
+ channelIndex--;
+
+ PictureResource *flex = _vm->_res->getPicture(flexIndex);
+
+ if (flex) {
+ Graphics::Surface *surf = flex->getPicture();
+
+ int16 state = 1;
+ int16 x1, y1, x2, y2;
+
+ x1 = x;
+ y1 = y;
+ x2 = x + surf->w + 1;
+ y2 = y + surf->h + 1;
+ //TODO: clipRect(x1, y1, x2, y2);
+
+ if (_ground == 0)
+ state |= 2;
+ if (_clip != 0)
+ state |= 4;
+ if (_exclude != 0)
+ state |= 8;
+
+ _channels[channelIndex].state = state;
+ _channels[channelIndex].type = 1;
+ _channels[channelIndex].index = flexIndex;
+ _channels[channelIndex].x = x;
+ _channels[channelIndex].y = y;
+ _channels[channelIndex].x1 = x1;
+ _channels[channelIndex].y1 = y1;
+ _channels[channelIndex].x2 = x2;
+ _channels[channelIndex].y2 = y2;
+ _channels[channelIndex].area = (x2 - x2) * (y2 - y1);
+
+ if (_channelsUsedCount <= channelIndex)
+ _channelsUsedCount = channelIndex + 1;
+
+ _vm->_res->freeResource(flex);
+ } else {
+ _channels[channelIndex].type = 0;
+ _channels[channelIndex].state = 0;
+ }
+
+ return channelIndex + 1;
+
+}
+
+uint16 Screen::placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y, int16 frameNum) {
+
+ if (channelIndex < 1 || channelIndex >= 100)
+ return 0;
+
+ channelIndex--;
+
+ AnimationResource *anim = _vm->_res->getAnimation(animIndex);
+
+ if (anim) {
+
+ int16 state = 1;
+ int16 x1, y1, x2, y2;
+
+ x1 = x;
+ y1 = y;
+ x2 = x + anim->getWidth();
+ y2 = y + anim->getHeight();
+ //TODO: clipRect(x1, y1, x2, y2);
+
+ if (anim->getFlags() == 1 || _ground == 0)
+ state |= 2;
+ if (_clip != 0)
+ state |= 4;
+ if (_exclude != 0)
+ state |= 8;
+
+ _channels[channelIndex].state = state;
+ _channels[channelIndex].type = 3;
+ _channels[channelIndex].index = animIndex;
+ _channels[channelIndex].frameNum = frameNum;
+ _channels[channelIndex].needRefresh = 1;
+ _channels[channelIndex].x = x;
+ _channels[channelIndex].y = y;
+ _channels[channelIndex].x1 = x1;
+ _channels[channelIndex].y1 = y1;
+ _channels[channelIndex].x2 = x2;
+ _channels[channelIndex].y2 = y2;
+ _channels[channelIndex].area = (x2 - x2) * (y2 - y1);
+
+ if (_channelsUsedCount <= channelIndex)
+ _channelsUsedCount = channelIndex + 1;
+
+ _vm->_res->freeResource(anim);
+ } else {
+ _channels[channelIndex].type = 0;
+ _channels[channelIndex].state = 0;
+ }
+
+ return channelIndex + 1;
+
+}
+
+int16 Screen::setAnimFrame(uint16 channelIndex, int16 frameNum) {
+ if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
+ return 0;
+ channelIndex--;
+ _channels[channelIndex].frameNum = frameNum;
+ _channels[channelIndex].needRefresh = 1;
+ return updateChannel(channelIndex) + 1;
+}
+
+int16 Screen::getAnimFrame(uint16 channelIndex) {
+ if (channelIndex < 1 || channelIndex >= 100 || _channels[channelIndex - 1].type == 0)
+ return -1;
+ return _channels[channelIndex - 1].frameNum;
+}
+
+int16 Screen::getAnimFrameCount(uint16 animIndex) {
+ int16 frameCount = 0;
+ AnimationResource *anim = _vm->_res->getAnimation(animIndex);
+ if (anim) {
+ frameCount = anim->getCount();
+ _vm->_res->freeResource(anim);
+ }
+ return frameCount;
+}
+
+
+uint16 Screen::placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor) {
+ return 0;
+}
+
+void Screen::show() {
+
+ // TODO
+
+ memcpy(_screen2->pixels, _screen1->pixels, 64000);
+
+ drawSpriteChannels(_clipInfo2, 0, 0);
+
+ //drawSpriteChannels(_clipInfo2, 3, 0);//CHECKME
+ //drawSpriteChannels(_clipInfo2, 1, 2);//CHECKME
+
+ //_vm->_system->copyRectToScreen((const byte*)_screen1->pixels, _screen1->pitch, 0, 0, _screen1->w, _screen1->h);
+ _vm->_system->copyRectToScreen((const byte*)_screen2->pixels, _screen2->pitch, 0, 0, _screen2->w, _screen2->h);
+
+}
+
+} // End of namespace Made
diff --git a/engines/made/screen.h b/engines/made/screen.h
new file mode 100644
index 0000000000..9197663383
--- /dev/null
+++ b/engines/made/screen.h
@@ -0,0 +1,123 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_SCREEN_H
+#define MADE_SCREEN_H
+
+#include "common/endian.h"
+#include "common/util.h"
+
+#include "graphics/surface.h"
+
+namespace Made {
+
+struct SpriteChannel {
+ int16 type;
+ int16 state;
+ int16 needRefresh;
+ uint16 index;
+ int16 x, y;
+ int16 x1, y1, x2, y2;
+ uint32 area;
+ uint16 fontNum;
+ int16 textColor, outlineColor;
+ int16 frameNum;
+};
+
+struct ClipInfo {
+ uint16 x, y, w, h;
+ Graphics::Surface *destSurface;
+};
+
+class MadeEngine;
+
+class Screen {
+public:
+ Screen(MadeEngine *vm);
+ ~Screen();
+
+ void clearScreen();
+
+ void drawSurface(Graphics::Surface *source, int x, int y);
+ void setPalette(byte *palette, int start, int count);
+
+ uint16 updateChannel(uint16 channelIndex);
+ void deleteChannel(uint16 channelIndex);
+ int16 getChannelType(uint16 channelIndex);
+ int16 getChannelState(uint16 channelIndex);
+ void setChannelState(uint16 channelIndex, int16 state);
+ uint16 setChannelLocation(uint16 channelIndex, int16 x, int16 y);
+ uint16 setChannelContent(uint16 channelIndex, uint16 index);
+ void drawSpriteChannels(const ClipInfo &clipInfo, int16 includeStateMask, int16 excludeStateMask);
+ void updateSprites();
+ void clearChannels();
+
+ uint16 drawFlex(uint16 flexIndex, int16 x, int16 y, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo);
+ void drawAnimFrame(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2, const ClipInfo &clipInfo);
+
+ uint16 drawPic(uint16 index, int16 x, int16 y, uint16 flag1, uint16 flag2);
+ uint16 drawAnimPic(uint16 animIndex, int16 x, int16 y, int16 frameNum, uint16 flag1, uint16 flag2);
+
+ uint16 addSprite(uint16 spriteIndex);
+
+ uint16 drawSprite(uint16 flexIndex, int16 x, int16 y);
+ uint16 placeSprite(uint16 channelIndex, uint16 flexIndex, int16 x, int16 y);
+
+ uint16 placeAnim(uint16 channelIndex, uint16 animIndex, int16 x, int16 y, int16 frameNum);
+ int16 setAnimFrame(uint16 channelIndex, int16 frameNum);
+ int16 getAnimFrame(uint16 channelIndex);
+ // TODO: Move to script function
+ int16 getAnimFrameCount(uint16 animIndex);
+
+ uint16 placeText(uint16 channelIndex, uint16 textObjectIndex, int16 x, int16 y, uint16 fontNum, int16 textColor, int16 outlineColor);
+
+ void show();
+
+ void setClip(uint16 clip);
+ void setExclude(uint16 exclude);
+ void setGround(uint16 ground);
+
+ byte _palette[256 * 4];
+
+protected:
+ MadeEngine *_vm;
+
+ bool _screenLock;
+
+ uint16 _clip, _exclude, _ground;
+
+ Graphics::Surface *_screen1, *_screen2;
+ ClipInfo _clipArea, _clipInfo1, _clipInfo2;
+
+ ClipInfo _excludeClipArea[4];
+ bool _excludeClipAreaEnabled[4];
+
+ uint16 _channelsUsedCount;
+ SpriteChannel _channels[100];
+};
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/script.cpp b/engines/made/script.cpp
new file mode 100644
index 0000000000..abbdf94eaa
--- /dev/null
+++ b/engines/made/script.cpp
@@ -0,0 +1,738 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/util.h"
+
+#include "made/made.h"
+#include "made/script.h"
+#include "made/database.h"
+#include "made/scriptfuncs.h"
+
+namespace Made {
+
+
+const char *extendFuncNames[] = {
+ "SYSTEM",
+ "INITGRAF",
+ "RESTOREGRAF",
+ "DRAWPIC",
+ "CLS",
+ "SHOWPAGE",
+ "EVENT",
+ "EVENTX",
+ "EVENTY",
+ "EVENTKEY",
+ "VISUALFX",
+ "PLAYSND",
+ "PLAYMUS",
+ "STOPMUS",
+ "ISMUS",
+ "TEXTPOS",
+ "FLASH",
+ "PLAYNOTE",
+ "STOPNOTE",
+ "PLAYTELE",
+ "STOPTELE",
+ "HIDECURS",
+ "SHOWCURS",
+ "MUSICBEAT",
+ "SCREENLOCK",
+ "ADDSPRITE",
+ "FREEANIM",
+ "DRAWSPRITE",
+ "ERASESPRITES",
+ "UPDATESPRITES",
+ "GETTIMER",
+ "SETTIMER",
+ "RESETTIMER",
+ "ALLOCTIMER",
+ "FREETIMER",
+ "PALETTELOCK",
+ "FONT",
+ "DRAWTEXT",
+ "HOMETEXT",
+ "TEXTRECT",
+ "TEXTXY",
+ "DROPSHADOW",
+ "TEXTCOLOR",
+ "OUTLINE",
+ "LOADCURSOR",
+ "SETGROUND",
+ "RESTEXT",
+ "CLIPAREA",
+ "SETCLIP",
+ "ISSND",
+ "STOPSND",
+ "PLAYVOICE",
+ "CDPLAY",
+ "STOPCD",
+ "CDSTATUS",
+ "CDTIME",
+ "CDPLAYSEG",
+ "PRINTF",
+ "MONOCLS",
+ "SNDENERGY",
+ "CLEARTEXT",
+ "ANIMTEXT",
+ "TEXTWIDTH",
+ "PLAYMOVIE",
+ "LOADSND",
+ "LOADMUS",
+ "LOADPIC",
+ "MUSICVOL",
+ "RESTARTEVENTS",
+ "PLACESPRITE",
+ "PLACETEXT",
+ "DELETECHANNEL",
+ "CHANNELTYPE",
+ "SETSTATE",
+ "SETLOCATION",
+ "SETCONTENT",
+ "EXCLUDEAREA",
+ "SETEXCLUDE",
+ "GETSTATE",
+ "PLACEANIM",
+ "SETFRAME",
+ "GETFRAME",
+ "GETFRAMECOUNT",
+ "PICWIDTH",
+ "PICHEIGHT",
+ "SOUNDRATE",
+ "DRAWANIMPIC",
+ "LOADANIM",
+ "READTEXT",
+ "READMENU",
+ "DRAWMENU",
+ "MENUCOUNT",
+ "SAVEGAME",
+ "LOADGAME",
+ "GAMENAME",
+ "SHAKESCREEN",
+ "PLACEMENU",
+ "SETVOLUME",
+ "WHATSYNTH",
+ "SLOWSYSTEM"
+};
+
+/* ScriptStack */
+
+ScriptStack::ScriptStack() {
+ for (int16 i = 0; i < kScriptStackSize; i++)
+ _stack[i] = 0;
+ _stackPos = kScriptStackSize;
+}
+
+ScriptStack::~ScriptStack() {
+}
+
+int16 ScriptStack::top() {
+ return _stack[_stackPos];
+}
+
+int16 ScriptStack::pop() {
+ if (_stackPos == kScriptStackSize)
+ error("ScriptStack::pop() Stack underflow");
+ return _stack[_stackPos++];
+}
+
+void ScriptStack::push(int16 value) {
+ if (_stackPos == 0)
+ error("ScriptStack::push() Stack overflow");
+ _stack[--_stackPos] = value;
+}
+
+void ScriptStack::setTop(int16 value) {
+ _stack[_stackPos] = value;
+}
+
+int16 ScriptStack::peek(int16 index) {
+ return _stack[index];
+}
+
+void ScriptStack::poke(int16 index, int16 value) {
+ _stack[index] = value;
+}
+
+void ScriptStack::alloc(int16 count) {
+ _stackPos -= count;
+}
+
+void ScriptStack::free(int16 count) {
+ _stackPos += count;
+}
+
+void ScriptStack::setStackPos(int16 stackPtr) {
+ _stackPos = stackPtr;
+}
+
+int16 *ScriptStack::getStackPtr() {
+ return &_stack[_stackPos];
+}
+
+/* ScriptInterpreter */
+
+ScriptInterpreter::ScriptInterpreter(MadeEngine *vm) : _vm(vm) {
+#define COMMAND(x) { &ScriptInterpreter::x, #x }
+ static CommandEntry commandProcs[] = {
+ /* 01 */
+ COMMAND(cmd_branchTrue),
+ COMMAND(cmd_branchFalse),
+ COMMAND(cmd_branch),
+ COMMAND(cmd_true),
+ /* 05 */
+ COMMAND(cmd_false),
+ COMMAND(cmd_push),
+ COMMAND(cmd_not),
+ COMMAND(cmd_add),
+ /* 09 */
+ COMMAND(cmd_sub),
+ COMMAND(cmd_mul),
+ COMMAND(cmd_div),
+ COMMAND(cmd_mod),
+ /* 13 */
+ COMMAND(cmd_band),
+ COMMAND(cmd_bor),
+ COMMAND(cmd_bnot),
+ COMMAND(cmd_lt),
+ /* 17 */
+ COMMAND(cmd_eq),
+ COMMAND(cmd_gt),
+ COMMAND(cmd_loadConstant),
+ COMMAND(cmd_loadVariable),
+ /* 21 */
+ COMMAND(cmd_getObjectProperty),
+ COMMAND(cmd_setObjectProperty),
+ COMMAND(cmd_set),
+ COMMAND(cmd_print),
+ /* 25 */
+ COMMAND(cmd_terpri),
+ COMMAND(cmd_printNumber),
+ COMMAND(cmd_vref),
+ COMMAND(cmd_vset),
+ /* 29 */
+ COMMAND(cmd_vsize),
+ COMMAND(cmd_exit),
+ COMMAND(cmd_return),
+ COMMAND(cmd_call),
+ /* 33 */
+ COMMAND(cmd_svar),
+ COMMAND(cmd_sset),
+ COMMAND(cmd_split),
+ COMMAND(cmd_snlit),
+ /* 37 */
+ COMMAND(cmd_yorn),
+ COMMAND(cmd_save),
+ COMMAND(cmd_restore),
+ COMMAND(cmd_arg),
+ /* 41 */
+ COMMAND(cmd_aset),
+ COMMAND(cmd_tmp),
+ COMMAND(cmd_tset),
+ COMMAND(cmd_tspace),
+ /* 45 */
+ COMMAND(cmd_class),
+ COMMAND(cmd_objectp),
+ COMMAND(cmd_vectorp),
+ COMMAND(cmd_restart),
+ /* 49 */
+ COMMAND(cmd_rand),
+ COMMAND(cmd_randomize),
+ COMMAND(cmd_send),
+ COMMAND(cmd_extend),
+ /* 53 */
+ COMMAND(cmd_catch),
+ COMMAND(cmd_cdone),
+ COMMAND(cmd_throw),
+ COMMAND(cmd_functionp),
+ /* 57 */
+ COMMAND(cmd_le),
+ COMMAND(cmd_ge),
+ COMMAND(cmd_varx),
+ COMMAND(cmd_setx)
+ };
+ _commands = commandProcs;
+ _commandsMax = ARRAYSIZE(commandProcs) + 1;
+
+ _functions = new ScriptFunctionsRtz(_vm);
+ _functions->setupExternalsTable();
+
+#undef COMMAND
+}
+
+ScriptInterpreter::~ScriptInterpreter() {
+ delete _functions;
+}
+
+void ScriptInterpreter::runScript(int16 scriptObjectIndex) {
+
+ _terminated = false;
+ _runningScriptObjectIndex = scriptObjectIndex;
+
+ _localStackPos = _stack.getStackPos();
+
+ _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
+ _codeIp = _codeBase;
+
+ while (!_terminated) {
+ byte opcode = readByte();
+ if (opcode >= 1 && opcode <= _commandsMax) {
+ debug(4, "opcode = %s\n", _commands[opcode - 1].desc);
+ (this->*_commands[opcode - 1].proc)();
+ } else {
+ printf("ScriptInterpreter::runScript(%d) Unknown opcode %02X\n", _runningScriptObjectIndex, opcode);
+ }
+ }
+
+}
+
+byte ScriptInterpreter::readByte() {
+ return *_codeIp++;
+}
+
+int16 ScriptInterpreter::readInt16() {
+ int16 temp = (int16)READ_LE_UINT16(_codeIp);
+ _codeIp += 2;
+ debug(4, "readInt16() value = %04X\n", temp);
+ return temp;
+}
+
+void ScriptInterpreter::cmd_branchTrue() {
+ int16 ofs = readInt16();
+ if (_stack.top() != 0)
+ _codeIp = _codeBase + ofs;
+}
+
+void ScriptInterpreter::cmd_branchFalse() {
+ int16 ofs = readInt16();
+ if (_stack.top() == 0)
+ _codeIp = _codeBase + ofs;
+}
+
+void ScriptInterpreter::cmd_branch() {
+ int16 ofs = readInt16();
+ _codeIp = _codeBase + ofs;
+}
+
+void ScriptInterpreter::cmd_true() {
+ _stack.setTop(-1);
+}
+
+void ScriptInterpreter::cmd_false() {
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_push() {
+ _stack.push();
+}
+
+void ScriptInterpreter::cmd_not() {
+ if (_stack.top() == 0)
+ _stack.setTop(-1);
+ else
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_add() {
+ int16 value = _stack.pop();
+ _stack.setTop(_stack.top() + value);
+}
+
+void ScriptInterpreter::cmd_sub() {
+ int16 value = _stack.pop();
+ _stack.setTop(_stack.top() - value);
+}
+
+void ScriptInterpreter::cmd_mul() {
+ int16 value = _stack.pop();
+ _stack.setTop(_stack.top() * value);
+}
+
+void ScriptInterpreter::cmd_div() {
+ int16 value = _stack.pop();
+ if (value == 0)
+ _stack.setTop(0);
+ else
+ _stack.setTop(_stack.top() / value);
+}
+
+void ScriptInterpreter::cmd_mod() {
+ int16 value = _stack.pop();
+ if (value == 0)
+ _stack.setTop(0);
+ else
+ _stack.setTop(_stack.top() % value);
+}
+
+void ScriptInterpreter::cmd_band() {
+ int16 value = _stack.pop();
+ _stack.setTop(_stack.top() & value);
+}
+
+void ScriptInterpreter::cmd_bor() {
+ int16 value = _stack.pop();
+ _stack.setTop(_stack.top() | value);
+}
+
+void ScriptInterpreter::cmd_bnot() {
+ _stack.setTop(~_stack.top());
+}
+
+void ScriptInterpreter::cmd_lt() {
+ int16 value = _stack.pop();
+ if (_stack.top() < value)
+ _stack.setTop(-1);
+ else
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_eq() {
+ int16 value = _stack.pop();
+ if (_stack.top() == value)
+ _stack.setTop(-1);
+ else
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_gt() {
+ int16 value = _stack.pop();
+ if (_stack.top() > value)
+ _stack.setTop(-1);
+ else
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_loadConstant() {
+ int16 value = readInt16();
+ debug(4, "value = %04X (%d)\n", value, value);
+ _stack.setTop(value);
+}
+
+void ScriptInterpreter::cmd_loadVariable() {
+ int16 variable = readInt16();
+ int16 value = _vm->_dat->getVar(variable);
+ debug(4, "variable = %d; value = %d (%04X)\n", variable, value, value); fflush(stdout);
+ _stack.setTop(value);
+}
+
+void ScriptInterpreter::cmd_getObjectProperty() {
+ int16 propertyId = _stack.pop();
+ int16 objectIndex = _stack.top();
+ int16 value = _vm->_dat->getObjectProperty(objectIndex, propertyId);
+ debug(4, "value = %04X(%d)\n", value, value);
+ //fflush(stdout); g_system->delayMillis(5000);
+ _stack.setTop(value);
+}
+
+void ScriptInterpreter::cmd_setObjectProperty() {
+ int16 value = _stack.pop();
+ int16 propertyId = _stack.pop();
+ int16 objectIndex = _stack.top();
+ value = _vm->_dat->setObjectProperty(objectIndex, propertyId, value);
+ //fflush(stdout); g_system->delayMillis(5000);
+ _stack.setTop(value);
+}
+
+void ScriptInterpreter::cmd_set() {
+ int16 variable = readInt16();
+ debug(4, "var(%d) = %04d (%d)\n", variable, _stack.top(), _stack.top());
+ _vm->_dat->setVar(variable, _stack.top());
+}
+
+void ScriptInterpreter::cmd_print() {
+ // TODO: This opcode was used for printing debug messages
+ Object *obj = _vm->_dat->getObject(_stack.top());
+ const char *text = obj->getString();
+ debug(4, "%s", text); fflush(stdout);
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_terpri() {
+ // TODO: This opcode was used for printing debug messages
+ debug(4, "\n");
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_printNumber() {
+ // TODO: This opcode was used for printing debug messages
+ debug(4, "%d", _stack.top());
+}
+
+void ScriptInterpreter::cmd_vref() {
+ int16 index = _stack.pop();
+ int16 objectIndex = _stack.top();
+ int16 value = 0;
+ debug(4, "index = %d; objectIndex = %d\n", index, objectIndex); fflush(stdout);
+ if (objectIndex > 0) {
+ Object *obj = _vm->_dat->getObject(objectIndex);
+ value = obj->getVectorItem(index);
+ }
+ _stack.setTop(value);
+ debug(4, "--> value = %d\n", value); fflush(stdout);
+}
+
+void ScriptInterpreter::cmd_vset() {
+ int16 value = _stack.pop();
+ int16 index = _stack.pop();
+ int16 objectIndex = _stack.top();
+ debug(4, "index = %d; objectIndex = %d; value = %d\n", index, objectIndex, value); fflush(stdout);
+ if (objectIndex > 0) {
+ Object *obj = _vm->_dat->getObject(objectIndex);
+ obj->setVectorItem(index, value);
+ }
+ _stack.setTop(value);
+}
+
+void ScriptInterpreter::cmd_vsize() {
+ int16 objectIndex = _stack.top();
+ if (objectIndex < 1) objectIndex = 1; // HACK
+ Object *obj = _vm->_dat->getObject(objectIndex);
+ int16 size = obj->getVectorSize();
+ _stack.setTop(size);
+}
+
+void ScriptInterpreter::cmd_exit() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_return() {
+ // TODO: Check if returning from main function
+ int16 funcResult = _stack.top();
+ _stack.setStackPos(_localStackPos);
+ _localStackPos = kScriptStackLimit - _stack.pop();
+ //_localStackPos = _stack.pop();
+ _runningScriptObjectIndex = _stack.pop();
+ _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
+ _codeIp = _codeBase + _stack.pop();
+ byte argc = _stack.pop();
+ _stack.free(argc);
+ _stack.setTop(funcResult);
+ debug(4, "LEAVE: stackPtr = %d; _localStackPos = %d\n\n\n", _stack.getStackPos(), _localStackPos);
+}
+
+void ScriptInterpreter::cmd_call() {
+ debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos);
+ byte argc = readByte();
+ _stack.push(argc);
+ _stack.push(_codeIp - _codeBase);
+ _stack.push(_runningScriptObjectIndex);
+ _stack.push(kScriptStackLimit - _localStackPos);
+ _localStackPos = _stack.getStackPos();
+ _runningScriptObjectIndex = _stack.peek(_localStackPos + argc + 4);
+ debug(4, "argc = %d; _runningScriptObjectIndex = %04X\n", argc, _runningScriptObjectIndex); fflush(stdout);
+ _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
+ _codeIp = _codeBase;
+ //_vm->_dat->dumpObject(_runningScriptObjectIndex);
+}
+
+void ScriptInterpreter::cmd_svar() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_sset() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_split() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_snlit() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_yorn() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_save() {
+ //fflush(stdout); g_system->delayMillis(5000);
+ // TODO
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_restore() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_arg() {
+ int16 argIndex = readByte();
+ debug(4, "argIndex = %d; value = %04X (%d)\n", argIndex, _stack.peek(_localStackPos + 4 + argIndex), _stack.peek(_localStackPos + 4 + argIndex));
+ _stack.setTop(_stack.peek(_localStackPos + 4 + argIndex));
+}
+
+void ScriptInterpreter::cmd_aset() {
+ int16 argIndex = readByte();
+ debug(4, "argIndex = %d; value = %d\n", argIndex, _stack.peek(_localStackPos + 4 + argIndex));
+ _stack.poke(_localStackPos + 4 + argIndex, _stack.top());
+}
+
+void ScriptInterpreter::cmd_tmp() {
+ int16 tempIndex = readByte();
+ debug(4, "tempIndex = %d; value = %d\n", tempIndex, _stack.peek(_localStackPos - tempIndex - 1));
+ _stack.setTop(_stack.peek(_localStackPos - tempIndex - 1));
+}
+
+void ScriptInterpreter::cmd_tset() {
+ int16 tempIndex = readByte();
+ debug(4, "tempIndex = %d; value = %d\n", tempIndex, _stack.top());
+ _stack.poke(_localStackPos - tempIndex - 1, _stack.top());
+}
+
+void ScriptInterpreter::cmd_tspace() {
+ int16 tempCount = readByte();
+ debug(4, "tempCount = %d\n", tempCount);
+ _stack.alloc(tempCount);
+}
+
+void ScriptInterpreter::cmd_class() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_objectp() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_vectorp() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_restart() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_rand() {
+ //fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_randomize() {
+ // TODO
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_send() {
+
+ debug(4, "\n\n\nENTER: stackPtr = %d; _localStackPos = %d\n", _stack.getStackPos(), _localStackPos);
+
+ byte argc = readByte();
+
+ debug(4, "argc = %d\n", argc);
+
+ _stack.push(argc);
+ _stack.push(_codeIp - _codeBase);
+ _stack.push(_runningScriptObjectIndex);
+ _stack.push(kScriptStackLimit - _localStackPos);
+ _localStackPos = _stack.getStackPos();
+
+ int16 propertyId = _stack.peek(_localStackPos + argc + 2);
+ int16 objectIndex = _stack.peek(_localStackPos + argc + 4);
+
+ debug(4, "objectIndex = %d (%04X); propertyId = %d(%04X)\n", objectIndex, objectIndex, propertyId, propertyId); fflush(stdout);
+
+ if (objectIndex != 0) {
+ objectIndex = _vm->_dat->getObject(objectIndex)->getClass();
+ } else {
+ objectIndex = _stack.peek(_localStackPos + argc + 3);
+ }
+
+ debug(4, "--> objectIndex = %d(%04X)\n", objectIndex, objectIndex); fflush(stdout);
+
+ if (objectIndex != 0) {
+ _runningScriptObjectIndex = _vm->_dat->getObjectProperty(objectIndex, propertyId);
+ if (_runningScriptObjectIndex != 0) {
+ _codeBase = _vm->_dat->getObject(_runningScriptObjectIndex)->getData();
+ _codeIp = _codeBase;
+ } else {
+ _stack.push(0);
+ cmd_return();
+ }
+ } else {
+ _stack.push(0);
+ cmd_return();
+ }
+
+}
+
+void ScriptInterpreter::cmd_extend() {
+
+ byte func = readByte();
+
+ byte argc = readByte();
+ int16 *argv = _stack.getStackPtr();
+
+ debug(4, "func = %d (%s); argc = %d\n", func, extendFuncNames[func], argc); fflush(stdout);
+ for (int i = 0; i < argc; i++)
+ debug(4, "argv[%02d] = %04X (%d)\n", i, argv[i], argv[i]);
+
+ int16 result = _functions->callFunction(func, argc, argv);
+ debug(4, "result = %04X (%d)\n", result, result);
+
+ _stack.free(argc);
+
+ _stack.setTop(result);
+
+}
+
+void ScriptInterpreter::cmd_catch() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_cdone() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_throw() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_functionp() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_le() {
+ int16 value = _stack.pop();
+ if (_stack.top() <= value)
+ _stack.setTop(-1);
+ else
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_ge() {
+ int16 value = _stack.pop();
+ if (_stack.top() >= value)
+ _stack.setTop(-1);
+ else
+ _stack.setTop(0);
+}
+
+void ScriptInterpreter::cmd_varx() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+void ScriptInterpreter::cmd_setx() {
+ fflush(stdout); g_system->delayMillis(5000);
+}
+
+} // End of namespace Made
diff --git a/engines/made/script.h b/engines/made/script.h
new file mode 100644
index 0000000000..5831d3edd2
--- /dev/null
+++ b/engines/made/script.h
@@ -0,0 +1,154 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_SCRIPT_H
+#define MADE_SCRIPT_H
+
+#include "common/util.h"
+#include "common/file.h"
+#include "common/stream.h"
+
+namespace Made {
+
+class MadeEngine;
+class ScriptFunctions;
+
+const int kScriptStackSize = 1000;
+const int kScriptStackLimit = kScriptStackSize + 1;
+
+class ScriptStack {
+public:
+ ScriptStack();
+ ~ScriptStack();
+ int16 top();
+ int16 pop();
+ void push(int16 value = 0);
+ void setTop(int16 value);
+ int16 peek(int16 index);
+ void poke(int16 index, int16 value);
+ void alloc(int16 count);
+ void free(int16 count);
+ int16 getStackPos() const { return _stackPos; }
+ void setStackPos(int16 stackPtr);
+ int16 *getStackPtr();
+protected:
+ int16 _stack[kScriptStackSize];
+ int16 _stackPos;
+};
+
+class ScriptInterpreter {
+public:
+ ScriptInterpreter(MadeEngine *vm);
+ ~ScriptInterpreter();
+ void runScript(int16 scriptObjectIndex);
+protected:
+ MadeEngine *_vm;
+
+ ScriptStack _stack;
+ int16 _localStackPos;
+ int16 _runningScriptObjectIndex;
+ byte *_codeBase, *_codeIp;
+ bool _terminated;
+
+ ScriptFunctions *_functions;
+
+ byte readByte();
+ int16 readInt16();
+
+ typedef void (ScriptInterpreter::*CommandProc)();
+ struct CommandEntry {
+ CommandProc proc;
+ const char *desc;
+ };
+
+ const CommandEntry *_commands;
+ int16 _commandsMax;
+
+ void cmd_branchTrue();
+ void cmd_branchFalse();
+ void cmd_branch();
+ void cmd_true();
+ void cmd_false();
+ void cmd_push();
+ void cmd_not();
+ void cmd_add();
+ void cmd_sub();
+ void cmd_mul();
+ void cmd_div();
+ void cmd_mod();
+ void cmd_band();
+ void cmd_bor();
+ void cmd_bnot();
+ void cmd_lt();
+ void cmd_eq();
+ void cmd_gt();
+ void cmd_loadConstant();
+ void cmd_loadVariable();
+ void cmd_getObjectProperty();
+ void cmd_setObjectProperty();
+ void cmd_set();
+ void cmd_print();
+ void cmd_terpri();
+ void cmd_printNumber();
+ void cmd_vref();
+ void cmd_vset();
+ void cmd_vsize();
+ void cmd_exit();
+ void cmd_return();
+ void cmd_call();
+ void cmd_svar();
+ void cmd_sset();
+ void cmd_split();
+ void cmd_snlit();
+ void cmd_yorn();
+ void cmd_save();
+ void cmd_restore();
+ void cmd_arg();
+ void cmd_aset();
+ void cmd_tmp();
+ void cmd_tset();
+ void cmd_tspace();
+ void cmd_class();
+ void cmd_objectp();
+ void cmd_vectorp();
+ void cmd_restart();
+ void cmd_rand();
+ void cmd_randomize();
+ void cmd_send();
+ void cmd_extend();
+ void cmd_catch();
+ void cmd_cdone();
+ void cmd_throw();
+ void cmd_functionp();
+ void cmd_le();
+ void cmd_ge();
+ void cmd_varx();
+ void cmd_setx();
+
+};
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/scriptfuncs.cpp b/engines/made/scriptfuncs.cpp
new file mode 100644
index 0000000000..3f3ad98380
--- /dev/null
+++ b/engines/made/scriptfuncs.cpp
@@ -0,0 +1,718 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/util.h"
+#include "common/events.h"
+
+#include "graphics/cursorman.h"
+
+#include "made/made.h"
+#include "made/resource.h"
+#include "made/database.h"
+#include "made/screen.h"
+#include "made/script.h"
+#include "made/pmvplayer.h"
+#include "made/scriptfuncs.h"
+
+namespace Made {
+
+int16 ScriptFunctions::callFunction(uint16 index, int16 argc, int16 *argv) {
+ if (index >= _externalFuncs.size()) {
+ // TODO: ERROR!
+ return 0;
+ }
+
+ fflush(stdout);
+ //g_system->delayMillis(2000);
+
+ return (*_externalFuncs[index])(argc, argv);
+}
+
+typedef Functor2Mem<int16, int16*, int16, ScriptFunctionsRtz> ExternalFuncRtz;
+#define External(x) ExternalFuncRtz(this, &ScriptFunctionsRtz::x)
+void ScriptFunctionsRtz::setupExternalsTable() {
+ static const ExternalFuncRtz externalsTable[] = {
+ External(o1_SYSTEM),
+ External(o1_INITGRAF),
+ External(o1_RESTOREGRAF),
+ External(o1_DRAWPIC),
+ External(o1_CLS),
+ External(o1_SHOWPAGE),
+ External(o1_EVENT),
+ External(o1_EVENTX),
+ External(o1_EVENTY),
+ External(o1_EVENTKEY),
+ External(o1_VISUALFX),
+ External(o1_PLAYSND),
+ External(o1_PLAYMUS),
+ External(o1_STOPMUS),
+ External(o1_ISMUS),
+ External(o1_TEXTPOS),
+ External(o1_FLASH),
+ External(o1_PLAYNOTE),
+ External(o1_STOPNOTE),
+ External(o1_PLAYTELE),
+ External(o1_STOPTELE),
+ External(o1_HIDECURS),
+ External(o1_SHOWCURS),
+ External(o1_MUSICBEAT),
+ External(o1_SCREENLOCK),
+ External(o1_ADDSPRITE),
+ External(o1_FREEANIM),
+ External(o1_DRAWSPRITE),
+ External(o1_ERASESPRITES),
+ External(o1_UPDATESPRITES),
+ External(o1_GETTIMER),
+ External(o1_SETTIMER),
+ External(o1_RESETTIMER),
+ External(o1_ALLOCTIMER),
+ External(o1_FREETIMER),
+ External(o1_PALETTELOCK),
+ External(o1_FONT),
+ External(o1_DRAWTEXT),
+ External(o1_HOMETEXT),
+ External(o1_TEXTRECT),
+ External(o1_TEXTXY),
+ External(o1_DROPSHADOW),
+ External(o1_TEXTCOLOR),
+ External(o1_OUTLINE),
+ External(o1_LOADCURSOR),
+ External(o1_SETGROUND),
+ External(o1_RESTEXT),
+ External(o1_CLIPAREA),
+ External(o1_SETCLIP),
+ External(o1_ISSND),
+ External(o1_STOPSND),
+ External(o1_PLAYVOICE),
+ External(o1_CDPLAY),
+ External(o1_STOPCD),
+ External(o1_CDSTATUS),
+ External(o1_CDTIME),
+ External(o1_CDPLAYSEG),
+ External(o1_PRINTF),
+ External(o1_MONOCLS),
+ External(o1_SNDENERGY),
+ External(o1_CLEARTEXT),
+ External(o1_ANIMTEXT),
+ External(o1_TEXTWIDTH),
+ External(o1_PLAYMOVIE),
+ External(o1_LOADSND),
+ External(o1_LOADMUS),
+ External(o1_LOADPIC),
+ External(o1_MUSICVOL),
+ External(o1_RESTARTEVENTS),
+ External(o1_PLACESPRITE),
+ External(o1_PLACETEXT),
+ External(o1_DELETECHANNEL),
+ External(o1_CHANNELTYPE),
+ External(o1_SETSTATE),
+ External(o1_SETLOCATION),
+ External(o1_SETCONTENT),
+ External(o1_EXCLUDEAREA),
+ External(o1_SETEXCLUDE),
+ External(o1_GETSTATE),
+ External(o1_PLACEANIM),
+ External(o1_SETFRAME),
+ External(o1_GETFRAME),
+ External(o1_GETFRAMECOUNT),
+ External(o1_PICWIDTH),
+ External(o1_PICHEIGHT),
+ External(o1_SOUNDRATE),
+ External(o1_DRAWANIMPIC),
+ External(o1_LOADANIM),
+ External(o1_READTEXT),
+ External(o1_READMENU),
+ External(o1_DRAWMENU),
+ External(o1_MENUCOUNT),
+ External(o1_SAVEGAME),
+ External(o1_LOADGAME),
+ External(o1_GAMENAME),
+ External(o1_SHAKESCREEN),
+ External(o1_PLACEMENU),
+ External(o1_SETVOLUME),
+ External(o1_WHATSYNTH),
+ External(o1_SLOWSYSTEM)
+ };
+
+ for (int i = 0; i < ARRAYSIZE(externalsTable); ++i)
+ _externalFuncs.push_back(&externalsTable[i]);
+
+}
+#undef External
+
+int16 ScriptFunctionsRtz::o1_SYSTEM(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_INITGRAF(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_RESTOREGRAF(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_DRAWPIC(int16 argc, int16 *argv) {
+
+ fflush(stdout);
+ //g_system->delayMillis(5000);
+
+ int16 channel = _vm->_screen->drawPic(argv[4], argv[3], argv[2], argv[1], argv[0]);
+ return channel;
+}
+
+int16 ScriptFunctionsRtz::o1_CLS(int16 argc, int16 *argv) {
+ //_vm->_screen->clearScreen();
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SHOWPAGE(int16 argc, int16 *argv) {
+ //_vm->_system->setPalette(_vm->_screen->_palette, 0, 256);
+ _vm->_screen->show();
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_EVENT(int16 argc, int16 *argv) {
+
+ Common::Event event;
+ Common::EventManager *eventMan = g_system->getEventManager();
+
+ int16 eventNum = 0;
+
+ if (eventMan->pollEvent(event)) {
+ switch (event.type) {
+
+ case Common::EVENT_MOUSEMOVE:
+ _vm->_eventMouseX = event.mouse.x;
+ _vm->_eventMouseY = event.mouse.y;
+ break;
+
+ case Common::EVENT_LBUTTONDOWN:
+ eventNum = 1;
+ break;
+
+ case Common::EVENT_RBUTTONDOWN:
+ eventNum = 3;
+ break;
+
+ case Common::EVENT_KEYDOWN:
+ switch (event.kbd.ascii) {
+ case '1':
+ eventNum = 1;
+ break;
+ case '2':
+ eventNum = 2;
+ break;
+ case '3':
+ eventNum = 3;
+ break;
+ case '4':
+ eventNum = 4;
+ break;
+ case '5':
+ eventNum = 5;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+
+ }
+ }
+
+ _vm->_system->updateScreen();
+ //g_system->delayMillis(10);
+
+ return eventNum;
+}
+
+int16 ScriptFunctionsRtz::o1_EVENTX(int16 argc, int16 *argv) {
+ return _vm->_eventMouseX;
+}
+
+int16 ScriptFunctionsRtz::o1_EVENTY(int16 argc, int16 *argv) {
+ return _vm->_eventMouseY;
+}
+
+int16 ScriptFunctionsRtz::o1_EVENTKEY(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_VISUALFX(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLAYSND(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLAYMUS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_STOPMUS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_ISMUS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_TEXTPOS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_FLASH(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLAYNOTE(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_STOPNOTE(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLAYTELE(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_STOPTELE(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_HIDECURS(int16 argc, int16 *argv) {
+ _vm->_system->showMouse(false);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SHOWCURS(int16 argc, int16 *argv) {
+ _vm->_system->showMouse(true);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_MUSICBEAT(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SCREENLOCK(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_ADDSPRITE(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_FREEANIM(int16 argc, int16 *argv) {
+ _vm->_screen->clearChannels();
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_DRAWSPRITE(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_ERASESPRITES(int16 argc, int16 *argv) {
+ _vm->_screen->clearChannels();
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_UPDATESPRITES(int16 argc, int16 *argv) {
+ _vm->_screen->updateSprites();
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_GETTIMER(int16 argc, int16 *argv) {
+ return _vm->getTimer(argv[0]);
+}
+
+int16 ScriptFunctionsRtz::o1_SETTIMER(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_RESETTIMER(int16 argc, int16 *argv) {
+ _vm->resetTimer(argv[0]);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_ALLOCTIMER(int16 argc, int16 *argv) {
+ int16 timerNum = _vm->allocTimer();
+ return timerNum;
+}
+
+int16 ScriptFunctionsRtz::o1_FREETIMER(int16 argc, int16 *argv) {
+ _vm->freeTimer(argv[0]);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PALETTELOCK(int16 argc, int16 *argv) {
+ //g_system->delayMillis(1000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_FONT(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_DRAWTEXT(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_HOMETEXT(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_TEXTRECT(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_TEXTXY(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_DROPSHADOW(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_TEXTCOLOR(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_OUTLINE(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_LOADCURSOR(int16 argc, int16 *argv) {
+ PictureResource *flex = _vm->_res->getPicture(argv[2]);
+ Graphics::Surface *surf = flex->getPicture();
+ CursorMan.replaceCursor((const byte *)surf->pixels, surf->w, surf->h, argv[1], argv[0], 0);
+ CursorMan.showMouse(true);
+ _vm->_res->freeResource(flex);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SETGROUND(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_RESTEXT(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CLIPAREA(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SETCLIP(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_ISSND(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_STOPSND(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLAYVOICE(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CDPLAY(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_STOPCD(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CDSTATUS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CDTIME(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CDPLAYSEG(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PRINTF(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_MONOCLS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SNDENERGY(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CLEARTEXT(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_ANIMTEXT(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_TEXTWIDTH(int16 argc, int16 *argv) {
+ Object *obj = _vm->_dat->getObject(argv[1]);
+ const char *text = obj->getString();
+ debug(4, "text = %s\n", text); fflush(stdout);
+ //!!g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLAYMOVIE(int16 argc, int16 *argv) {
+ const char *movieName = _vm->_dat->getObject(argv[1])->getString();
+ printf("movieName = %s\n", movieName); fflush(stdout);
+ _vm->_pmvPlayer->play(movieName);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_LOADSND(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_LOADMUS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_LOADPIC(int16 argc, int16 *argv) {
+ PictureResource *flex = _vm->_res->getPicture(argv[0]);
+ if (flex) {
+ _vm->_res->freeResource(flex);
+ return 1;
+ }
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_MUSICVOL(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_RESTARTEVENTS(int16 argc, int16 *argv) {
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLACESPRITE(int16 argc, int16 *argv) {
+ return _vm->_screen->placeSprite(argv[3], argv[2], argv[1], argv[0]);
+}
+
+int16 ScriptFunctionsRtz::o1_PLACETEXT(int16 argc, int16 *argv) {
+ Object *obj = _vm->_dat->getObject(argv[5]);
+ _vm->_dat->dumpObject(argv[5]);
+ const char *text = obj->getString();
+ debug(4, "text = %s\n", text); fflush(stdout);
+ //!! g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_DELETECHANNEL(int16 argc, int16 *argv) {
+ _vm->_screen->deleteChannel(argv[0]);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_CHANNELTYPE(int16 argc, int16 *argv) {
+ return _vm->_screen->getChannelType(argv[0]);
+}
+
+int16 ScriptFunctionsRtz::o1_SETSTATE(int16 argc, int16 *argv) {
+ _vm->_screen->setChannelState(argv[1], argv[0]);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SETLOCATION(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SETCONTENT(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_EXCLUDEAREA(int16 argc, int16 *argv) {
+ //!! g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SETEXCLUDE(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_GETSTATE(int16 argc, int16 *argv) {
+ //!! g_system->delayMillis(5000);
+ int16 state = _vm->_screen->getChannelState(argv[0]);
+ return state;
+}
+
+int16 ScriptFunctionsRtz::o1_PLACEANIM(int16 argc, int16 *argv) {
+ printf("anim = %04X\n", argv[3]); fflush(stdout);
+ int16 channel = _vm->_screen->placeAnim(argv[4], argv[3], argv[2], argv[1], argv[0]);
+ //g_system->delayMillis(5000);
+ return channel;
+}
+
+int16 ScriptFunctionsRtz::o1_SETFRAME(int16 argc, int16 *argv) {
+ _vm->_screen->setAnimFrame(argv[1], argv[0]);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_GETFRAME(int16 argc, int16 *argv) {
+ return _vm->_screen->getAnimFrame(argv[0]);
+}
+
+int16 ScriptFunctionsRtz::o1_GETFRAMECOUNT(int16 argc, int16 *argv) {
+ debug(4, "anim = %04X\n", argv[0]);
+ int16 frameCount = _vm->_screen->getAnimFrameCount(argv[0]);
+ debug(4, "frameCount = %04X\n", frameCount);
+ //fflush(stdout);
+ //g_system->delayMillis(5000);
+ return frameCount;
+}
+
+int16 ScriptFunctionsRtz::o1_PICWIDTH(int16 argc, int16 *argv) {
+ int16 width = 0;
+ PictureResource *flex = _vm->_res->getPicture(argv[0]);
+ if (flex) {
+ width = flex->getPicture()->w;
+ _vm->_res->freeResource(flex);
+ }
+ return width;
+}
+
+int16 ScriptFunctionsRtz::o1_PICHEIGHT(int16 argc, int16 *argv) {
+ int16 height = 0;
+ PictureResource *flex = _vm->_res->getPicture(argv[0]);
+ if (flex) {
+ height = flex->getPicture()->h;
+ _vm->_res->freeResource(flex);
+ }
+ return height;
+}
+
+int16 ScriptFunctionsRtz::o1_SOUNDRATE(int16 argc, int16 *argv) {
+ //g_system->delayMillis(5000);
+ return 1;
+}
+
+int16 ScriptFunctionsRtz::o1_DRAWANIMPIC(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_LOADANIM(int16 argc, int16 *argv) {
+ //g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_READTEXT(int16 argc, int16 *argv) {
+ //g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_READMENU(int16 argc, int16 *argv) {
+ /*
+ int16 objectIndex = argv[2];
+ int16 menuIndex = argv[1];
+ int16 textIndex = argv[0];
+ MenuResource *menu = _vm->_res->getMenu(menuIndex);
+ if (menu) {
+ const char *text = menu->getString(textIndex).c_str();
+ debug(4, "text = %s\n", text); fflush(stdout);
+ _vm->_res->freeResource(menu);
+ }
+ g_system->delayMillis(5000);
+ */
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_DRAWMENU(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_MENUCOUNT(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SAVEGAME(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_LOADGAME(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_GAMENAME(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SHAKESCREEN(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_PLACEMENU(int16 argc, int16 *argv) {
+ g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SETVOLUME(int16 argc, int16 *argv) {
+ //!! g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_WHATSYNTH(int16 argc, int16 *argv) {
+ //g_system->delayMillis(5000);
+ return 0;
+}
+
+int16 ScriptFunctionsRtz::o1_SLOWSYSTEM(int16 argc, int16 *argv) {
+ //!! g_system->delayMillis(5000);
+ return 0;
+}
+
+} // End of namespace Made
diff --git a/engines/made/scriptfuncs.h b/engines/made/scriptfuncs.h
new file mode 100644
index 0000000000..fc09886bf0
--- /dev/null
+++ b/engines/made/scriptfuncs.h
@@ -0,0 +1,188 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_SCRIPTFUNCS_H
+#define MADE_SCRIPTFUNCS_H
+
+#include "common/util.h"
+#include "common/file.h"
+#include "common/stream.h"
+
+namespace Made {
+
+class MadeEngine;
+
+template<class Arg1, class Arg2, class Res>
+struct Functor2 : public Common::BinaryFunction<Arg1, Arg2, Res> {
+ virtual ~Functor2() {}
+
+ virtual bool isValid() const = 0;
+ virtual Res operator()(Arg1, Arg2) const = 0;
+};
+
+template<class Arg1, class Arg2, class Res, class T>
+class Functor2Mem : public Functor2<Arg1, Arg2, Res> {
+public:
+ typedef Res (T::*FuncType)(Arg1, Arg2);
+
+ Functor2Mem(T *t, const FuncType &func) : _t(t), _func(func) {}
+
+ bool isValid() const { return _func != 0; }
+ Res operator()(Arg1 v1, Arg2 v2) const {
+ return (_t->*_func)(v1, v2);
+ }
+private:
+ mutable T *_t;
+ Res (T::*_func)(Arg1, Arg2);
+};
+
+typedef Functor2<int16, int16*, int16> ExternalFunc;
+
+class ScriptFunctions {
+public:
+ ScriptFunctions(MadeEngine *vm) : _vm(vm) {}
+ virtual ~ScriptFunctions() {}
+ int16 callFunction(uint16 index, int16 argc, int16 *argv);
+ virtual void setupExternalsTable() = 0;
+protected:
+ MadeEngine *_vm;
+
+ Common::Array<const ExternalFunc*> _externalFuncs;
+
+};
+
+class ScriptFunctionsRtz : public ScriptFunctions {
+public:
+ ScriptFunctionsRtz(MadeEngine *vm) : ScriptFunctions(vm) {}
+ ~ScriptFunctionsRtz() {}
+ void setupExternalsTable();
+protected:
+
+ int16 o1_SYSTEM(int16 argc, int16 *argv);
+ int16 o1_INITGRAF(int16 argc, int16 *argv);
+ int16 o1_RESTOREGRAF(int16 argc, int16 *argv);
+ int16 o1_DRAWPIC(int16 argc, int16 *argv);
+ int16 o1_CLS(int16 argc, int16 *argv);
+ int16 o1_SHOWPAGE(int16 argc, int16 *argv);
+ int16 o1_EVENT(int16 argc, int16 *argv);
+ int16 o1_EVENTX(int16 argc, int16 *argv);
+ int16 o1_EVENTY(int16 argc, int16 *argv);
+ int16 o1_EVENTKEY(int16 argc, int16 *argv);
+ int16 o1_VISUALFX(int16 argc, int16 *argv);
+ int16 o1_PLAYSND(int16 argc, int16 *argv);
+ int16 o1_PLAYMUS(int16 argc, int16 *argv);
+ int16 o1_STOPMUS(int16 argc, int16 *argv);
+ int16 o1_ISMUS(int16 argc, int16 *argv);
+ int16 o1_TEXTPOS(int16 argc, int16 *argv);
+ int16 o1_FLASH(int16 argc, int16 *argv);
+ int16 o1_PLAYNOTE(int16 argc, int16 *argv);
+ int16 o1_STOPNOTE(int16 argc, int16 *argv);
+ int16 o1_PLAYTELE(int16 argc, int16 *argv);
+ int16 o1_STOPTELE(int16 argc, int16 *argv);
+ int16 o1_HIDECURS(int16 argc, int16 *argv);
+ int16 o1_SHOWCURS(int16 argc, int16 *argv);
+ int16 o1_MUSICBEAT(int16 argc, int16 *argv);
+ int16 o1_SCREENLOCK(int16 argc, int16 *argv);
+ int16 o1_ADDSPRITE(int16 argc, int16 *argv);
+ int16 o1_FREEANIM(int16 argc, int16 *argv);
+ int16 o1_DRAWSPRITE(int16 argc, int16 *argv);
+ int16 o1_ERASESPRITES(int16 argc, int16 *argv);
+ int16 o1_UPDATESPRITES(int16 argc, int16 *argv);
+ int16 o1_GETTIMER(int16 argc, int16 *argv);
+ int16 o1_SETTIMER(int16 argc, int16 *argv);
+ int16 o1_RESETTIMER(int16 argc, int16 *argv);
+ int16 o1_ALLOCTIMER(int16 argc, int16 *argv);
+ int16 o1_FREETIMER(int16 argc, int16 *argv);
+ int16 o1_PALETTELOCK(int16 argc, int16 *argv);
+ int16 o1_FONT(int16 argc, int16 *argv);
+ int16 o1_DRAWTEXT(int16 argc, int16 *argv);
+ int16 o1_HOMETEXT(int16 argc, int16 *argv);
+ int16 o1_TEXTRECT(int16 argc, int16 *argv);
+ int16 o1_TEXTXY(int16 argc, int16 *argv);
+ int16 o1_DROPSHADOW(int16 argc, int16 *argv);
+ int16 o1_TEXTCOLOR(int16 argc, int16 *argv);
+ int16 o1_OUTLINE(int16 argc, int16 *argv);
+ int16 o1_LOADCURSOR(int16 argc, int16 *argv);
+ int16 o1_SETGROUND(int16 argc, int16 *argv);
+ int16 o1_RESTEXT(int16 argc, int16 *argv);
+ int16 o1_CLIPAREA(int16 argc, int16 *argv);
+ int16 o1_SETCLIP(int16 argc, int16 *argv);
+ int16 o1_ISSND(int16 argc, int16 *argv);
+ int16 o1_STOPSND(int16 argc, int16 *argv);
+ int16 o1_PLAYVOICE(int16 argc, int16 *argv);
+ int16 o1_CDPLAY(int16 argc, int16 *argv);
+ int16 o1_STOPCD(int16 argc, int16 *argv);
+ int16 o1_CDSTATUS(int16 argc, int16 *argv);
+ int16 o1_CDTIME(int16 argc, int16 *argv);
+ int16 o1_CDPLAYSEG(int16 argc, int16 *argv);
+ int16 o1_PRINTF(int16 argc, int16 *argv);
+ int16 o1_MONOCLS(int16 argc, int16 *argv);
+ int16 o1_SNDENERGY(int16 argc, int16 *argv);
+ int16 o1_CLEARTEXT(int16 argc, int16 *argv);
+ int16 o1_ANIMTEXT(int16 argc, int16 *argv);
+ int16 o1_TEXTWIDTH(int16 argc, int16 *argv);
+ int16 o1_PLAYMOVIE(int16 argc, int16 *argv);
+ int16 o1_LOADSND(int16 argc, int16 *argv);
+ int16 o1_LOADMUS(int16 argc, int16 *argv);
+ int16 o1_LOADPIC(int16 argc, int16 *argv);
+ int16 o1_MUSICVOL(int16 argc, int16 *argv);
+ int16 o1_RESTARTEVENTS(int16 argc, int16 *argv);
+ int16 o1_PLACESPRITE(int16 argc, int16 *argv);
+ int16 o1_PLACETEXT(int16 argc, int16 *argv);
+ int16 o1_DELETECHANNEL(int16 argc, int16 *argv);
+ int16 o1_CHANNELTYPE(int16 argc, int16 *argv);
+ int16 o1_SETSTATE(int16 argc, int16 *argv);
+ int16 o1_SETLOCATION(int16 argc, int16 *argv);
+ int16 o1_SETCONTENT(int16 argc, int16 *argv);
+ int16 o1_EXCLUDEAREA(int16 argc, int16 *argv);
+ int16 o1_SETEXCLUDE(int16 argc, int16 *argv);
+ int16 o1_GETSTATE(int16 argc, int16 *argv);
+ int16 o1_PLACEANIM(int16 argc, int16 *argv);
+ int16 o1_SETFRAME(int16 argc, int16 *argv);
+ int16 o1_GETFRAME(int16 argc, int16 *argv);
+ int16 o1_GETFRAMECOUNT(int16 argc, int16 *argv);
+ int16 o1_PICWIDTH(int16 argc, int16 *argv);
+ int16 o1_PICHEIGHT(int16 argc, int16 *argv);
+ int16 o1_SOUNDRATE(int16 argc, int16 *argv);
+ int16 o1_DRAWANIMPIC(int16 argc, int16 *argv);
+ int16 o1_LOADANIM(int16 argc, int16 *argv);
+ int16 o1_READTEXT(int16 argc, int16 *argv);
+ int16 o1_READMENU(int16 argc, int16 *argv);
+ int16 o1_DRAWMENU(int16 argc, int16 *argv);
+ int16 o1_MENUCOUNT(int16 argc, int16 *argv);
+ int16 o1_SAVEGAME(int16 argc, int16 *argv);
+ int16 o1_LOADGAME(int16 argc, int16 *argv);
+ int16 o1_GAMENAME(int16 argc, int16 *argv);
+ int16 o1_SHAKESCREEN(int16 argc, int16 *argv);
+ int16 o1_PLACEMENU(int16 argc, int16 *argv);
+ int16 o1_SETVOLUME(int16 argc, int16 *argv);
+ int16 o1_WHATSYNTH(int16 argc, int16 *argv);
+ int16 o1_SLOWSYSTEM(int16 argc, int16 *argv);
+
+};
+
+} // End of namespace Made
+
+#endif /* MADE_H */
diff --git a/engines/made/sound.cpp b/engines/made/sound.cpp
new file mode 100644
index 0000000000..520239135d
--- /dev/null
+++ b/engines/made/sound.cpp
@@ -0,0 +1,131 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/endian.h"
+#include "common/util.h"
+
+#include "made/sound.h"
+
+namespace Made {
+
+void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount) {
+
+ int16 prevSample = 0;
+ byte soundBuffer[1025];
+ byte soundBuffer3[1024];
+ int16 soundBuffer2[16];
+
+ while (chunkCount--) {
+
+ byte deltaType = (*source) >> 6;
+
+ uint16 workChunkSize = chunkSize;
+ if (deltaType == 1)
+ workChunkSize /= 2;
+ else if (deltaType == 2)
+ workChunkSize /= 4;
+
+ byte type = (*source++) & 0x0F;
+
+ int16 workSample = prevSample;
+
+ switch (type) {
+
+ case 0:
+ memset(soundBuffer, 0x80, workChunkSize);
+ workSample = 0;
+ break;
+
+ case 1:
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ {
+
+ const int modeValues[3][4] = {
+ { 2, 8, 0x01, 1},
+ { 4, 4, 0x03, 2},
+ {16, 2, 0x0F, 4}
+ };
+
+ uint16 byteCount = modeValues[type - 2][0];
+ uint16 bitCount = modeValues[type - 2][1];
+ byte bitMask = modeValues[type - 2][2];
+ byte bitShift = modeValues[type - 2][3];
+
+ uint16 ofs = 0;
+
+ for (uint16 i = 0; i < byteCount; i++)
+ soundBuffer2[i] = (*source++) * 2 - 128;
+
+ while (ofs < workChunkSize) {
+ byte val = *source++;
+ for (uint i = 0; i < bitCount; i++) {
+ workSample = CLIP<int16>(workSample + soundBuffer2[val & bitMask], -127, 127);
+ val >>= bitShift;
+ soundBuffer[ofs++] = workSample + 128;
+ }
+ }
+
+ break;
+ }
+
+ case 5:
+ {
+ for (uint16 i = 0; i < workChunkSize; i++)
+ soundBuffer[i] = *source++;
+ workSample = soundBuffer[workChunkSize - 1] - 128;
+ break;
+ }
+
+ default:
+ return;
+
+ }
+
+ if (deltaType == 1) {
+ for (uint16 i = 0; i < chunkSize - 1; i += 2) {
+ uint16 l = i / 2;
+ soundBuffer3[i] = soundBuffer[l];
+ soundBuffer3[i + 1] = (soundBuffer[l + 1] + soundBuffer[l]) / 2;
+ }
+ for (uint16 i = 0; i < chunkSize; i++) {
+ soundBuffer[i] = soundBuffer3[i];
+ }
+ } else if (deltaType == 2) {
+ debug(2, "****************************************");
+ }
+
+ prevSample = workSample;
+ memcpy(dest, soundBuffer, chunkSize);
+ dest += chunkSize;
+
+ }
+
+}
+
+} // End of namespace Made
diff --git a/engines/made/sound.h b/engines/made/sound.h
new file mode 100644
index 0000000000..288dc38609
--- /dev/null
+++ b/engines/made/sound.h
@@ -0,0 +1,39 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef MADE_SOUND_H
+#define MADE_SOUND_H
+
+#include "common/util.h"
+#include "common/file.h"
+#include "common/stream.h"
+
+namespace Made {
+
+void decompressSound(byte *source, byte *dest, uint16 chunkSize, uint16 chunkCount);
+
+} // End of namespace Made
+
+#endif /* MADE_H */