aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/iff_container.h196
-rw-r--r--engines/parallaction/disk.cpp38
-rw-r--r--engines/parallaction/disk.h6
-rw-r--r--engines/parallaction/disk_br.cpp1
-rw-r--r--engines/parallaction/disk_ns.cpp1
-rw-r--r--engines/parallaction/iff.cpp186
-rw-r--r--engines/parallaction/iff.h206
-rw-r--r--engines/parallaction/module.mk1
-rw-r--r--engines/saga/scene.cpp7
-rw-r--r--graphics/iff.cpp258
-rw-r--r--graphics/iff.h101
-rw-r--r--sound/iff.cpp16
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;
}