Exemplo n.º 1
0
void DECFile::load(Common::SeekableSubReadStreamEndian &dec, const Common::String &fileName) {
	dec.skip(2); // Unused

	int16 backdropCount = dec.readUint16();
	int16 layerCount    = dec.readUint16();

	// Sanity checks
	if (backdropCount > 1)
		warning("DECFile::load(): More than one backdrop (%d) in file \"%s\"",
		        backdropCount, fileName.c_str());
	if (layerCount < 1)
		warning("DECFile::load(): Less than one layer (%d) in file \"%s\"",
		        layerCount, fileName.c_str());

	// Load the backdrop
	if (backdropCount > 0) {
		loadBackdrop(dec);

		// We only support one backdrop, skip the rest
		dec.skip((backdropCount - 1) * (13 + (_hasPadding ? 1 : 0)));
	}

	// Load the layers
	_layers.reserve(MAX(0, layerCount - 1));
	for (int i = 0; i < layerCount - 1; i++)
		_layers.push_back(loadLayer(dec));

	// Load the backdrop parts
	if (backdropCount > 0)
		loadParts(dec);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
void Frame::readPaletteInfo(Common::SeekableSubReadStreamEndian &stream) {
	_palette->firstColor = stream.readByte();
	_palette->lastColor = stream.readByte();
	_palette->flags = stream.readByte();
	_palette->speed = stream.readByte();
	_palette->frameCount = stream.readUint16();
	stream.skip(8); //unknown
}
Exemplo n.º 4
0
void DECFile::loadPart(Part &part, Common::SeekableSubReadStreamEndian &dec) {
	part.layer = dec.readByte() - 1;
	part.part  = dec.readByte();

	dec.skip(1); // Unknown

	part.x = dec.readUint16();
	part.y = dec.readUint16();

	part.transp = dec.readByte() != 0;
}
Exemplo n.º 5
0
void DECFile::loadParts(Common::SeekableSubReadStreamEndian &dec) {
	dec.skip(13); // Name
	if (_hasPadding)
		dec.skip(1);

	dec.skip(13); // File?
	if (_hasPadding)
		dec.skip(1);

	uint16 partCount = dec.readUint16();

	_parts.resize(partCount);
	for (PartArray::iterator p = _parts.begin(); p != _parts.end(); ++p)
		loadPart(*p, dec);
}
Exemplo n.º 6
0
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;
}
Exemplo n.º 7
0
void DECFile::loadBackdrop(Common::SeekableSubReadStreamEndian &dec) {
	// Interestingly, DEC files reference "FOO.LBM" instead of "FOO.CMP"
	Common::String file = Util::setExtension(Util::readString(dec, 13), "");
	if (_hasPadding)
		dec.skip(1);

	_backdrop = new CMPFile(_vm, file, _width, _height, _bpp);
}
Exemplo n.º 8
0
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);
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
0
void LBGraphics::setPalette(uint16 id) {
	// Old Living Books games use the old CTBL-style palette format while newer
	// games use the better tPAL format which can store partial palettes.
	if (_vm->isPreMohawk()) {
		Common::SeekableSubReadStreamEndian *ctblStream = _vm->wrapStreamEndian(ID_CTBL, id);
		uint16 colorCount = ctblStream->readUint16();
		byte *palette = new byte[colorCount * 3];

		for (uint16 i = 0; i < colorCount; i++) {
			palette[i * 3 + 0] = ctblStream->readByte();
			palette[i * 3 + 1] = ctblStream->readByte();
			palette[i * 3 + 2] = ctblStream->readByte();
			ctblStream->readByte();
		}

		delete ctblStream;

		_vm->_system->getPaletteManager()->setPalette(palette, 0, colorCount);
		delete[] palette;
	} else {
		GraphicsManager::setPalette(id);
	}
}
Exemplo n.º 11
0
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();
}
Exemplo n.º 12
0
void Frame::renderText(Graphics::ManagedSurface &surface, uint16 spriteID) {
	uint16 castID = _sprites[spriteID]->_castId;

	TextCast *textCast = static_cast<TextCast *>(_vm->_currentScore->_casts[castID]);
	Common::SeekableSubReadStreamEndian *textStream;

	if (_vm->_currentScore->_movieArchive->hasResource(MKTAG('S','T','X','T'), castID + 1024)) {
		textStream = _vm->_currentScore->_movieArchive->getResource(MKTAG('S','T','X','T'), castID + 1024);
	} else {
		textStream = _vm->getSharedSTXT()->getVal(spriteID + 1024);
	}
	/*uint32 unk1 = */ textStream->readUint32();
	uint32 strLen = textStream->readUint32();
	/*uin32 dataLen = */ textStream->readUint32();
	Common::String text;

	for (uint32 i = 0; i < strLen; i++) {
		byte ch = textStream->readByte();
		if (ch == 0x0d) {
			ch = '\n';
		}
		text += ch;
	}

	uint32 rectLeft = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.left;
	uint32 rectTop = static_cast<TextCast *>(_sprites[spriteID]->_cast)->initialRect.top;

	int x = _sprites[spriteID]->_startPoint.x + rectLeft;
	int y = _sprites[spriteID]->_startPoint.y + rectTop;
	int height = _sprites[spriteID]->_height;
	int width = _sprites[spriteID]->_width;

	const char *fontName;

	if (_vm->_currentScore->_fontMap.contains(textCast->fontId)) {
		fontName = _vm->_currentScore->_fontMap[textCast->fontId].c_str();
	} else if ((fontName = _vm->_wm->getFontName(textCast->fontId, textCast->fontSize)) == NULL) {
		warning("Unknown font id %d, falling back to default", textCast->fontId);
		fontName = _vm->_wm->getFontName(0, 12);
	}

	const Graphics::Font *font = _vm->_wm->getFont(fontName, Graphics::FontManager::kBigGUIFont);

	font->drawString(&surface, text, x, y, width, 0);

	if (textCast->borderSize != kSizeNone) {
		uint16 size = textCast->borderSize;

		//Indent from borders, measured in d4
		x -= 1;
		y -= 4;

		height += 4;
		width += 1;

		while (size) {
			surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);
			x--;
			y--;
			height += 2;
			width += 2;
			size--;
		}
	}

	if (textCast->gutterSize != kSizeNone) {
		x -= 1;
		y -= 4;

		height += 4;
		width += 1;
		uint16 size = textCast->gutterSize;

		surface.frameRect(Common::Rect(x, y, x + height, y + width), 0);

		while (size) {
			surface.drawLine(x + width, y, x + width, y + height, 0);
			surface.drawLine(x, y + height, x + width, y + height, 0);
			x++;
			y++;
			size--;
		}
	}
}
Exemplo n.º 13
0
void Frame::readSprite(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
	uint16 spritePosition = (offset - 32) / 16;
	uint16 spriteStart = spritePosition * 16 + 32;

	uint16 fieldPosition = offset - spriteStart;
	uint16 finishPosition = fieldPosition + size;

	Sprite &sprite = *_sprites[spritePosition];

	while (fieldPosition < finishPosition) {
		switch (fieldPosition) {
		case kSpritePositionUnk1:
			/*byte x1 = */ stream.readByte();
			fieldPosition++;
			break;
		case kSpritePositionEnabled:
			sprite._enabled = (stream.readByte() != 0);
			fieldPosition++;
			break;
		case kSpritePositionUnk2:
			/*byte x2 = */ stream.readUint16();
			fieldPosition += 2;
			break;
		case kSpritePositionFlags:
			sprite._flags = stream.readUint16();
			sprite._ink = static_cast<InkType>(sprite._flags & 0x3f);

			if (sprite._flags & 0x40)
				sprite._trails = 1;
			else
				sprite._trails = 0;

			fieldPosition += 2;
			break;
		case kSpritePositionCastId:
			sprite._castId = stream.readUint16();
			fieldPosition += 2;
			break;
		case kSpritePositionY:
			sprite._startPoint.y = stream.readUint16();
			fieldPosition += 2;
			break;
		case kSpritePositionX:
			sprite._startPoint.x = stream.readUint16();
			fieldPosition += 2;
			break;
		case kSpritePositionWidth:
			sprite._width = stream.readUint16();
			fieldPosition += 2;
			break;
		case kSpritePositionHeight:
			sprite._height = stream.readUint16();
			fieldPosition += 2;
			break;
		default:
			//end cycle, go to next sprite channel
			readSprite(stream, spriteStart + 16, finishPosition - fieldPosition);
			fieldPosition = finishPosition;
			break;
		}
	}
}
Exemplo n.º 14
0
void Frame::readMainChannels(Common::SeekableSubReadStreamEndian &stream, uint16 offset, uint16 size) {
	uint16 finishPosition = offset + size;

	while (offset < finishPosition) {
		switch(offset) {
		case kScriptIdPosition:
			_actionId = stream.readByte();
			offset++;
			break;
		case kSoundType1Position:
			_soundType1 = stream.readByte();
			offset++;
			break;
		case kTransFlagsPosition: {
			uint8 transFlags = stream.readByte();
			if (transFlags & 0x80)
				_transArea = 1;
			else
				_transArea = 0;
			_transDuration = transFlags & 0x7f;
			offset++;
			}
			break;
		case kTransChunkSizePosition:
			_transChunkSize = stream.readByte();
			offset++;
			break;
		case kTempoPosition:
			_tempo = stream.readByte();
			offset++;
			break;
		case kTransTypePosition:
			_transType = static_cast<TransitionType>(stream.readByte());
			offset++;
			break;
		case kSound1Position:
			_sound1 = stream.readUint16();
			offset+=2;
			break;
		case kSkipFrameFlagsPosition:
			_skipFrameFlag = stream.readByte();
			offset++;
			break;
		case kBlendPosition:
			_blend = stream.readByte();
			offset++;
			break;
		case kSound2Position:
			_sound2 = stream.readUint16();
			offset += 2;
			break;
		case kSound2TypePosition:
			_soundType2 = stream.readByte();
			offset += 1;
			break;
		case kPaletePosition:
			if (stream.readUint16())
				readPaletteInfo(stream);
			offset += 16;
			break;
		default:
			offset++;
			stream.readByte();
			debugC(kDebugLoading, "Frame::readMainChannels: Field Position %d, Finish Position %d", offset, finishPosition);
			break;
		}
	}
}
Exemplo n.º 15
0
Stxt::Stxt(Common::SeekableSubReadStreamEndian &textStream) {
	// TODO: Side effects on textStream make this a little hard to understand in context?
	uint32 unk1 = textStream.readUint32();
	uint32 strLen = textStream.readUint32();
	uint32 dataLen = textStream.readUint32();
	Common::String text;

	for (uint32 i = 0; i < strLen; i++) {
		byte ch = textStream.readByte();
		if (ch == 0x0d) {
			ch = '\n';
		}
		text += ch;
	}
	debugC(3, kDebugText, "Stxt init: unk1: %d strLen: %d dataLen: %d textlen: %u", unk1, strLen, dataLen, text.size());
	if (strLen < 200)
		debugC(3, kDebugText, "text: '%s'", text.c_str());

	uint16 formattingCount = textStream.readUint16();
	uint32 prevPos = 0;

	while (formattingCount) {
		uint32 formatStartOffset = textStream.readUint32();
		uint16 unk1f = textStream.readUint16();
		uint16 unk2f = textStream.readUint16();

		_fontId = textStream.readUint16();
		_textSlant = textStream.readByte();
		byte unk3f = textStream.readByte();
		_fontSize = textStream.readUint16();

		_palinfo1 = textStream.readUint16();
		_palinfo2 = textStream.readUint16();
		_palinfo3 = textStream.readUint16();

		debugC(3, kDebugText, "Stxt init: formattingCount: %u, formatStartOffset: %d, unk1: %d unk2: %d, fontId: %d, textSlant: %d",
			   formattingCount, formatStartOffset, unk1f, unk2f, _fontId, _textSlant);

		debugC(3, kDebugText, "        unk3: %d, fontSize: %d, p0: %x p1: %x p2: %x", unk3f, _fontSize, _palinfo1, _palinfo2, _palinfo3);

		assert(prevPos <= formatStartOffset);  // If this is triggered, we have to implement sorting

		while (prevPos != formatStartOffset) {
			char f = text.firstChar();
			_ftext += text.firstChar();
			text.deleteChar(0);

			if (f == '\001')    // Insert two \001s as a replacement
				_ftext += '\001';

			prevPos++;

			debugCN(4, kDebugText, "%c", f);
		}

		debugCN(4, kDebugText, "*");

		_ftext += Common::String::format("\001\015%c%c%c%c%c%c%c%c%c%c%c%c",
										 (_fontId >> 8) & 0xff, _fontId & 0xff,
										 _textSlant & 0xff, unk3f & 0xff,
										 (_fontSize >> 8) & 0xff, _fontSize & 0xff,
										 (_palinfo1 >> 8) & 0xff, _palinfo1 & 0xff,
										 (_palinfo2 >> 8) & 0xff, _palinfo2 & 0xff,
										 (_palinfo3 >> 8) & 0xff, _palinfo3 & 0xff);

		formattingCount--;
	}

	debugC(4, kDebugText, "%s", text.c_str());
	_ftext += text;
}