Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile, bool suppressErrors) { // Open up the library for access Common::SeekableReadStream *libStream = load(libraryFile); // Check if the library has already had its index read, and if not, load it if (!_indexes.contains(libraryFile)) loadLibraryIndex(libraryFile, libStream, false); LibraryIndex &libIndex = _indexes[libraryFile]; // Handle if resource is not present if (!libIndex.contains(filename)) { if (!suppressErrors) error("Could not find resource - %s", filename.c_str()); delete libStream; return nullptr; } // Extract the data for the specified resource and return it LibraryEntry &entry = libIndex[filename]; libStream->seek(entry._offset); Common::SeekableReadStream *stream = libStream->readStream(entry._size); decompressIfNecessary(stream); delete libStream; return stream; }
Common::SeekableReadStream *HERFFile::getResource(uint32 index) const { const IResource &res = getIResource(index); if (res.size == 0) return new Common::MemoryReadStream(0, 0); Common::SeekableReadStream *herf = ResMan.getResource(TypeMan.setFileType(_fileName, kFileTypeNone), kFileTypeHERF); if (!herf) throw Common::Exception(Common::kOpenError); if (!herf->seek(res.offset)) { delete herf; throw Common::Exception(Common::kSeekError); } Common::SeekableReadStream *resStream = herf->readStream(res.size); if (!resStream || (((uint32) resStream->size()) != res.size)) { delete herf; delete resStream; throw Common::Exception(Common::kReadError); } delete herf; return resStream; }
void ASFStream::parseStreamHeader() { ASFGUID guid = ASFGUID(*_stream); if (guid != s_asfAudioStream) throw Common::Exception("ASFStream::parseStreamHeader(): Found non-audio stream"); _stream->skip(16); // skip a guid _stream->readUint64LE(); // total size uint32 typeSpecificSize = _stream->readUint32LE(); _stream->readUint32LE(); _streamID = _stream->readUint16LE(); _stream->readUint32LE(); // Parse the wave header _compression = _stream->readUint16LE(); _channels = _stream->readUint16LE(); _sampleRate = _stream->readUint32LE(); _bitRate = _stream->readUint32LE() * 8; _blockAlign = _stream->readUint16LE(); _bitsPerCodedSample = (typeSpecificSize == 14) ? 8 : _stream->readUint16LE(); if (typeSpecificSize >= 18) { uint32 cbSize = _stream->readUint16LE(); cbSize = MIN<int>(cbSize, typeSpecificSize - 18); _extraData = _stream->readStream(cbSize); } _codec = createCodec(); }
Common::SeekableReadStream *Resources::load(const Common::String &filename) { // First check if the file is directly in the cache if (_cache.isCached(filename)) return _cache.get(filename); // Secondly, iterate through any loaded library file looking for a resource // that has the same name for (LibraryIndexes::iterator i = _indexes.begin(); i != _indexes.end(); ++i) { if (i->_value.contains(filename)) { // Get a stream reference to the given library file Common::SeekableReadStream *stream = load(i->_key); LibraryEntry &entry = i->_value[filename]; _resourceIndex = entry._index; stream->seek(entry._offset); Common::SeekableReadStream *resStream = stream->readStream(entry._size); decompressIfNecessary(resStream); delete stream; return resStream; } } // At this point, fall back on a physical file with the given name Common::File f; if (!f.open(filename)) error("Could not load file - %s", filename.c_str()); Common::SeekableReadStream *stream = f.readStream(f.size()); f.close(); decompressIfNecessary(stream); return stream; }
Common::SeekableReadStream *QuickTimeDecoder::VideoTrackHandler::getNextFramePacket(uint32 &descId) { // First, we have to track down which chunk holds the sample and which sample in the chunk contains the frame we are looking for. int32 totalSampleCount = 0; int32 sampleInChunk = 0; int32 actualChunk = -1; uint32 sampleToChunkIndex = 0; for (uint32 i = 0; i < _parent->chunkCount; i++) { if (sampleToChunkIndex < _parent->sampleToChunkCount && i >= _parent->sampleToChunk[sampleToChunkIndex].first) sampleToChunkIndex++; totalSampleCount += _parent->sampleToChunk[sampleToChunkIndex - 1].count; if (totalSampleCount > _curFrame) { actualChunk = i; descId = _parent->sampleToChunk[sampleToChunkIndex - 1].id; sampleInChunk = _parent->sampleToChunk[sampleToChunkIndex - 1].count - totalSampleCount + _curFrame; break; } } if (actualChunk < 0) { warning("Could not find data for frame %d", _curFrame); return 0; } // Next seek to that frame Common::SeekableReadStream *stream = _decoder->_fd; stream->seek(_parent->chunkOffsets[actualChunk]); // Then, if the chunk holds more than one frame, seek to where the frame we want is located for (int32 i = _curFrame - sampleInChunk; i < _curFrame; i++) { if (_parent->sampleSize != 0) stream->skip(_parent->sampleSize); else stream->skip(_parent->sampleSizes[i]); } // Finally, read in the raw data for the frame //debug("Frame Data[%d]: Offset = %d, Size = %d", _curFrame, stream->pos(), _parent->sampleSizes[_curFrame]); if (_parent->sampleSize != 0) return stream->readStream(_parent->sampleSize); return stream->readStream(_parent->sampleSizes[_curFrame]); }
void TPC::readTXI(Common::SeekableReadStream &tpc) { const size_t txiDataSize = tpc.size() - tpc.pos(); if (txiDataSize == 0) return; Common::SeekableReadStream *txiData = tpc.readStream(txiDataSize); try { _txi.load(*txiData); } catch (...) { } delete txiData; }
bool CWaveFile::loadMusic(const CString &name) { assert(!_stream); StdCWadFile file; if (!file.open(name)) return false; Common::SeekableReadStream *stream = file.readStream(); _size = stream->size(); _stream = Audio::makeWAVStream(stream->readStream(_size), DisposeAfterUse::YES); _soundType = Audio::Mixer::kMusicSoundType; return true; }
void LocString::readString(uint32 languageID, Common::SeekableReadStream &stream) { uint32 length = stream.readUint32LE(); std::pair<StringMap::iterator, bool> s = _strings.insert(std::make_pair(languageID, "")); if (length == 0) return; s.first->second = "[???]"; Common::ScopedPtr<Common::MemoryReadStream> data(stream.readStream(length)); Common::ScopedPtr<Common::MemoryReadStream> parsed(LangMan.preParseColorCodes(*data)); Common::Encoding encoding = LangMan.getEncodingLocString(LangMan.getLanguageGendered(languageID)); if (encoding != Common::kEncodingInvalid) s.first->second = Common::readString(*parsed, encoding); }
Common::SeekableReadStream *Resources::load(const Common::String &filename, const Common::String &libraryFile) { // Open up the library for access Common::SeekableReadStream *libStream = load(libraryFile); // Check if the library has already had it's index read, and if not, load it if (!_indexes.contains(libraryFile)) loadLibraryIndex(libraryFile, libStream, false); // Extract the data for the specified resource and return it LibraryEntry &entry = _indexes[libraryFile][filename]; libStream->seek(entry._offset); Common::SeekableReadStream *stream = libStream->readStream(entry._size); decompressIfNecessary(stream); delete libStream; return stream; }
void LocString::readString(uint32 languageID, Common::SeekableReadStream &stream) { uint32 length = stream.readUint32LE(); std::pair<StringMap::iterator, bool> s = _strings.insert(std::make_pair(languageID, "")); if (length == 0) return; Common::MemoryReadStream *data = stream.readStream(length); Common::MemoryReadStream *parsed = LangMan.preParseColorCodes(*data); Common::Encoding encoding = LangMan.getEncodingLocString(LangMan.getLanguageGendered(languageID)); if (encoding == Common::kEncodingInvalid) encoding = Common::kEncodingUTF8; try { s.first->second = Common::readString(*parsed, encoding); } catch (...) { parsed->seek(0); s.first->second = Common::readString(*parsed, Common::kEncodingCP1252); } delete parsed; delete data; }
void RivenGraphics::scheduleWaterEffect(uint16 sfxeID) { Common::SeekableReadStream *sfxeStream = _vm->getResource(ID_SFXE, sfxeID); if (sfxeStream->readUint16BE() != 'SL') error ("Unknown sfxe tag"); // Read in header info SFXERecord sfxeRecord; sfxeRecord.frameCount = sfxeStream->readUint16BE(); uint32 offsetTablePosition = sfxeStream->readUint32BE(); sfxeRecord.rect.left = sfxeStream->readUint16BE(); sfxeRecord.rect.top = sfxeStream->readUint16BE(); sfxeRecord.rect.right = sfxeStream->readUint16BE(); sfxeRecord.rect.bottom = sfxeStream->readUint16BE(); sfxeRecord.speed = sfxeStream->readUint16BE(); // Skip the rest of the fields... // Read in offsets sfxeStream->seek(offsetTablePosition); uint32 *frameOffsets = new uint32[sfxeRecord.frameCount]; for (uint16 i = 0; i < sfxeRecord.frameCount; i++) frameOffsets[i] = sfxeStream->readUint32BE(); sfxeStream->seek(frameOffsets[0]); // Read in the scripts for (uint16 i = 0; i < sfxeRecord.frameCount; i++) sfxeRecord.frameScripts.push_back(sfxeStream->readStream((i == sfxeRecord.frameCount - 1) ? sfxeStream->size() - frameOffsets[i] : frameOffsets[i + 1] - frameOffsets[i])); // Set it to the first frame sfxeRecord.curFrame = 0; sfxeRecord.lastFrameTime = 0; delete[] frameOffsets; delete sfxeStream; _waterEffects.push_back(sfxeRecord); }
ASFStream::Packet *ASFStream::readPacket() { if (_curPacket == _packetCount) throw Common::Exception("ASFStream::readPacket(): Reading too many packets"); uint32 packetStartPos = _stream->pos(); // Read a single ASF packet if (_stream->readByte() != 0x82) throw Common::Exception("ASFStream::readPacket(): Missing packet header"); if (_stream->readUint16LE() != 0) throw Common::Exception("ASFStream::readPacket(): Unknown is not zero"); Packet *packet = new Packet(); packet->flags = _stream->readByte(); packet->segmentType = _stream->readByte(); packet->packetSize = (packet->flags & 0x40) ? _stream->readUint16LE() : 0; uint16 paddingSize = 0; if (packet->flags & 0x10) paddingSize = _stream->readUint16LE(); else if (packet->flags & 0x08) paddingSize = _stream->readByte(); packet->sendTime = _stream->readUint32LE(); packet->duration = _stream->readUint16LE(); byte segmentCount = (packet->flags & 0x01) ? _stream->readByte() : 1; packet->segments.resize(segmentCount & 0x3F); for (uint32 i = 0; i < packet->segments.size(); i++) { Packet::Segment &segment = packet->segments[i]; segment.streamID = _stream->readByte(); segment.sequenceNumber = _stream->readByte(); segment.isKeyframe = (segment.streamID & 0x80) != 0; segment.streamID &= 0x7F; uint32 fragmentOffset = 0; if (packet->segmentType == 0x55) fragmentOffset = _stream->readByte(); else if (packet->segmentType == 0x59) fragmentOffset = _stream->readUint16LE(); else if (packet->segmentType == 0x5D) fragmentOffset = _stream->readUint32LE(); else throw Common::Exception("ASFStream::readPacket(): Unknown packet segment type 0x%02x", packet->segmentType); byte flags = _stream->readByte(); if (flags == 1) { //uint32 objectStartTime = fragmentOffset; // reused purpose _stream->readByte(); // unknown uint32 dataLength = (packet->segments.size() == 1) ? (_maxPacketSize - (_stream->pos() - packetStartPos) - paddingSize) : _stream->readUint16LE(); uint32 startObjectPos = _stream->pos(); while ((uint32)_stream->pos() < dataLength + startObjectPos) segment.data.push_back(_stream->readStream(_stream->readByte())); } else if (flags == 8) { /* uint32 objectLength = */ _stream->readUint32LE(); /* uint32 objectStartTime = */ _stream->readUint32LE(); uint32 dataLength = 0; if (packet->segments.size() == 1) dataLength = _maxPacketSize - (_stream->pos() - packetStartPos) - fragmentOffset - paddingSize; else if (segmentCount & 0x40) dataLength = _stream->readByte(); else dataLength = _stream->readUint16LE(); _stream->skip(fragmentOffset); segment.data.push_back(_stream->readStream(dataLength)); } else throw Common::Exception("ASFStream::readPacket(): Unknown packet flags 0x%02x", flags); } // Skip any padding _stream->skip(paddingSize); // We just read a packet _curPacket++; if ((uint32)_stream->pos() != packetStartPos + _maxPacketSize) throw Common::Exception("ASFStream::readPacket(): Mismatching packet pos: %d (should be %d)", _stream->pos(), _maxPacketSize + packetStartPos); return packet; }
void ConversationData::load(const Common::String &filename) { Common::File inFile; char buffer[16]; inFile.open(filename); MadsPack convFileUnpacked(&inFile); // **** Section 0: Header ************************************************* Common::SeekableReadStream *convFile = convFileUnpacked.getItemStream(0); _nodeCount = convFile->readUint16LE(); _dialogCount = convFile->readUint16LE(); _messageCount = convFile->readUint16LE(); _textLineCount = convFile->readUint16LE(); _unk2 = convFile->readUint16LE(); _maxImports = convFile->readUint16LE(); _speakerCount = convFile->readUint16LE(); for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) { convFile->read(buffer, 16); _portraits[idx] = buffer; } for (uint idx = 0; idx < MAX_SPEAKERS; ++idx) { _speakerFrame[idx] = convFile->readUint16LE(); } convFile->read(buffer, 14); _speechFile = Common::String(buffer); // Total text length in section 5 _textSize = convFile->readUint32LE(); _commandsSize = convFile->readUint32LE(); // The rest of the section 0 is padding to allow room for a set of pointers // to the contents of the remaining sections loaded into memory as a // continuous data block containing both the header and the sections delete convFile; // **** Section 1: Nodes ************************************************** convFile = convFileUnpacked.getItemStream(1); _nodes.clear(); for (uint i = 0; i < _nodeCount; i++) { ConvNode node; node._index = convFile->readUint16LE(); node._dialogCount = convFile->readUint16LE(); node._unk1 = convFile->readSint16LE(); // TODO node._active = convFile->readSint16LE() != 0; node._unk3 = convFile->readSint16LE(); // TODO _nodes.push_back(node); } delete convFile; // **** Section 2: Dialogs ************************************************ convFile = convFileUnpacked.getItemStream(2); assert(convFile->size() == _dialogCount * 8); _dialogs.resize(_dialogCount); for (uint idx = 0; idx < _dialogCount; ++idx) { _dialogs[idx]._textLineIndex = convFile->readSint16LE(); _dialogs[idx]._speechIndex = convFile->readSint16LE(); _dialogs[idx]._scriptOffset = convFile->readUint16LE(); _dialogs[idx]._scriptSize = convFile->readUint16LE(); } delete convFile; // **** Section 3: Messages *********************************************** convFile = convFileUnpacked.getItemStream(3); assert(convFile->size() == _messageCount * 4); _messages.resize(_messageCount); for (uint idx = 0; idx < _messageCount; ++idx) { _messages[idx]._stringIndex = convFile->readUint16LE(); _messages[idx]._count = convFile->readUint16LE(); } delete convFile; // **** Section 4: Text line offsets ************************************** convFile = convFileUnpacked.getItemStream(4); assert(convFile->size() == _textLineCount * 2); uint16 *textLineOffsets = new uint16[_textLineCount]; // deleted below in section 5 for (uint16 i = 0; i < _textLineCount; i++) textLineOffsets[i] = convFile->readUint16LE(); delete convFile; // **** Section 5: Text lines ********************************************* convFile = convFileUnpacked.getItemStream(5); assert(convFile->size() == _textSize); Common::String textLine; _textLines.resize(_textLineCount); char textLineBuffer[256]; uint16 nextOffset; for (uint16 i = 0; i < _textLineCount; i++) { nextOffset = (i != _textLineCount - 1) ? textLineOffsets[i + 1] : convFile->size(); convFile->read(textLineBuffer, nextOffset - textLineOffsets[i]); _textLines[i] = Common::String(textLineBuffer); } delete[] textLineOffsets; delete convFile; // **** Section 6: Scripts ************************************************ convFile = convFileUnpacked.getItemStream(6); assert(convFile->size() == _commandsSize); for (uint idx = 0; idx < _dialogs.size(); ++idx) { // Move to the correct position for the dialog's script, and create // a memory stream to represent the data for just that script convFile->seek(_dialogs[idx]._scriptOffset); Common::SeekableReadStream *scriptStream = convFile->readStream(_dialogs[idx]._scriptSize); // Pass it to the dialog's script set class to parse into commands _dialogs[idx]._script.load(*scriptStream, _dialogs[idx]._scriptOffset); delete scriptStream; } delete convFile; inFile.close(); }