diff options
| author | Alyssa Milburn | 2011-07-14 23:36:49 +0200 | 
|---|---|---|
| committer | Alyssa Milburn | 2011-07-14 23:36:49 +0200 | 
| commit | 3935b3ed6be6bde5272b0d84a3dbe0df54f205fc (patch) | |
| tree | 84cea0660339a7dfac9aab50a7d1889d9002084f | |
| parent | 40a6c232e9169a9cfe0d6a698b728c8565cd8959 (diff) | |
| download | scummvm-rg350-3935b3ed6be6bde5272b0d84a3dbe0df54f205fc.tar.gz scummvm-rg350-3935b3ed6be6bde5272b0d84a3dbe0df54f205fc.tar.bz2 scummvm-rg350-3935b3ed6be6bde5272b0d84a3dbe0df54f205fc.zip  | |
COMPOSER: Manage/render sprites.
| -rw-r--r-- | engines/composer/composer.cpp | 181 | ||||
| -rw-r--r-- | engines/composer/composer.h | 13 | 
2 files changed, 177 insertions, 17 deletions
diff --git a/engines/composer/composer.cpp b/engines/composer/composer.cpp index b2dcc3b36c..3651a49328 100644 --- a/engines/composer/composer.cpp +++ b/engines/composer/composer.cpp @@ -212,7 +212,7 @@ Common::SeekableReadStream *Pipe::getResource(uint32 tag, uint16 id, bool buffer  	for (uint i = 0; i < res.entries.size(); i++)  		size += res.entries[i].size; -	byte *buffer = new byte[size]; +	byte *buffer = (byte *)malloc(size);  	uint32 offset = 0;  	for (uint i = 0; i < res.entries.size(); i++) {  		_stream->seek(res.entries[i].offset, SEEK_SET); @@ -397,15 +397,19 @@ void ComposerEngine::processAnimFrame() {  						break;  					case 4:  						if (entry.word10 && (!data || data != entry.word10)) { -							// TODO: erase old sprite -							warning("ignoring anim sprite erase (%d)", entry.word10); +							debug(4, "anim: erase sprite %d", entry.word10); +							removeSprite(data, anim->_id);  						}  						if (data) {  							uint16 x = anim->_stream->readUint16LE();  							uint16 y = anim->_stream->readUint16LE(); +							Common::Point pos(x, y);  							anim->_offset += 4; -							// TODO: sprite change -							warning("ignoring anim sprite draw (%d @ %d,%d)", data, x, y); +							uint16 animId = anim->_id; +							if (anim->_state == entry.dword0) +								animId = 0; +							debug(4, "anim: draw sprite %d at (relative) %d,%d", data, x, y); +							addSprite(data, animId, entry.word6, anim->_basePos + pos);  						}  						break;  					default: @@ -424,6 +428,33 @@ void ComposerEngine::processAnimFrame() {  	}  } +void ComposerEngine::addSprite(uint16 id, uint16 animId, uint16 zorder, const Common::Point &pos) { +	Sprite sprite; +	sprite.id = id; +	sprite.animId = animId; +	sprite.zorder = zorder; +	sprite.pos = pos; + +	for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) { +		if (sprite.zorder < i->zorder) +			continue; +		_sprites.insert(i, sprite); +		return; +	} +	_sprites.push_back(sprite); +} + +void ComposerEngine::removeSprite(uint16 id, uint16 animId) { +	for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) { +		if (i->id != id) +			continue; +		if (animId && i->animId != animId) +			continue; +		i = _sprites.reverse_erase(i); +		return; +	} +} +  ComposerEngine::ComposerEngine(OSystem *syst, const ComposerGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) {  	_rnd = new Common::RandomSource("composer");  	_audioStream = NULL; @@ -471,12 +502,6 @@ Common::Error ComposerEngine::run() {  	uint frameTime = 1000 / fps;  	uint32 lastDrawTime = 0;  	while (!shouldQuit()) { -		if (hasResource(ID_BMAP, 1000)) -			drawBMAP(1000, 0, 0); - -		_system->copyRectToScreen((byte *)_surface.pixels, _surface.pitch, 0, 0, _surface.w, _surface.h); -		_system->updateScreen(); -  		uint32 thisTime = _system->getMillis();  		for (uint i = 0; i < _queuedScripts.size(); i++) {  			QueuedScript &script = _queuedScripts[i]; @@ -494,6 +519,15 @@ Common::Error ComposerEngine::run() {  		if (lastDrawTime + frameTime <= thisTime) {  			lastDrawTime += frameTime; +			if (hasResource(ID_BMAP, 1000)) +				drawBMAP(1000, 0, 0); +			for (Common::List<Sprite>::iterator i = _sprites.begin(); i != _sprites.end(); i++) { +				drawBMAP(i->id, i->pos.x, i->pos.y); +			} + +			_system->copyRectToScreen((byte *)_surface.pixels, _surface.pitch, 0, 0, _surface.w, _surface.h); +			_system->updateScreen(); +  			processAnimFrame();  		} @@ -853,19 +887,130 @@ void ComposerEngine::loadCTBL(uint id, uint fadePercent) {  	_system->getPaletteManager()->setPalette(buffer, 0, numEntries);  } -void ComposerEngine::decompressBitmap(uint16 type, Common::SeekableReadStream *stream, byte *buffer, uint32 size) { +static void decompressSLWM(byte *buffer, Common::SeekableReadStream *stream) { +	uint bitsLeft = 0; +	uint16 lastBits; +	byte currBit; +	while (true) { +		if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); } +		currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--; + +		if (currBit) { +			// single byte +			*buffer++ = stream->readByte(); +			continue; +		} + +		if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); } +		currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--; + +		uint start; +		uint count; +		if (currBit) { +			uint orMask = stream->readByte(); +			uint in = stream->readByte(); +			count = in & 7; +			start = ((in & ~7) << 5) | orMask; +			if (!count) { +				count = stream->readByte(); +				if (!count) +					break; +				count -= 2; +			} +		} else { +			// count encoded in the next two bits +			count = 0; + +			if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); } +			currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--; + +			count = (count << 1) | currBit; + +			if (bitsLeft == 0) { bitsLeft = 16; lastBits = stream->readUint16LE(); } +			currBit = (lastBits & 1); lastBits >>= 1; bitsLeft--; + +			count = (count << 1) | currBit; + +			start = stream->readByte(); +		} + +		count += 2; +		start++; +		memcpy(buffer, buffer - start, count); +		buffer += count; +	} +} + +void ComposerEngine::decompressBitmap(uint16 type, Common::SeekableReadStream *stream, byte *buffer, uint32 size, uint width, uint height) {  	switch (type) {  	case kBitmapUncompressed:  		assert(stream->size() - (uint)stream->pos() == size); +		assert(size == width * height);  		stream->read(buffer, size);  		break; +	case kBitmapRLESLWM: +		{ +		uint32 bufSize = stream->readUint32LE(); +		byte *tempBuf = new byte[bufSize]; +		decompressSLWM(tempBuf, stream); + +		uint instrPos = tempBuf[0] + 1; +		instrPos += READ_LE_UINT16(tempBuf + instrPos) + 2; +		byte *instr = tempBuf + instrPos; + +		uint line = 0; +		while (line++ < height) { +			uint pixels = 0; + +			while (pixels < width) { +				byte data = *instr++; +				byte color = tempBuf[(data & 0x7F) + 1]; +				if (!(data & 0x80)) { +					*buffer++ = color; +					pixels++; +				} else { +					byte count = *instr++; +					if (!count) { +						while (pixels++ < width) +							*buffer++ = color; +						break; +					} +					for (uint i = 0; i < count; i++) { +						*buffer++ = color; +						pixels++; +					} +				} +			} +		} +		delete[] tempBuf; +		} +		break; +	case kBitmapSLWM: +		decompressSLWM(buffer, stream); +		break;  	default:  		error("decompressBitmap can't handle type %d", type);  	}  }  void ComposerEngine::drawBMAP(uint id, uint x, uint y) { -	Common::SeekableReadStream *stream = getResource(ID_BMAP, id); +	Common::SeekableReadStream *stream = NULL; +	if (hasResource(ID_BMAP, id)) +		stream = getResource(ID_BMAP, id); +	else +		for (Common::List<Pipe *>::iterator k = _pipes.begin(); k != _pipes.end(); k++) { +			Pipe *pipe = *k; +			if (!pipe->hasResource(ID_BMAP, id)) +				continue; +			stream = pipe->getResource(ID_BMAP, id, true); +			break; +		} + +	if (!stream) { +		// FIXME +		warning("couldn't find BMAP %d", id); +		return; +	}  	uint16 type = stream->readUint16LE();  	uint16 height = stream->readUint16LE(); @@ -874,12 +1019,18 @@ void ComposerEngine::drawBMAP(uint id, uint x, uint y) {  	debug(1, "BMAP: type %d, width %d, height %d, size %d", type, width, height, size);  	byte *buffer = new byte[width * height]; -	decompressBitmap(type, stream, buffer, size); +	decompressBitmap(type, stream, buffer, size, width, height); + +	debug(1, "draw at %d,%d", x, y);  	// incoming data is BMP-style (bottom-up), so flip it  	byte *pixels = (byte *)_surface.pixels;  	for (uint j = 0; j < height; j++) { -		memcpy(pixels + (j * width), buffer + (height - j - 1) * width, width); +		byte *in = buffer + (height - j - 1) * width; +		byte *out = pixels + ((j + y) * _surface.w) + x; +		for (uint i = 0; i < width; i++) +			if (in[i]) +				out[i] = in[i];  	}  	delete[] buffer; diff --git a/engines/composer/composer.h b/engines/composer/composer.h index 5d4233a1ba..e535bfbc6e 100644 --- a/engines/composer/composer.h +++ b/engines/composer/composer.h @@ -59,7 +59,11 @@ enum GameType {  class Archive;  class ComposerEngine; -class Sprite { +struct Sprite { +	uint16 id; +	uint16 animId; +	uint16 zorder; +	Common::Point pos;  };  struct AnimationEntry { @@ -158,6 +162,8 @@ private:  	Audio::QueuingAudioStream *_audioStream;  	Graphics::Surface _surface; +	Common::List<Sprite> _sprites; +  	Common::ConfigFile _bookIni;  	Common::List<Library> _libraries; @@ -187,8 +193,11 @@ private:  	void playWaveForAnim(uint16 id, bool bufferingOnly);  	void processAnimFrame(); +	void addSprite(uint16 id, uint16 animId, uint16 zorder, const Common::Point &pos); +	void removeSprite(uint16 id, uint16 animId); +  	void loadCTBL(uint id, uint fadePercent); -	void decompressBitmap(uint16 type, Common::SeekableReadStream *stream, byte *buffer, uint32 size); +	void decompressBitmap(uint16 type, Common::SeekableReadStream *stream, byte *buffer, uint32 size, uint width, uint height);  	void drawBMAP(uint id, uint x, uint y);  };  | 
