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; } |