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 /engines/made/database.cpp | |
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
Diffstat (limited to 'engines/made/database.cpp')
-rw-r--r-- | engines/made/database.cpp | 393 |
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 |