diff options
-rw-r--r-- | engines/made/database.cpp | 621 | ||||
-rw-r--r-- | engines/made/database.h | 124 | ||||
-rw-r--r-- | engines/made/made.cpp | 10 |
3 files changed, 402 insertions, 353 deletions
diff --git a/engines/made/database.cpp b/engines/made/database.cpp index f7fce52b21..4a331d5ca1 100644 --- a/engines/made/database.cpp +++ b/engines/made/database.cpp @@ -47,7 +47,79 @@ Object::~Object() { delete[] _objData; } -int Object::loadVersion2(Common::SeekableReadStream &source) { +const char *Object::getString() { + if (getClass() == 0x7FFF) + return (const char*)getData(); + else + return NULL; +} + +void Object::setString(const char *str) { + if (getClass() == 0x7FFF) { + char *objStr = (char*)getData(); + if (str) + strncpy(objStr, str, getSize()); + else + objStr[0] = '\0'; + } +} + +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 { + // should never reach here + error("Unknown object class"); + return 0; + } +} + +int16 Object::getVectorItem(int16 index) { + if (getClass() == 0x7FFF) { + byte *vector = (byte*)getData(); + return vector[index]; + } else if (getClass() == 0x7FFE) { + int16 *vector = (int16*)getData(); + return READ_LE_UINT16(&vector[index]); + } else if (getClass() < 0x7FFE) { + int16 *vector = (int16*)getData(); + return READ_LE_UINT16(&vector[index]); + } else { + // should never reach here + error("Unknown object class"); + return 0; + } +} + +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(); + WRITE_LE_UINT16(&vector[index], value); + } +} + +void Object::dump(const char *filename) { + /* + FILE *o = fopen(filename, "wb"); + fwrite(_objData, _objSize, 1, o); + fclose(o); + */ +} + +int ObjectV2::load(Common::SeekableReadStream &source) { if (_freeData && _objData) delete[] _objData; @@ -67,22 +139,51 @@ int Object::loadVersion2(Common::SeekableReadStream &source) { byte count2 = header[3]; _objSize = (count1 + count2) * 2; } - _objSize += 6; + _objSize += 4; _objData = new byte[_objSize]; - WRITE_LE_UINT16(_objData, 1); - memcpy(_objData + 2, header, 4); - source.read(_objData + 6, _objSize - 6); + memcpy(_objData, header, 4); + source.read(_objData + 4, _objSize - 4); - return _objSize - 2; + return _objSize; + +} +int ObjectV2::load(byte *source) { + // Not implemented/used for version 2 objects + return 0; } -int Object::saveVersion2(Common::WriteStream &dest) { - dest.write(_objData + 2, _objSize - 2); +int ObjectV2::save(Common::WriteStream &dest) { + dest.write(_objData, _objSize); return 0; } -int Object::loadVersion3(Common::SeekableReadStream &source) { +uint16 ObjectV2::getFlags() { + return 1; +} + +uint16 ObjectV2::getClass() { + return READ_LE_UINT16(_objData); +} + +uint16 ObjectV2::getSize() { + return READ_LE_UINT16(_objData + 2); +} + +byte ObjectV2::getCount1() { + return _objData[2]; +} + +byte ObjectV2::getCount2() { + return _objData[3]; +} + +byte *ObjectV2::getData() { + return _objData + 4; +} + +int ObjectV3::load(Common::SeekableReadStream &source) { + _freeData = true; source.readUint16LE(); // skip flags uint16 type = source.readUint16LE(); @@ -100,9 +201,10 @@ int Object::loadVersion3(Common::SeekableReadStream &source) { _objData = new byte[_objSize]; source.read(_objData, _objSize); return _objSize; + } -int Object::loadVersion3(byte *source) { +int ObjectV3::load(byte *source) { _objData = source; _freeData = false; if (getClass() < 0x7FFE) { @@ -114,111 +216,43 @@ int Object::loadVersion3(byte *source) { return _objSize; } -uint16 Object::getFlags() const { +int ObjectV3::save(Common::WriteStream &dest) { + // Not implemented/used for version 3 objects + return 0; +} + +uint16 ObjectV3::getFlags() { return READ_LE_UINT16(_objData); } -uint16 Object::getClass() const { +uint16 ObjectV3::getClass() { return READ_LE_UINT16(_objData + 2); } -uint16 Object::getSize() const { +uint16 ObjectV3::getSize() { return READ_LE_UINT16(_objData + 4); } -byte Object::getCount1() const { +byte ObjectV3::getCount1() { return _objData[4]; } -byte Object::getCount2() const { +byte ObjectV3::getCount2() { return _objData[5]; } -byte *Object::getData() { +byte *ObjectV3::getData() { return _objData + 6; } -const char *Object::getString() { - if (getClass() == 0x7FFF) - return (const char*)getData(); - else - return NULL; -} - -void Object::setString(const char *str) { - if (getClass() == 0x7FFF) { - char *objStr = (char*)getData(); - if (str) - strncpy(objStr, str, getSize()); - else - objStr[0] = '\0'; - } -} - -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 { - // should never reach here - error("Unknown object class"); - return 0; - } -} - -int16 Object::getVectorItem(int16 index) { - if (getClass() == 0x7FFF) { - byte *vector = (byte*)getData(); - return vector[index]; - } else if (getClass() == 0x7FFE) { - int16 *vector = (int16*)getData(); - return READ_LE_UINT16(&vector[index]); - } else if (getClass() < 0x7FFE) { - int16 *vector = (int16*)getData(); - return READ_LE_UINT16(&vector[index]); - } else { - // should never reach here - error("Unknown object class"); - return 0; - } -} -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(); - WRITE_LE_UINT16(&vector[index], value); - } -} - -void Object::dump(const char *filename) { - /* - FILE *o = fopen(filename, "wb"); - fwrite(_objData, _objSize, 1, o); - fclose(o); - */ -} GameDatabase::GameDatabase(MadeEngine *vm) : _vm(vm) { - _gameText = NULL; } GameDatabase::~GameDatabase() { if (_gameState) delete[] _gameState; - if (_gameText) - delete[] _gameText; } void GameDatabase::open(const char *filename) { @@ -239,19 +273,71 @@ void GameDatabase::openFromRed(const char *redFilename, const char *filename) { delete fileS; } -void GameDatabase::load(Common::SeekableReadStream &sourceS) { +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::getObjectProperty(int16 objectIndex, int16 propertyId) { + + if (objectIndex == 0) + return 0; + + int16 propertyFlag; + int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag); + + if (property) { + return (int16)READ_LE_UINT16(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 (_vm->getGameID() == GID_MANHOLE || _vm->getGameID() == GID_LGOP2) { - debug(2, "loading version 2 dat"); - loadVersion2(sourceS); - } else if (_vm->getGameID() == GID_RTZ) { - debug(2, "loading version 3 dat"); - loadVersion3(sourceS); + if (property) { + if (propertyFlag == 1) { + WRITE_LE_UINT16(property, value); + } else { + warning("GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n", + objectIndex, propertyId, value); + } + return value; + } else { + return 0; } } -void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { +void GameDatabase::dumpObject(int16 index) { + Object *obj = getObject(index); + char fn[512]; + sprintf(fn, "obj%04X.0", index); + obj->dump(fn); +} + + +/* GameDatabaseV2 */ + +GameDatabaseV2::GameDatabaseV2(MadeEngine *vm) : GameDatabase(vm), _gameText(NULL) { +} + +GameDatabaseV2::~GameDatabaseV2() { + if (_gameText) + delete[] _gameText; +} + +void GameDatabaseV2::load(Common::SeekableReadStream &sourceS) { // TODO: Read/verifiy header @@ -285,8 +371,8 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { sourceS.seek(objectsOffs); for (uint32 i = 0; i < objectCount; i++) { - Object *obj = new Object(); - int objSize = obj->loadVersion2(sourceS); + Object *obj = new ObjectV2(); + int objSize = obj->load(sourceS); // objects are aligned on 2-byte-boundaries, skip unused bytes sourceS.skip(objSize % 2); _objects.push_back(obj); @@ -294,176 +380,43 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) { } -void GameDatabase::loadVersion3(Common::SeekableReadStream &sourceS) { - - // TODO: Read/verifiy header - - sourceS.seek(0x1E); - - uint32 objectIndexOffs = sourceS.readUint32LE(); - uint16 objectCount = sourceS.readUint16LE(); - uint32 gameStateOffs = sourceS.readUint32LE(); - _gameStateSize = sourceS.readUint32LE(); - uint32 objectsOffs = sourceS.readUint32LE(); - uint32 objectsSize = sourceS.readUint32LE(); - _mainCodeObjectIndex = sourceS.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]; - sourceS.seek(gameStateOffs); - sourceS.read(_gameState, _gameStateSize); - - Common::Array<uint32> objectOffsets; - sourceS.seek(objectIndexOffs); - for (uint32 i = 0; i < objectCount; i++) - objectOffsets.push_back(sourceS.readUint32LE()); - - for (uint32 i = 0; i < objectCount; i++) { - Object *obj = new Object(); - - // The LSB indicates if it's a constant or variable object. - // Constant objects are loaded from disk, while variable objects exist - // in the _gameState buffer. - - //debug(2, "obj(%04X) ofs = %08X\n", i, objectOffsets[i]); - - if (objectOffsets[i] & 1) { - //debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1); - sourceS.seek(objectsOffs + objectOffsets[i] - 1); - obj->loadVersion3(sourceS); - } else { - //debug(2, "-> var\n"); - obj->loadVersion3(_gameState + objectOffsets[i]); - } - _objects.push_back(obj); - } - -} - -bool GameDatabase::getSavegameDescription(const char *filename, Common::String &description) { - - Common::InSaveFile *in; - - if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { - return false; - } - - char desc[64]; - - in->skip(4); // TODO: Verify marker 'SGAM' - in->skip(4); // TODO: Verify size - in->skip(2); // TODO: Verify version - in->read(desc, 64); - description = desc; - - delete in; - - return true; - +bool GameDatabaseV2::getSavegameDescription(const char *filename, Common::String &description) { + // Not used in version 2 games + return false; } -int16 GameDatabase::savegame(const char *filename, const char *description, int16 version) { - +int16 GameDatabaseV2::savegame(const char *filename, const char *description, int16 version) { Common::OutSaveFile *out; int16 result = 0; - if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { warning("Can't create file '%s', game not saved", filename); return 6; } - - switch (_vm->_engineVersion) { - case 2: - result = savegameV2(out, description, version); - break; - case 3: - result = savegameV3(out, description, version); - break; - default: - error("GameDatabase::savegame() Unknown engine version"); - } - + // Variable 0 is not saved + out->write(_gameState + 2, _gameStateSize - 2); + for (uint i = 0; i < _objects.size(); i++) + _objects[i]->save(*out); delete out; - return result; - } -int16 GameDatabase::loadgame(const char *filename, int16 version) { - +int16 GameDatabaseV2::loadgame(const char *filename, int16 version) { Common::InSaveFile *in; int16 result = 0; - if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { warning("Can't open file '%s', game not loaded", filename); return 1; } - - switch (_vm->_engineVersion) { - case 2: - result = loadgameV2(in, version); - break; - case 3: - result = loadgameV3(in, version); - break; - default: - error("GameDatabase::loadgame() Unknown engine version"); + // Variable 0 is not loaded + in->read(_gameState + 2, _gameStateSize - 2); + for (uint i = 0; i < _objects.size(); i++) { + _objects[i]->load(*in); } - delete in; - return result; - -} - -int16 GameDatabase::savegameV2(Common::OutSaveFile *out, const char *description, int16 version) { - // Variable 0 is not saved - out->write(_gameState + 2, _gameStateSize - 2); - for (uint i = 0; i < _objects.size(); i++) - _objects[i]->saveVersion2(*out); - return 0; -} - -int16 GameDatabase::loadgameV2(Common::InSaveFile *in, int16 version) { - // Variable 0 is not loaded - in->read(_gameState + 2, _gameStateSize - 2); - for (uint i = 0; i < _objects.size(); i++) - _objects[i]->loadVersion2(*in); - return 0; } -int16 GameDatabase::savegameV3(Common::OutSaveFile *out, const char *description, int16 version) { - uint32 size = 4 + 4 + 2 + _gameStateSize; - char desc[64]; - strncpy(desc, description, 64); - out->writeUint32BE(MKID_BE('SGAM')); - out->writeUint32LE(size); - out->writeUint16LE(version); - out->write(desc, 64); - out->write(_gameState, _gameStateSize); - return 0; -} - -int16 GameDatabase::loadgameV3(Common::InSaveFile *in, int16 version) { - //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; - in->skip(4); // TODO: Verify marker 'SGAM' - in->skip(4); // TODO: Verify size - in->skip(2); // TODO: Verify version - in->skip(64); // skip savegame description - in->read(_gameState, _gameStateSize); - return 0; -} - -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::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { +int16 *GameDatabaseV2::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { Object *obj = getObject(objectIndex); int16 *prop = (int16*)obj->getData(); @@ -486,14 +439,11 @@ int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, // Now check in the object hierarchy of the given object int16 parentObjectIndex = obj->getClass(); if (parentObjectIndex == 0) { - debug(2, "GameDatabase::getObjectPropertyPtrV2() NULL(1)"); return NULL; } while (parentObjectIndex != 0) { - //debug(2, "parentObjectIndex = %04X\n", parentObjectIndex); - obj = getObject(parentObjectIndex); prop = (int16*)obj->getData(); @@ -525,12 +475,115 @@ int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, } - debug(2, "GameDatabase::getObjectPropertyPtrV2() NULL(2)"); return NULL; } -int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { +const char *GameDatabaseV2::getString(uint16 offset) { + return (const char*)&_gameText[offset * 4]; +} + + +/* GameDatabaseV3 */ + +GameDatabaseV3::GameDatabaseV3(MadeEngine *vm) : GameDatabase(vm) { +} + +void GameDatabaseV3::load(Common::SeekableReadStream &sourceS) { + + // TODO: Read/verifiy header + + sourceS.seek(0x1E); + + uint32 objectIndexOffs = sourceS.readUint32LE(); + uint16 objectCount = sourceS.readUint16LE(); + uint32 gameStateOffs = sourceS.readUint32LE(); + _gameStateSize = sourceS.readUint32LE(); + uint32 objectsOffs = sourceS.readUint32LE(); + uint32 objectsSize = sourceS.readUint32LE(); + _mainCodeObjectIndex = sourceS.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]; + sourceS.seek(gameStateOffs); + sourceS.read(_gameState, _gameStateSize); + + Common::Array<uint32> objectOffsets; + sourceS.seek(objectIndexOffs); + for (uint32 i = 0; i < objectCount; i++) + objectOffsets.push_back(sourceS.readUint32LE()); + + for (uint32 i = 0; i < objectCount; i++) { + Object *obj = new ObjectV3(); + + // The LSB indicates if it's a constant or variable object. + // Constant objects are loaded from disk, while variable objects exist + // in the _gameState buffer. + + if (objectOffsets[i] & 1) { + sourceS.seek(objectsOffs + objectOffsets[i] - 1); + obj->load(sourceS); + } else { + obj->load(_gameState + objectOffsets[i]); + } + _objects.push_back(obj); + } + +} + +bool GameDatabaseV3::getSavegameDescription(const char *filename, Common::String &description) { + Common::InSaveFile *in; + char desc[64]; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + return false; + } + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->read(desc, 64); + description = desc; + delete in; + return true; +} + +int16 GameDatabaseV3::savegame(const char *filename, const char *description, int16 version) { + Common::OutSaveFile *out; + char desc[64]; + int16 result = 0; + uint32 size = 4 + 4 + 2 + _gameStateSize; + if (!(out = g_system->getSavefileManager()->openForSaving(filename))) { + warning("Can't create file '%s', game not saved", filename); + return 6; + } + strncpy(desc, description, 64); + out->writeUint32BE(MKID_BE('SGAM')); + out->writeUint32LE(size); + out->writeUint16LE(version); + out->write(desc, 64); + out->write(_gameState, _gameStateSize); + delete out; + return result; +} + +int16 GameDatabaseV3::loadgame(const char *filename, int16 version) { + Common::InSaveFile *in; + int16 result = 0; + //uint32 expectedSize = 4 + 4 + 2 + _gameStateSize; + if (!(in = g_system->getSavefileManager()->openForLoading(filename))) { + warning("Can't open file '%s', game not loaded", filename); + return 1; + } + in->skip(4); // TODO: Verify marker 'SGAM' + in->skip(4); // TODO: Verify size + in->skip(2); // TODO: Verify version + in->skip(64); // skip savegame description + in->read(_gameState, _gameStateSize); + delete in; + return result; +} + +int16 *GameDatabaseV3::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { Object *obj = getObject(objectIndex); int16 *prop = (int16*)obj->getData(); @@ -558,14 +611,11 @@ int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, // 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); - obj = getObject(parentObjectIndex); prop = (int16*)obj->getData(); @@ -607,70 +657,13 @@ int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, } - //debug(2, "! NULL(nf)\n"); return NULL; - -} - -int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) { - switch (_vm->_engineVersion) { - case 2: - return getObjectPropertyPtrV2(objectIndex, propertyId, propertyFlag); - case 3: - return getObjectPropertyPtrV3(objectIndex, propertyId, propertyFlag); - default: - error("GameDatabase::getObjectPropertyPtr() Unknown engine version"); - return NULL; - } -} - -int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) { - - if (objectIndex == 0) - return 0; - - int16 propertyFlag; - int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag); - if (property) { - return (int16)READ_LE_UINT16(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) { - WRITE_LE_UINT16(property, value); - } else { - warning("GameDatabase::setObjectProperty(%04X, %04X, %04X) Trying to set constant property\n", - objectIndex, propertyId, value); - } - return value; - } else { - return 0; - } - -} - -const char *GameDatabase::getString(uint16 offset) { - return (const char*)&_gameText[offset * 4]; -} - -void GameDatabase::dumpObject(int16 index) { - Object *obj = getObject(index); - char fn[512]; - sprintf(fn, "obj%04X.0", index); - obj->dump(fn); +const char *GameDatabaseV3::getString(uint16 offset) { + // Not used in version 3 games + return NULL; } } // End of namespace Made diff --git a/engines/made/database.h b/engines/made/database.h index 0924200374..49655e41ae 100644 --- a/engines/made/database.h +++ b/engines/made/database.h @@ -40,29 +40,25 @@ namespace Made { class Object { public: Object(); - ~Object(); + virtual ~Object(); + + virtual int load(Common::SeekableReadStream &source) = 0; + virtual int load(byte *source) = 0; + virtual int save(Common::WriteStream &dest) = 0; + virtual uint16 getFlags() = 0; + virtual uint16 getClass() = 0; + virtual uint16 getSize() = 0; + virtual byte getCount1() = 0; + virtual byte getCount2() = 0; + virtual byte *getData() = 0; + virtual bool isConstant() = 0; - int loadVersion2(Common::SeekableReadStream &source); - int saveVersion2(Common::WriteStream &dest); - - int loadVersion3(Common::SeekableReadStream &source); - int loadVersion3(byte *source); - - uint16 getFlags() const; - uint16 getClass() const; - uint16 getSize() const; - - byte getCount1() const; - byte getCount2() const; - - byte *getData(); const char *getString(); void setString(const char *str); bool isObject(); bool isVector(); - bool isConstant() const { return !(getFlags() & 1); } - + int16 getVectorSize(); int16 getVectorItem(int16 index); void setVectorItem(int16 index, int16 value); @@ -75,20 +71,52 @@ protected: byte *_objData; }; +class ObjectV2 : public Object { +public: + int load(Common::SeekableReadStream &source); + int load(byte *source); + int save(Common::WriteStream &dest); + uint16 getFlags(); + uint16 getClass(); + uint16 getSize(); + byte getCount1(); + byte getCount2(); + byte *getData(); + + bool isConstant() { + return false; + } + +}; + +class ObjectV3 : public Object { +public: + int load(Common::SeekableReadStream &source); + int load(byte *source); + int save(Common::WriteStream &dest); + uint16 getFlags(); + uint16 getClass(); + uint16 getSize(); + byte getCount1(); + byte getCount2(); + byte *getData(); + + bool isConstant() { + return !(getFlags() & 1); + } + +}; + class GameDatabase { public: GameDatabase(MadeEngine *vm); - ~GameDatabase(); + virtual ~GameDatabase(); void open(const char *filename); void openFromRed(const char *redFilename, const char *filename); - bool getSavegameDescription(const char *filename, Common::String &description); - int16 savegame(const char *filename, const char *description, int16 version); - int16 loadgame(const char *filename, int16 version); - - Object *getObject(int16 index) const { + Object *getObject(int16 index) const { if (index >= 1) return _objects[index - 1]; else @@ -101,32 +129,52 @@ public: int16 getVar(int16 index); void setVar(int16 index, int16 value); - - int16 *getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - int16 *getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag); - + + virtual int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) = 0; + virtual const char *getString(uint16 offset) = 0; + virtual bool getSavegameDescription(const char *filename, Common::String &description) = 0; + virtual int16 savegame(const char *filename, const char *description, int16 version) = 0; + virtual int16 loadgame(const char *filename, int16 version) = 0; + int16 getObjectProperty(int16 objectIndex, int16 propertyId); int16 setObjectProperty(int16 objectIndex, int16 propertyId, int16 value); - - const char *getString(uint16 offset); void dumpObject(int16 index); - + protected: MadeEngine *_vm; Common::Array<Object*> _objects; byte *_gameState; uint32 _gameStateSize; - char *_gameText; int16 _mainCodeObjectIndex; + virtual void load(Common::SeekableReadStream &sourceS) = 0; +}; + +class GameDatabaseV2 : public GameDatabase { +public: + GameDatabaseV2(MadeEngine *vm); + ~GameDatabaseV2(); + int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag); + const char *getString(uint16 offset); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); +protected: + char *_gameText; + void load(Common::SeekableReadStream &sourceS); +}; + +class GameDatabaseV3 : public GameDatabase { +public: + GameDatabaseV3(MadeEngine *vm); + int16 *getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag); + const char *getString(uint16 offset); + bool getSavegameDescription(const char *filename, Common::String &description); + int16 savegame(const char *filename, const char *description, int16 version); + int16 loadgame(const char *filename, int16 version); +protected: + char *_gameText; void load(Common::SeekableReadStream &sourceS); - void loadVersion2(Common::SeekableReadStream &sourceS); - void loadVersion3(Common::SeekableReadStream &sourceS); - int16 savegameV2(Common::OutSaveFile *out, const char *description, int16 version); - int16 loadgameV2(Common::InSaveFile *in, int16 version); - int16 savegameV3(Common::OutSaveFile *out, const char *description, int16 version); - int16 loadgameV3(Common::InSaveFile *in, int16 version); }; } // End of namespace Made diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 92efb881e2..da7ab23f5d 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -86,7 +86,15 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _pmvPlayer = new PmvPlayer(this, _mixer); _res = new ProjectReader(); _screen = new Screen(this); - _dat = new GameDatabase(this); + + if (getGameID() == GID_LGOP2 || getGameID() == GID_MANHOLE) { + _dat = new GameDatabaseV2(this); + } else if (getGameID() == GID_RTZ) { + _dat = new GameDatabaseV3(this); + } else { + error("Unknown GameID"); + } + _script = new ScriptInterpreter(this); int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); |