bool SaveContainer::write(Common::WriteStream &stream) const { // Write the header if (!_header.write(stream)) return false; // Write the part count stream.writeUint32LE(_partCount); // Iterate over all parts for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it) { // Part doesn't actually exist => error if (!*it) return false; // Write the part's size stream.writeUint32LE((*it)->size); } if (!flushStream(stream)) return false; // Iterate over all parts for (PartConstIterator it = _parts.begin(); it != _parts.end(); ++it) { Part * const &p = *it; // Write the part if (stream.write(p->data, p->size) != p->size) return false; } return flushStream(stream); }
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 SaveHeader::write(Common::WriteStream &stream) const { stream.writeUint32BE(kID1); stream.writeUint32BE(kID2); stream.writeUint32BE(_type); stream.writeUint32LE(_version); stream.writeUint32LE(_size); return flushStream(stream); }
void LocString::writeLocString(Common::WriteStream &stream, bool withNullTerminate) const { for (StringMap::const_iterator iter = _strings.begin(); iter != _strings.end() ; iter++) { stream.writeUint32LE((*iter).first); stream.writeUint32LE((*iter).second.size()); stream.write((*iter).second.c_str(), (*iter).second.size()); if (withNullTerminate) stream.writeByte(0); } }
void MainWindow::exportWAVImpl(Sound::AudioStream *sound, Common::WriteStream &wav) { assert(sound); const uint16 channels = sound->getChannels(); const uint32 rate = sound->getRate(); std::deque<SoundBuffer> buffers; uint64 length = getSoundLength(sound); if (length != Sound::RewindableAudioStream::kInvalidLength) buffers.resize((length / (SoundBuffer::kBufferSize / channels)) + 1); uint32 samples = 0; std::deque<SoundBuffer>::iterator buffer = buffers.begin(); while (!sound->endOfStream()) { if (buffer == buffers.end()) { buffers.push_back(SoundBuffer()); buffer = --buffers.end(); } buffer->samples = sound->readBuffer(buffer->buffer, SoundBuffer::kBufferSize); if (buffer->samples > 0) samples += buffer->samples; ++buffer; } samples /= channels; const uint32 dataSize = samples * channels * 2; const uint32 byteRate = rate * channels * 2; const uint16 blockAlign = channels * 2; wav.writeUint32BE(MKTAG('R', 'I', 'F', 'F')); wav.writeUint32LE(36 + dataSize); wav.writeUint32BE(MKTAG('W', 'A', 'V', 'E')); wav.writeUint32BE(MKTAG('f', 'm', 't', ' ')); wav.writeUint32LE(16); wav.writeUint16LE(1); wav.writeUint16LE(channels); wav.writeUint32LE(rate); wav.writeUint32LE(byteRate); wav.writeUint16LE(blockAlign); wav.writeUint16LE(16); wav.writeUint32BE(MKTAG('d', 'a', 't', 'a')); wav.writeUint32LE(dataSize); for (std::deque<SoundBuffer>::const_iterator b = buffers.begin(); b != buffers.end(); ++b) for (int i = 0; i < b->samples; i++) wav.writeUint16LE(b->buffer[i]); }
bool SavePartInfo::write(Common::WriteStream &stream) const { if (!_header.write(stream)) return false; stream.writeUint32LE(_gameID); stream.writeUint32LE(_gameVersion); stream.writeByte(_endian); stream.writeUint32LE(_varCount); stream.writeUint32LE(_descMaxLength); if (stream.write(_desc, _descMaxLength) != _descMaxLength) return false; return flushStream(stream); }
bool BladeRunnerEngine::saveGame(Common::WriteStream &stream, const Graphics::Surface &thumbnail) { if (!playerHasControl() || _sceneScript->isInsideScript() || _aiScripts->isInsideScript()) { return false; } Common::MemoryWriteStreamDynamic memoryStream(DisposeAfterUse::YES); SaveFileWriteStream s(memoryStream); s.write(thumbnail.getPixels(), SaveFileManager::kThumbnailSize); s.writeFloat(1.0f); _settings->save(s); _scene->save(s); _scene->_exits->save(s); _scene->_regions->save(s); _scene->_set->save(s); for (uint i = 0; i != _gameInfo->getGlobalVarCount(); ++i) { s.writeInt(_gameVars[i]); } _music->save(s); // _audioPlayer->save(s) // zero func // _audioSpeech->save(s) // zero func _combat->save(s); _gameFlags->save(s); _items->save(s); _sceneObjects->save(s); _ambientSounds->save(s); _overlays->save(s); _spinner->save(s); _scores->save(s); _dialogueMenu->save(s); _obstacles->save(s); _actorDialogueQueue->save(s); _waypoints->save(s); for (uint i = 0; i != _gameInfo->getActorCount(); ++i) { _actors[i]->save(s); int animationState, animationFrame, animationStateNext, nextAnimation; _aiScripts->queryAnimationState(i, &animationState, &animationFrame, &animationStateNext, &nextAnimation); s.writeInt(animationState); s.writeInt(animationFrame); s.writeInt(animationStateNext); s.writeInt(nextAnimation); } _actors[kActorVoiceOver]->save(s); _policeMaze->save(s); _crimesDatabase->save(s); s.finalize(); stream.writeUint32LE(memoryStream.size() + 4); stream.write(memoryStream.getData(), memoryStream.size()); stream.flush(); return true; }
bool SavePartSprite::write(Common::WriteStream &stream) const { if (!_header.write(stream)) return false; // The sprite's dimensions stream.writeUint32LE(_width); stream.writeUint32LE(_height); stream.writeByte(_trueColor); // Sprite data if (stream.write(_dataSprite, _spriteSize) != _spriteSize) return false; // Palette data if (stream.write(_dataPalette, 768) != 768) return false; return flushStream(stream); }
void GameState::writeState(uint32 sceneId, uint32 threadId) { Common::WriteStream *writeStream = newWriteStream(); writeStream->writeUint32LE(sceneId); writeStream->writeUint32LE(threadId); writeStateInternal(writeStream); }
void TwoDAFile::writeBinary(Common::WriteStream &out) const { const size_t columnCount = _headers.size(); const size_t rowCount = _rows.size(); const size_t cellCount = columnCount * rowCount; out.writeString("2DA V2.b\n"); // Write the column headers for (std::vector<Common::UString>::const_iterator h = _headers.begin(); h != _headers.end(); ++h) { out.writeString(*h); out.writeByte('\t'); } out.writeByte('\0'); // Write the row indices out.writeUint32LE((uint32) rowCount); for (size_t i = 0; i < rowCount; i++) { out.writeString(Common::composeString(i)); out.writeByte('\t'); } /* Deduplicate cell data strings. Binary 2DA files don't store the * data for each cell directly: instead, each cell contains an offset * into a data array. This way, cells with the same data only need to * to store this data once. * * The original binary 2DA files in KotOR/KotOR2 make extensive use * of that, and we should do this as well. * * Basically, this involves going through each cell, and looking up * if we already saved this particular piece of data. If not, save * it, otherwise only remember the offset. There's no need to be * particularly smart about it, so we're just doing it the naive * O(n^2) way. */ std::vector<Common::UString> data; std::vector<size_t> offsets; data.reserve(cellCount); offsets.reserve(cellCount); size_t dataSize = 0; std::vector<size_t> cells; cells.reserve(cellCount); for (size_t i = 0; i < rowCount; i++) { assert(_rows[i]); for (size_t j = 0; j < columnCount; j++) { const Common::UString cell = _rows[i]->getString(j); // Do we already know about this cell data string? size_t foundCell = SIZE_MAX; for (size_t k = 0; k < data.size(); k++) { if (data[k] == cell) { foundCell = k; break; } } // If not, add it to the cell data array if (foundCell == SIZE_MAX) { foundCell = data.size(); data.push_back(cell); offsets.push_back(dataSize); dataSize += data.back().size() + 1; if (dataSize > 65535) throw Common::Exception("TwoDAFile::writeBinary(): Cell data size overflow"); } // Remember the offset to the cell data array cells.push_back(offsets[foundCell]); } } // Write cell data offsets for (std::vector<size_t>::const_iterator c = cells.begin(); c != cells.end(); ++c) out.writeUint16LE((uint16) *c); // Size of the all cell data strings out.writeUint16LE((uint16) dataSize); // Write cell data strings for (std::vector<Common::UString>::const_iterator d = data.begin(); d != data.end(); ++d) { out.writeString(*d); out.writeByte('\0'); } }