Пример #1
0
void DarkMoonEngine::loadMonsterDecoration(const char *file, int16 monsterIndex) {
	Common::SeekableReadStream *s = _res->createReadStream(Common::String::format("%s.dcr", file));
	if (!s)
		return;

	int len = s->readUint16LE();

	for (int i = 0; i < len; i++) {
		for (int ii = 0; ii < 6; ii++) {
			uint8 dc[6];
			s->read(dc, 6);
			if (!dc[2] || !dc[3])
				continue;

			SpriteDecoration *m = &_monsterDecorations[i * 6 + ii + monsterIndex];

			m->shp = _screen->encodeShape(dc[0], dc[1], dc[2], dc[3]);
			m->x = (int8)dc[4];
			m->y = (int8)dc[5];
		}
	}

	delete s;
}
Пример #2
0
bool StaticResource::loadSpellData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
	size = stream.size() / 28;
	SpellProperty *spellData = new SpellProperty[size];

	for (int i = 0; i < size; i++) {
		SpellProperty *t = &spellData[i];

		t->spellNameCode = stream.readUint16LE();
		for (int ii = 0; ii < 4; ii++)
			t->mpRequired[ii] = stream.readUint16LE();
		t->field_a = stream.readUint16LE();
		t->field_c = stream.readUint16LE();
		for (int ii = 0; ii < 4; ii++)
			t->hpRequired[ii] = stream.readUint16LE();
		t->field_16 = stream.readUint16LE();
		t->field_18 = stream.readUint16LE();
		t->flags = stream.readUint16LE();
	};

	ptr = spellData;
	return true;
}
Пример #3
0
bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate, byte &flags, uint16 *wavType, int *blockAlign_) {
	const int32 initialPos = stream.pos();
	byte buf[4+1];

	buf[4] = 0;

	stream.read(buf, 4);
	if (memcmp(buf, "RIFF", 4) != 0) {
		warning("getWavInfo: No 'RIFF' header");
		return false;
	}

	int32 wavLength = stream.readUint32LE();

	stream.read(buf, 4);
	if (memcmp(buf, "WAVE", 4) != 0) {
		warning("getWavInfo: No 'WAVE' header");
		return false;
	}

	stream.read(buf, 4);
	if (memcmp(buf, "fmt ", 4) != 0) {
		warning("getWavInfo: No 'fmt' header");
		return false;
	}

	uint32 fmtLength = stream.readUint32LE();
	if (fmtLength < 16) {
		// A valid fmt chunk always contains at least 16 bytes
		warning("getWavInfo: 'fmt' header is too short");
		return false;
	}

	// Next comes the "type" field of the fmt header. Some typical
	// values for it:
	// 1  -> uncompressed PCM
	// 17 -> IMA ADPCM compressed WAVE
	// See <http://www.saettler.com/RIFFNEW/RIFFNEW.htm> for a more complete
	// list of common WAVE compression formats...
	uint16 type = stream.readUint16LE();	// == 1 for PCM data
	uint16 numChannels = stream.readUint16LE();	// 1 for mono, 2 for stereo
	uint32 samplesPerSec = stream.readUint32LE();	// in Hz
	uint32 avgBytesPerSec = stream.readUint32LE();	// == SampleRate * NumChannels * BitsPerSample/8

	uint16 blockAlign = stream.readUint16LE();	// == NumChannels * BitsPerSample/8
	uint16 bitsPerSample = stream.readUint16LE();	// 8, 16 ...
	// 8 bit data is unsigned, 16 bit data signed


	if (wavType != 0)
		*wavType = type;

	if (blockAlign_ != 0)
		*blockAlign_ = blockAlign;
#if 0
	debug("WAVE information:");
	debug("  total size: %d", wavLength);
	debug("  fmt size: %d", fmtLength);
	debug("  type: %d", type);
	debug("  numChannels: %d", numChannels);
	debug("  samplesPerSec: %d", samplesPerSec);
	debug("  avgBytesPerSec: %d", avgBytesPerSec);
	debug("  blockAlign: %d", blockAlign);
	debug("  bitsPerSample: %d", bitsPerSample);
#endif

	if (type != 1 && type != 2 && type != 17) {
		warning("getWavInfo: only PCM, MS ADPCM or IMA ADPCM data is supported (type %d)", type);
		return false;
	}

	if (blockAlign != numChannels * bitsPerSample / 8 && type != 2) {
		debug(0, "getWavInfo: blockAlign is invalid");
	}

	if (avgBytesPerSec != samplesPerSec * blockAlign && type != 2) {
		debug(0, "getWavInfo: avgBytesPerSec is invalid");
	}

	// Prepare the return values.
	rate = samplesPerSec;

	flags = 0;
	if (bitsPerSample == 8)		// 8 bit data is unsigned
		flags |= Audio::FLAG_UNSIGNED;
	else if (bitsPerSample == 16)	// 16 bit data is signed little endian
		flags |= (Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN);
	else if (bitsPerSample == 4 && (type == 2 || type == 17))
		flags |= Audio::FLAG_16BITS;
	else {
		warning("getWavInfo: unsupported bitsPerSample %d", bitsPerSample);
		return false;
	}

	if (numChannels == 2)
		flags |= Audio::FLAG_STEREO;
	else if (numChannels != 1) {
		warning("getWavInfo: unsupported number of channels %d", numChannels);
		return false;
	}

	// It's almost certainly a WAV file, but we still need to find its
	// 'data' chunk.

	// Skip over the rest of the fmt chunk.
	int offset = fmtLength - 16;

	do {
		stream.seek(offset, SEEK_CUR);
		if (stream.pos() >= initialPos + wavLength + 8) {
			warning("getWavInfo: Can't find 'data' chunk");
			return false;
		}
		stream.read(buf, 4);
		offset = stream.readUint32LE();

#if 0
		debug("  found a '%s' tag of size %d", buf, offset);
#endif
	} while (memcmp(buf, "data", 4) != 0);

	// Stream now points at 'offset' bytes of sample data...
	size = offset;

	return true;
}
Пример #4
0
bool WinFont::loadFromFNT(Common::SeekableReadStream &stream) {
	uint16 version = stream.readUint16LE();

	// We'll accept Win1, Win2, and Win3 fonts
	if (version != 0x100 && version != 0x200 && version != 0x300) {
		warning("Bad FNT version %04x", version);
		return false;
	}

	/* uint32 size = */ stream.readUint32LE();
	stream.skip(60); // Copyright info
	uint16 fontType = stream.readUint16LE();
	/* uint16 points = */ stream.readUint16LE();
	/* uint16 vertRes = */ stream.readUint16LE();
	/* uint16 horizRes = */ stream.readUint16LE();
	/* uint16 ascent = */ stream.readUint16LE();
	/* uint16 internalLeading = */ stream.readUint16LE();
	/* uint16 externalLeading = */ stream.readUint16LE();
	/* byte italic = */ stream.readByte();
	/* byte underline = */ stream.readByte();
	/* byte strikeOut = */ stream.readByte();
	/* uint16 weight = */ stream.readUint16LE();
	/* byte charSet = */ stream.readByte();
	uint16 pixWidth = stream.readUint16LE();
	_pixHeight = stream.readUint16LE();
	/* byte pitchAndFamily = */ stream.readByte();
	/* uint16 avgWidth = */ stream.readUint16LE();
	_maxWidth = stream.readUint16LE();
	_firstChar = stream.readByte();
	_lastChar = stream.readByte();
	_defaultChar = stream.readByte();
	/* byte breakChar = */ stream.readByte();
	/* uint16 widthBytes = */ stream.readUint16LE();
	/* uint32 device = */ stream.readUint32LE();
	/* uint32 face = */ stream.readUint32LE();
	/* uint32 bitsPointer = */ stream.readUint32LE();
	uint32 bitsOffset = stream.readUint32LE();
	/* byte reserved = */ stream.readByte();

	if (version == 0x100) {
		// Seems Win1 has an extra byte?
		stream.readByte();
	} else if (version == 0x300) {
		// For Windows 3.0, Microsoft added 6 new fields. All of which are
		// guaranteed to be 0. Which leads to the question: Why add these at all?

		/* uint32 flags = */ stream.readUint32LE();
		/* uint16 aSpace = */ stream.readUint16LE();
		/* uint16 bSpace = */ stream.readUint16LE();
		/* uint16 cSpace = */ stream.readUint16LE();
		/* uint32 colorPointer = */ stream.readUint32LE();
		stream.skip(16); // Reserved
	}

	// Begin loading in the glyphs
	_glyphCount = (_lastChar - _firstChar) + 2;
	_glyphs = new GlyphEntry[_glyphCount];

	for (uint16 i = 0; i < _glyphCount; i++) {
		_glyphs[i].charWidth = stream.readUint16LE();

		// Use the default if present
		if (pixWidth)
			_glyphs[i].charWidth = pixWidth;

		_glyphs[i].offset = (version == 0x300) ? stream.readUint32LE() : stream.readUint16LE();

		// Seems the offsets in the Win1 font format are based on bitsOffset
		if (version == 0x100)
			_glyphs[i].offset += bitsOffset;
	}

	// TODO: Currently only raster fonts are supported!
	if (fontType & 1) {
		warning("Vector FNT files not supported yet");
		return false;
	}

	// Read in the bitmaps for the raster images
	for (uint16 i = 0; i < _glyphCount - 1; i++) {
		stream.seek(_glyphs[i].offset);

		_glyphs[i].bitmap = new byte[_pixHeight * _glyphs[i].charWidth];

		// Calculate the amount of columns
		byte colCount = (_glyphs[i].charWidth + 7) / 8;

		for (uint16 j = 0; j < colCount; j++) {
			for (uint16 k = 0; k < _pixHeight; k++) {
				byte x = stream.readByte();
				uint offset = j * 8 + k * _glyphs[i].charWidth;

				for (byte l = 0; l < 8 && j * 8 + l < _glyphs[i].charWidth; l++)
					_glyphs[i].bitmap[offset + l] = (x & (1 << (7 - l))) ? 1 : 0;
			}
		}

#if 0
		// Debug print
		debug("Character %02x '%c' at %08x", indexToCharacter(i), indexToCharacter(i), _glyphs[i].offset);
		for (uint16 j = 0; j < _pixHeight; j++) {
			for (uint16 k = 0; k < _glyphs[i].charWidth; k++)
				debugN("%c", _glyphs[i].bitmap[k + j * _glyphs[i].charWidth] ? 'X' : ' ');

			debugN("\n");
		}
#endif
	}

	return true;
}
Пример #5
0
void CUP_Player::handleHEAD(Common::SeekableReadStream &dataStream, uint32 dataSize) {
	_playbackRate = dataStream.readUint16LE();
	_width = dataStream.readUint16LE();
	_height = dataStream.readUint16LE();
}
Пример #6
0
void TPC::readHeader(Common::SeekableReadStream &tpc, byte &encoding) {
	// Number of bytes for the pixel data in one full image
	uint32 dataSize = tpc.readUint32LE();

	tpc.skip(4); // Some float

	// Image dimensions
	uint32 width  = tpc.readUint16LE();
	uint32 height = tpc.readUint16LE();

	if ((width >= 0x8000) || (height >= 0x8000))
		throw Common::Exception("Unsupported image dimensions (%ux%u)", width, height);

	// How's the pixel data encoded?
	encoding = tpc.readByte();

	// Number of mip maps in the image
	size_t mipMapCount = tpc.readByte();

	tpc.skip(114); // Reserved

	uint32 minDataSize = 0;
	if (dataSize == 0) {
		// Uncompressed

		if        (encoding == kEncodingGray) {
			// 8bpp grayscale

			_format = kPixelFormatR8G8B8;

			minDataSize = 1;
			dataSize    = width * height;

		} else if (encoding == kEncodingRGB) {
			// RGB, no alpha channel

			_format = kPixelFormatR8G8B8;

			minDataSize = 3;
			dataSize    = width * height * 3;

		} else if (encoding == kEncodingRGBA) {
			// RGBA, alpha channel

			_format = kPixelFormatR8G8B8A8;

			minDataSize = 4;
			dataSize    = width * height * 4;

		} else if (encoding == kEncodingSwizzledBGRA) {
			// BGRA, alpha channel, texture memory layout is "swizzled"

			_format = kPixelFormatB8G8R8A8;

			minDataSize = 4;
			dataSize    = width * height * 4;

		} else
			throw Common::Exception("Unknown TPC raw encoding: %d (%d), %dx%d, %u", encoding, dataSize, width, height, (uint) mipMapCount);

	} else if (encoding == kEncodingRGB) {
		// S3TC DXT1

		_format = kPixelFormatDXT1;

		minDataSize = 8;

		checkCubeMap(width, height);

		if (dataSize != ((width * height) / 2))
			throw Common::Exception("Invalid data size for a texture of %ux%u pixels and format %u",
			                        width, height, encoding);

	} else if (encoding == kEncodingRGBA) {
		// S3TC DXT5

		_format = kPixelFormatDXT5;

		minDataSize = 16;

		checkCubeMap(width, height);

		if (dataSize != (width * height))
			throw Common::Exception("Invalid data size for a texture of %ux%u pixels and format %u",
			                        width, height, encoding);

	} else
		throw Common::Exception("Unknown TPC encoding: %d (%d)", encoding, dataSize);

	if (!hasValidDimensions(_format, width, height))
		throw Common::Exception("Invalid dimensions (%dx%d) for format %d", width, height, _format);

	const size_t fullImageDataSize = getDataSize(_format, width, height);

	size_t fullDataSize = tpc.size() - 128;
	if (fullDataSize < (_layerCount * fullImageDataSize))
		throw Common::Exception("Image wouldn't fit into data");

	_mipMaps.reserve(mipMapCount * _layerCount);

	size_t layerCount;
	for (layerCount = 0; layerCount < _layerCount; layerCount++) {
		uint32 layerWidth  = width;
		uint32 layerHeight = height;
		uint32 layerSize   = dataSize;

		for (size_t i = 0; i < mipMapCount; i++) {
			MipMap *mipMap = new MipMap;

			mipMap->width  = MAX<uint32>(layerWidth,  1);
			mipMap->height = MAX<uint32>(layerHeight, 1);

			mipMap->size = MAX<uint32>(layerSize, minDataSize);

			mipMap->data = 0;

			const size_t mipMapDataSize = getDataSize(_format, mipMap->width, mipMap->height);

			if ((fullDataSize < mipMap->size) || (mipMap->size < mipMapDataSize)) {
				// Wouldn't fit
				delete mipMap;
				break;
			}

			fullDataSize -= mipMap->size;

			_mipMaps.push_back(mipMap);

			layerWidth  >>= 1;
			layerHeight >>= 1;
			layerSize   >>= 2;

			if ((layerWidth < 1) && (layerHeight < 1))
				break;
		}
	}

	if ((layerCount != _layerCount) || ((_mipMaps.size() % _layerCount) != 0))
		throw Common::Exception("Failed to correctly read all texture layers (%u, %u, %u, %u)",
		                        (uint) _layerCount, (uint) mipMapCount,
		                        (uint) layerCount, (uint) _mipMaps.size());
}
Пример #7
0
bool StaticResource::loadCharData(Common::SeekableReadStream &stream, void *&ptr, int &size) {
	size = stream.size() / 130;
	LoLCharacter *charData = new LoLCharacter[size];

	for (int i = 0; i < size; i++) {
		LoLCharacter *t = &charData[i];

		t->flags = stream.readUint16LE();
		stream.read(t->name, 11);
		t->raceClassSex = stream.readByte();
		t->id = stream.readSint16LE();
		t->curFaceFrame = stream.readByte();
		t->tempFaceFrame = stream.readByte();
		t->screamSfx = stream.readByte();
		stream.readUint32LE();
		for (int ii = 0; ii < 8; ii++)
			t->itemsMight[ii] = stream.readUint16LE();
		for (int ii = 0; ii < 8; ii++)
			t->protectionAgainstItems[ii] = stream.readUint16LE();
		t->itemProtection = stream.readUint16LE();
		t->hitPointsCur = stream.readSint16LE();
		t->hitPointsMax = stream.readUint16LE();
		t->magicPointsCur = stream.readSint16LE();
		t->magicPointsMax = stream.readUint16LE();
		t->field_41 = stream.readByte();
		t->damageSuffered = stream.readUint16LE();
		t->weaponHit = stream.readUint16LE();
		t->totalMightModifier = stream.readUint16LE();
		t->totalProtectionModifier = stream.readUint16LE();
		t->might = stream.readUint16LE();
		t->protection = stream.readUint16LE();
		t->nextAnimUpdateCountdown = stream.readSint16LE();
		for (int ii = 0; ii < 11; ii++)
			t->items[ii] = stream.readUint16LE();
		for (int ii = 0; ii < 3; ii++)
			t->skillLevels[ii] = stream.readByte();
		for (int ii = 0; ii < 3; ii++)
			t->skillModifiers[ii] = stream.readByte();
		for (int ii = 0; ii < 3; ii++)
			t->experiencePts[ii] = stream.readUint32LE();
		for (int ii = 0; ii < 5; ii++)
			t->characterUpdateEvents[ii] = stream.readByte();
		for (int ii = 0; ii < 5; ii++)
			t->characterUpdateDelay[ii] = stream.readByte();
	};

	ptr = charData;
	return true;
}
Пример #8
0
void TPC::readHeader(Common::SeekableReadStream &tpc, byte &encoding) {
	// Number of bytes for the pixel data in one full image
	uint32 dataSize = tpc.readUint32LE();

	tpc.skip(4); // Some float

	// Image dimensions
	uint32 width  = tpc.readUint16LE();
	uint32 height = tpc.readUint16LE();

	// How's the pixel data encoded?
	encoding = tpc.readByte();

	// Number of mip maps in the image
	byte mipMapCount = tpc.readByte();

	tpc.skip(114); // Reserved

	uint32 minDataSize = 0;
	if (dataSize == 0) {
		// Uncompressed

		if        (encoding == kEncodingGray) {
			// 8bpp grayscale

			_format = kPixelFormatR8G8B8;

			minDataSize = 1;
			dataSize    = width * height;

		} else if (encoding == kEncodingRGB) {
			// RGB, no alpha channel

			_format = kPixelFormatR8G8B8;

			minDataSize = 3;
			dataSize    = width * height * 3;

		} else if (encoding == kEncodingRGBA) {
			// RGBA, alpha channel

			_format = kPixelFormatR8G8B8A8;

			minDataSize = 4;
			dataSize    = width * height * 4;

		} else if (encoding == kEncodingSwizzledBGRA) {
			// BGRA, alpha channel, texture memory layout is "swizzled"

			_format = kPixelFormatB8G8R8A8;

			minDataSize = 4;
			dataSize    = width * height * 4;

		} else
			throw Common::Exception("Unknown TPC raw encoding: %d (%d), %dx%d, %d", encoding, dataSize, width, height, mipMapCount);

	} else if (encoding == kEncodingRGB) {
		// S3TC DXT1

		_format = kPixelFormatDXT1;

		minDataSize = 8;

	} else if (encoding == kEncodingRGBA) {
		// S3TC DXT5

		_format = kPixelFormatDXT5;

		minDataSize = 16;

	} else
		throw Common::Exception("Unknown TPC encoding: %d (%d)", encoding, dataSize);

	size_t fullDataSize = tpc.size() - 128;

	_mipMaps.reserve(mipMapCount);
	for (uint32 i = 0; i < mipMapCount; i++) {
		MipMap *mipMap = new MipMap;

		mipMap->width  = MAX<uint32>(width,  1);
		mipMap->height = MAX<uint32>(height, 1);

		mipMap->size = MAX<uint32>(dataSize, minDataSize);

		mipMap->data = 0;

		if (fullDataSize < mipMap->size) {
			// Wouldn't fit
			delete mipMap;
			break;
		}

		fullDataSize -= mipMap->size;

		_mipMaps.push_back(mipMap);

		width    >>= 1;
		height   >>= 1;
		dataSize >>= 2;

		if ((width < 1) && (height < 1))
			break;
	}

}
Пример #9
0
void SmushPlayer::handleIACT(int32 subSize, Common::SeekableReadStream &b) {
	debugC(DEBUG_SMUSH, "SmushPlayer::IACT()");
	assert(subSize >= 8);

	int code = b.readUint16LE();
	int flags = b.readUint16LE();
	int unknown = b.readSint16LE();
	int track_flags = b.readUint16LE();

	if ((code != 8) && (flags != 46)) {
		_vm->_insane->procIACT(_dst, 0, 0, 0, b, 0, 0, code, flags, unknown, track_flags);
		return;
	}

	if (_compressedFileMode) {
		return;
	}

	assert(flags == 46 && unknown == 0);
	int track_id = b.readUint16LE();
	int index = b.readUint16LE();
	int nbframes = b.readUint16LE();
	int32 size = b.readUint32LE();
	int32 bsize = subSize - 18;

	if (_vm->_game.id != GID_CMI) {
		int32 track = track_id;
		if (track_flags == 1) {
			track = track_id + 100;
		} else if (track_flags == 2) {
			track = track_id + 200;
		} else if (track_flags == 3) {
			track = track_id + 300;
		} else if ((track_flags >= 100) && (track_flags <= 163)) {
			track = track_id + 400;
		} else if ((track_flags >= 200) && (track_flags <= 263)) {
			track = track_id + 500;
		} else if ((track_flags >= 300) && (track_flags <= 363)) {
			track = track_id + 600;
		} else {
			error("SmushPlayer::handleIACT(): bad track_flags: %d", track_flags);
		}
		debugC(DEBUG_SMUSH, "SmushPlayer::handleIACT(): %d, %d, %d", track, index, track_flags);

		SmushChannel *c = _smixer->findChannel(track);
		if (c == 0) {
			c = new ImuseChannel(track);
			_smixer->addChannel(c);
		}
		if (index == 0)
			c->setParameters(nbframes, size, track_flags, unknown, 0);
		else
			c->checkParameters(index, nbframes, size, track_flags, unknown);
		c->appendData(b, bsize);
	} else {
		// TODO: Move this code into another SmushChannel subclass?
		byte *src = (byte *)malloc(bsize);
		b.read(src, bsize);
		byte *d_src = src;
		byte value;

		while (bsize > 0) {
			if (_IACTpos >= 2) {
				int32 len = READ_BE_UINT16(_IACToutput) + 2;
				len -= _IACTpos;
				if (len > bsize) {
					memcpy(_IACToutput + _IACTpos, d_src, bsize);
					_IACTpos += bsize;
					bsize = 0;
				} else {
					byte *output_data = (byte *)malloc(4096);

					memcpy(_IACToutput + _IACTpos, d_src, len);
					byte *dst = output_data;
					byte *d_src2 = _IACToutput;
					d_src2 += 2;
					int32 count = 1024;
					byte variable1 = *d_src2++;
					byte variable2 = variable1 / 16;
					variable1 &= 0x0f;
					do {
						value = *(d_src2++);
						if (value == 0x80) {
							*dst++ = *d_src2++;
							*dst++ = *d_src2++;
						} else {
							int16 val = (int8)value << variable2;
							*dst++ = val >> 8;
							*dst++ = (byte)(val);
						}
						value = *(d_src2++);
						if (value == 0x80) {
							*dst++ = *d_src2++;
							*dst++ = *d_src2++;
						} else {
							int16 val = (int8)value << variable1;
							*dst++ = val >> 8;
							*dst++ = (byte)(val);
						}
					} while (--count);

					if (!_IACTstream) {
						_IACTstream = Audio::makeQueuingAudioStream(22050, true);
						_vm->_mixer->playStream(Audio::Mixer::kSFXSoundType, &_IACTchannel, _IACTstream);
					}
					_IACTstream->queueBuffer(output_data, 0x1000, DisposeAfterUse::YES, Audio::FLAG_STEREO | Audio::FLAG_16BITS);

					bsize -= len;
					d_src += len;
					_IACTpos = 0;
				}
			} else {
				if (bsize > 1 && _IACTpos == 0) {
					*(_IACToutput + 0) = *d_src++;
					_IACTpos = 1;
					bsize--;
				}
				*(_IACToutput + _IACTpos) = *d_src++;
				_IACTpos++;
				bsize--;
			}
		}
Пример #10
0
bool TGADecoder::readDataRLE(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
	// RLE-TrueColor / RLE-Black/White
	if (imageType == TYPE_RLE_TRUECOLOR || imageType == TYPE_RLE_BW || imageType == TYPE_RLE_CMAP) {
		_surface.create(_surface.w, _surface.h, _format);
		uint32 count = _surface.w * _surface.h;
		byte *data = (byte *)_surface.getPixels();

		while (count > 0) {
			uint32 header = tga.readByte();
			byte type = (header & 0x80) >> 7;
			uint32 rleCount = (header & 0x7F) + 1;

			// RLE-packet
			if (type == 1) {
				if (pixelDepth == 32 && imageType == TYPE_RLE_TRUECOLOR) {
					uint32 color = tga.readUint32LE();
					while (rleCount-- > 0) {
						*((uint32 *)data) = color;
						data += 4;
						count--;
					}
				} else if (pixelDepth == 24 && imageType == TYPE_RLE_TRUECOLOR) {
					byte r = tga.readByte();
					byte g = tga.readByte();
					byte b = tga.readByte();
					while (rleCount-- > 0) {
#ifdef SCUMM_LITTLE_ENDIAN
						*data++ = r;
						*data++ = g;
						*data++ = b;
#else
						*data++ = b;
						*data++ = g;
						*data++ = r;
#endif
						count--;
					}
				} else if (pixelDepth == 16 && imageType == TYPE_RLE_TRUECOLOR) {
					const uint16 rgb = tga.readUint16LE();
					while (rleCount-- > 0) {
						*((uint16 *)data) = rgb;
						data += 2;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_BW) {
					byte color = tga.readByte();
					while (rleCount-- > 0) {
						*data++ = color;
						*data++ = color;
						*data++ = color;
						*data++ = color;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_CMAP) {
					byte index = tga.readByte();
					while (rleCount-- > 0) {
						*data++ = index;
						count--;
					}
				} else {
					warning("Unhandled pixel-depth for image-type 10");
					return false;
				}
				// Raw-packet
			} else if (type == 0) {
				if (pixelDepth == 32 && imageType == TYPE_RLE_TRUECOLOR) {
					while (rleCount-- > 0) {
						uint32 color = tga.readUint32LE();
						*((uint32 *)data) = color;
						data += 4;
						count--;
					}
				} else if (pixelDepth == 24 && imageType == TYPE_RLE_TRUECOLOR) {
					while (rleCount-- > 0) {
						byte r = tga.readByte();
						byte g = tga.readByte();
						byte b = tga.readByte();
#ifdef SCUMM_LITTLE_ENDIAN
						*data++ = r;
						*data++ = g;
						*data++ = b;
#else
						*data++ = b;
						*data++ = g;
						*data++ = r;
#endif
						count--;
					}
				} else if (pixelDepth == 16 && imageType == TYPE_RLE_TRUECOLOR) {
					while (rleCount-- > 0) {
						*((uint16 *)data) = tga.readUint16LE();
						data += 2;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_BW) {
					while (rleCount-- > 0) {
						byte color = tga.readByte();
						*data++ = color;
						*data++ = color;
						*data++ = color;
						*data++ = color;
						count--;
					}
				} else if (pixelDepth == 8 && imageType == TYPE_RLE_CMAP) {
					while (rleCount-- > 0) {
						byte index = tga.readByte();
						*data++ = index;
						count--;
					}
				} else {
					warning("Unhandled pixel-depth for image-type 10");
					return false;
				}
			} else {
				warning("Unknown header for RLE-packet %d", type);
				return false;
			}
		}
	} else {
Пример #11
0
// Additional information found from http://paulbourke.net/dataformats/tga/
// With some details from the link referenced in the header.
bool TGADecoder::readData(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
	// TrueColor
	if (imageType == TYPE_TRUECOLOR) {
		_surface.create(_surface.w, _surface.h, _format);

		if (pixelDepth == 16) {
			for (int i = 0; i < _surface.h; i++) {
				uint16 *dst;
				if (!_originTop) {
					dst = (uint16 *)_surface.getBasePtr(0, _surface.h - i - 1);
				} else {
					dst = (uint16 *)_surface.getBasePtr(0, i);
				}
				for (int j = 0; j < _surface.w; j++) {
					*dst++ = tga.readUint16LE();
				}
			}
		} else if (pixelDepth == 32) {
			for (int i = 0; i < _surface.h; i++) {
				uint32 *dst;
				if (!_originTop) {
					dst = (uint32 *)_surface.getBasePtr(0, _surface.h - i - 1);
				} else {
					dst = (uint32 *)_surface.getBasePtr(0, i);
				}
				for (int j = 0; j < _surface.w; j++) {
					*dst++ = tga.readUint32LE();
				}
			}
		} else if (pixelDepth == 24) {
			for (int i = 0; i < _surface.h; i++) {
				byte *dst;
				if (!_originTop) {
					dst = (byte *)_surface.getBasePtr(0, _surface.h - i - 1);
				} else {
					dst = (byte *)_surface.getBasePtr(0, i);
				}
				for (int j = 0; j < _surface.w; j++) {
					byte r = tga.readByte();
					byte g = tga.readByte();
					byte b = tga.readByte();
#ifdef SCUMM_LITTLE_ENDIAN
					*dst++ = r;
					*dst++ = g;
					*dst++ = b;
#else
					*dst++ = b;
					*dst++ = g;
					*dst++ = r;
#endif
				}
			}
		}
		// Black/White
	} else if (imageType == TYPE_BW) {
		_surface.create(_surface.w, _surface.h, _format);

		byte *data  = (byte *)_surface.getPixels();
		uint32 count = _surface.w * _surface.h;

		while (count-- > 0) {
			byte g = tga.readByte();
			*data++ = g;
			*data++ = g;
			*data++ = g;
			*data++ = g;
		}
	}
	return true;
}
Пример #12
0
Common::Point GameModule::readPoint(Common::SeekableReadStream &s) {
	Common::Point p;
	p.x = s.readUint16LE();
	p.y = s.readUint16LE();
	return p;
}
Пример #13
0
bool WinCursor::readFromStream(Common::SeekableReadStream &stream) {
	clear();

	_hotspotX = stream.readUint16LE();
	_hotspotY = stream.readUint16LE();

	// Check header size
	if (stream.readUint32LE() != 40)
		return false;

	// Check dimensions
	_width = stream.readUint32LE();
	_height = stream.readUint32LE() / 2;

	if (_width & 3) {
		// Cursors should always be a power of 2
		// Of course, it wouldn't be hard to handle but if we have no examples...
		warning("Non-divisible-by-4 width cursor found");
		return false;
	}

	// Color planes
	if (stream.readUint16LE() != 1)
		return false;

	// Only 1bpp and 8bpp supported
	uint16 bitsPerPixel = stream.readUint16LE();
	if (bitsPerPixel != 1 && bitsPerPixel != 8)
		return false;

	// Compression
	if (stream.readUint32LE() != 0)
		return false;

	// Image size + X resolution + Y resolution
	stream.skip(12);

	uint32 numColors = stream.readUint32LE();

	// If the color count is 0, then it uses up the maximum amount
	if (numColors == 0)
		numColors = 1 << bitsPerPixel;

	// Reading the palette
	stream.seek(40 + 4);
	for (uint32 i = 0 ; i < numColors; i++) {
		_palette[i * 3 + 2] = stream.readByte();
		_palette[i * 3 + 1] = stream.readByte();
		_palette[i * 3    ] = stream.readByte();
		stream.readByte();
	}

	// Reading the bitmap data
	uint32 dataSize = stream.size() - stream.pos();
	byte *initialSource = new byte[dataSize];
	stream.read(initialSource, dataSize);

	// Parse the XOR map
	const byte *src = initialSource;
	_surface = new byte[_width * _height];
	byte *dest = _surface + _width * (_height - 1);
	uint32 imagePitch = _width * bitsPerPixel / 8;

	for (uint32 i = 0; i < _height; i++) {
		byte *rowDest = dest;

		if (bitsPerPixel == 1) {
			// 1bpp
			for (uint16 j = 0; j < (_width / 8); j++) {
				byte p = src[j];

				for (int k = 0; k < 8; k++, rowDest++, p <<= 1) {
					if ((p & 0x80) == 0x80)
						*rowDest = 1;
					else
						*rowDest = 0;
				}
			}
		} else {
			// 8bpp
			memcpy(rowDest, src, _width);
		}

		dest -= _width;
		src += imagePitch;
	}

	// Calculate our key color
	if (numColors < 256) {
		// If we're not using the maximum colors in a byte, we can fit it in
		_keyColor = numColors;
	} else {
		// HACK: Try to find a color that's not being used so it can become
		// our keycolor. It's quite impossible to fit 257 entries into 256...
		for (uint32 i = 0; i < 256; i++) {
			for (int j = 0; j < _width * _height; j++) {
				// TODO: Also check to see if the space is transparent

				if (_surface[j] == i)
					break;

				if (j == _width * _height - 1) {
					_keyColor = i;
					i = 256;
					break;
				}
			}
		}
	}

	// Now go through and apply the AND map to get the transparency
	uint32 andWidth = (_width + 7) / 8;
	src += andWidth * (_height - 1);

	for (uint32 y = 0; y < _height; y++) {
		for (uint32 x = 0; x < _width; x++)
			if (src[x / 8] & (1 << (7 - x % 8)))
				_surface[y * _width + x] = _keyColor;

		src -= andWidth;
	}

	delete[] initialSource;
	return true;
}
Пример #14
0
void ConversationData::load(const Common::String &filename) {
	Common::File inFile;
	char buffer[16];

	inFile.open(filename);
	MadsPack convFileUnpacked(&inFile);
	Common::SeekableReadStream *convFile = convFileUnpacked.getItemStream(0);

	// **** Section 0: Header *************************************************
	_nodeCount = convFile->readUint16LE();
	_dialogCount = convFile->readUint16LE();
	_messageCount = convFile->readUint16LE();
	_textLineCount = convFile->readUint16LE();
	_unk2 = convFile->readUint16LE();
	_importCount = 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) {
		_speakerExists[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);

	_convNodes.clear();
	for (uint i = 0; i < _nodeCount; i++) {
		ConvNode node;
		node._index = convFile->readUint16LE();
		node._dialogCount = convFile->readUint16LE();
		node._unk1 = convFile->readSint16LE();	// TODO
		node._unk2 = convFile->readSint16LE();	// TODO
		node._unk3 = convFile->readSint16LE();	// TODO
		_convNodes.push_back(node);
		//debug("Node %d, index %d, entries %d - %d, %d, %d", i, node.index, node.dialogCount, node.unk1, node.unk2, node.unk3);
	}
	delete convFile;

	// **** Section 2: Dialogs ************************************************
	convFile = convFileUnpacked.getItemStream(2);
	assert(convFile->size() == _dialogCount * 8);

	for (uint idx = 0; idx < _nodeCount; ++idx) {
		uint dialogCount = _convNodes[idx]._dialogCount;

		for (uint j = 0; j < dialogCount; ++j) {
			ConvDialog dialog;
			dialog._textLineIndex = convFile->readSint16LE();
			dialog._speechIndex = convFile->readSint16LE();
			dialog._nodeOffset = convFile->readUint16LE();
			dialog._nodeSize = convFile->readUint16LE();
			_convNodes[idx]._dialogs.push_back(dialog);
		}
	}
	delete convFile;

	// **** Section 3: Messages ***********************************************
	convFile = convFileUnpacked.getItemStream(3);
	assert(convFile->size() == _messageCount * 8);

	_messages.resize(_messageCount);
	for (uint idx = 0; idx < _messageCount; ++idx)
		_messages[idx] = convFile->readUint32LE();

	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: Node entry commands ************************************
	convFile = convFileUnpacked.getItemStream(6);
	assert(convFile->size() == _commandsSize);

	for (uint16 i = 0; i < _nodeCount; i++) {
		uint16 dialogCount = _convNodes[i]._dialogCount;

		for (uint16 j = 0; j < dialogCount; j++) {
			//ConvDialog dialog = _convNodes[i].dialogs[j];
			byte command;
			uint16 chk;

			do {
				command = convFile->readByte();
				chk = convFile->readUint16BE();
				if (chk != 0xFF00 && chk != 0x0000) {
					warning("Error while reading conversation node entries - bailing out");
					break;
				}

				switch (command) {
				case cmdNodeEnd:
					//debug("Node end");
					break;
				case cmdDialogEnd:
					//debug("Dialog end");
					break;
				case cmdHide: {
					byte count = convFile->readByte();
					for (byte k = 0; k < count; k++) {
						/*uint16 nodeRef = */convFile->readUint16LE();
						//debug("Hide node %d", nodeRef);
					}

				}
							  break;
				case cmdUnhide: {
					byte count = convFile->readByte();
					for (byte k = 0; k < count; k++) {
						/*uint16 nodeRef = */convFile->readUint16LE();
						//debug("Unhide node %d", nodeRef);
					}

				}
								break;
				case cmdMessage:
					//debug("Message");
					convFile->skip(7);	// TODO
					break;
				case cmdGoto: {
					convFile->skip(3);	// unused?
					/*byte nodeRef = */convFile->readByte();
					//debug("Goto %d", nodeRef);
				}
							  break;
				case cmdAssign: {
					convFile->skip(3);	// unused?
					/*uint16 value = */convFile->readUint16LE();
					/*uint16 variable = */convFile->readUint16LE();
					//debug("Variable %d = %d", variable, value);
				}
								break;
				default:
					error("Unknown conversation command %d", command);
					break;
				}
			} while (command != cmdNodeEnd && command != cmdDialogEnd);
		}
	}

	delete convFile;
	inFile.close();

	// TODO: Still stuff to do
	warning("TODO GameConversations::get");
}
Пример #15
0
bool T7GFont::load(Common::SeekableReadStream &stream) {
	// Read the mapping of characters to glyphs
	if (stream.read(_mapChar2Glyph, 128) < 128) {
		error("Groovie::T7GFont: Couldn't read the character to glyph map");
		return false;
	}

	// Calculate the number of glyphs
	byte numGlyphs = 0;
	for (int i = 0; i < 128; i++)
		if (_mapChar2Glyph[i] >= numGlyphs)
			numGlyphs = _mapChar2Glyph[i] + 1;

	// Read the glyph offsets
	uint16 *glyphOffsets = new uint16[numGlyphs];
	for (int i = 0; i < numGlyphs; i++)
		glyphOffsets[i] = stream.readUint16LE();

	if (stream.eos()) {
		error("Groovie::T7GFont: Couldn't read the glyph offsets");
		delete[] glyphOffsets;
		return false;
	}

	// Allocate the glyph data
	delete[] _glyphs;
	_glyphs = new Glyph[numGlyphs];

	// Ensure we're ready to read the first glyph. (Most versions don't
	// need it, but the russian one does. This fixes bug #3095031.)
	stream.seek(glyphOffsets[0]);

	// Read the glyphs
	_maxHeight = _maxWidth = 0;
	for (int i = 0; (i < numGlyphs) && !stream.eos(); i++) {
		// Verify we're at the expected stream position
		if (stream.pos() != glyphOffsets[i]) {
			uint16 offset = glyphOffsets[i];
			delete[] glyphOffsets;
			error("Groovie::T7GFont: Glyph %d starts at %d but the current "
				"offset is %d", i, offset, stream.pos());
			return false;
		}

		// Read the glyph information
		Glyph *g = &_glyphs[i];
		g->width = stream.readByte();
		g->julia = stream.readByte();

		// Read the pixels data into a dynamic array (we don't know its length)
		Common::Array<byte> data;
		data.reserve(300);
		byte b = stream.readByte();
		while (!stream.eos() && (b != 0xFF)) {
			data.push_back(b);
			b = stream.readByte();
		}

		// Verify the pixel data size
		assert (data.size() % g->width == 0);
		g->height = data.size() / g->width;

		// Copy the pixel data into the definitive static array
		g->pixels = new byte[data.size()];
		memcpy(g->pixels, data.begin(), data.size());

		// Update the max values
		if (g->width > _maxWidth)
			_maxWidth = g->width;
		if (g->height > _maxHeight)
			_maxHeight = g->height;
	}

	delete[] glyphOffsets;
	return true;
}
Пример #16
0
bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) {
	destroy();

	if (stream.readByte() != 0x0a)	// ZSoft PCX
		return false;

	byte version = stream.readByte();	// 0 - 5
	if (version > 5)
		return false;

	bool compressed = stream.readByte(); // encoding, 1 = run length encoding
	byte bitsPerPixel = stream.readByte();	// 1, 2, 4 or 8

	// Window
	uint16 xMin = stream.readUint16LE();
	uint16 yMin = stream.readUint16LE();
	uint16 xMax = stream.readUint16LE();
	uint16 yMax = stream.readUint16LE();

	uint16 width  = xMax - xMin + 1;
	uint16 height = yMax - yMin + 1;

	if (xMax < xMin || yMax < yMin) {
		warning("Invalid PCX image dimensions");
		return false;
	}

	stream.skip(4);	// HDpi, VDpi

	// Read the EGA palette (colormap)
	_palette = new byte[16 * 3];
	for (uint16 i = 0; i < 16; i++) {
		_palette[i * 3 + 0] = stream.readByte();
		_palette[i * 3 + 1] = stream.readByte();
		_palette[i * 3 + 2] = stream.readByte();
	}

	if (stream.readByte() != 0)	// reserved, should be set to 0
		return false;

	byte nPlanes = stream.readByte();
	uint16 bytesPerLine = stream.readUint16LE();
	uint16 bytesPerscanLine = nPlanes * bytesPerLine;

	if (bytesPerscanLine < width * bitsPerPixel * nPlanes / 8) {
		warning("PCX data is corrupted");
		return false;
	}

	stream.skip(60);	// PaletteInfo, HscreenSize, VscreenSize, Filler

	_surface = new Graphics::Surface();

	byte *scanLine = new byte[bytesPerscanLine];
	byte *dst;
	int x, y;

	if (nPlanes == 3 && bitsPerPixel == 8) {	// 24bpp
		Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
		_surface->create(width, height, format);
		dst = (byte *)_surface->getPixels();
		_paletteColorCount = 0;

		for (y = 0; y < height; y++) {
			decodeRLE(stream, scanLine, bytesPerscanLine, compressed);

			for (x = 0; x < width; x++) {
				byte b = scanLine[x];
				byte g = scanLine[x +  bytesPerLine];
				byte r = scanLine[x + (bytesPerLine << 1)];
				uint32 color = format.RGBToColor(r, g, b);

				*((uint32 *)dst) = color;
				dst += format.bytesPerPixel;
			}
		}
	} else if (nPlanes == 1 && bitsPerPixel == 8) {	// 8bpp indexed
		_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
		dst = (byte *)_surface->getPixels();
		_paletteColorCount = 16;

		for (y = 0; y < height; y++, dst += _surface->pitch) {
			decodeRLE(stream, scanLine, bytesPerscanLine, compressed);
			memcpy(dst, scanLine, width);
		}

		if (version == 5) {
			if (stream.readByte() != 12) {
				warning("Expected a palette after the PCX image data");
				delete[] scanLine;
				return false;
			}

			// Read the VGA palette
			delete[] _palette;
			_palette = new byte[256 * 3];
			for (uint16 i = 0; i < 256; i++) {
				_palette[i * 3 + 0] = stream.readByte();
				_palette[i * 3 + 1] = stream.readByte();
				_palette[i * 3 + 2] = stream.readByte();
			}

			_paletteColorCount = 256;
		}
	} else if ((nPlanes == 2 || nPlanes == 3 || nPlanes == 4) && bitsPerPixel == 1) {	// planar, 4, 8 or 16 colors
		_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
		dst = (byte *)_surface->getPixels();
		_paletteColorCount = 16;

		for (y = 0; y < height; y++, dst += _surface->pitch) {
			decodeRLE(stream, scanLine, bytesPerscanLine, compressed);

			for (x = 0; x < width; x++) {
				int m = 0x80 >> (x & 7), v = 0;
				for (int i = nPlanes - 1; i >= 0; i--) {
					v <<= 1;
					v  += (scanLine[i * bytesPerLine + (x >> 3)] & m) == 0 ? 0 : 1;
				}
				dst[x] = v;
			}
		}
	} else {
Пример #17
0
void GameDatabaseV2::load(Common::SeekableReadStream &sourceS) {
	int16 version = sourceS.readUint16LE();

	// Manhole:NE, Rodney's Funscreen and LGOP2 are version 54
	// The earlier EGA version of Manhole is version 40
	if (version != 54 && version != 40)
		warning("Unknown database version, known versions are 54 and 40");

	char header[6];
	sourceS.read(header, 6);
	if (strncmp(header, "ADVSYS", 6))
		warning ("Unexpected database header, expected ADVSYS");

	uint32 textOffs = 0, objectsOffs = 0, objectsSize = 0, textSize;
	uint16 objectCount = 0, varObjectCount = 0;

	sourceS.readUint16LE(); // skip sub-version
	sourceS.skip(18); // skip program name

	if (version == 40) {
		sourceS.readUint16LE(); // skip unused
		objectCount = sourceS.readUint16LE();
		_gameStateSize = sourceS.readUint16LE() * 2;
		objectsOffs = sourceS.readUint16LE() * 512;
		textOffs = sourceS.readUint16LE() * 512;
		_mainCodeObjectIndex = sourceS.readUint16LE();
		varObjectCount = 0; // unused in V1
		objectsSize = 0; // unused in V1
	} else if (version == 54) {
		textOffs = sourceS.readUint16LE() * 512;
		objectCount = sourceS.readUint16LE();
		varObjectCount = sourceS.readUint16LE();
		_gameStateSize = sourceS.readUint16LE() * 2;
		sourceS.readUint16LE(); // unknown
		objectsOffs = sourceS.readUint16LE() * 512;
		sourceS.readUint16LE(); // unknown
		_mainCodeObjectIndex = sourceS.readUint16LE();
		sourceS.readUint16LE(); // unknown
		objectsSize = sourceS.readUint32LE() * 2;
	}

	textSize = objectsOffs - textOffs;

	debug(0, "textOffs = %08X; textSize = %08X; objectCount = %d; varObjectCount = %d; gameStateSize = %d; objectsOffs = %08X; objectsSize = %d; _mainCodeObjectIndex = %04X\n", textOffs, textSize, objectCount, varObjectCount, _gameStateSize, objectsOffs, objectsSize, _mainCodeObjectIndex);

	_gameState = new byte[_gameStateSize + 2];
	memset(_gameState, 0, _gameStateSize + 2);
	setVar(1, objectCount);

	sourceS.seek(textOffs);
	_gameText = new char[textSize];
	sourceS.read(_gameText, textSize);
	// "Decrypt" the text data
	for (uint32 i = 0; i < textSize; i++)
		_gameText[i] += 0x1E;

	sourceS.seek(objectsOffs);

	if (version == 40) {
		// Initialize the object array
		for (uint32 i = 0; i < objectCount; i++)
			_objects.push_back(NULL);
		// Read two "sections" of objects
		// It seems the first section is data while the second one is code.
		// The interpreter however doesn't care which section the objects come from.
		for (int section = 0; section < 2; section++) {
			while (!sourceS.eos()) {
				int16 objIndex = sourceS.readUint16LE();
				debug("objIndex = %04X; section = %d", objIndex, section);
				if (objIndex == 0)
					break;
				Object *obj = new ObjectV1();
				obj->load(sourceS);
				_objects[objIndex - 1] = obj;
			}
		}
	} else if (version == 54) {
		for (uint32 i = 0; i < objectCount; i++) {
			Object *obj = new ObjectV2();
			int objSize = obj->load(sourceS);
			// Objects are aligned on 2-byte-boundaries, skip unused bytes
			sourceS.skip(objSize % 2);
			_objects.push_back(obj);
		}
	}

}
Пример #18
0
bool TGADecoder::readHeader(Common::SeekableReadStream &tga, byte &imageType, byte &pixelDepth) {
	if (!tga.seek(0)) {
		warning("Failed reading TGA-file");
		return false;
	}

	// TGAs have an optional "id" string in the header
	uint32 idLength = tga.readByte();

	// Number of colors in the color map / palette
	int hasColorMap = tga.readByte();

	// Image type. See header for numeric constants
	imageType = tga.readByte();

	switch (imageType) {
	case TYPE_CMAP:
	case TYPE_TRUECOLOR:
	case TYPE_BW:
	case TYPE_RLE_CMAP:
	case TYPE_RLE_TRUECOLOR:
	case TYPE_RLE_BW:
		break;
	default:
		warning("Unsupported image type: %d", imageType);
		return false;
	}

	// Color map specifications
	if (hasColorMap == 0) {
		tga.skip(5);
	} else {
		_colorMapOrigin = tga.readUint16LE();
		_colorMapLength = tga.readUint16LE();
		_colorMapEntryLength = tga.readByte();
	}
	// Origin-defintions
	tga.skip(2 + 2);

	// Image dimensions
	_surface.w = tga.readUint16LE();
	_surface.h = tga.readUint16LE();

	// Bits per pixel
	pixelDepth = tga.readByte();
	_surface.format.bytesPerPixel = pixelDepth / 8;

	// Image descriptor
	byte imgDesc = tga.readByte();
	int attributeBits = imgDesc & 0x0F;
	assert((imgDesc & 0x10) == 0);
	_originTop = (imgDesc & 0x20);

	// Interleaving is not handled at this point
	//int interleave = (imgDesc & 0xC);
	if (imageType == TYPE_CMAP || imageType == TYPE_RLE_CMAP) {
		if (pixelDepth == 8) {
			_format = Graphics::PixelFormat::createFormatCLUT8();
		} else {
			warning("Unsupported index-depth: %d", pixelDepth);
			return false;
		}
	} else if (imageType == TYPE_TRUECOLOR || imageType == TYPE_RLE_TRUECOLOR) {
		if (pixelDepth == 24) {
			_format = Graphics::PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
		} else if (pixelDepth == 32) {
			// HACK: According to the spec, attributeBits should determine the amount
			// of alpha-bits, however, as the game files that use this decoder seems
			// to ignore that fact, we force the amount to 8 for 32bpp files for now.
			_format = Graphics::PixelFormat(4, 8, 8, 8, /* attributeBits */ 8, 16, 8, 0, 24);
		} else if (pixelDepth == 16) {
			// 16bpp TGA is ARGB1555
			_format = Graphics::PixelFormat(2, 5, 5, 5, attributeBits, 10, 5, 0, 15);
		} else {
			warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
			return false;
		}
	} else if (imageType == TYPE_BW || imageType == TYPE_RLE_BW) {
		if (pixelDepth == 8) {
			_format = Graphics::PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
		} else {
			warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
			return false;
		}

	} else {
		warning("Unsupported image type: %d", imageType);
		return false;
	}

	// Skip the id string
	tga.skip(idLength);

	if (hasColorMap) {
		return readColorMap(tga, imageType, pixelDepth);
	}
	return true;
}
Пример #19
0
void SEQFile::load(Common::SeekableReadStream &seq) {
	const uint16 decCount = (uint16)seq.readByte() + 1;
	const uint16 aniCount = (uint16)seq.readByte() + 1;

	// Load backgrounds
	_backgrounds.reserve(decCount);
	for (uint i = 0; i < decCount; i++) {
		const Common::String dec = Util::readString(seq, 13);

		if (!_vm->_dataIO->hasFile(dec)) {
			warning("SEQFile::load(): No such background \"%s\"", dec.c_str());
			return;
		}

		_backgrounds.push_back(new DECFile(_vm, dec, 320, 200));
	}

	// Load animations
	_animations.reserve(aniCount);
	for (uint i = 0; i < aniCount; i++) {
		const Common::String ani = Util::readString(seq, 13);

		if (!_vm->_dataIO->hasFile(ani)) {
			warning("SEQFile::load(): No such animation \"%s\"", ani.c_str());
			return;
		}

		_animations.push_back(new ANIFile(_vm, ani));
	}

	_frameRate = seq.readUint16LE();

	// Load background change keys

	const uint16 bgKeyCount = seq.readUint16LE();
	_bgKeys.resize(bgKeyCount);

	for (uint16 i = 0; i < bgKeyCount; i++) {
		const uint16 frame = seq.readUint16LE();
		const uint16 index = seq.readUint16LE();

		_bgKeys[i].frame      = frame;
		_bgKeys[i].background = index < _backgrounds.size() ? _backgrounds[index] : 0;
	}

	// Load animation keys for all 4 objects

	for (uint i = 0; i < kObjectCount; i++) {
		const uint16 animKeyCount = seq.readUint16LE();
		_animKeys.reserve(_animKeys.size() + animKeyCount);

		for (uint16 j = 0; j < animKeyCount; j++) {
			_animKeys.push_back(AnimationKey());

			const uint16 frame = seq.readUint16LE();
			const uint16 index = seq.readUint16LE();

			uint16 animation;
			const ANIFile *ani = findANI(index, animation);

			_animKeys.back().object    = i;
			_animKeys.back().frame     = frame;
			_animKeys.back().ani       = ani;
			_animKeys.back().animation = animation;
			_animKeys.back().x         = seq.readSint16LE();
			_animKeys.back().y         = seq.readSint16LE();
			_animKeys.back().order     = seq.readSint16LE();
		}
	}

}
Пример #20
0
void Insane::iactScene6(byte *renderBitmap, int32 codecparam, int32 setupsan12,
					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
					  int16 par1, int16 par2, int16 par3, int16 par4) {
	int16 par5;

	switch (par1) {
	case 7:
		par5 = b.readUint16LE();
		if (par4 != 3)
			break;

		if (par5 >= _actor[0].x)
			break;

		_actor[0].x = par5;
		break;
	case 2:
	case 4:
		par5 = b.readUint16LE();
		switch (par3) {
		case 1:
			if (par4 == 1) {
				if (readArray(6))
					setBit(par5);
				else
					clearBit(par5);
			} else {
				if (readArray(6))
					clearBit(par5);
				else
					setBit(par5);
			}
			break;
		case 2:
			if (readArray(5))
				clearBit(par5);
			else
				setBit(par5);
			break;
		}
		break;
	case 6:
		switch (par2) {
		case 38:
			smlayer_drawSomething(renderBitmap, codecparam, 270-19, 20-13, 3,
								  _smush_icons2Nut, 10, 0, 0);
			_roadBranch = true;
			_iactSceneId = par4;
			break;
		case 7:
			if (readArray(4) != 0)
				return;

			_roadStop = true;
			smlayer_drawSomething(renderBitmap, codecparam, 160-13, 20-10, 3, //QW
								  _smush_icons2Nut, 8, 0, 0);
			break;
		case 8:
			if (readArray(4) == 0 || readArray(6) == 0)
				return;

			writeArray(1, _posBrokenTruck);
			writeArray(3, _posVista);
			smush_setToFinish();

			break;
		case 25:
			if (readArray(5) == 0)
				return;

			_carIsBroken = true;
			smlayer_drawSomething(renderBitmap, codecparam, 160-13, 20-10, 3, //QW
								  _smush_icons2Nut, 8, 0, 0);
			break;
		case 11:
			smlayer_drawSomething(renderBitmap, codecparam, 50-19, 20-13, 3,
								  _smush_icons2Nut, 9, 0, 0);
			_roadBranch = true;
			_iactSceneId = par4;
			break;
		}
		break;
	}
}
Пример #21
0
void Insane::iactScene1(byte *renderBitmap, int32 codecparam, int32 setupsan12,
					  int32 setupsan13, Common::SeekableReadStream &b, int32 size, int32 flags,
					  int16 par1, int16 par2, int16 par3, int16 par4) {
	int16 par5, par6, par7, par9, par11, par13, tmp;

	switch (par1) {
	case 2: // PATCH
		if (par3 != 1)
			break;

		par5 = b.readUint16LE(); // si
		if (_actor[0].field_8 == 112) {
			setBit(par5);
			break;
		}

		if (_approachAnim == -1) {
			chooseEnemy(); //PATCH
			_approachAnim = _enemy[_currEnemy].apprAnim;
		}

		if (_approachAnim == par4)
			clearBit(par5);
		else
			setBit(par5);
		break;
	case 3:
		if (par3 == 1) {
			setBit(b.readUint16LE());
			_approachAnim = -1;
		}
		break;
	case 4:
		if (par3 == 1 && (_approachAnim < 0 || _approachAnim > 4))
			setBit(b.readUint16LE());
		break;
	case 5:
		if (par2 != 13)
			break;

		tmp = b.readUint16LE();   // +8
		tmp = b.readUint16LE();   // +10
		par7 = b.readUint16LE();  // +12 dx
		tmp = b.readUint16LE();   // +14
		par9 = b.readUint16LE();  // +16 bx
		tmp = b.readUint16LE();   // +18
		par11 = b.readUint16LE(); // +20 cx
		tmp = b.readUint16LE();   // +22
		par13 = b.readUint16LE(); // +24 ax

		if (par13 > _actor[0].x || par11 < _actor[0].x) {
			_tiresRustle = true;
			_actor[0].x1 = -_actor[0].x1;
			_actor[0].damage++; // PATCH
		}

		if (par9 < _actor[0].x || par7 > _actor[0].x) {
			_tiresRustle = true;
			_actor[0].damage += 4; // PATCH
		}
		break;
	case 6:
		switch (par2) {
		case 38:
			smlayer_drawSomething(renderBitmap, codecparam, 50-19, 20-13, 3,
								  _smush_iconsNut, 7, 0, 0);
			_roadBranch = true;
			_iactSceneId = par4;
			break;
		case 25:
			_roadBumps = true;
			_actor[0].y1 = -_actor[0].y1;
			break;
		case 11:
			if (_approachAnim >= 1 && _approachAnim <= 4 && !_needSceneSwitch)
				queueSceneSwitch(13, _smush_minefiteFlu, "minefite.san", 64, 0,
								 _continueFrame1, 1300);
			break;
		case 9:
			par5 = b.readUint16LE(); // si
			par6 = b.readUint16LE(); // bx
			smlayer_setFluPalette(_smush_roadrsh3Rip, 0);
			if (par5 == par6 - 1)
				smlayer_setFluPalette(_smush_roadrashRip, 0);
		}
		break;
	case 7:
		switch (par4) {
		case 1:
			_actor[0].x -= (b.readUint16LE() - 160) / 10;
			break;
		case 2:
			par5 = b.readUint16LE();

			if (par5 - 8 > _actor[0].x || par5 + 8 < _actor[0].x) {
				if (smlayer_isSoundRunning(86))
					smlayer_stopSound(86);
			} else {
				if (!smlayer_isSoundRunning(86))
					smlayer_startSfx(86);
			}
			break;
		}
		break;
	}

	if (_approachAnim < 0 || _approachAnim > 4)
		if (readArray(8)) {
			smlayer_drawSomething(renderBitmap, codecparam, 270-19, 20-18, 3,
								  _smush_iconsNut, 20, 0, 0);
			_benHasGoggles = true;
		}
}
Пример #22
0
bool Sprite::loadFromBMP(Common::SeekableReadStream &bmp) {
	discard();

	if (!bmp.seek(0))
		return false;

	uint32 fSize = bmp.size();

	//                         'BM'
	if (bmp.readUint16BE() != 0x424D)
		return false;

	// Size of image + reserved + reserved
	bmp.skip(8);

	uint32 bmpDataOffset = bmp.readUint32LE();
	if (bmpDataOffset >= fSize)
		return false;

	// Header size
	if (bmp.readUint32LE() != 40)
		return false;

	int32 width  = (int32) bmp.readUint32LE();
	int32 height = (int32) bmp.readUint32LE();

	// Sanity checks
	assert((width > 0) && (height > 0) && (width <= 0x7FFF) && (height <= 0x7FFF));

	// Create surfaces
	create(width, height);

	// Number of color planes
	if (bmp.readUint16LE() != 1)
		return false;

	// Bits per pixel
	if (bmp.readUint16LE() != 8)
		return false;

	uint32 compression = bmp.readUint32LE();

	if ((compression != 0) && (compression != 2))
		return false;

	uint32 bmpDataSize = bmp.readUint32LE();

	// Sprite's feet position
	_feetX = (int32) MIN<uint16>(ABS(((int16) bmp.readUint16LE())), width  - 1);
	_feetY = (int32) MIN<uint16>(ABS(((int16) bmp.readUint16LE())), height - 1);

	// Default coordinates
	_defaultX = (int32) bmp.readUint16LE();
	_defaultY = (int32) bmp.readUint16LE();

	uint32 numPalColors = bmp.readUint32LE();
	if (numPalColors == 0)
		numPalColors = 256;
	if (numPalColors > 256)
		numPalColors = 256;

	if (bmpDataOffset == 54) {
		// Image data begins right after the header => no palette
		numPalColors = 0;
	}

	// Important colors
	bmp.skip(4);

	loadPalette(bmp, numPalColors);

	if (!bmp.seek(bmpDataOffset))
		return false;

	if (compression == 0) {
		if (!readBMPDataComp0(bmp, bmpDataSize))
			return false;
	} else if (compression == 2) {
		if (!readBMPDataComp2(bmp, bmpDataSize))
			return false;
	}

	createTransparencyMap();
	convertToTrueColor();

	return true;
}
Пример #23
0
void ComposerEngine::loadLibrary(uint id) {
	if (getGameType() == GType_ComposerV1 && !_libraries.empty()) {
		// kill the previous page, starting with any scripts running on it

		for (Common::List<OldScript *>::iterator i = _oldScripts.begin(); i != _oldScripts.end(); i++)
			delete *i;
		_oldScripts.clear();

		Library *library = &_libraries.front();
		unloadLibrary(library->_id);
	}

	Common::String filename;

	if (getGameType() == GType_ComposerV1) {
		if (!id || _bookGroup.empty())
			filename = getStringFromConfig("Common", "StartPage");
		else
			filename = getStringFromConfig(_bookGroup, Common::String::format("%d", id));
		filename = mangleFilename(filename);

		// bookGroup is the basename of the path.
		// TODO: tidy this up.
		_bookGroup.clear();
		for (uint i = 0; i < filename.size(); i++) {
			if (filename[i] == '~' || filename[i] == '/' || filename[i] == ':')
				continue;
			for (uint j = 0; j < filename.size(); j++) {
				if (filename[j] == '/') {
					_bookGroup.clear();
					continue;
				}
				if (filename[j] == '.')
					break;
				_bookGroup += filename[j];
			}
			break;
		}
	} else {
		if (!id)
			id = atoi(getStringFromConfig("Common", "StartUp").c_str());
		filename = getFilename("Libs", id);
	}

	Library library;

	library._id = id;
	library._archive = new ComposerArchive();
	if (!library._archive->openFile(filename))
		error("failed to open '%s'", filename.c_str());
	_libraries.push_front(library);

	Library &newLib = _libraries.front();

	Common::Array<uint16> buttonResources = library._archive->getResourceIDList(ID_BUTN);
	for (uint i = 0; i < buttonResources.size(); i++) {
		uint16 buttonId = buttonResources[i];
		Common::SeekableReadStream *stream = library._archive->getResource(ID_BUTN, buttonId);
		Button button(stream, buttonId, getGameType());

		bool inserted = false;
		for (Common::List<Button>::iterator b = newLib._buttons.begin(); b != newLib._buttons.end(); b++) {
			if (button._zorder < b->_zorder)
				continue;
			newLib._buttons.insert(b, button);
			inserted = true;
			break;
		}
		if (!inserted)
			newLib._buttons.push_back(button);
	}

	Common::Array<uint16> ambientResources = library._archive->getResourceIDList(ID_AMBI);
	for (uint i = 0; i < ambientResources.size(); i++) {
		Common::SeekableReadStream *stream = library._archive->getResource(ID_AMBI, ambientResources[i]);
		Button button(stream);
		newLib._buttons.insert(newLib._buttons.begin(), button);
	}

	Common::Array<uint16> accelResources = library._archive->getResourceIDList(ID_ACEL);
	for (uint i = 0; i < accelResources.size(); i++) {
		Common::SeekableReadStream *stream = library._archive->getResource(ID_ACEL, accelResources[i]);
		KeyboardHandler handler;
		handler.keyId = stream->readUint16LE();
		handler.modifierId = stream->readUint16LE();
		handler.scriptId = stream->readUint16LE();
		newLib._keyboardHandlers.push_back(handler);
	}

	Common::Array<uint16> randResources = library._archive->getResourceIDList(ID_RAND);
	for (uint i = 0; i < randResources.size(); i++) {
		Common::SeekableReadStream *stream = library._archive->getResource(ID_RAND, randResources[i]);
		Common::Array<RandomEvent> &events = _randomEvents[randResources[i]];
		uint16 count = stream->readUint16LE();
		for (uint j = 0; j < count; j++) {
			RandomEvent random;
			random.scriptId = stream->readUint16LE();
			random.weight = stream->readUint16LE();
			events.push_back(random);
		}
		delete stream;
	}

	// add background sprite, if it exists
	if (hasResource(ID_BMAP, 1000))
		setBackground(1000);

	// TODO: better CTBL logic
	loadCTBL(1000, 100);

	// Run the startup script.
	runScript(1000, 0, 0, 0);

	_mouseEnabled = true;
	onMouseMove(_lastMousePos);

	runEvent(kEventLoad, id, 0, 0);
}
Пример #24
0
void TXB::readHeader(Common::SeekableReadStream &txb, bool &needDeSwizzle) {
    // Number of bytes for the pixel data in one full image
    uint32 dataSize = txb.readUint32LE();

    _dataSize = dataSize;

    txb.skip(4); // Some float

    // Image dimensions
    uint32 width  = txb.readUint16LE();
    uint32 height = txb.readUint16LE();

    // How's the pixel data encoded?
    byte encoding    = txb.readByte();
    // Number of mip maps in the image
    byte mipMapCount = txb.readByte();

    txb.skip(2); // Unknown (Always 0x0101 on 0x0A and 0x0C types, 0x0100 on 0x09?)
    txb.skip(4); // Some float
    txb.skip(108); // Reserved

    needDeSwizzle = false;

    uint32 minDataSize, mipMapSize;
    if        (encoding == kEncodingBGRA) {
        // Raw BGRA

        needDeSwizzle = true;

        _compressed = false;
        _hasAlpha   = true;
        _format     = kPixelFormatBGRA;
        _formatRaw  = kPixelFormatRGBA8;
        _dataType   = kPixelDataType8;

        minDataSize = 4;
        mipMapSize  = width * height * 4;

    } else if (encoding == kEncodingDXT1) {
        // S3TC DXT1

        _compressed = true;
        _hasAlpha   = false;
        _format     = kPixelFormatBGR;
        _formatRaw  = kPixelFormatDXT1;
        _dataType   = kPixelDataType8;

        minDataSize = 8;
        mipMapSize  = width * height / 2;

    } else if (encoding == kEncodingDXT5) {
        // S3TC DXT5

        _compressed = true;
        _hasAlpha   = true;
        _format     = kPixelFormatBGRA;
        _formatRaw  = kPixelFormatDXT5;
        _dataType   = kPixelDataType8;

        minDataSize = 16;
        mipMapSize  = width * height;

    } else if (encoding == 0x09)
        // TODO: This seems to be some compression with 8bit per pixel. No min
        //       data size; 2*2 and 1*1 mipmaps seem to be just that big.
        //       Image data doesn't seem to be simple grayscale, paletted,
        //       RGB2222 or RGB332 data either.
        throw Common::Exception("Unsupported TXB encoding 0x09");
    else
        throw Common::Exception("Unknown TXB encoding 0x%02X (%dx%d, %d, %d)",
                                encoding, width, height, mipMapCount, dataSize);

    _mipMaps.reserve(mipMapCount);
    for (uint32 i = 0; i < mipMapCount; i++) {
        MipMap *mipMap = new MipMap;

        mipMap->width  = MAX<uint32>(width,  1);
        mipMap->height = MAX<uint32>(height, 1);

        if (((width < 4) || (height < 4)) && (width != height))
            // Invalid mipmap dimensions
            break;

        mipMap->size = MAX<uint32>(mipMapSize, minDataSize);

        mipMap->data = 0;

        if (dataSize < mipMap->size) {
            // Wouldn't fit
            delete mipMap;
            break;
        }

        dataSize -= mipMap->size;

        _mipMaps.push_back(mipMap);

        width      >>= 1;
        height     >>= 1;
        mipMapSize >>= 2;

        if ((width < 1) && (height < 1))
            break;
    }

}
Пример #25
0
void MidiMusic::load(Common::SeekableReadStream &stream) {
	_musicId = stream.readUint32LE();
	_looping = stream.readUint16LE() != 0;
	stream.skip(2 + 32 + 4); // Skip unused/unknown values
	debug(1, "MidiMusic::load() _musicId: %08X; _looping: %d", _musicId, _looping);
}
Пример #26
0
void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface) {
	char buffer1[80];
	const char *sceneName;

	// TODO: Initialise spriteSet / xp_list

	if (sceneNumber > 0) {
		sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT");
	} else {
		strcpy(buffer1, "*");
		strcat(buffer1, resName);
		sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form'
	}

	Common::SeekableReadStream *rawStream = _vm->_resourceManager->get(sceneName);
	MadsPack sceneInfo(rawStream);

	// Chunk 0:
	// Basic scene info
	Common::SeekableReadStream *stream = sceneInfo.getItemStream(0);

	if (_vm->getGameType() == GType_RexNebular) {
		int resSceneId = stream->readUint16LE();
		assert(resSceneId == sceneNumber);
	} else {
		char roomFilename[10];
		char roomFilenameExpected[10];
		sprintf(roomFilenameExpected, "*RM%d", sceneNumber);

		stream->read(roomFilename, 6);
		roomFilename[6] = 0;
		assert(!strcmp(roomFilename, roomFilenameExpected));
	}

	// TODO: The following is wrong for Phantom/Dragon
	_artFileNum = stream->readUint16LE();
	_depthStyle = stream->readUint16LE();
	_width = stream->readUint16LE();
	_height = stream->readUint16LE();
	
	stream->skip(24);

	int nodeCount = stream->readUint16LE();
	_yBandsEnd = stream->readUint16LE();
	_yBandsStart = stream->readUint16LE();
	_maxScale = stream->readSint16LE();
	_minScale = stream->readSint16LE();
	for (int i = 0; i < DEPTH_BANDS_SIZE; ++i)
		_depthBands[i] = stream->readUint16LE();
	stream->skip(2);

	// Load in any scene objects
	for (int i = 0; i < nodeCount; ++i) {
		SceneNode rec;
		rec.load(stream);
		_nodes.push_back(rec);
	}
	for (int i = 0; i < 20 - nodeCount; ++i)
		stream->skip(48);

	// Add two extra nodes in that will be used for player movement
	for (int i = 0; i < 2; ++i) {
		SceneNode rec;
		_nodes.push_back(rec);
	}

	int setCount = stream->readUint16LE();
	stream->readUint16LE();
	for (int i = 0; i < setCount; ++i) {
		char buffer2[64];
		Common::String s(buffer2, 64);
		_setNames.push_back(s);
	}

	delete stream;

	// Initialise a copy of the surfaces if they weren't provided
	bool dsFlag = false, ssFlag = false;
	if (!surface) {
		surface = new M4Surface(_width, _height);
		ssFlag = true;
	} else if ((_width != surface->width()) || (_height != surface->height()))
		surface->setSize(_width, _height);

	if (!depthSurface) {
		depthSurface = new M4Surface(_width, _height);
		dsFlag = true;
	} else if ((_width != depthSurface->width()) || (_height != depthSurface->height()))
		depthSurface->setSize(_width, _height);


	// For Rex Nebular, read in the scene's compressed walk surface information
	if (_vm->getGameType() == GType_RexNebular) {
		assert(depthSurface);
		stream = sceneInfo.getItemStream(1);
		byte *walkData = (byte *)malloc(stream->size());
		stream->read(walkData, stream->size());

		// For Rex Nebular, the walk areas are part of the scene info
		byte *destP = depthSurface->getBasePtr(0, 0);
		const byte *srcP = walkData;
		byte runLength;

		// Run length encoded depth data
		while ((runLength = *srcP++) != 0) {
			if (_depthStyle == 2) {
				// 2-bit depth pixels
				byte byteVal = *srcP++;
				for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) {
					byte v = byteVal;
					for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2)
						*destP++ = (((v & 1) + 1) << 3) - 1;
				}
			} else {
Пример #27
0
void FileIdent::load(Common::SeekableReadStream &s) {
	_fileNum = s.readSint16LE();
	_subfile = s.readUint16LE();
}
Пример #28
0
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;
}
Пример #29
0
bool WinFont::loadFromFON(const Common::String &fileName, const WinFontDirEntry &dirEntry) {
	// TODO: PE libraries (If it's used anywhere by a ScummVM game)

	Common::NEResources exe;

	if (!exe.loadFromEXE(fileName))
		return false;

	// Let's pull out the font directory
	Common::SeekableReadStream *fontDirectory = exe.getResource(Common::kNEFontDir, Common::String("FONTDIR"));
	if (!fontDirectory) {
		warning("No font directory in '%s'", fileName.c_str());
		return false;
	}

	uint16 numFonts = fontDirectory->readUint16LE();

	// Probably not possible, so this is really a sanity check
	if (numFonts == 0) {
		warning("No fonts in '%s'", fileName.c_str());
		return false;
	}

	// Scour the directory for our matching name
	int fontId = -1;
	for (uint16 i = 0; i < numFonts; i++) {
		uint16 id = fontDirectory->readUint16LE();

		if (dirEntry.faceName.empty()) {
			// Use the first name when empty
			fontId = id;
			break;
		}

		WinFontDirEntry entry = readDirEntry(*fontDirectory);

		if (dirEntry.faceName.equalsIgnoreCase(entry.faceName) && dirEntry.points == entry.points) {
			// Match!
			fontId = id;
			break;
		}
	}

	delete fontDirectory;

	// Couldn't match the face name
	if (fontId < 0) {
		warning("Could not find face '%s' in '%s'", dirEntry.faceName.c_str(), fileName.c_str());
		return false;
	}

	// Actually go get our font now...
	Common::SeekableReadStream *fontStream = exe.getResource(Common::kNEFont, fontId);
	if (!fontStream) {
		warning("Could not find font %d in %s", fontId, fileName.c_str());
		return false;
	}

	bool ok = loadFromFNT(*fontStream);
	delete fontStream;
	return ok;
}
Пример #30
0
void Map_v1::loadObjects(Common::SeekableReadStream &data, uint32 objsPos) {
	Goblin::Gob_State *pState;
	uint32 tmpStateData[40 * 6];
	uint32 tmpPos;

	_vm->_goblin->_objCount = data.readUint16LE();
	for (int i = 0; i < _vm->_goblin->_objCount; i++) {
		_vm->_goblin->_objects[i] = new Goblin::Gob_Object;
		memset(_vm->_goblin->_objects[i], 0, sizeof(Goblin::Gob_Object));

		tmpPos = data.pos();
		data.seek(objsPos);
		_vm->_goblin->_objects[i]->xPos = data.readUint16LE();
		_vm->_goblin->_objects[i]->yPos = data.readUint16LE();
		_vm->_goblin->_objects[i]->order = data.readUint16LE();
		_vm->_goblin->_objects[i]->state = data.readUint16LE();
		objsPos = data.pos();
		data.seek(tmpPos);

		_vm->_goblin->_objects[i]->stateMach = new Goblin::Gob_StateLine[40];
		for (int state = 0; state < 40; ++state) {
			for (int col = 0; col < 6; ++col) {
				_vm->_goblin->_objects[i]->stateMach[state][col] = 0;
				tmpStateData[state * 6 + col] = data.readUint32LE();
			}
		}

		data.skip(160);
		_vm->_goblin->_objects[i]->multObjIndex = data.readByte();
		data.skip(1);

		_vm->_goblin->_objects[i]->realStateMach =
			_vm->_goblin->_objects[i]->stateMach;
		for (int state = 0; state < 40; state++) {
			for (int col = 0; col < 6; col++) {
				if (tmpStateData[state * 6 + col] == 0) {
					_vm->_goblin->_objects[i]->stateMach[state][col] = 0;
					continue;
				}

				Goblin::Gob_State *tmpState = new Goblin::Gob_State;
				memset(tmpState, 0, sizeof(Goblin::Gob_State));
				_vm->_goblin->_objects[i]->stateMach[state][col] = tmpState;

				tmpState->animation = data.readUint16LE();
				tmpState->layer = data.readUint16LE();
				data.skip(8);
				tmpState->unk0 = data.readUint16LE();
				tmpState->unk1 = data.readUint16LE();

				data.skip(2);
				if (data.readUint32LE() == 0) {
					data.skip(2);
					tmpState->sndItem = -1;
				} else
					tmpState->sndItem = data.readUint16LE();

				tmpState->freq = data.readUint16LE();
				tmpState->repCount = data.readUint16LE();
				tmpState->sndFrame = data.readUint16LE();
			}
		}
	}

	_vm->_goblin->_objects[10] = new Goblin::Gob_Object;
	memset(_vm->_goblin->_objects[10], 0, sizeof(Goblin::Gob_Object));

	_vm->_goblin->_objects[10]->stateMach = new Goblin::Gob_StateLine[40];
	for (int state = 0; state < 40; ++state)
		for (int col = 0; col < 6; ++col)
			_vm->_goblin->_objects[10]->stateMach[state][col] = 0;

	pState = new Goblin::Gob_State;
	memset(pState, 0, sizeof(Goblin::Gob_State));
	_vm->_goblin->_objects[10]->stateMach[0][0] = pState;

	pState->animation = 9;
	pState->layer = 27;
	pState->sndItem = -1;

	_vm->_goblin->placeObject(_vm->_goblin->_objects[10], 1, 0, 0, 0, 0);

	_vm->_goblin->_objects[10]->realStateMach =
		_vm->_goblin->_objects[10]->stateMach;
	_vm->_goblin->_objects[10]->type = 1;
	_vm->_goblin->_objects[10]->unk14 = 1;
}