aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--graphics/wincursor.cpp99
1 files changed, 59 insertions, 40 deletions
diff --git a/graphics/wincursor.cpp b/graphics/wincursor.cpp
index 8690e1b18f..2f3f29d8a0 100644
--- a/graphics/wincursor.cpp
+++ b/graphics/wincursor.cpp
@@ -83,12 +83,22 @@ bool WinCursor::readFromStream(Common::SeekableReadStream &stream) {
_width = stream.readUint32LE();
_height = stream.readUint32LE() / 2;
+ if (_width & 3) {
+ // Cursors should always be a power of 2
+ // Of course, it wouldn't be hard to handle but if we have no examples...
+ warning("Non-divisible-by-4 width cursor found");
+ return false;
+ }
+
// Color planes
if (stream.readUint16LE() != 1)
return false;
- // Bits per pixel
- if (stream.readUint16LE() != 1)
+
+ // Only 1bpp and 8bpp supported
+ uint16 bitsPerPixel = stream.readUint16LE();
+ if (bitsPerPixel != 1 && bitsPerPixel != 8)
return false;
+
// Compression
if (stream.readUint32LE() != 0)
return false;
@@ -98,26 +108,16 @@ bool WinCursor::readFromStream(Common::SeekableReadStream &stream) {
uint32 numColors = stream.readUint32LE();
+ // If the color count is 0, then it uses up the maximum amount
if (numColors == 0)
- numColors = 2;
- else if (numColors > 2)
- return false;
-
- // Sanity check: ensure that enough data is there for the whole cursor
- if ((uint32)(stream.size() - stream.pos()) < 40 + numColors * 4 + _width * _height * 2 / 8)
- return false;
-
- // Standard palette: transparent, black, white
- _palette[6] = 0xff;
- _palette[7] = 0xff;
- _palette[8] = 0xff;
+ numColors = 1 << bitsPerPixel;
// Reading the palette
stream.seek(40 + 4);
for (uint32 i = 0 ; i < numColors; i++) {
- _palette[(i + 1) * 3 + 2] = stream.readByte();
- _palette[(i + 1) * 3 + 1] = stream.readByte();
- _palette[(i + 1) * 3 + 0] = stream.readByte();
+ _palette[i * 3 + 2] = stream.readByte();
+ _palette[i * 3 + 1] = stream.readByte();
+ _palette[i * 3 ] = stream.readByte();
stream.readByte();
}
@@ -125,33 +125,57 @@ bool WinCursor::readFromStream(Common::SeekableReadStream &stream) {
uint32 dataSize = stream.size() - stream.pos();
byte *initialSource = new byte[dataSize];
stream.read(initialSource, dataSize);
- const byte *srcP = initialSource;
- const byte *srcM = srcP + ((_width * _height) / 8);
+ // Parse the XOR map
+ const byte *src = initialSource;
_surface = new byte[_width * _height];
byte *dest = _surface + _width * (_height - 1);
+ uint32 imagePitch = _width * bitsPerPixel / 8;
for (uint32 i = 0; i < _height; i++) {
byte *rowDest = dest;
- for (uint32 j = 0; j < (_width / 8); j++) {
- byte p = srcP[j];
- byte m = srcM[j];
+ if (bitsPerPixel == 1) {
+ // 1bpp
+ for (uint32 j = 0; j < (_width / 8); j++) {
+ byte p = src[j];
- for (int k = 0; k < 8; k++, rowDest++, p <<= 1, m <<= 1) {
- if ((m & 0x80) != 0x80) {
+ for (int k = 0; k < 8; k++, rowDest++, p <<= 1) {
if ((p & 0x80) == 0x80)
- *rowDest = 2;
- else
*rowDest = 1;
- } else
- *rowDest = _keyColor;
+ else
+ *rowDest = 0;
+ }
}
+ } else {
+ // 8bpp
+ memcpy(rowDest, src, _width);
}
dest -= _width;
- srcP += _width / 8;
- srcM += _width / 8;
+ src += imagePitch;
+ }
+
+ // Calculate our key color
+ if (numColors < 256) {
+ // If we're not using the maximum colors in a byte, we can fit it in
+ _keyColor = numColors;
+ } else {
+ // TODO
+ warning("Handle 8bpp cursors with all colors");
+ return false;
+ }
+
+ // Now go through and apply the AND map to get the transparency
+ uint32 andWidth = (_width + 7) / 8;
+ src += andWidth * (_height - 1);
+
+ for (uint32 y = 0; y < _height; y++) {
+ for (uint32 x = 0; x < _width; x++)
+ if (src[x / 8] & (1 << (7 - x % 8)))
+ _surface[y * _width + x] = _keyColor;
+
+ src -= andWidth;
}
delete[] initialSource;
@@ -195,7 +219,8 @@ WinCursorGroup *WinCursorGroup::createCursorGroup(Common::NEResources &exe, cons
return 0;
}
- // Bit count
+ // Bits per pixel
+ // NE cursors can only be 1bpp
if (stream->readUint16LE() != 1) {
delete stream;
delete group;
@@ -241,7 +266,7 @@ WinCursorGroup *WinCursorGroup::createCursorGroup(Common::PEResources &exe, cons
stream->skip(4);
uint32 cursorCount = stream->readUint16LE();
- if ((uint32)stream->size() < (6 + cursorCount * 16))
+ if ((uint32)stream->size() < (6 + cursorCount * 14))
return 0;
WinCursorGroup *group = new WinCursorGroup();
@@ -258,15 +283,9 @@ WinCursorGroup *WinCursorGroup::createCursorGroup(Common::PEResources &exe, cons
return 0;
}
- // Bit count
- if (stream->readUint16LE() != 1) {
- delete stream;
- delete group;
- return 0;
- }
-
+ stream->readUint16LE(); // bits per pixel
stream->readUint32LE(); // data size
- uint32 cursorId = stream->readUint32LE();
+ uint32 cursorId = stream->readUint16LE();
Common::SeekableReadStream *cursorStream = exe.getResource(Common::kPECursor, cursorId);
if (!cursorStream) {