diff options
author | Nicola Mettifogo | 2009-06-12 05:03:18 +0000 |
---|---|---|
committer | Nicola Mettifogo | 2009-06-12 05:03:18 +0000 |
commit | 5fccc0f98dda5cbcec208b17c2e6d36a36fadf1e (patch) | |
tree | 4077bb476edd1bd959eca925a6f5d80bceff230f /engines/parallaction/iff.h | |
parent | f5b2e69522153c47438895ea80129ad5e3c9b952 (diff) | |
download | scummvm-rg350-5fccc0f98dda5cbcec208b17c2e6d36a36fadf1e.tar.gz scummvm-rg350-5fccc0f98dda5cbcec208b17c2e6d36a36fadf1e.tar.bz2 scummvm-rg350-5fccc0f98dda5cbcec208b17c2e6d36a36fadf1e.zip |
* Final version of the IFF parsing code.
* Refactored ILBMDecoder usage from disk code.
svn-id: r41458
Diffstat (limited to 'engines/parallaction/iff.h')
-rw-r--r-- | engines/parallaction/iff.h | 191 |
1 files changed, 146 insertions, 45 deletions
diff --git a/engines/parallaction/iff.h b/engines/parallaction/iff.h index 43f78bf001..98e36e1b00 100644 --- a/engines/parallaction/iff.h +++ b/engines/parallaction/iff.h @@ -27,39 +27,126 @@ #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 -// this IFF parser code is courtesy of the Kyra engine team ;) 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() : _stream(0), _startOffset(0), _endOffset(0) {} - IFFParser(Common::SeekableReadStream *stream) : _stream(0), _startOffset(0), _endOffset(0) { + IFFParser(Common::ReadStream *stream, bool disposeStream = false) : _stream(stream), _disposeStream(stream) { setInputStream(stream); } - ~IFFParser() { destroy(); } - - void setInputStream(Common::SeekableReadStream *stream); + ~IFFParser() { + if (_disposeStream) { + delete _stream; + } + _stream = 0; + } - operator bool() const { return (_startOffset != _endOffset) && _stream; } + /** + * 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; - Common::IFF_ID getFORMType() const; - uint32 getIFFBlockSize(Common::IFF_ID chunk); - bool loadIFFBlock(Common::IFF_ID chunk, void *loadTo, uint32 ptrSize); - Common::SeekableReadStream *getIFFBlockStream(Common::IFF_ID chunkName); -private: - void destroy(); - uint32 moveToIFFBlock(Common::IFF_ID chunkName); + /** + * Callback type for the parser. + */ + typedef Common::Functor1< IFFChunk&, bool > IFFCallback; - Common::SeekableReadStream *_stream; - uint32 _startOffset; - uint32 _endOffset; + /** + * 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; }; @@ -67,35 +154,49 @@ private: -class ILBMDecoder { - Common::SeekableReadStream *_in; - bool _disposeStream; - +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); - -protected: - IFFParser _parser; - Graphics::BMHD _header; - bool _hasHeader; - uint32 _bodySize; - uint32 _paletteSize; - - -public: - ILBMDecoder(Common::SeekableReadStream *input, bool disposeStream = false); - - virtual ~ILBMDecoder(); - - uint32 getWidth(); - uint32 getHeight(); - uint32 getNumColors(); - byte *getPalette(); - - byte *getBitmap(uint32 numPlanes, bool packPlanes); - byte *getBitmap() { - assert(_hasHeader); - return getBitmap(_header.depth, false); - } }; |