[Scummvm-git-logs] scummvm master -> 7a4ef281779d47fd9f76674320ab86c2878ad978
eriktorbjorn
noreply at scummvm.org
Sat Jan 4 10:55:22 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
7a4ef28177 PEGASUS: Replaced cicn cursor loader, fixing #15600 in the process
Commit: 7a4ef281779d47fd9f76674320ab86c2878ad978
https://github.com/scummvm/scummvm/commit/7a4ef281779d47fd9f76674320ab86c2878ad978
Author: Torbjörn Andersson (eriktorbjorn at users.sourceforge.net)
Date: 2025-01-04T11:54:58+01:00
Commit Message:
PEGASUS: Replaced cicn cursor loader, fixing #15600 in the process
The cicn cursor loader was introduced recently for the Mac SCUMM v6-7
games. I still haven't played Pegasus Prime, but I have forced it to
load all the nine cursors (ID 128-133, 900-901, and 20000) and it seems
to work fine for all of them. At least after I made a few fixes to the
loader itself.
I did get some crashes with the old code when trying to compare them, so
it's possible that we should backport this to 2.9. But I haven't seen
any bug reports about it, so maybe not...?
Changed paths:
engines/pegasus/cursor.cpp
image/cicn.cpp
diff --git a/engines/pegasus/cursor.cpp b/engines/pegasus/cursor.cpp
index b4c790ff39b..c23b4645afc 100644
--- a/engines/pegasus/cursor.cpp
+++ b/engines/pegasus/cursor.cpp
@@ -27,6 +27,7 @@
#include "common/system.h"
#include "graphics/cursorman.h"
#include "graphics/surface.h"
+#include "image/cicn.h"
#include "image/pict.h"
#include "pegasus/cursor.h"
@@ -154,74 +155,17 @@ void Cursor::loadCursorImage(CursorInfo &cursorInfo) {
// The CD version uses (only) lower color cicn images for its cursors
Common::SeekableReadStream *cicnStream = g_vm->_resFork->getResource(MKTAG('c', 'i', 'c', 'n'), cursorInfo.tag);
- if (!cicnStream)
- error("Failed to find color icon %d", cursorInfo.tag);
-
- // PixMap section
- Image::PICTDecoder::PixMap pixMap = Image::PICTDecoder::readPixMap(*cicnStream);
-
- // Mask section
- cicnStream->readUint32BE(); // mask baseAddr
- uint16 maskRowBytes = cicnStream->readUint16BE(); // mask rowBytes
- cicnStream->skip(3 * 2); // mask rect
- /* uint16 maskHeight = */ cicnStream->readUint16BE();
-
- // Bitmap section
- cicnStream->readUint32BE(); // baseAddr
- uint16 rowBytes = cicnStream->readUint16BE();
- cicnStream->readUint16BE(); // top
- cicnStream->readUint16BE(); // left
- uint16 height = cicnStream->readUint16BE(); // bottom
- cicnStream->readUint16BE(); // right
-
- // Data section
- cicnStream->readUint32BE(); // icon handle
- cicnStream->skip(maskRowBytes * height); // FIXME: maskHeight doesn't work here, though the specs say it should
- cicnStream->skip(rowBytes * height);
-
- // Palette section
- cicnStream->readUint32BE(); // always 0
- cicnStream->readUint16BE(); // always 0
- cursorInfo.colorCount = cicnStream->readUint16BE() + 1;
-
- cursorInfo.palette = new byte[cursorInfo.colorCount * 3];
- for (uint16 i = 0; i < cursorInfo.colorCount; i++) {
- cicnStream->readUint16BE();
- cursorInfo.palette[i * 3] = cicnStream->readUint16BE() >> 8;
- cursorInfo.palette[i * 3 + 1] = cicnStream->readUint16BE() >> 8;
- cursorInfo.palette[i * 3 + 2] = cicnStream->readUint16BE() >> 8;
- }
-
- // PixMap data
- if (pixMap.pixelSize == 8) {
- cursorInfo.surface->create(pixMap.rowBytes, pixMap.bounds.height(), Graphics::PixelFormat::createFormatCLUT8());
- cicnStream->read(cursorInfo.surface->getPixels(), pixMap.rowBytes * pixMap.bounds.height());
-
- // While this looks sensible, it actually doesn't work for some cursors
- // (ie. the 'can grab' hand)
- //cursorInfo.surface->w = pixMap.bounds.width();
- } else if (pixMap.pixelSize == 1) {
- cursorInfo.surface->create(pixMap.bounds.width(), pixMap.bounds.height(), Graphics::PixelFormat::createFormatCLUT8());
-
- for (int y = 0; y < pixMap.bounds.height(); y++) {
- byte *line = (byte *)cursorInfo.surface->getBasePtr(0, y);
-
- for (int x = 0; x < pixMap.bounds.width();) {
- byte b = cicnStream->readByte();
+ if (cicnStream) {
+ Image::CicnDecoder cicn;
+ if (!cicn.loadStream(*cicnStream))
+ error("Failed to decode cursor cicn %d", cursorInfo.tag);
- for (int i = 0; i < 8; i++) {
- *line++ = ((b & (1 << (7 - i))) != 0) ? 1 : 0;
-
- if (++x == pixMap.bounds.width())
- break;
- }
- }
- }
- } else {
- error("Unhandled %dbpp cicn images", pixMap.pixelSize);
+ cursorInfo.surface = cicn.getSurface()->convertTo(g_system->getScreenFormat(), cicn.getPalette(), cicn.getPaletteColorCount());
+ delete cicnStream;
+ return;
}
- delete cicnStream;
+ error("Failed to find color icon %d", cursorInfo.tag);
}
} // End of namespace Pegasus
diff --git a/image/cicn.cpp b/image/cicn.cpp
index b7c05648e9d..8ff345b381a 100644
--- a/image/cicn.cpp
+++ b/image/cicn.cpp
@@ -79,7 +79,7 @@ bool CicnDecoder::loadStream(Common::SeekableReadStream &stream) {
stream.readUint16BE(); // top
stream.readUint16BE(); // left
uint16 bitmapHeight = stream.readUint16BE(); // bottom
- stream.readUint16BE(); // right
+ uint16 bitmapWidth = stream.readUint16BE(); // right
// Mask and bitmap data
stream.skip(4);
@@ -122,12 +122,22 @@ bool CicnDecoder::loadStream(Common::SeekableReadStream &stream) {
_surface = new Graphics::Surface();
_surface->create(pixMap.bounds.width(), pixMap.bounds.height(), Graphics::PixelFormat::createFormatCLUT8());
- if (pixMap.pixelSize == 2) {
+ if (pixMap.pixelSize == 1) {
byte *buf = new byte[pixMap.rowBytes];
for (int y = 0; y < pixMap.bounds.height(); y++) {
stream.read(buf, pixMap.rowBytes);
- for (int x = 0; x < pixMap.bounds.width(); x += 4) {
- for (int i = 0; i < 4 && x + i < pixMap.bounds.width(); i++) {
+ for (int x = 0; x < bitmapWidth; x += 8) {
+ for (int i = 0; i < 8 && x + i < bitmapWidth; i++) {
+ _surface->setPixel(x + i, y, (buf[x / 8] >> (7 - i)) & 0x01);
+ }
+ }
+ }
+ } else if (pixMap.pixelSize == 2) {
+ byte *buf = new byte[pixMap.rowBytes];
+ for (int y = 0; y < bitmapHeight; y++) {
+ stream.read(buf, pixMap.rowBytes);
+ for (int x = 0; x < bitmapWidth; x += 4) {
+ for (int i = 0; i < 4 && x + i < bitmapWidth; i++) {
_surface->setPixel(x + i, y, (buf[x / 4] >> (6 - 2 * i)) & 0x03);
}
}
@@ -135,17 +145,21 @@ bool CicnDecoder::loadStream(Common::SeekableReadStream &stream) {
delete[] buf;
} else if (pixMap.pixelSize == 4) {
byte *buf = new byte[pixMap.rowBytes];
- for (int y = 0; y < pixMap.bounds.height(); y++) {
+ for (int y = 0; y < bitmapHeight; y++) {
stream.read(buf, pixMap.rowBytes);
- for (int x = 0; x < pixMap.bounds.width(); x += 2) {
- for (int i = 0; i < 2 && x + i < pixMap.bounds.width(); i++) {
+ for (int x = 0; x < bitmapWidth; x += 2) {
+ for (int i = 0; i < 2 && x + i < bitmapWidth; i++) {
_surface->setPixel(x + i, y, (buf[x / 2] >> (4 - 4 * i)) & 0x0F);
}
}
}
delete[] buf;
} else if (pixMap.pixelSize == 8) {
- stream.read(_surface->getPixels(), pixMap.rowBytes * pixMap.bounds.height());
+ byte *buf = new byte[pixMap.rowBytes];
+ for (int y = 0; y < bitmapHeight; y++) {
+ stream.read(buf, pixMap.rowBytes);
+ memcpy(_surface->getBasePtr(0, y), buf, bitmapWidth);
+ }
} else {
error("CicnDecoder::loadStream(): Invalid pixel size %d", pixMap.pixelSize);
}
More information about the Scummvm-git-logs
mailing list