diff options
-rw-r--r-- | engines/mohawk/bitmap.cpp | 118 | ||||
-rw-r--r-- | engines/mohawk/bitmap.h | 15 |
2 files changed, 133 insertions, 0 deletions
diff --git a/engines/mohawk/bitmap.cpp b/engines/mohawk/bitmap.cpp index 6e829be477..d3d560b1a6 100644 --- a/engines/mohawk/bitmap.cpp +++ b/engines/mohawk/bitmap.cpp @@ -759,4 +759,122 @@ MohawkSurface *OldMohawkBitmap::decodeImage(Common::SeekableReadStream *stream) return mhkSurface; } +// Partially based on the Prince of Persia Format Specifications +// See http://sdfg.com.ar/git/?p=fp-git.git;a=blob;f=FP/doc/FormatSpecifications + +MohawkSurface *DOSBitmap::decodeImage(Common::SeekableReadStream *stream) { + _header.height = stream->readUint16LE(); + _header.width = stream->readUint16LE(); + stream->readByte(); // Always 0 + _header.format = stream->readByte(); + + debug(2, "Decoding DOS Bitmap (%dx%d, %dbpp, Compression %d)", _header.width, _header.height, getBitsPerPixel(), _header.format & 0xf); + + // All the PoP games seem to have this flag, but at least CSWorld Deluxe doesn't... + // Perhaps this differentiates between normal bitmap mode and planar mode? + if (_header.format & 0x80) + error("Unknown EGA flag?"); + + // Calculate the bytes per row + byte pixelsPerByte = 8 / getBitsPerPixel(); + _header.bytesPerRow = (_header.width + pixelsPerByte - 1) / pixelsPerByte; + + // Only Raw and LZ L/R are supported currently + // Notice how Broderbund used their same LZ compression for every PC game possibly ever? + switch (_header.format & 0xf) { + case 0: // Raw + _data = stream; + break; + case 3: // LZ Left/Right + _data = decompressLZ(stream, _header.bytesPerRow * _header.height); + delete stream; + break; + case 1: // RLE Left/Right (Used by PoP, haven't seen in a CS game) + case 2: // RLE Up/Down (Used by PoP, haven't seen in a CS game) + case 4: // LZ Up/Down (Used by CS America's Past and CS Space) + error("Unhandled DOS bitmap compression %d", _header.format & 0xf); + break; + default: + error("Unknown DOS bitmap compression %d", _header.format & 0xf); + } + + Graphics::Surface *surface = createSurface(_header.width, _header.height); + memset(surface->pixels, 0, _header.width * _header.height); + + // Expand the <8bpp data to one byte per pixel + switch (getBitsPerPixel()) { + case 1: + expandMonochromePlane(surface, _data); + break; + case 4: + expandEGAPlanes(surface, _data); + break; + default: + error("Unhandled %dbpp", getBitsPerPixel()); + } + + delete _data; + + return new MohawkSurface(surface); +} + +void DOSBitmap::expandMonochromePlane(Graphics::Surface *surface, Common::SeekableReadStream *rawStream) { + assert(surface->bytesPerPixel == 1); + + byte *dst = (byte *)surface->pixels; + + // Expand the 8 pixels in a byte into a full byte per pixel + + for (uint32 i = 0; i < surface->h; i++) { + for (uint x = 0; x < surface->w;) { + byte temp = rawStream->readByte(); + + for (int j = 7; j >= 0 && x < surface->w; j--) { + if (temp & (1 << j)) + *dst++ = 0xf; + else + *dst++ = 0; + + x++; + } + } + } +} + +#define ADD_BIT(dstPixel, srcBit) \ + *(dst + j * 4 + dstPixel) = (*(dst + j * 4 + dstPixel) >> 1) | (((temp >> srcBit) & 1) << 3) + +void DOSBitmap::expandEGAPlanes(Graphics::Surface *surface, Common::SeekableReadStream *rawStream) { + assert(surface->bytesPerPixel == 1); + + // Note that the image is in EGA planar form and not just standard 4bpp + // This seems to contradict the PoP specs which seem to do + + byte *dst = (byte *)surface->pixels; + + for (uint32 i = 0; i < surface->h; i++) { + uint x = 0; + + for (int32 j = 0; j < surface->w / 4; j++) { + byte temp = rawStream->readByte(); + ADD_BIT(3, 4); + ADD_BIT(2, 5); + ADD_BIT(1, 6); + ADD_BIT(0, 7); + j++; + ADD_BIT(3, 0); + ADD_BIT(2, 1); + ADD_BIT(1, 2); + ADD_BIT(0, 3); + + if (x < 3 && j + 1 >= surface->w / 4) { + j = -1; + x++; + } + } + + dst += surface->w; + } +} + } // End of namespace Mohawk diff --git a/engines/mohawk/bitmap.h b/engines/mohawk/bitmap.h index 8f3f6af436..6dd6b1115d 100644 --- a/engines/mohawk/bitmap.h +++ b/engines/mohawk/bitmap.h @@ -188,6 +188,21 @@ protected: byte getBitsPerPixel() { return 8; } }; +class DOSBitmap : public MohawkBitmap { +public: + DOSBitmap() : MohawkBitmap() {} + ~DOSBitmap() {} + + MohawkSurface *decodeImage(Common::SeekableReadStream *stream); + +protected: + byte getBitsPerPixel() { return ((_header.format & 0x30) >> 4) + 1; } + +private: + void expandMonochromePlane(Graphics::Surface *surface, Common::SeekableReadStream *rawStream); + void expandEGAPlanes(Graphics::Surface *surface, Common::SeekableReadStream *rawStream); +}; + } // End of namespace Mohawk #endif |