aboutsummaryrefslogtreecommitdiff
path: root/engines/made/database.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/made/database.cpp')
-rw-r--r--engines/made/database.cpp154
1 files changed, 133 insertions, 21 deletions
diff --git a/engines/made/database.cpp b/engines/made/database.cpp
index 108d1391e5..406639a1fc 100644
--- a/engines/made/database.cpp
+++ b/engines/made/database.cpp
@@ -47,7 +47,7 @@ Object::~Object() {
delete[] _objData;
}
-int Object::load(Common::SeekableReadStream &source) {
+int Object::loadVersion2(Common::SeekableReadStream &source) {
_freeData = true;
uint16 type = source.readUint16LE();
if (type == 0x7FFF) {
@@ -59,6 +59,27 @@ int Object::load(Common::SeekableReadStream &source) {
byte count2 = source.readByte();
_objSize = (count1 + count2) * 2;
}
+ source.seek(-4, SEEK_CUR);
+ _objSize += 6;
+ _objData = new byte[_objSize];
+ WRITE_LE_UINT16(_objData, 1);
+ source.read(_objData + 2, _objSize - 2);
+ return _objSize - 2;
+}
+
+int Object::loadVersion3(Common::SeekableReadStream &source) {
+ _freeData = true;
+ source.readUint16LE(); // skip flags
+ uint16 type = 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];
@@ -66,7 +87,7 @@ int Object::load(Common::SeekableReadStream &source) {
return _objSize;
}
-int Object::load(byte *source) {
+int Object::loadVersion3(byte *source) {
_objData = source;
_freeData = false;
if (getClass() < 0x7FFE) {
@@ -175,11 +196,14 @@ void Object::dump(const char *filename) {
}
GameDatabase::GameDatabase(MadeEngine *vm) : _vm(vm) {
+ _gameText = NULL;
}
GameDatabase::~GameDatabase() {
if (_gameState)
delete[] _gameState;
+ if (_gameText)
+ delete[] _gameText;
}
void GameDatabase::open(const char *filename) {
@@ -218,7 +242,7 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) {
sourceS.seek(0x1C);
- uint32 textStartOffs = sourceS.readUint16LE() * 512;
+ uint32 textOffs = sourceS.readUint16LE() * 512;
uint16 objectCount = sourceS.readUint16LE();
uint16 varObjectCount = sourceS.readUint16LE();
_gameStateSize = sourceS.readUint16LE() * 2;
@@ -228,25 +252,31 @@ void GameDatabase::loadVersion2(Common::SeekableReadStream &sourceS) {
_mainCodeObjectIndex = sourceS.readUint16LE();
sourceS.readUint16LE(); // unknown
uint32 objectsSize = sourceS.readUint32LE() * 2;
+ uint32 textSize = objectsOffs - textOffs;
- debug(2, "textStartOffs = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", textStartOffs, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize);
+ debug(2, "textOffs = %08X; textSize = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d\n", textOffs, textSize, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize);
_gameState = new byte[_gameStateSize];
memset(_gameState, 0, _gameStateSize);
+ sourceS.seek(textOffs);
+ _gameText = new char[textSize];
+ sourceS.read(_gameText, textSize);
+ // "Decrypt" the text data
+ for (int i = 0; i < textSize; i++)
+ _gameText[i] += 0x1E;
+
sourceS.seek(objectsOffs);
for (uint32 i = 0; i < objectCount; i++) {
Object *obj = new Object();
- int objSize = obj->load(sourceS);
+ int objSize = obj->loadVersion2(sourceS);
objSize = objSize % 2;
// objects are aligned on 2-byte-boundaries, skip unused bytes
sourceS.skip(objSize);
_objects.push_back(obj);
}
- printf("ok!\n"); fflush(stdout);
-
}
void GameDatabase::loadVersion3(Common::SeekableReadStream &sourceS) {
@@ -286,11 +316,10 @@ void GameDatabase::loadVersion3(Common::SeekableReadStream &sourceS) {
if (objectOffsets[i] & 1) {
debug(2, "-> const %08X\n", objectsOffs + objectOffsets[i] - 1);
sourceS.seek(objectsOffs + objectOffsets[i] - 1);
- sourceS.readUint16LE(); // skip flags
- obj->load(sourceS);
+ obj->loadVersion3(sourceS);
} else {
debug(2, "-> var\n");
- obj->load(_gameState + objectOffsets[i]);
+ obj->loadVersion3(_gameState + objectOffsets[i]);
}
_objects.push_back(obj);
}
@@ -378,13 +407,80 @@ void GameDatabase::setVar(int16 index, int16 value) {
WRITE_LE_UINT16(_gameState + index * 2, value);
}
-int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
+int16 *GameDatabase::getObjectPropertyPtrV2(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
Object *obj = getObject(objectIndex);
int16 *prop = (int16*)obj->getData();
byte count1 = obj->getCount1();
byte count2 = obj->getCount2();
-
+
+ int16 *propPtr1 = prop + count1;
+ int16 *propPtr2 = prop + count2;
+
+ // First see if the property exists in the given object
+ while (count2-- > 0) {
+ if ((READ_LE_UINT16(prop) & 0x7FFF) == propertyId) {
+ 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);
+
+ 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 (!(READ_LE_UINT16(prop) & 0x8000)) {
+ if ((READ_LE_UINT16(prop) & 0x7FFF) == propertyId) {
+ propertyFlag = obj->getFlags() & 1;
+ return propPtr1;
+ } else {
+ propPtr1++;
+ }
+ } else {
+ if ((READ_LE_UINT16(prop) & 0x7FFF) == propertyId) {
+ propertyFlag = obj->getFlags() & 1;
+ return propertyPtr;
+ }
+ }
+ prop++;
+ propertyPtr++;
+ }
+
+ parentObjectIndex = obj->getClass();
+
+ }
+
+ //debug(2, "! NULL(nf)\n");
+ return NULL;
+
+}
+
+int16 *GameDatabase::getObjectPropertyPtrV3(int16 objectIndex, int16 propertyId, int16 &propertyFlag) {
+ Object *obj = getObject(objectIndex);
+
+ int16 *prop = (int16*)obj->getData();
+ byte count1 = obj->getCount1();
+ byte count2 = obj->getCount2();
+
int16 *propPtr1 = prop + count1;
int16 *propPtr2 = prop + count2;
@@ -402,27 +498,27 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i
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);
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 (!(READ_LE_UINT16(prop) & 0x8000)) {
if ((READ_LE_UINT16(prop) & 0x3FFF) == propertyId) {
@@ -450,14 +546,26 @@ int16 *GameDatabase::getObjectPropertyPtr(int16 objectIndex, int16 propertyId, i
prop++;
propertyPtr++;
}
-
+
parentObjectIndex = obj->getClass();
-
+
}
//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) {
@@ -467,7 +575,7 @@ int16 GameDatabase::getObjectProperty(int16 objectIndex, int16 propertyId) {
int16 propertyFlag;
int16 *property = getObjectPropertyPtr(objectIndex, propertyId, propertyFlag);
-
+
if (property) {
return (int16)READ_LE_UINT16(property);
} else {
@@ -498,6 +606,10 @@ int16 GameDatabase::setObjectProperty(int16 objectIndex, int16 propertyId, int16
}
+const char *GameDatabase::getString(uint16 offset) {
+ return (const char*)&_gameText[offset * 4];
+}
+
void GameDatabase::dumpObject(int16 index) {
Object *obj = getObject(index);
char fn[512];