Example #1
0
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);
}
Example #2
0
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());
		}
	}
}
Example #3
0
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);
}
Example #4
0
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);
	}
}
Example #5
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]);
}
Example #6
0
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);
}
Example #7
0
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;
}
Example #8
0
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);
}
Example #9
0
void GameState::writeState(uint32 sceneId, uint32 threadId) {
	Common::WriteStream *writeStream = newWriteStream();
	writeStream->writeUint32LE(sceneId);
	writeStream->writeUint32LE(threadId);
	writeStateInternal(writeStream);
}
Example #10
0
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');
	}
}