From 4467a25db97acd671c516a09dbf8e0066a4d6300 Mon Sep 17 00:00:00 2001
From: Nicola Mettifogo <peres@scummvm.org>
Date: Tue, 27 Mar 2007 19:45:09 +0000
Subject: [PATCH] - added new subclass ILBMDecoder, to decode ILBM subtype of
 IFF files - some bug fixing on the hierarchy

svn-id: r26310
---
 graphics/ilbm.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++----
 graphics/ilbm.h   |  21 +++++++-
 2 files changed, 139 insertions(+), 13 deletions(-)

diff --git a/graphics/ilbm.cpp b/graphics/ilbm.cpp
index a1280b52ee5..c237dd0f922 100644
--- a/graphics/ilbm.cpp
+++ b/graphics/ilbm.cpp
@@ -135,7 +135,8 @@ page 376) */
 /* ? */
 #define ID_TINY     MKID_BE('TINY')
 /* ? */
-
+#define ID_DPPV     MKID_BE('DPPV')
+/* ? */
 
 void IFFDecoder::readBMHD() {
 
@@ -156,19 +157,22 @@ void IFFDecoder::readBMHD() {
 
 
 	_colorCount = 1 << _bitmapHeader.depth;
-	_colors = (byte*)malloc(sizeof(*_colors) * _colorCount * 3);
+	*_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3);
 	_surface->create(_bitmapHeader.width, _bitmapHeader.height, 1);
 
 }
 
+void IFFDecoder::readCRNG() {
+}
+
 void IFFDecoder::readCMAP() {
-	if (_colors == NULL) {
+	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();
+		(*_colors)[i * 3 + 0] = _chunk.readByte();
+		(*_colors)[i * 3 + 1] = _chunk.readByte();
+		(*_colors)[i * 3 + 2] = _chunk.readByte();
 	}
 }
 
@@ -181,7 +185,8 @@ IFFDecoder::IFFDecoder(Common::ReadStream &input) : _formChunk(&input), _chunk(&
 
 void IFFDecoder::decode(Surface &surface, byte *&colors) {
 	_surface = &surface;
-	_colors = colors;
+	_colors = &colors;
+	*_colors = 0;
 
 	if (!isTypeSupported(_formChunk.readUint32())) {
 		error( "IFFDecoder input is not a valid subtype");
@@ -205,10 +210,10 @@ void IFFDecoder::decode(Surface &surface, byte *&colors) {
 			break;
 
 		case ID_CRNG:
-//				readCRNG();
+			readCRNG();
 			break;
 
-		case ID_GRAB: case ID_TINY: case ID_DPPS:
+		case ID_GRAB: case ID_TINY: case ID_DPPS: case ID_DPPV: case ID_CAMG:
 			break;
 
 		default:
@@ -224,7 +229,7 @@ bool PBMDecoder::isTypeSupported(IFF_ID type) {
 	return type == ID_PBM;
 }
 
-void PBMDecoder::readBody() {
+void PBMDecoder::readBODY() {
 	byte byteRun;
 	byte idx;
 	uint32 si = 0, i, j;
@@ -266,6 +271,110 @@ void PBMDecoder::readBody() {
 
 }
 
+
+bool ILBMDecoder::isTypeSupported(IFF_ID type) {
+	return type == ID_ILBM;
+}
+
+void ILBMDecoder::expandLine(byte *buf, uint32 width) {
+
+	byte byteRun;
+	byte idx;
+
+	uint32 si = 0, i, j;
+
+	while (si != width) {
+		byteRun = _chunk.readByte();
+		if (byteRun <= 127) {
+			i = byteRun + 1;
+			for (j = 0; j < i; j++){
+				idx = _chunk.readByte();
+				buf[si++] = idx;
+			}
+		} else if (byteRun != 128) {
+			i = (256 - byteRun) + 1;
+			idx = _chunk.readByte();
+			for (j = 0; j < i; j++) {
+				buf[si++] = idx;
+			}
+		}
+	}
+
+}
+
+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;
+	}
+
+}
+
+void ILBMDecoder::readBODY() {
+
+	if (_bitmapHeader.depth > 8) {
+		error("ILBMDecoder depth > 8");
+	}
+
+	if (_bitmapHeader.pack != 1) {
+		error("ILBMDecoder unsupported pack");
+	}
+
+	if (_bitmapHeader.masking == 1) {
+		error("ILBMDecoder mask not supported");
+	}
+
+	uint32 scanWidth = _bitmapHeader.width >> 3;
+	byte *scan = (byte*)malloc(scanWidth);
+	byte *out = (byte*)_surface->pixels;
+
+	switch (_bitmapHeader.pack) {
+//	case 0:
+//		while (!_chunk.eos()) {
+//			idx = _chunk.readByte();
+//			((byte*)_surface->pixels)[si++] = idx;
+//		}
+//		break;
+	case 1:
+		for (uint32 line = 0; line < _bitmapHeader.height; line++) {
+
+			for (uint32 plane = 0; plane < _bitmapHeader.depth; plane++) {
+				expandLine(scan, scanWidth);
+				fillPlane(out, scan, scanWidth, plane);
+			}
+
+			out += _bitmapHeader.width;
+		}
+		break;
+	}
+
+	free(scan);
+
+}
+
+void ILBMDecoder::readCRNG() {
+	// TODO: implement this. May require changing decode(), too, or adding
+	// another parameter to ILBMDecoder constructor
+}
+
+ILBMDecoder::ILBMDecoder(Common::ReadStream &input) : IFFDecoder(input) {
+
+}
+
+ILBMDecoder::~ILBMDecoder() {
+
+}
+
+
+
 void decodeILBM(Common::ReadStream &input, Surface &surface, byte *&colors) {
 	IFF_ID typeId;
 	BMHD bitmapHeader;
@@ -274,7 +383,7 @@ void decodeILBM(Common::ReadStream &input, Surface &surface, byte *&colors) {
 	uint32 colorCount = 0, i, j, si;
 	byte byteRun;
 	byte idx;
-	colors = 0; 
+	colors = 0;
 	si = 0;
 
 	formChunk.readHeader();
diff --git a/graphics/ilbm.h b/graphics/ilbm.h
index 45c01933f51..8c50d9fe5e0 100644
--- a/graphics/ilbm.h
+++ b/graphics/ilbm.h
@@ -125,13 +125,14 @@ protected:
 	uint32 	_colorCount;
 
 	Surface *_surface;
-	byte    *_colors;
+	byte    **_colors;
 
 	virtual bool isTypeSupported(IFF_ID type) = 0;
 	virtual void readBODY() = 0;
 
 	virtual void readBMHD();
 	virtual void readCMAP();
+	virtual void readCRNG();
 };
 
 class PBMDecoder : public IFFDecoder {
@@ -139,7 +140,23 @@ public:
 	PBMDecoder(Common::ReadStream &input) : IFFDecoder(input) {}
 protected:
 	bool isTypeSupported(IFF_ID type);
-	void readBody();
+	void readBODY();
+};
+
+
+
+class ILBMDecoder : public IFFDecoder {
+
+protected:
+	bool isTypeSupported(IFF_ID type);
+	void readBODY();
+	void readCRNG();
+	void expandLine(byte *buf, uint32 width);
+	void fillPlane(byte *out, byte* buf, uint32 width, uint32 plane);
+
+public:
+	ILBMDecoder(Common::ReadStream &input);
+	~ILBMDecoder();
 };
 
 }	// End of namespace Graphics