aboutsummaryrefslogtreecommitdiff
path: root/engines/made/database.cpp
diff options
context:
space:
mode:
authorFilippos Karapetis2008-04-20 14:43:56 +0000
committerFilippos Karapetis2008-04-20 14:43:56 +0000
commitd0590a09eac68d5cde64d37fb2e5bbd1471a676a (patch)
tree3e29857746449aaea4c9834bedad0d18ce487ff7 /engines/made/database.cpp
parentd484c7ed434e9f8e8267049fccbe3dbb5c39fe0b (diff)
downloadscummvm-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
Diffstat (limited to 'engines/made/database.cpp')
-rw-r--r--engines/made/database.cpp393
1 files changed, 393 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