void ImageFile::loadPalette(Common::SeekableReadStream &stream) { // Check for palette uint16 width = stream.readUint16LE() + 1; uint16 height = stream.readUint16LE() + 1; byte paletteBase = stream.readByte(); byte rleEncoded = stream.readByte(); byte offsetX = stream.readByte(); byte offsetY = stream.readByte(); uint32 palSignature = 0; if ((width == 390) && (height == 2) && (!paletteBase) && (!rleEncoded) && (!offsetX) && (!offsetY)) { // We check for these specific values // We can't do "width * height", because at least the first German+Spanish menu bar is 60 x 13 // which is 780, which is the size of the palette. We obviously don't want to detect it as palette. // As another security measure, we also check for the signature text palSignature = stream.readUint32BE(); if (palSignature != MKTAG('V', 'G', 'A', ' ')) { // signature mismatch, rewind stream.seek(-12, SEEK_CUR); return; } // Found palette, so read it in stream.seek(8, SEEK_CUR); // Skip over the rest of the signature text "VGA palette" for (int idx = 0; idx < PALETTE_SIZE; ++idx) _palette[idx] = VGA_COLOR_TRANS(stream.readByte()); } else { // Not a palette, so rewind to start of frame data for normal frame processing stream.seek(-8, SEEK_CUR); } }
void DirectorEngine::loadEXE() { Common::SeekableReadStream *exeStream = SearchMan.createReadStreamForMember(getEXEName()); if (!exeStream) error("Failed to open EXE '%s'", getEXEName().c_str()); _lingo->processEvent(kEventStart, 0); exeStream->seek(-4, SEEK_END); exeStream->seek(exeStream->readUint32LE()); switch (getVersion()) { case 3: loadEXEv3(exeStream); break; case 4: loadEXEv4(exeStream); break; case 5: loadEXEv5(exeStream); break; case 7: loadEXEv7(exeStream); break; default: error("Unhandled Windows EXE version %d", getVersion()); } }
void KEYFile::readBIFList(Common::SeekableReadStream &key, uint32 offset) { key.seek(offset); for (BIFList::iterator bif = _bifs.begin(); bif != _bifs.end(); ++bif) { key.skip(4); // File size of the bif uint32 nameOffset = key.readUint32LE(); uint32 nameSize = 0; // nameSize is expanded to 4 bytes in 1.1 and the location is dropped if (_version == kVersion11) { nameSize = key.readUint32LE(); } else { nameSize = key.readUint16LE(); key.skip(2); // Location of the bif (HD, CD, ...) } uint32 curPos = key.seek(nameOffset); *bif = Common::readStringFixed(key, Common::kEncodingASCII, nameSize); key.seek(curPos); bif->replaceAll('\\', '/'); if (bif->beginsWith("/")) bif->erase(bif->begin()); } }
bool WagFileParser::checkWagVersion(Common::SeekableReadStream &stream) { if (stream.size() >= WINAGI_VERSION_LENGTH) { // Stream has space to contain the WinAGI version string // Read the last WINAGI_VERSION_LENGTH bytes of the stream and make a string out of it char str[WINAGI_VERSION_LENGTH+1]; // Allocate space for the trailing zero also uint32 oldStreamPos = stream.pos(); // Save the old stream position stream.seek(stream.size() - WINAGI_VERSION_LENGTH); uint32 readBytes = stream.read(str, WINAGI_VERSION_LENGTH); stream.seek(oldStreamPos); // Seek back to the old stream position str[readBytes] = 0; // Set the trailing zero to finish the C-style string if (readBytes != WINAGI_VERSION_LENGTH) { // Check that we got the whole version string debug(3, "WagFileParser::checkWagVersion: Error reading WAG file version from stream"); return false; } debug(3, "WagFileParser::checkWagVersion: Read WinAGI version string (\"%s\")", str); // Check that the WinAGI version string is one of the two version strings // WinAGI 1.1.21 recognizes as acceptable in the end of a *.wag file. // Note that they are all of length 16 and are padded with spaces to be that long. return scumm_stricmp(str, "WINAGI v1.0 ") == 0 || scumm_stricmp(str, "1.0 BETA ") == 0; } else { // Stream is too small to contain the WinAGI version string debug(3, "WagFileParser::checkWagVersion: Stream is too small to contain a valid WAG file"); return false; } }
void Archive::_decryptHeader(Common::SeekableReadStream &inStream, Common::WriteStream &outStream) { static const uint32 addKey = 0x3C6EF35F; static const uint32 multKey = 0x0019660D; inStream.seek(0); uint32 size = inStream.readUint32LE(); bool encrypted = size > 1000000; inStream.seek(0); if (encrypted) { uint32 decryptedSize = size ^ addKey; uint32 currentKey = 0; for (uint i = 0; i < decryptedSize; i++) { currentKey += addKey; outStream.writeUint32LE(inStream.readUint32LE() ^ currentKey); currentKey *= multKey; } } else { for (uint i = 0; i < size; i++) { outStream.writeUint32LE(inStream.readUint32LE()); } } }
bool SaveReader::getInfo(Common::SeekableReadStream &stream, SavePartInfo &info) { // Remeber the stream's starting position to seek back to uint32 startPos = stream.pos(); // Get parts' basic information Common::Array<SaveContainer::PartInfo> *partsInfo = getPartsInfo(stream); // No parts => fail if (!partsInfo) { stream.seek(startPos); return false; } bool result = false; // Iterate over all parts for (Common::Array<SaveContainer::PartInfo>::iterator it = partsInfo->begin(); it != partsInfo->end(); ++it) { // Check for the info part if (it->id == SavePartInfo::kID) { if (!stream.seek(it->offset)) break; // Read it result = info.read(stream); break; } } stream.seek(startPos); delete partsInfo; return result; }
Common::Archive *Resource::loadArchive(const Common::String &name, Common::ArchiveMemberPtr member) { ArchiveMap::iterator cachedArchive = _archiveCache.find(name); if (cachedArchive != _archiveCache.end()) return cachedArchive->_value; Common::SeekableReadStream *stream = member->createReadStream(); if (!stream) return 0; Common::Archive *archive = 0; for (LoaderList::const_iterator i = _loaders.begin(); i != _loaders.end(); ++i) { if ((*i)->checkFilename(name)) { if ((*i)->isLoadable(name, *stream)) { stream->seek(0, SEEK_SET); archive = (*i)->load(member, *stream); break; } else { stream->seek(0, SEEK_SET); } } } delete stream; if (!archive) return 0; _archiveCache[name] = archive; return archive; }
Common::String Resource::getMessage(uint16 id, uint16 message) { Common::SeekableReadStream *lookup = _text->createReadStreamForIndex(id + 6); Common::SeekableReadStream *strings = _text->createReadStreamForIndex(id + 7); char buff[1024]; int j = 0; int size = lookup->size()/2; for (int i = 0; i < size; ++i) { uint16 val = lookup->readUint16LE(); if (val == message) { strings->seek(i*2); uint16 offset = strings->readUint16LE(); char c = 0; strings->seek(offset); do { c = strings->readByte(); buff[j++] = c; } while (c != 0); return buff; } } return ""; }
void GameModule::loadActions(Common::SeekableReadStream &s) { debug(0, "GameModule::loadActions()"); s.seek(0x180); _actionsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _actions = new Action[_actionsCount]; for (int i = 0; i < _actionsCount; ++i) { s.seek(offs + i * 72); debug(0, "Action(%d) offs: %08X", i, offs + i * 72); _actions[i].conditions = readConditions(s); for (int j = 0; j < 8; ++j) { _actions[i].results.actionResults[j].kind = s.readByte(); _actions[i].results.actionResults[j].value1 = s.readByte(); _actions[i].results.actionResults[j].value2 = s.readUint16LE(); } const int actionListCount = s.readUint32LE(); const uint32 actionListOffs = s.readUint32LE(); s.seek(actionListOffs); for (int j = 0; j < actionListCount; ++j) { ActionCommand actionCommand; actionCommand.cmd = s.readUint16LE(); actionCommand.sceneObjectIndex = s.readUint16LE(); actionCommand.timeStamp = s.readUint32LE(); actionCommand.walkDest = readPoint(s); actionCommand.param = s.readUint32LE(); _actions[i].actionCommands.push_back(actionCommand); } } }
void DrasculaEngine::playFile(const char *fname) { Common::SeekableReadStream *stream = _archives.open(fname); if (stream) { int soundSize = stream->size(); byte *soundData = (byte *)malloc(soundSize); if (!(!strcmp(fname, "3.als") && soundSize == 145166 && _lang != kSpanish)) { stream->seek(32); } else { // WORKAROUND: File 3.als with English speech files has a big silence at // its beginning and end. We seek past the silence at the beginning, // and ignore the silence at the end // Fixes bug #2111815 - "DRASCULA: Voice delayed" stream->seek(73959, SEEK_SET); soundSize = 117158 - 73959; } stream->read(soundData, soundSize); delete stream; _subtitlesDisabled = !ConfMan.getBool("subtitles"); if (ConfMan.getBool("speech_mute")) memset(soundData, 0x80, soundSize); // Mute speech but keep the pause Audio::AudioStream *sound = Audio::makeRawStream(soundData, soundSize - 64, 11025, Audio::FLAG_UNSIGNED); _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_soundHandle, sound); } else warning("playFile: Could not open %s", fname); }
/** * Load animDataTable from save * @param fHandle Savefile open for reading * @param saveGameFormat The used savegame format * @todo Add Operation Stealth savefile support * * Unlike the old code, this one actually rebuilds the table one frame * at a time. */ void loadResourcesFromSave(Common::SeekableReadStream &fHandle, enum CineSaveGameFormat saveGameFormat) { int16 foundFileIdx; char *animName, part[256], name[10]; strcpy(part, currentPartName); // We only support these variations of the savegame format at the moment. assert(saveGameFormat == ANIMSIZE_23 || saveGameFormat == ANIMSIZE_30_PTRS_INTACT); const int entrySize = ((saveGameFormat == ANIMSIZE_23) ? 23 : 30); const int fileStartPos = fHandle.pos(); for(int resourceIndex=0; resourceIndex<NUM_MAX_ANIMDATA; resourceIndex++) { // Seek to the start of the current animation's entry fHandle.seek(fileStartPos + resourceIndex * entrySize); // Read in the current animation entry fHandle.readUint16BE(); // width fHandle.readUint16BE(); fHandle.readUint16BE(); // bpp fHandle.readUint16BE(); // height bool validPtr = false; // Handle variables only present in animation entries of size 30 if (entrySize == 30) { validPtr = (fHandle.readUint32BE() != 0); // Read data pointer fHandle.readUint32BE(); // Discard mask pointer } foundFileIdx = fHandle.readSint16BE(); int16 frameIndex = fHandle.readSint16BE(); // frame fHandle.read(name, 10); // Handle variables only present in animation entries of size 23 if (entrySize == 23) { validPtr = (fHandle.readByte() != 0); } // Don't try to load invalid entries. if (foundFileIdx < 0 || !validPtr) { //resourceIndex++; // Jump over the invalid entry continue; } // Alright, the animation entry looks to be valid so let's start handling it... if (strcmp(currentPartName, name) != 0) { closePart(); loadPart(name); } animName = g_cine->_partBuffer[foundFileIdx].partName; loadRelatedPalette(animName); // Is this for Future Wars only? loadResource(animName, resourceIndex, frameIndex); } loadPart(part); // Make sure we jump over all the animation entries fHandle.seek(fileStartPos + NUM_MAX_ANIMDATA * entrySize); }
bool Animation::loadStream(Common::SeekableReadStream &stream) { stream.skip(2); // skip not used x and y coord diff _loopCount = stream.readUint16LE(); _phaseCount = stream.readUint16LE(); stream.skip(2); // skip _frameCount here _baseX = stream.readUint16LE(); _baseY = stream.readUint16LE(); uint32 phaseTableOffset = stream.readUint32LE(); uint32 tableOfFrameOffsets = stream.pos(); stream.seek(phaseTableOffset); Phase tempPhase; _frameCount = 0; for (int phase = 0; phase < _phaseCount; phase++) { tempPhase._phaseOffsetX = stream.readSint16LE(); tempPhase._phaseOffsetY = stream.readSint16LE(); tempPhase._phaseToFrameIndex = stream.readUint16LE(); if (tempPhase._phaseToFrameIndex > _frameCount) { _frameCount = tempPhase._phaseToFrameIndex; } _phaseList.push_back(tempPhase); stream.skip(2); } if (_phaseCount) { _frameCount++; } Frame tempFrame; for (int frame = 0; frame < _frameCount; frame++) { stream.seek(tableOfFrameOffsets + frame * 4); uint32 frameInfoOffset = stream.readUint32LE(); stream.seek(frameInfoOffset); uint16 frameWidth = stream.readUint16LE(); uint16 frameHeight = stream.readUint16LE(); uint32 frameDataPos = stream.pos(); uint32 frameDataOffset = stream.readUint32BE(); tempFrame._surface = new Graphics::Surface(); tempFrame._surface->create(frameWidth, frameHeight, Graphics::PixelFormat::createFormatCLUT8()); if (frameDataOffset == MKTAG('m', 'a', 's', 'm')) { tempFrame._isCompressed = true; tempFrame._dataSize = stream.readUint32LE(); tempFrame._compressedData = (byte *)malloc(tempFrame._dataSize); stream.read(tempFrame._compressedData, tempFrame._dataSize); } else { tempFrame._isCompressed = false; tempFrame._dataSize = 0; tempFrame._compressedData = nullptr; stream.seek(frameDataPos); for (uint16 i = 0; i < frameHeight; i++) { stream.read(tempFrame._surface->getBasePtr(0, i), frameWidth); } } _frameList.push_back(tempFrame); } return true; }
void GameModule::loadInventoryItemSpriteIndices(Common::SeekableReadStream &s) { debug(0, "GameModule::loadInventoryItemSpriteIndices()"); s.seek(0x18C); uint32 offs = s.readUint32LE(); s.seek(offs); for (int i = 0; i < kInventoryItemSpriteCount; ++i) _inventoryItemSpriteIndices[i] = s.readUint32LE(); }
void GameModule::loadGuiSpriteIndices(Common::SeekableReadStream &s) { debug(0, "GameModule::loadGuiSpriteIndices()"); s.seek(0x188); uint32 offs = s.readUint32LE(); s.seek(offs); for (int i = 0; i < kGuiSpriteCount; ++i) _guiSpriteIndices[i] = s.readUint32LE(); }
void GameModule::loadDialogItemSpriteIndices(Common::SeekableReadStream &s) { debug(0, "GameModule::loadDialogItemSpriteIndices()"); s.seek(0x194); uint32 offs = s.readUint32LE(); s.seek(offs); for (int i = 0; i < kDialogItemSpriteCount; ++i) { _dialogItemSpriteIndices[i] = s.readUint32LE(); } }
void GameModule::loadWalkRects(Common::SeekableReadStream &s) { debug(0, "GameModule::loadWalkRects()"); s.seek(0x150); _walkRectsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _walkRects = new Common::Rect[_walkRectsCount]; s.seek(offs); for (int i = 0; i < _walkRectsCount; ++i) _walkRects[i] = readRect(s); }
void GameModule::loadPreloadSounds(Common::SeekableReadStream &s) { debug(0, "GameModule::loadPreloadSounds()"); s.seek(0x198); _preloadSoundsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _preloadSounds = new uint[_preloadSoundsCount]; s.seek(offs); for (uint i = 0; i < _preloadSoundsCount; ++i) _preloadSounds[i] = s.readUint32LE(); }
Common::UString GFF4Struct::getString(Common::SeekableReadStream &data, Common::Encoding encoding, uint32 offset) const { const uint32 pos = data.seek(offset); Common::UString str = getString(data, encoding); data.seek(pos); return str; }
bool skipThumbnail(Common::SeekableReadStream &in) { uint32 position = in.pos(); ThumbnailHeader header; if (!loadHeader(in, header, false)) { in.seek(position, SEEK_SET); return false; } in.seek(header.size - (in.pos() - position), SEEK_CUR); return true; }
void GameModule::loadBgObjects(Common::SeekableReadStream &s) { debug(0, "GameModule::loadBgObjects()"); s.seek(0x160); _bgObjectsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _bgObjects = new BgObject[_bgObjectsCount]; s.seek(offs); for (int i = 0; i < _bgObjectsCount; ++i) { s.read(_bgObjects[i].name, 20); _bgObjects[i].rect = readRect(s); } }
void GameModule::loadSceneSounds(Common::SeekableReadStream &s) { debug(0, "GameModule::loadSceneSounds()"); s.seek(0x1A0); _sceneSoundsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _sceneSounds = new SceneSound[_sceneSoundsCount]; s.seek(offs); for (int i = 0; i < _sceneSoundsCount; ++i) { _sceneSounds[i].conditions = readConditions(s); _sceneSounds[i].soundNum = s.readUint32LE(); } }
bool ResLoaderInsMalcolm::isLoadable(const Common::String &filename, Common::SeekableReadStream &stream) const { stream.seek(3, SEEK_SET); int32 size = stream.readUint32LE(); if (size + 7 > stream.size()) return false; stream.seek(size + 5, SEEK_SET); uint8 buffer[2]; stream.read(&buffer, 2); return (buffer[0] == 0x0D && buffer[1] == 0x0A); }
void GameModule::loadSceneExits(Common::SeekableReadStream &s) { debug(0, "GameModule::loadSceneExits()"); s.seek(0x158); _sceneExitsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _sceneExits = new SceneExit[_sceneExitsCount]; s.seek(offs); for (int i = 0; i < _sceneExitsCount; ++i) { _sceneExits[i].rect = readRect(s); _sceneExits[i].newModuleNum = s.readUint32LE(); } }
bool NDSFile::isNDS(Common::SeekableReadStream &stream) { if (!stream.seek(0)) return false; Common::UString gameName; gameName.readFixedASCII(stream, 12); if (gameName != "SONICCHRON") // Should be the only game we will accept. return false; if (!stream.seek(0x40)) return false; return true; }
void GameModule::loadInventoryItemInfos(Common::SeekableReadStream &s) { debug(0, "GameModule::loadInventoryItemInfos()"); s.seek(0x190); uint32 offs = s.readUint32LE(); s.seek(offs); for (int i = 0; i < kInventoryItemCount; ++i) { _inventoryItemInfos[i].xOffs = s.readUint16LE(); _inventoryItemInfos[i].yOffs = s.readUint16LE(); _inventoryItemInfos[i].width = s.readUint16LE(); _inventoryItemInfos[i].height = s.readUint16LE(); s.skip(8); // Unused } }
Common::UString GFF4Struct::getString(Common::SeekableReadStream &data, Common::Encoding encoding, uint32 offset) const { if (_parent->hasSharedStrings()) return _parent->getSharedString(offset); const uint32 pos = data.seek(offset); Common::UString str = getString(data, encoding); data.seek(pos); return str; }
void NewFeature::resetScript() { // FIXME: registrations, etc Common::SeekableReadStream *ourSCRB = _view->getSCRB(_data.scrbIndex, _scrbId); ourSCRB->seek(16); Common::Point scriptBase, scriptSize; scriptBase.x = ourSCRB->readUint16BE(); scriptBase.y = ourSCRB->readUint16BE(); scriptSize.x = ourSCRB->readUint16BE(); scriptSize.y = ourSCRB->readUint16BE(); ourSCRB->seek(26); Common::Point one, two; while (true) { if (ourSCRB->pos() == ourSCRB->size()) error("resetScript (getNewXYAndReg) ran out of script"); byte opcode = ourSCRB->readByte(); byte size = ourSCRB->readByte(); if (opcode != 0x10) { ourSCRB->skip(size - 2); } else if (size) { assert(size >= 1); ourSCRB->skip(2); int16 x = ourSCRB->readUint16BE(); int16 y = ourSCRB->readUint16BE(); one.x = -x; one.y = -y; two.x = scriptBase.x + x; two.y = scriptBase.y + y; break; } } delete ourSCRB; if ((_needsReset || false /* TODO: param */) && (_unknown168 == 0x7FFFFFFF || false /* TODO: param */)) { _data.currentPos = two; _data.nextPos = one; _unknown168 = 0; if (_needsReset || false /* TODO: param */) { _data.bounds = Common::Rect(scriptBase.x, scriptBase.y, scriptSize.x, scriptSize.y); } } else { if (false /* FIXME: 0 shapes? */) { _data.nextPos.x = one.x + two.x - _data.currentPos.x; _data.nextPos.y = one.y + two.y - _data.currentPos.y; } else if (_unknown168 != 0x7FFFFFFF) { _data.nextPos = one; } } // _needsReset = 0; (handled by caller) }
void GameModule::loadSceneObjectDefs(Common::SeekableReadStream &s) { debug(0, "GameModule::loadSceneObjectDefs()"); s.seek(0x170); _sceneObjectDefsCount = s.readUint32LE(); uint32 offs = s.readUint32LE(); _sceneObjectDefs = new SceneObjectDef[_sceneObjectDefsCount]; s.seek(offs); for (int i = 0; i < _sceneObjectDefsCount; ++i) { s.read(_sceneObjectDefs[i].name, 20); _sceneObjectDefs[i].walkSpeed = s.readUint32LE(); for (int j = 0; j < 16; ++j) _sceneObjectDefs[i].animIndices[j] = s.readUint32LE(); } }
void Model_KotOR::readStrings(Common::SeekableReadStream &mdl, const std::vector<uint32> &offsets, uint32 offset, std::vector<Common::UString> &strings) { size_t pos = mdl.pos(); strings.reserve(offsets.size()); for (std::vector<uint32>::const_iterator o = offsets.begin(); o != offsets.end(); ++o) { mdl.seek(offset + *o); strings.push_back(Common::readString(mdl, Common::kEncodingASCII)); } mdl.seek(pos); }
bool Mob::loadFromStream(Common::SeekableReadStream &stream) { int32 pos = stream.pos(); uint16 visible = stream.readUint16LE(); if (visible == 0xFFFF) return false; _visible = visible; _type = stream.readUint16LE(); _rect.left = stream.readUint16LE(); _rect.top = stream.readUint16LE(); _rect.right = stream.readUint16LE(); _rect.bottom = stream.readUint16LE(); _mask = stream.readUint16LE(); _examPosition.x = stream.readUint16LE(); _examPosition.y = stream.readUint16LE(); _examDirection = (Direction)stream.readUint16LE(); _usePosition.x = stream.readByte(); _usePosition.y = stream.readByte(); _useDirection = (Direction)stream.readUint16LE(); uint32 nameOffset = stream.readUint32LE(); uint32 examTextOffset = stream.readUint32LE(); byte c; stream.seek(nameOffset); _name.clear(); while ((c = stream.readByte())) _name += c; stream.seek(examTextOffset); _examText.clear(); c = stream.readByte(); if (c) { _examText += c; do { c = stream.readByte(); _examText += c; } while (c != 255); } stream.seek(pos + 32); return true; }