Common::Array<NodePtr> Database::loadRoomScripts(RoomData *room) { Common::Array<NodePtr> nodes; Common::SeekableSubReadStreamEndian *file = openDatabaseFile(); // Load the node scripts if (room->scriptsOffset) { file->seek(room->scriptsOffset); loadRoomNodeScripts(file, nodes); } // Load the ambient sound scripts, if any if (room->ambSoundsOffset) { file->seek(room->ambSoundsOffset); loadRoomSoundScripts(file, nodes, false); } if (room->unkOffset) { file->seek(room->unkOffset); loadRoomSoundScripts(file, nodes, true); } delete file; return nodes; }
Database::Database(Myst3Engine *vm) : _vm(vm), _currentRoomID(0), _executableVersion(0), _currentRoomData(0) { _executableVersion = _vm->getExecutableVersion(); if (_executableVersion != 0) { debug("Initializing database from %s (Platform: %s) (%s)", _executableVersion->executable, getPlatformDescription(_vm->getPlatform()), _executableVersion->description); } else { error("Could not find any executable to load"); } // Load the ages and rooms description Common::SeekableSubReadStreamEndian *file = openDatabaseFile(); file->seek(_executableVersion->ageTableOffset); _ages = loadAges(*file); for (uint i = 0; i < _ages.size(); i++) { file->seek(_ages[i].roomsOffset); // Read the room offset table Common::Array<uint32> roomsOffsets; for (uint j = 0; j < _ages[i].roomCount; j++) { uint32 offset = file->readUint32() - _executableVersion->baseOffset; roomsOffsets.push_back(offset); } // Load the rooms for (uint j = 0; j < roomsOffsets.size(); j++) { file->seek(roomsOffsets[j]); _ages[i].rooms.push_back(loadRoomDescription(*file)); } } file->seek(_executableVersion->nodeInitScriptOffset); _nodeInitScript = loadOpcodes(*file); file->seek(_executableVersion->soundNamesOffset); loadSoundNames(file); delete file; preloadCommonRooms(); }
void TalkTable_GFF::readString05(Common::SeekableSubReadStreamEndian &huffTree, Common::SeekableSubReadStreamEndian &bitStream, Entry &entry) const { /* Read a string encoded in a Huffman'd bitstream. * * The Huffman tree itself is made up of signed 32bit nodes: * - Positive values are internal nodes, encoding a child index * - Negative values are leaf nodes, encoding an UTF-16 character value * * Kudos to Rick (gibbed) (<http://gib.me/>). */ std::vector<uint16> utf16Str; const uint32 startOffset = entry.strct->getUint(kGFF4HuffTalkStringBitOffset); uint32 index = startOffset >> 5; uint32 shift = startOffset & 0x1F; do { ptrdiff_t e = (huffTree.size() / 8) - 1; while (e >= 0) { bitStream.seek(index * 4); const ptrdiff_t offset = (bitStream.readUint32() >> shift) & 1; huffTree.seek(((e * 2) + offset) * 4); e = huffTree.readSint32(); shift++; index += (shift >> 5); shift %= 32; } utf16Str.push_back(TO_LE_16(0xFFFF - e)); } while (utf16Str.back() != 0); const byte *data = reinterpret_cast<const byte *>(&utf16Str[0]); const size_t size = utf16Str.size() * 2; entry.text = Common::readString(data, size, Common::kEncodingUTF16LE); }
Database::Database(Myst3Engine *vm) : _vm(vm), _currentRoomID(0), _executableVersion(0), _currentRoomData(0) { _executableVersion = _vm->getExecutableVersion(); if (_executableVersion != 0) { debug("Initializing database from %s (Platform: %s) (%s)", _executableVersion->executable, getPlatformDescription(_vm->getPlatform()), _executableVersion->description); } else { error("Could not find any executable to load"); } // Load the ages and rooms description Common::SeekableSubReadStreamEndian *file = openDatabaseFile(); file->seek(_executableVersion->ageTableOffset); _ages = loadAges(*file); for (uint i = 0; i < _ages.size(); i++) { file->seek(_ages[i].roomsOffset); // Read the room offset table Common::Array<uint32> roomsOffsets; for (uint j = 0; j < _ages[i].roomCount; j++) { uint32 offset = file->readUint32() - _executableVersion->baseOffset; roomsOffsets.push_back(offset); } // Load the rooms for (uint j = 0; j < roomsOffsets.size(); j++) { file->seek(roomsOffsets[j]); _ages[i].rooms.push_back(loadRoomDescription(*file)); } } file->seek(_executableVersion->nodeInitScriptOffset); _nodeInitScript = loadOpcodes(*file); file->seek(_executableVersion->soundNamesOffset); loadSoundNames(file); // TODO: Remove once the offset table is complete if (!_executableVersion->ambientCuesOffset) { error("The description for this executable (%s, %s) does not contain the ambient cues offset. Please contact the ResidualVM team.", _executableVersion->executable, _executableVersion->description); } file->seek(_executableVersion->ambientCuesOffset); loadAmbientCues(file); preloadCommonRooms(file); initializeZipBitIndexTable(file); delete file; }
CondScript Database::loadCondScript(Common::SeekableSubReadStreamEndian &s) { CondScript script; script.condition = s.readUint16(); if(!script.condition) return script; // WORKAROUND: Original data bug in MATO 32765 // The script data for node MATO 32765 is missing its first two bytes // of data, resulting in incorrect opcodes being read // Original disassembly: // init 0 > c[v565 != 0] // op 115, ifVarInRange ( ) // op 45, inventoryAddBack ( ) // op 53, varSetValue ( vSunspotColor 4090 ) // op 53, varSetValue ( vSunspotRadius 40 ) // op 33, waterEffectSetWave ( 100 80 ) // op 32, waterEffectSetAttenuation ( 359 ) // op 31, waterEffectSetSpeed ( 15 ) // Fixed disassembly // init 0 > c[v1 != 0] // op 53, varSetValue ( vSunspotIntensity 45 ) // op 53, varSetValue ( vSunspotColor 4090 ) // op 53, varSetValue ( vSunspotRadius 40 ) // op 33, waterEffectSetWave ( 100 80 ) // op 32, waterEffectSetAttenuation ( 359 ) // op 31, waterEffectSetSpeed ( 15 ) if (script.condition == 565) { script.condition = 1; s.seek(-2, SEEK_CUR); } // END WORKAROUND script.script = loadOpcodes(s); return script; }