mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 21:59:17 +00:00
283 lines
7.7 KiB
C++
283 lines
7.7 KiB
C++
/* 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.
|
|
*
|
|
*/
|
|
|
|
#ifndef COMMON_IFF_CONTAINER_H
|
|
#define COMMON_IFF_CONTAINER_H
|
|
|
|
#include "common/scummsys.h"
|
|
#include "common/endian.h"
|
|
#include "common/func.h"
|
|
#include "common/stream.h"
|
|
#include "common/textconsole.h"
|
|
|
|
namespace Common {
|
|
|
|
/**
|
|
* @defgroup common_iff Interchange File Format (IFF)
|
|
* @ingroup common
|
|
*
|
|
* @brief API for operations on IFF container files.
|
|
*
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
typedef uint32 IFF_ID;
|
|
|
|
#define ID_FORM MKTAG('F','O','R','M')
|
|
/* EA IFF 85 group identifier */
|
|
#define ID_CAT MKTAG('C','A','T',' ')
|
|
/* EA IFF 85 group identifier */
|
|
#define ID_LIST MKTAG('L','I','S','T')
|
|
/* EA IFF 85 group identifier */
|
|
#define ID_PROP MKTAG('P','R','O','P')
|
|
/* EA IFF 85 group identifier */
|
|
#define ID_END MKTAG('E','N','D',' ')
|
|
/* unofficial END-of-FORM identifier (see Amiga RKM Devices Ed.3
|
|
page 376) */
|
|
#define ID_ILBM MKTAG('I','L','B','M')
|
|
/* EA IFF 85 raster bitmap form */
|
|
#define ID_DEEP MKTAG('D','E','E','P')
|
|
/* Chunky pixel image files (Used in TV Paint) */
|
|
#define ID_RGB8 MKTAG('R','G','B','8')
|
|
/* RGB image forms, Turbo Silver (Impulse) */
|
|
#define ID_RGBN MKTAG('R','G','B','N')
|
|
/* RGB image forms, Turbo Silver (Impulse) */
|
|
#define ID_PBM MKTAG('P','B','M',' ')
|
|
/* 256-color chunky format (DPaint 2 ?) */
|
|
#define ID_ACBM MKTAG('A','C','B','M')
|
|
/* Amiga Contiguous Bitmap (AmigaBasic) */
|
|
#define ID_8SVX MKTAG('8','S','V','X')
|
|
/* Amiga 8 bits voice */
|
|
|
|
/* generic */
|
|
|
|
#define ID_FVER MKTAG('F','V','E','R')
|
|
/* AmigaOS version string */
|
|
#define ID_JUNK MKTAG('J','U','N','K')
|
|
/* always ignore this chunk */
|
|
#define ID_ANNO MKTAG('A','N','N','O')
|
|
/* EA IFF 85 Generic Annotation chunk */
|
|
#define ID_AUTH MKTAG('A','U','T','H')
|
|
/* EA IFF 85 Generic Author chunk */
|
|
#define ID_CHRS MKTAG('C','H','R','S')
|
|
/* EA IFF 85 Generic character string chunk */
|
|
#define ID_NAME MKTAG('N','A','M','E')
|
|
/* EA IFF 85 Generic Name of art, music, etc. chunk */
|
|
#define ID_TEXT MKTAG('T','E','X','T')
|
|
/* EA IFF 85 Generic unformatted ASCII text chunk */
|
|
#define ID_copy MKTAG('(','c',')',' ')
|
|
/* EA IFF 85 Generic Copyright text chunk */
|
|
|
|
/* IFF chunks */
|
|
|
|
#define ID_BMHD MKTAG('B','M','H','D')
|
|
/* IFF BitmapHeader */
|
|
#define ID_CMAP MKTAG('C','M','A','P')
|
|
/* IFF 8bit RGB colormap */
|
|
#define ID_GRAB MKTAG('G','R','A','B')
|
|
/* IFF "hotspot" coordiantes */
|
|
#define ID_DEST MKTAG('D','E','S','T')
|
|
/* IFF destination image info */
|
|
#define ID_SPRT MKTAG('S','P','R','T')
|
|
/* IFF sprite identifier */
|
|
#define ID_CAMG MKTAG('C','A','M','G')
|
|
/* Amiga viewportmodes */
|
|
#define ID_BODY MKTAG('B','O','D','Y')
|
|
/* IFF image data */
|
|
#define ID_CRNG MKTAG('C','R','N','G')
|
|
/* color cycling */
|
|
#define ID_CCRT MKTAG('C','C','R','T')
|
|
/* color cycling */
|
|
#define ID_CLUT MKTAG('C','L','U','T')
|
|
/* Color Lookup Table chunk */
|
|
#define ID_DPI MKTAG('D','P','I',' ')
|
|
/* Dots per inch chunk */
|
|
#define ID_DPPV MKTAG('D','P','P','V')
|
|
/* DPaint perspective chunk (EA) */
|
|
#define ID_DRNG MKTAG('D','R','N','G')
|
|
/* DPaint IV enhanced color cycle chunk (EA) */
|
|
#define ID_EPSF MKTAG('E','P','S','F')
|
|
/* Encapsulated Postscript chunk */
|
|
#define ID_CMYK MKTAG('C','M','Y','K')
|
|
/* Cyan, Magenta, Yellow, & Black color map (Soft-Logik) */
|
|
#define ID_CNAM MKTAG('C','N','A','M')
|
|
/* Color naming chunk (Soft-Logik) */
|
|
#define ID_PCHG MKTAG('P','C','H','G')
|
|
/* Line by line palette control information (Sebastiano Vigna) */
|
|
#define ID_PRVW MKTAG('P','R','V','W')
|
|
/* A mini duplicate IFF used for preview (Gary Bonham) */
|
|
#define ID_XBMI MKTAG('X','B','M','I')
|
|
/* eXtended BitMap Information (Soft-Logik) */
|
|
#define ID_CTBL MKTAG('C','T','B','L')
|
|
/* Newtek Dynamic Ham color chunk */
|
|
#define ID_DYCP MKTAG('D','Y','C','P')
|
|
/* Newtek Dynamic Ham chunk */
|
|
#define ID_SHAM MKTAG('S','H','A','M')
|
|
/* Sliced HAM color chunk */
|
|
#define ID_ABIT MKTAG('A','B','I','T')
|
|
/* ACBM body chunk */
|
|
#define ID_DCOL MKTAG('D','C','O','L')
|
|
/* unofficial direct color */
|
|
#define ID_DPPS MKTAG('D','P','P','S')
|
|
/* ? */
|
|
#define ID_TINY MKTAG('T','I','N','Y')
|
|
/* ? */
|
|
#define ID_DPPV MKTAG('D','P','P','V')
|
|
/* ? */
|
|
|
|
/* 8SVX chunks */
|
|
|
|
#define ID_VHDR MKTAG('V','H','D','R')
|
|
/* 8SVX Voice8Header */
|
|
|
|
|
|
/**
|
|
* Represents a IFF chunk available to client code.
|
|
*
|
|
* Client code must *not* deallocate _stream when done.
|
|
*/
|
|
struct IFFChunk {
|
|
IFF_ID _type;
|
|
uint32 _size;
|
|
ReadStream *_stream;
|
|
|
|
IFFChunk(IFF_ID type, uint32 size, 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 ReadStream {
|
|
protected:
|
|
ReadStream *_input;
|
|
uint32 _bytesRead;
|
|
public:
|
|
IFF_ID id;
|
|
uint32 size;
|
|
|
|
IFFChunkNav() : _input(nullptr) {
|
|
}
|
|
void setInputStream(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();
|
|
}
|
|
}
|
|
// 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);
|
|
}
|
|
};
|
|
|
|
protected:
|
|
IFFChunkNav _formChunk; ///< The root chunk of the file.
|
|
IFFChunkNav _chunk; ///< The current chunk.
|
|
|
|
uint32 _formSize;
|
|
IFF_ID _formType;
|
|
|
|
ReadStream *_stream;
|
|
bool _disposeStream;
|
|
|
|
void setInputStream(ReadStream *stream);
|
|
|
|
public:
|
|
IFFParser(ReadStream *stream, bool disposeStream = false);
|
|
~IFFParser();
|
|
|
|
/**
|
|
* Callback type for the parser.
|
|
*/
|
|
typedef 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);
|
|
};
|
|
|
|
|
|
/**
|
|
* Decode a given PackBits encoded stream.
|
|
*
|
|
* PackBits is an RLE compression algorithm introduced by Apple. It is also
|
|
* used to encode ILBM and PBM subtypes of IFF files, and some flavors of
|
|
* TIFF.
|
|
*
|
|
* As there is no compression across row boundaries in the above formats,
|
|
* read() will extract a *new* line on each call, discarding any alignment
|
|
* or padding.
|
|
*/
|
|
class PackBitsReadStream : public Common::ReadStream {
|
|
|
|
protected:
|
|
Common::ReadStream *_input;
|
|
|
|
public:
|
|
PackBitsReadStream(Common::ReadStream &input);
|
|
~PackBitsReadStream();
|
|
|
|
virtual bool eos() const;
|
|
|
|
uint32 read(void *dataPtr, uint32 dataSize);
|
|
};
|
|
|
|
/** @} */
|
|
|
|
} // namespace Common
|
|
|
|
#endif
|