diff options
author | Filippos Karapetis | 2008-04-20 14:43:56 +0000 |
---|---|---|
committer | Filippos Karapetis | 2008-04-20 14:43:56 +0000 |
commit | d0590a09eac68d5cde64d37fb2e5bbd1471a676a (patch) | |
tree | 3e29857746449aaea4c9834bedad0d18ce487ff7 | |
parent | d484c7ed434e9f8e8267049fccbe3dbb5c39fe0b (diff) | |
download | scummvm-rg350-d0590a09eac68d5cde64d37fb2e5bbd1471a676a.tar.gz scummvm-rg350-d0590a09eac68d5cde64d37fb2e5bbd1471a676a.tar.bz2 scummvm-rg350-d0590a09eac68d5cde64d37fb2e5bbd1471a676a.zip |
Initial import of the work in progress MADE engine
svn-id: r31599
-rw-r--r-- | engines/made/database.cpp | 393 | ||||
-rw-r--r-- | engines/made/database.h | 105 | ||||
-rw-r--r-- | engines/made/detection.cpp | 172 | ||||
-rw-r--r-- | engines/made/graphics.cpp | 152 | ||||
-rw-r--r-- | engines/made/graphics.h | 40 | ||||
-rw-r--r-- | engines/made/made.cpp | 155 | ||||
-rw-r--r-- | engines/made/made.h | 106 | ||||
-rw-r--r-- | engines/made/module.mk | 22 | ||||
-rw-r--r-- | engines/made/pmvplayer.cpp | 152 | ||||
-rw-r--r-- | engines/made/pmvplayer.h | 39 | ||||
-rw-r--r-- | engines/made/resource.cpp | 333 | ||||
-rw-r--r-- | engines/made/resource.h | 178 | ||||
-rw-r--r-- | engines/made/screen.cpp | 459 | ||||
-rw-r--r-- | engines/made/screen.h | 123 | ||||
-rw-r--r-- | engines/made/script.cpp | 738 | ||||
-rw-r--r-- | engines/made/script.h | 154 | ||||
-rw-r--r-- | engines/made/scriptfuncs.cpp | 718 | ||||
-rw-r--r-- | engines/made/scriptfuncs.h | 188 | ||||
-rw-r--r-- | engines/made/sound.cpp | 131 | ||||
-rw-r--r-- | engines/made/sound.h | 39 |
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 */ |