diff options
| -rw-r--r-- | common/iff_container.h | 196 | ||||
| -rw-r--r-- | engines/parallaction/disk.cpp | 38 | ||||
| -rw-r--r-- | engines/parallaction/disk.h | 6 | ||||
| -rw-r--r-- | engines/parallaction/disk_br.cpp | 1 | ||||
| -rw-r--r-- | engines/parallaction/disk_ns.cpp | 1 | ||||
| -rw-r--r-- | engines/parallaction/iff.cpp | 186 | ||||
| -rw-r--r-- | engines/parallaction/iff.h | 206 | ||||
| -rw-r--r-- | engines/parallaction/module.mk | 1 | ||||
| -rw-r--r-- | engines/saga/scene.cpp | 7 | ||||
| -rw-r--r-- | graphics/iff.cpp | 258 | ||||
| -rw-r--r-- | graphics/iff.h | 101 | ||||
| -rw-r--r-- | sound/iff.cpp | 16 | 
12 files changed, 359 insertions, 658 deletions
| diff --git a/common/iff_container.h b/common/iff_container.h index 617bdde690..8a1b934a30 100644 --- a/common/iff_container.h +++ b/common/iff_container.h @@ -27,6 +27,7 @@  #include "common/scummsys.h"  #include "common/endian.h" +#include "common/func.h"  #include "common/stream.h"  #include "common/util.h" @@ -145,90 +146,159 @@ page 376) */  char * ID2string(Common::IFF_ID id); -class IFFChunk : public Common::ReadStream { - -protected: -	Common::ReadStream *_input; -	uint32 bytesRead; - -public: -	IFF_ID id; -	uint32 size; - -	IFFChunk(Common::ReadStream *input): _input(input) { -		size = bytesRead = 0; -	} - -	void incBytesRead(uint32 inc) { -		bytesRead += inc; -		if (bytesRead > size) { -			error("Chunk '%s' overread", ID2string(id)); -		} -	} +/** + *  Represents a IFF chunk available to client code. + * + *  Client code must *not* deallocate _stream when done. + */ +struct IFFChunk { +	Common::IFF_ID			_type; +	uint32					_size; +	Common::ReadStream		*_stream; -	void readHeader() { -		id = _input->readUint32BE(); -		size = _input->readUint32BE(); -		bytesRead = 0; +	IFFChunk(Common::IFF_ID type, uint32 size, Common::ReadStream *stream) : _type(type), _size(size), _stream(stream) { +		assert(_stream);  	} +}; -	bool hasReadAll() const { -		return (size - bytesRead) == 0; -	} +/** + *  Parser for IFF containers. + */ +class IFFParser { -	void feed() { -		if (size % 2) { -			size++; +	/** +	 *  This private class implements IFF chunk navigation. +	 */ +	class IFFChunkNav : public Common::ReadStream { +	protected: +		Common::ReadStream *_input; +		uint32 _bytesRead; +	public: +		Common::IFF_ID id; +		uint32 size; + +		IFFChunkNav() : _input(0) {  		} -		while (!hasReadAll()) { -			readByte(); +		void setInputStream(Common::ReadStream *input) { +			_input = input; +			size = _bytesRead = 0;  		} -	} +		void incBytesRead(uint32 inc) { +			_bytesRead += inc; +			if (_bytesRead > size) { +				error("Chunk overread"); +			} +		} +		void readHeader() { +			id = _input->readUint32BE(); +			size = _input->readUint32BE(); +			_bytesRead = 0; +		} +		bool hasReadAll() const { +			return (size - _bytesRead) == 0; +		} +		void feed() { +			if (size % 2) { +				size++; +			} +			while (!hasReadAll()) { +				readByte(); +			} +		} +		// Common::ReadStream implementation +		bool eos() const { return _input->eos(); } +		bool err() const { return _input->err(); } +		void clearErr() { _input->clearErr(); } + +		uint32 read(void *dataPtr, uint32 dataSize) { +			incBytesRead(dataSize); +			return _input->read(dataPtr, dataSize); +		} +	}; -	// Common::ReadStream implementation -	bool eos() const { return _input->eos(); } -	bool err() const { return _input->err(); } -	void clearErr() { _input->clearErr(); } +	IFFChunkNav _formChunk;	//!< The root chunk of the file. +	IFFChunkNav _chunk; 	//!< The current chunk. -	uint32 read(void *dataPtr, uint32 dataSize) { -		incBytesRead(dataSize); -		return _input->read(dataPtr, dataSize); -	} +	Common::ReadStream *_stream; +	bool _disposeStream; -}; +	void setInputStream(Common::ReadStream *stream) { +		assert(stream); +		_formChunk.setInputStream(stream); +		_chunk.setInputStream(stream); -class IFFParser { -public: -	IFFParser(Common::ReadStream &input) : _formChunk(&input), _chunk(&input) {  		_formChunk.readHeader();  		if (_formChunk.id != ID_FORM) {  			error("IFFParser input is not a FORM type IFF file");  		} -		_typeId = _formChunk.readUint32BE(); +		_formSize = _formChunk.size; +		_formType = _formChunk.readUint32BE();  	} -	virtual ~IFFParser() {} - -	IFFChunk *nextChunk() { -		_chunk.feed(); -		_formChunk.incBytesRead(_chunk.size); - -		if (_formChunk.hasReadAll()) -			return 0; - -		_formChunk.incBytesRead(8); -		_chunk.readHeader(); - -		return &_chunk; +public: +	IFFParser(Common::ReadStream *stream, bool disposeStream = false) : _stream(stream), _disposeStream(stream) { +		setInputStream(stream); +	} +	~IFFParser() { +		if (_disposeStream) { +			delete _stream; +		} +		_stream = 0;  	} -	IFF_ID	_typeId; +	/** +	 * Returns the IFF FORM type. +	 * @return the IFF FORM type of the stream, or 0 if FORM header is not found. +	 */ +	Common::IFF_ID getFORMType() const; + +	/** +	 * Returns the size of the data. +	 * @return the size of the data in file, or -1 if FORM header is not found. +	 */ +	uint32 getFORMSize() const; + +	/** +	 * Callback type for the parser. +	 */ +	typedef Common::Functor1< IFFChunk&, bool > IFFCallback; + +	/** +	 * Parse the IFF container, invoking the callback on each chunk encountered. +	 * The callback can interrupt the parsing by returning 'true'. +	 */ +	void parse(IFFCallback &callback) { +		bool stop; +		do { +			_chunk.feed(); +			_formChunk.incBytesRead(_chunk.size); + +			if (_formChunk.hasReadAll()) { +				break; +			} + +			_formChunk.incBytesRead(8); +			_chunk.readHeader(); + +			// invoke the callback +			Common::SubReadStream stream(&_chunk, _chunk.size); +			IFFChunk chunk(_chunk.id, _chunk.size, &stream); +			stop = callback(chunk); + +			// eats up all the remaining data in the chunk +			while (!stream.eos()) { +				stream.readByte(); +			} + +		} while (!stop); +	} -protected: -	IFFChunk	_formChunk; -	IFFChunk	_chunk; +private: +	uint32 _formSize; +	Common::IFF_ID _formType;  }; +  } // namespace Common  #endif diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp index a58fa35655..6928c1eefc 100644 --- a/engines/parallaction/disk.cpp +++ b/engines/parallaction/disk.cpp @@ -1,6 +1,30 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ +  #include "parallaction/disk.h"  #include "parallaction/graphics.h" -#include "parallaction/iff.h"  namespace Parallaction { @@ -13,7 +37,7 @@ void ILBMLoader::setupBuffer(uint32 w, uint32 h) {  			assert(_surf);  		}  		_surf->create(w, h, 1); -		_mode  = ILBMDecoder::ILBM_UNPACK_PLANES; +		_mode  = Graphics::ILBMDecoder::ILBM_UNPACK_PLANES;  		_intBuffer = (byte*)_surf->pixels;  		break; @@ -23,7 +47,7 @@ void ILBMLoader::setupBuffer(uint32 w, uint32 h) {  			assert(_maskBuffer);  		}  		_maskBuffer->create(w, h); -		_mode  = ILBMDecoder::ILBM_2_PACK_PLANES; +		_mode  = Graphics::ILBMDecoder::ILBM_2_PACK_PLANES;  		_intBuffer = _maskBuffer->data;  		break; @@ -33,7 +57,7 @@ void ILBMLoader::setupBuffer(uint32 w, uint32 h) {  			assert(_pathBuffer);  		}  		_pathBuffer->create(w, h); -		_mode  = ILBMDecoder::ILBM_1_PACK_PLANES; +		_mode  = Graphics::ILBMDecoder::ILBM_1_PACK_PLANES;  		_intBuffer = _pathBuffer->data;  		break; @@ -43,7 +67,7 @@ void ILBMLoader::setupBuffer(uint32 w, uint32 h) {  	}  } -bool ILBMLoader::callback(IFFChunk &chunk) { +bool ILBMLoader::callback(Common::IFFChunk &chunk) {  	switch (chunk._type) {  	case ID_BMHD:  		_decoder.loadHeader(chunk._stream); @@ -77,8 +101,8 @@ bool ILBMLoader::callback(IFFChunk &chunk) {  }  void ILBMLoader::load(Common::ReadStream *in, bool disposeStream) { -	IFFParser parser(in, disposeStream); -	Common::Functor1Mem< IFFChunk&, bool, ILBMLoader > c(this, &ILBMLoader::callback); +	Common::IFFParser parser(in, disposeStream); +	Common::Functor1Mem< Common::IFFChunk&, bool, ILBMLoader > c(this, &ILBMLoader::callback);  	parser.parse(c);  } diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index 936be1e140..a9da429473 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -33,7 +33,7 @@  #include "common/file.h"  #include "graphics/surface.h" -#include "parallaction/iff.h" +#include "graphics/iff.h" @@ -99,14 +99,14 @@ struct ILBMLoader {  	uint32 _mode;  	byte* _intBuffer;  	uint32 _numCRNG; -	ILBMDecoder _decoder; +	Graphics::ILBMDecoder _decoder;  	ILBMLoader(uint32 bodyMode, byte *palette = 0, PaletteFxRange *crng = 0);  	ILBMLoader(Graphics::Surface *surf, byte *palette = 0, PaletteFxRange *crng = 0);  	ILBMLoader(MaskBuffer *buffer);  	ILBMLoader(PathBuffer *buffer); -	bool callback(IFFChunk &chunk); +	bool callback(Common::IFFChunk &chunk);  	void setupBuffer(uint32 w, uint32 h);  	void load(Common::ReadStream *in, bool disposeStream = false);  }; diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 3572129dc0..46c849e6f2 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -28,7 +28,6 @@  #include "common/config-manager.h"  #include "parallaction/parallaction.h"  #include "parallaction/parser.h" -#include "parallaction/iff.h"  namespace Parallaction { diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index b002d1e1f5..d35b338069 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -23,7 +23,6 @@   *   */ -#include "parallaction/iff.h"  #include "common/config-manager.h"  #include "parallaction/parser.h"  #include "parallaction/parallaction.h" diff --git a/engines/parallaction/iff.cpp b/engines/parallaction/iff.cpp deleted file mode 100644 index 024af5b6a7..0000000000 --- a/engines/parallaction/iff.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - - -#include "common/iff_container.h" -#include "common/stream.h" -#include "common/util.h" -#include "parallaction/iff.h" - -namespace Parallaction { - - -void IFFParser::setInputStream(Common::ReadStream *stream) { -	assert(stream); -	_formChunk.setInputStream(stream); -	_chunk.setInputStream(stream); - -	_formChunk.readHeader(); -	if (_formChunk.id != ID_FORM) { -		error("IFFParser input is not a FORM type IFF file"); -	} -	_formSize = _formChunk.size; -	_formType = _formChunk.readUint32BE(); -} - -uint32 IFFParser::getFORMSize() const { -	return _formSize; -} - -Common::IFF_ID IFFParser::getFORMType() const { -	return _formType; -} - -void IFFParser::parse(IFFCallback &callback) { -	bool stop; -	do { -		_chunk.feed(); -		_formChunk.incBytesRead(_chunk.size); - -		if (_formChunk.hasReadAll()) { -			break; -		} - -		_formChunk.incBytesRead(8); -		_chunk.readHeader(); - -		// invoke the callback -		Common::SubReadStream stream(&_chunk, _chunk.size); -		IFFChunk chunk(_chunk.id, _chunk.size, &stream); -		stop = callback(chunk); - -		// eats up all the remaining data in the chunk -		while (!stream.eos()) { -			stream.readByte(); -		} - - -	} while (!stop); -} - - - -void ILBMDecoder::loadHeader(Common::ReadStream *stream) { -	assert(stream); -	stream->read(&_header, sizeof(_header)); -	_header.width = FROM_BE_16(_header.width); -	_header.height = FROM_BE_16(_header.height); -	_header.x = FROM_BE_16(_header.x); -	_header.y = FROM_BE_16(_header.y); -	_header.transparentColor = FROM_BE_16(_header.transparentColor); -	_header.pageWidth = FROM_BE_16(_header.pageWidth); -	_header.pageHeight = FROM_BE_16(_header.pageHeight); -} - -void ILBMDecoder::loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream) { -	assert(stream); -	uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); -	assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); - -	bool packPixels = (mode & ILBM_PACK_PLANES) != 0; -	if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { -		packPixels = false; -	} - -	uint32 outPitch = _header.width; -	if (packPixels) { -		outPitch /= (8 / numPlanes); -	} -	byte *out = buffer; - -	switch (_header.pack) { -	case 1: {	// PackBits compressed bitmap -		Graphics::PackBitsReadStream packStream(*stream); - -		// setup a buffer to hold enough data to build a line in the output -		uint32 scanlineWidth = ((_header.width + 15)/16) << 1; -		byte *scanline = new byte[scanlineWidth * _header.depth]; - -		for (uint i = 0; i < _header.height; ++i) { -			byte *s = scanline; -			for (uint32 j = 0; j < _header.depth; ++j) { -				packStream.read(s, scanlineWidth); -				s += scanlineWidth; -			} - -			planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); -			out += outPitch; -		} - -		delete []scanline; -		break; -	} - -	default: -		// implement other compression types here! -		error("only RLE compressed ILBM files are supported"); -		break; -	} -} - -void ILBMDecoder::planarToChunky(byte *out, uint32 outPitch, byte *in, uint32 inWidth, uint32 nPlanes, bool packPlanes) { -	byte pix, ofs, bit; -	byte *s; - -	uint32 pixels = outPitch; -	if (packPlanes) { -		pixels *= (8 / nPlanes); -	} - -	for (uint32 x = 0; x < pixels; ++x) { - -		pix = 0; -		ofs = x >> 3; -		bit = 0x80 >> (x & 7); - -		// first build a pixel by scanning all the usable planes in the input -		s = in; -		for (uint32 plane = 0; plane < nPlanes; ++plane) { -			if (s[ofs] & bit) { -				pix |= (1 << plane); -			} -			s += inWidth; -		} - - -		// then output the pixel according to the requested packing -		if (!packPlanes) { -			out[x] = pix; -		} else -		if (nPlanes == 1) { -			out[x/8] |= (pix << (x & 7)); -		} else -		if (nPlanes == 2) { -			out[x/4] |= (pix << ((x & 3) << 1)); -		} else -		if (nPlanes == 4) { -			out[x/2] |= (pix << ((x & 1) << 2)); -		} -	} - -} - - -} // End of namespace Parallaction diff --git a/engines/parallaction/iff.h b/engines/parallaction/iff.h deleted file mode 100644 index 98e36e1b00..0000000000 --- a/engines/parallaction/iff.h +++ /dev/null @@ -1,206 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef PARALLACTION_IFF_H -#define PARALLACTION_IFF_H - -#include "common/stream.h" -#include "common/func.h" -#include "common/iff_container.h"		// for IFF chunk names -#include "graphics/iff.h"				// for BMHD - - -namespace Parallaction { - -/** - *  Represents a IFF chunk available to client code. - * - *  Client code must *not* deallocate _stream when done. - */ -struct IFFChunk { -	Common::IFF_ID			_type; -	uint32					_size; -	Common::ReadStream		*_stream; - -	IFFChunk(Common::IFF_ID type, uint32 size, Common::ReadStream *stream) : _type(type), _size(size), _stream(stream) { -		assert(_stream); -	} -}; - -/** - *  Parser for IFF containers. - */ -class IFFParser { - -	/** -	 *  This private class implements IFF chunk navigation. -	 */ -	class IFFChunkNav : public Common::ReadStream { -	protected: -		Common::ReadStream *_input; -		uint32 _bytesRead; -	public: -		Common::IFF_ID id; -		uint32 size; - -		IFFChunkNav() : _input(0) { -		} -		void setInputStream(Common::ReadStream *input) { -			_input = input; -			size = _bytesRead = 0; -		} -		void incBytesRead(uint32 inc) { -			_bytesRead += inc; -			if (_bytesRead > size) { -				error("Chunk overread"); -			} -		} -		void readHeader() { -			id = _input->readUint32BE(); -			size = _input->readUint32BE(); -			_bytesRead = 0; -		} -		bool hasReadAll() const { -			return (size - _bytesRead) == 0; -		} -		void feed() { -			if (size % 2) { -				size++; -			} -			while (!hasReadAll()) { -				readByte(); -			} -		} -		// Common::ReadStream implementation -		bool eos() const { return _input->eos(); } -		bool err() const { return _input->err(); } -		void clearErr() { _input->clearErr(); } - -		uint32 read(void *dataPtr, uint32 dataSize) { -			incBytesRead(dataSize); -			return _input->read(dataPtr, dataSize); -		} -	}; - -	IFFChunkNav _formChunk;	//!< The root chunk of the file. -	IFFChunkNav _chunk; 	//!< The current chunk. - -	Common::ReadStream *_stream; -	bool _disposeStream; - -	void setInputStream(Common::ReadStream *stream); - -public: -	IFFParser(Common::ReadStream *stream, bool disposeStream = false) : _stream(stream), _disposeStream(stream) { -		setInputStream(stream); -	} -	~IFFParser() { -		if (_disposeStream) { -			delete _stream; -		} -		_stream = 0; -	} - -	/** -	 * Returns the IFF FORM type. -	 * @return the IFF FORM type of the stream, or 0 if FORM header is not found. -	 */ -	Common::IFF_ID getFORMType() const; - -	/** -	 * Returns the size of the data. -	 * @return the size of the data in file, or -1 if FORM header is not found. -	 */ -	uint32 getFORMSize() const; - -	/** -	 * Callback type for the parser. -	 */ -	typedef Common::Functor1< IFFChunk&, bool > IFFCallback; - -	/** -	 * Parse the IFF container, invoking the callback on each chunk encountered. -	 * The callback can interrupt the parsing by returning 'true'. -	 */ -	void parse(IFFCallback &callback); - -private: -	uint32 _formSize; -	Common::IFF_ID _formType; -}; - - - - -struct ILBMDecoder { -	/** -	 * ILBM header data, necessary for loadBitmap() -	 */ -	Graphics::BMHD	_header; - -	/** -	 * Available decoding modes for loadBitmap(). -	 */ -	enum { -		ILBM_UNPACK_PLANES = 0xFF,		//!< Decode all bitplanes, and map 1 pixel to 1 byte. -		ILBM_PACK_PLANES   = 0x100,		//!< Request unpacking, used as a mask with below options. - -		ILBM_1_PLANES      = 1,									//!< Decode only the first bitplane, don't pack. -		ILBM_1_PACK_PLANES = ILBM_1_PLANES | ILBM_PACK_PLANES, 	//!< Decode only the first bitplane, pack 8 pixels in 1 byte. -		ILBM_2_PLANES      = 2,									//!< Decode first 2 bitplanes, don't pack. -		ILBM_2_PACK_PLANES = ILBM_2_PLANES | ILBM_PACK_PLANES,	//!< Decode first 2 bitplanes, pack 4 pixels in 1 byte. -		ILBM_3_PLANES      = 3,									//!< Decode first 3 bitplanes, don't pack. -		ILBM_4_PLANES      = 4,									//!< Decode first 4 bitplanes, don't pack. -		ILBM_4_PACK_PLANES = ILBM_4_PLANES | ILBM_PACK_PLANES,	//!< Decode first 4 bitplanes, pack 2 pixels in 1 byte. -		ILBM_5_PLANES      = 5,									//!< Decode first 5 bitplanes, don't pack. -		ILBM_8_PLANES      = 8									//!< Decode all 8 bitplanes. -	}; - -	/** -	 * Fills the _header member from the given stream. -	 */ -	void loadHeader(Common::ReadStream *stream); - -	/** -	 * Loads and unpacks the ILBM bitmap data from the stream into the buffer. -	 * The functions assumes the buffer is large enough to contain all data. -	 * The caller controls how data should be packed by choosing mode from -	 * the enum above. -	 */ -	void loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream); - -	/** -	 * Converts from bitplanar to chunky representation. Intended for internal -	 * usage, but you can be (ab)use it from client code if you know what you -	 * are doing. -	 */ -	void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); -}; - - -} - -#endif - diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index bd45598d17..d65653cd92 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -19,7 +19,6 @@ MODULE_OBJS := \  	gui.o \  	gui_br.o \  	gui_ns.o \ -	iff.o \  	input.o \  	inventory.o \  	objects.o \ diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index a7c802f0c9..f43db12d1a 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -472,7 +472,7 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy  		for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++) {  			if (sceneSubstitutes[i].sceneId == sceneNumber) {  				Surface bbmBuffer; -				byte *pal, *colors; +				byte *pal, colors[768];  				Common::File file;  				Rect rect;  				PalEntry cPal[PAL_ENTRIES]; @@ -480,8 +480,8 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy  				_vm->_interface->setMode(kPanelSceneSubstitute);  				if (file.open(sceneSubstitutes[i].image)) { -					Graphics::decodePBM(file, bbmBuffer, pal); -					colors = pal; +					Graphics::decodePBM(file, bbmBuffer, colors); +					pal = colors;  					rect.setWidth(bbmBuffer.w);  					rect.setHeight(bbmBuffer.h);  					_vm->_gfx->drawRegion(rect, (const byte*)bbmBuffer.pixels); @@ -490,7 +490,6 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy  						cPal[j].green = *pal++;  						cPal[j].blue = *pal++;  					} -					free(colors);  					_vm->_gfx->setPalette(cPal);  				} diff --git a/graphics/iff.cpp b/graphics/iff.cpp index ea6447ac01..902f97499a 100644 --- a/graphics/iff.cpp +++ b/graphics/iff.cpp @@ -48,194 +48,179 @@ char *ID2string(Common::IFF_ID id) {  namespace Graphics { - -void fillBMHD(BMHD &bitmapHeader, Common::ReadStream &stream) { - -	bitmapHeader.width = stream.readUint16BE(); -	bitmapHeader.height = stream.readUint16BE(); -	bitmapHeader.x = stream.readUint16BE(); -	bitmapHeader.y = stream.readUint16BE(); -	bitmapHeader.depth = stream.readByte(); -	bitmapHeader.masking = stream.readByte(); -	bitmapHeader.pack = stream.readByte(); -	bitmapHeader.flags = stream.readByte(); -	bitmapHeader.transparentColor = stream.readUint16BE(); -	bitmapHeader.xAspect = stream.readByte(); -	bitmapHeader.yAspect = stream.readByte(); -	bitmapHeader.pageWidth = stream.readUint16BE(); -	bitmapHeader.pageHeight = stream.readUint16BE(); - +void BMHD::load(Common::ReadStream *stream) { +	assert(stream); +	stream->read(this, sizeof(BMHD)); +	width = FROM_BE_16(width); +	height = FROM_BE_16(height); +	x = FROM_BE_16(x); +	y = FROM_BE_16(y); +	transparentColor = FROM_BE_16(transparentColor); +	pageWidth = FROM_BE_16(pageWidth); +	pageHeight = FROM_BE_16(pageHeight);  } -ILBMDecoder::ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { -	if (_typeId != ID_ILBM) -		error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void ILBMDecoder::loadHeader(Common::ReadStream *stream) { +	_header.load(stream);  } -void ILBMDecoder::decode() { - -	Common::IFFChunk *chunk; -	while ((chunk = nextChunk()) != 0) { -		switch (chunk->id) { -		case ID_BMHD: -			readBMHD(*chunk); -			break; +void ILBMDecoder::loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream) { +	assert(stream); +	uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); +	assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); -		case ID_CMAP: -			readCMAP(*chunk); -			break; - -		case ID_BODY: -			readBODY(*chunk); -			break; -		} +	bool packPixels = (mode & ILBM_PACK_PLANES) != 0; +	if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { +		packPixels = false;  	} -	return; -} +	uint32 outPitch = _header.width; +	if (packPixels) { +		outPitch /= (8 / numPlanes); +	} +	byte *out = buffer; -void ILBMDecoder::readBMHD(Common::IFFChunk &chunk) { +	switch (_header.pack) { +	case 1: {	// PackBits compressed bitmap +		Graphics::PackBitsReadStream packStream(*stream); -	fillBMHD(_bitmapHeader, chunk); +		// setup a buffer to hold enough data to build a line in the output +		uint32 scanlineWidth = ((_header.width + 15)/16) << 1; +		byte *scanline = new byte[scanlineWidth * _header.depth]; -	_colorCount = 1 << _bitmapHeader.depth; -	*_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); -	_surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); +		for (uint i = 0; i < _header.height; ++i) { +			byte *s = scanline; +			for (uint32 j = 0; j < _header.depth; ++j) { +				packStream.read(s, scanlineWidth); +				s += scanlineWidth; +			} -} +			planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); +			out += outPitch; +		} -void ILBMDecoder::readCMAP(Common::IFFChunk &chunk) { -	if (*_colors == NULL) { -		error("wrong input chunk sequence"); +		delete []scanline; +		break;  	} -	for (uint32 i = 0; i < _colorCount; i++) { -		(*_colors)[i * 3 + 0] = chunk.readByte(); -		(*_colors)[i * 3 + 1] = chunk.readByte(); -		(*_colors)[i * 3 + 2] = chunk.readByte(); + +	default: +		// implement other compression types here! +		error("only RLE compressed ILBM files are supported"); +		break;  	}  } -void ILBMDecoder::readBODY(Common::IFFChunk& chunk) { +void ILBMDecoder::planarToChunky(byte *out, uint32 outPitch, byte *in, uint32 inWidth, uint32 nPlanes, bool packPlanes) { +	byte pix, ofs, bit; +	byte *s; -	switch (_bitmapHeader.pack) { -	case 0: -		error("unpacked ILBM files are not supported"); -		break; +	uint32 pixels = outPitch; +	if (packPlanes) { +		pixels *= (8 / nPlanes); +	} -	case 1: { -		uint32 scanWidth = (_bitmapHeader.width + 7) >> 3; -		byte *scan = (byte*)malloc(scanWidth); -		byte *out = (byte*)_surface->pixels; +	for (uint32 x = 0; x < pixels; ++x) { -		PackBitsReadStream stream(chunk); +		pix = 0; +		ofs = x >> 3; +		bit = 0x80 >> (x & 7); -		for (uint32 i = 0; i < _bitmapHeader.height; i++) { -			for (uint32 j = 0; j < _bitmapHeader.depth; j++) { -				stream.read(scan, scanWidth); -				fillPlane(out, scan, scanWidth, j); +		// first build a pixel by scanning all the usable planes in the input +		s = in; +		for (uint32 plane = 0; plane < nPlanes; ++plane) { +			if (s[ofs] & bit) { +				pix |= (1 << plane);  			} - -			out += _bitmapHeader.width; +			s += inWidth;  		} -		free(scan); -		break; -	} - -	} -} -void ILBMDecoder::fillPlane(byte *out, byte* buf, uint32 width, uint32 plane) { -	byte src, idx, set; -	byte mask = 1 << plane; - -	for (uint32 j = 0; j < _bitmapHeader.width; j++) { -		src = buf[j >> 3]; -		idx = 7 - (j & 7); -		set = src & (1 << idx); - -		if (set) -			out[j] |= mask; +		// then output the pixel according to the requested packing +		if (!packPlanes) { +			out[x] = pix; +		} else +		if (nPlanes == 1) { +			out[x/8] |= (pix << (x & 7)); +		} else +		if (nPlanes == 2) { +			out[x/4] |= (pix << ((x & 3) << 1)); +		} else +		if (nPlanes == 4) { +			out[x/2] |= (pix << ((x & 1) << 2)); +		}  	}  } - - -PBMDecoder::PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { -	if (_typeId != ID_PBM) -		error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); +void PBMDecoder::loadHeader(Common::ReadStream *stream) { +	_header.load(stream);  } -void PBMDecoder::decode() { -	Common::IFFChunk *chunk; -	while ((chunk = nextChunk()) != 0) { -		switch (chunk->id) { -		case ID_BMHD: -			readBMHD(*chunk); -			break; +void PBMDecoder::loadBitmap(byte *buffer, Common::ReadStream *stream) { +	uint32 outSize = _header.width * _header.height; -		case ID_CMAP: -			readCMAP(*chunk); -			break; +	switch (_header.pack) { +	case 0: +		stream->read(buffer, outSize); +		break; -		case ID_BODY: -			readBODY(*chunk); -			break; +	case 1: { +		PackBitsReadStream packStream(*stream); +		packStream.read(buffer, outSize); +		break;  		}  	} - -	return;  } -void PBMDecoder::readBMHD(Common::IFFChunk &chunk) { -	fillBMHD(_bitmapHeader, chunk); +struct PBMLoader { +	PBMDecoder _decoder; +	Surface *_surface; +	byte *_colors; -	_colorCount = 1 << _bitmapHeader.depth; -	*_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); -	_surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); - -} - -void PBMDecoder::readCMAP(Common::IFFChunk &chunk) { -	if (*_colors == NULL) { -		error("wrong input chunk sequence"); -	} -	for (uint32 i = 0; i < _colorCount; i++) { -		(*_colors)[i * 3 + 0] = chunk.readByte(); -		(*_colors)[i * 3 + 1] = chunk.readByte(); -		(*_colors)[i * 3 + 2] = chunk.readByte(); +	void load(Common::ReadStream &input, Surface &surface, byte *&colors) { +		_surface = &surface; +		_colors = colors; +		Common::IFFParser parser(&input); +		Common::Functor1Mem< Common::IFFChunk&, bool, PBMLoader > c(this, &PBMLoader::callback); +		parser.parse(c);  	} -} -void PBMDecoder::readBODY(Common::IFFChunk& chunk) { +	bool callback(Common::IFFChunk &chunk) { +		switch (chunk._type) { +		case ID_BMHD: +			_decoder.loadHeader(chunk._stream); +			break; -	uint si = 0; +		case ID_CMAP: +			if (_colors) { +				chunk._stream->read(_colors, chunk._size); +			} +			break; -	switch (_bitmapHeader.pack) { -	case 0: -		while (!chunk.hasReadAll()) { -			((byte*)_surface->pixels)[si++] = chunk.readByte(); +		case ID_BODY: +			if (_surface) { +				_surface->create(_decoder._header.width, _decoder._header.height, 1); +				_decoder.loadBitmap((byte*)_surface->pixels, chunk._stream); +			} +			return true;	// stop the parser  		} -		break; -	case 1: { -		PackBitsReadStream stream(chunk); -		stream.read((byte*)_surface->pixels, _surface->w * _surface->h); -		break; +		return false;  	} +}; -	} +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors) { +	PBMLoader loader; +	loader.load(input, surface, colors);  } -  PackBitsReadStream::PackBitsReadStream(Common::ReadStream &input) : _input(&input) {  } @@ -282,9 +267,4 @@ uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) {  } -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors) { -	PBMDecoder decoder(input, surface, colors); -	decoder.decode(); -} -  } diff --git a/graphics/iff.h b/graphics/iff.h index 13b82a673c..fc1b6ceefa 100644 --- a/graphics/iff.h +++ b/graphics/iff.h @@ -52,55 +52,80 @@ struct BMHD {  	BMHD() {  		memset(this, 0, sizeof(*this));  	} -}; - -//	handles ILBM subtype of IFF FORM files -// -class ILBMDecoder : public Common::IFFParser { +	void load(Common::ReadStream *stream); +}; -protected: -	void readBMHD(Common::IFFChunk &chunk); -	void readCMAP(Common::IFFChunk &chunk); -	void readBODY(Common::IFFChunk &chunk); -	BMHD	_bitmapHeader; -	uint32	_colorCount; +struct ILBMDecoder { +	/** +	 * ILBM header data, necessary for loadBitmap() +	 */ +	Graphics::BMHD	_header; + +	/** +	 * Available decoding modes for loadBitmap(). +	 */ +	enum { +		ILBM_UNPACK_PLANES = 0xFF,		//!< Decode all bitplanes, and map 1 pixel to 1 byte. +		ILBM_PACK_PLANES   = 0x100,		//!< Request unpacking, used as a mask with below options. + +		ILBM_1_PLANES      = 1,									//!< Decode only the first bitplane, don't pack. +		ILBM_1_PACK_PLANES = ILBM_1_PLANES | ILBM_PACK_PLANES, 	//!< Decode only the first bitplane, pack 8 pixels in 1 byte. +		ILBM_2_PLANES      = 2,									//!< Decode first 2 bitplanes, don't pack. +		ILBM_2_PACK_PLANES = ILBM_2_PLANES | ILBM_PACK_PLANES,	//!< Decode first 2 bitplanes, pack 4 pixels in 1 byte. +		ILBM_3_PLANES      = 3,									//!< Decode first 3 bitplanes, don't pack. +		ILBM_4_PLANES      = 4,									//!< Decode first 4 bitplanes, don't pack. +		ILBM_4_PACK_PLANES = ILBM_4_PLANES | ILBM_PACK_PLANES,	//!< Decode first 4 bitplanes, pack 2 pixels in 1 byte. +		ILBM_5_PLANES      = 5,									//!< Decode first 5 bitplanes, don't pack. +		ILBM_8_PLANES      = 8									//!< Decode all 8 bitplanes. +	}; + +	/** +	 * Fills the _header member from the given stream. +	 */ +	void loadHeader(Common::ReadStream *stream); + +	/** +	 * Loads and unpacks the ILBM bitmap data from the stream into the buffer. +	 * The functions assumes the buffer is large enough to contain all data. +	 * The caller controls how data should be packed by choosing mode from +	 * the enum above. +	 */ +	void loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream); + +	/** +	 * Converts from bitplanar to chunky representation. Intended for internal +	 * usage, but you can be (ab)use it from client code if you know what you +	 * are doing. +	 */ +	void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); +}; -	Surface *_surface; -	byte    **_colors; -	void fillPlane(byte *out, byte* buf, uint32 width, uint32 plane); - -public: -	ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); -	virtual ~ILBMDecoder() { } -	void decode(); -};  //	handles PBM subtype of IFF FORM files  // -class PBMDecoder : public Common::IFFParser { - -protected: -	void readBMHD(Common::IFFChunk &chunk); -	void readCMAP(Common::IFFChunk &chunk); -	void readBODY(Common::IFFChunk &chunk); - -	BMHD	_bitmapHeader; -	uint32	_colorCount; - -	Surface *_surface; -	byte    **_colors; - -public: -	PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); -	virtual ~PBMDecoder() { } -	void decode(); +struct PBMDecoder { +	/** +	 * PBM header data, necessary for loadBitmap() +	 */ +	Graphics::BMHD	_header; + +	/** +	 * Fills the _header member from the given stream. +	 */ +	void loadHeader(Common::ReadStream *stream); + +	/** +	 * Loads and unpacks the PBM bitmap data from the stream into the buffer. +	 * The functions assumes the buffer is large enough to contain all data. +	 */ +	void loadBitmap(byte *buffer, Common::ReadStream *stream);  }; -void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors); +void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors);  /* diff --git a/sound/iff.cpp b/sound/iff.cpp index bf3318d80e..1df58b178c 100644 --- a/sound/iff.cpp +++ b/sound/iff.cpp @@ -47,24 +47,22 @@ struct A8SVXLoader {  	uint32 _dataSize;  	void load(Common::ReadStream &input) { -		Common::IFFParser parser(input); -		Common::IFFChunk *chunk; -		while (chunk = parser.nextChunk()) { -			callback(*chunk); -		} +		Common::IFFParser parser(&input); +		Common::Functor1Mem< Common::IFFChunk&, bool, A8SVXLoader > c(this, &A8SVXLoader::callback); +		parser.parse(c);  	}  	bool callback(Common::IFFChunk &chunk) { -		switch (chunk.id) { +		switch (chunk._type) {  		case ID_VHDR: -			_header.load(chunk); +			_header.load(*chunk._stream);  			break;  		case ID_BODY: -			_dataSize = chunk.size; +			_dataSize = chunk._size;  			_data = (int8*)malloc(_dataSize);  			assert(_data); -			loadData(&chunk); +			loadData(chunk._stream);  			return true;  		} | 
