diff options
-rw-r--r-- | common/winexe_ne.cpp | 277 | ||||
-rw-r--r-- | common/winexe_ne.h | 59 | ||||
-rw-r--r-- | engines/mohawk/cursors.cpp | 19 | ||||
-rw-r--r-- | graphics/module.mk | 3 | ||||
-rw-r--r-- | graphics/wincursor.cpp | 235 | ||||
-rw-r--r-- | graphics/wincursor.h | 94 |
6 files changed, 340 insertions, 347 deletions
diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp index 3149528566..eedda1ec66 100644 --- a/common/winexe_ne.cpp +++ b/common/winexe_ne.cpp @@ -32,153 +32,6 @@ namespace Common { -NECursor::NECursor() { - _width = 0; - _height = 0; - _hotspotX = 0; - _hotspotY = 0; - _surface = 0; - _keyColor = 0; - memset(_palette, 0, 256 * 3); -} - -NECursor::~NECursor() { - clear(); -} - -uint16 NECursor::getWidth() const { - return _width; -} - -uint16 NECursor::getHeight() const { - return _height; -} - -uint16 NECursor::getHotspotX() const { - return _hotspotX; -} - -uint16 NECursor::getHotspotY() const { - return _hotspotY; -} - -byte NECursor::getKeyColor() const { - return _keyColor; -} - -void NECursor::setDimensions(uint16 width, uint16 height) { - _width = width; - _height = height; -} - -void NECursor::setHotspot(uint16 x, uint16 y) { - _hotspotX = x; - _hotspotY = y; -} - -bool NECursor::readCursor(SeekableReadStream &stream, uint32 count) { - clear(); - - SeekableReadStream *bitmap = stream.readStream(count); - _surface = new byte[_width * _height]; - - uint32 width = _width; - uint32 height = _height * 2; - - // Sanity checks - assert((width > 0) && (height > 0)); - - // Check header size - if (bitmap->readUint32LE() != 40) - return false; - - // Check dimensions - if (bitmap->readUint32LE() != width) - return false; - if (bitmap->readUint32LE() != height) - return false; - - // Color planes - if (bitmap->readUint16LE() != 1) - return false; - // Bits per pixel - if (bitmap->readUint16LE() != 1) - return false; - // Compression - if (bitmap->readUint32LE() != 0) - return false; - - // Image size + X resolution + Y resolution - bitmap->skip(12); - - uint32 numColors = bitmap->readUint32LE(); - - if (numColors == 0) - numColors = 2; - else if (numColors > 2) - return false; - - // Assert that enough data is there for the whole cursor - if ((uint32)bitmap->size() < 40 + numColors * 4 + width * height / 8) - return false; - - // Height includes AND-mask and XOR-mask - height /= 2; - - // Standard palette: transparent, black, white - _palette[6] = 0xff; - _palette[7] = 0xff; - _palette[8] = 0xff; - - // Reading the palette - bitmap->seek(40); - for (uint32 i = 0 ; i < numColors; i++) { - _palette[(i + 1) * 3 + 2] = bitmap->readByte(); - _palette[(i + 1) * 3 + 1] = bitmap->readByte(); - _palette[(i + 1) * 3 + 0] = bitmap->readByte(); - bitmap->readByte(); - } - - // Reading the bitmap data - uint32 dataSize = bitmap->size() - 40 - numColors * 4; - byte *initialSource = new byte[dataSize]; - bitmap->read(initialSource, dataSize); - const byte *srcP = initialSource; - const byte *srcM = srcP + ((width * height) / 8); - byte *dest = _surface + width * (height - 1); - - 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]; - - for (int k = 0; k < 8; k++, rowDest++, p <<= 1, m <<= 1) { - if ((m & 0x80) != 0x80) { - if ((p & 0x80) == 0x80) - *rowDest = 2; - else - *rowDest = 1; - } else - *rowDest = _keyColor; - } - } - - dest -= width; - srcP += width / 8; - srcM += width / 8; - } - - delete bitmap; - delete[] initialSource; - return true; -} - -void NECursor::clear() { - delete[] _surface; _surface = 0; -} - NEResources::NEResources() { _exe = 0; } @@ -194,16 +47,6 @@ void NEResources::clear() { } _resources.clear(); - - for (uint32 i = 0; i < _cursors.size(); i++) - for (uint32 j = 0; j < _cursors[i].cursors.size(); j++) - delete _cursors[i].cursors[j]; - - _cursors.clear(); -} - -const Array<NECursorGroup> &NEResources::getCursors() const { - return _cursors; } bool NEResources::loadFromEXE(const String &fileName) { @@ -237,9 +80,6 @@ bool NEResources::loadFromEXE(SeekableReadStream *stream) { if (!readResourceTable(offsetResourceTable)) return false; - if (!readCursors()) - return false; - return true; } @@ -444,121 +284,4 @@ const Array<WinResourceID> NEResources::getIDList(uint16 type) const { return idArray; } -bool NEResources::readCursors() { - uint32 cursorCount = 0; - - for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) - if (it->type == kNEGroupCursor) - cursorCount++; - - if (cursorCount == 0) { - _cursors.clear(); - return true; - } - - _cursors.resize(cursorCount); - - Array<NECursorGroup>::iterator cursorGroup = _cursors.begin(); - for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) { - if (it->type == kNEGroupCursor) { - if (!readCursorGroup(*cursorGroup, *it)) - return false; - - ++cursorGroup; - } - } - - return true; -} - -bool NEResources::readCursorGroup(NECursorGroup &group, const Resource &resource) { - if (!_exe) - return false; - - if (resource.size <= 6) - return false; - - if (!_exe->seek(resource.offset)) - return false; - - byte *data = new byte[resource.size]; - - if (!_exe->read(data, resource.size)) { - delete[] data; - return false; - } - - uint32 cursorCount = READ_LE_UINT16(data + 4); - if (resource.size < (6 + cursorCount * 16)) { - delete[] data; - return false; - } - - group.cursors.resize(cursorCount); - - uint32 offset = 6; - for (uint32 i = 0; i < cursorCount; i++) { - group.cursors[i] = new NECursor(); - NECursor *cursor = group.cursors[i]; - - // Plane count - if (READ_LE_UINT16(data + offset + 4) != 1) { - delete[] data; - return false; - } - - // Bit count - if (READ_LE_UINT16(data + offset + 6) != 1) { - delete[] data; - return false; - } - - uint32 id = READ_LE_UINT32(data + offset + 12); - const Resource *cursorResource = findResource(kNECursor, id); - if (!cursorResource) { - delete[] data; - return false; - } - - cursor->setDimensions(READ_LE_UINT16(data + offset), READ_LE_UINT16(data + offset + 2) / 2); - - uint32 dataSize = READ_LE_UINT32(data + offset + 8); - if (!readCursor(*cursor, *cursorResource, dataSize)) { - delete[] data; - return false; - } - - offset += 16; - } - - group.id = resource.id; - - delete[] data; - return true; -} - -bool NEResources::readCursor(NECursor &cursor, const Resource &resource, uint32 size) { - if (!_exe) - return false; - - if (size <= 4) - return false; - if (resource.size < size) - return false; - - if (!_exe->seek(resource.offset)) - return false; - - uint32 hotspotX = _exe->readUint16LE(); - uint32 hotspotY = _exe->readUint16LE(); - cursor.setHotspot(hotspotX, hotspotY); - - size -= 4; - - if (!cursor.readCursor(*_exe, size)) - return false; - - return true; -} - } // End of namespace Common diff --git a/common/winexe_ne.h b/common/winexe_ne.h index 562c8f72da..c1d04080ba 100644 --- a/common/winexe_ne.h +++ b/common/winexe_ne.h @@ -36,54 +36,6 @@ class MemoryReadStream; class SeekableReadStream; class String; -/** A New Executable cursor. */ -class NECursor { -public: - NECursor(); - ~NECursor(); - - /** Return the cursor's width. */ - uint16 getWidth() const; - /** Return the cursor's height. */ - uint16 getHeight() const; - /** Return the cursor's hotspot's x coordinate. */ - uint16 getHotspotX() const; - /** Return the cursor's hotspot's y coordinate. */ - uint16 getHotspotY() const; - /** Return the cursor's transparent key. */ - byte getKeyColor() const; - - const byte *getSurface() const { return _surface; } - const byte *getPalette() const { return _palette; } - - /** Set the cursor's dimensions. */ - void setDimensions(uint16 width, uint16 height); - /** Set the cursor's hotspot. */ - void setHotspot(uint16 x, uint16 y); - - /** Read the cursor's data out of a stream. */ - bool readCursor(SeekableReadStream &stream, uint32 count); - -private: - byte *_surface; - byte _palette[256 * 3]; - - uint16 _width; ///< The cursor's width. - uint16 _height; ///< The cursor's height. - uint16 _hotspotX; ///< The cursor's hotspot's x coordinate. - uint16 _hotspotY; ///< The cursor's hotspot's y coordinate. - byte _keyColor; ///< The cursor's transparent key - - /** Clear the cursor. */ - void clear(); -}; - -/** A New Executable cursor group. */ -struct NECursorGroup { - WinResourceID id; - Array<NECursor *> cursors; ///< The cursors. -}; - /** The default Windows resources. */ enum NEResourceType { kNECursor = 0x8001, @@ -132,9 +84,6 @@ public: /** Load from a stream. */ bool loadFromEXE(SeekableReadStream *stream); - /** Get all cursor's read from the New Executable. */ - const Array<NECursorGroup> &getCursors() const; - /** Return a list of resources for a given type. */ const Array<WinResourceID> getIDList(uint16 type) const; @@ -161,19 +110,11 @@ private: /** All resources. */ List<Resource> _resources; - /** All cursor resources. */ - Array<NECursorGroup> _cursors; - /** Read the offset to the resource table. */ uint32 getResourceTableOffset(); /** Read the resource table. */ bool readResourceTable(uint32 offset); - // Cursor reading helpers - bool readCursors(); - bool readCursorGroup(NECursorGroup &group, const Resource &resource); - bool readCursor(NECursor &cursor, const Resource &resource, uint32 size); - /** Find a specific resource. */ const Resource *findResource(uint16 type, WinResourceID id) const; diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index cdfdbb3a78..fe4b434f9c 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -34,6 +34,7 @@ #include "common/system.h" #include "common/winexe_ne.h" #include "graphics/cursorman.h" +#include "graphics/wincursor.h" namespace Mohawk { @@ -295,16 +296,14 @@ NECursorManager::~NECursorManager() { } void NECursorManager::setCursor(uint16 id) { - if (!_exe) { - Common::Array<Common::NECursorGroup> cursors = _exe->getCursors(); - - for (uint32 i = 0; i < cursors.size(); i++) { - if (cursors[i].id == id) { - Common::NECursor *cursor = cursors[i].cursors[0]; - CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); - CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); - return; - } + if (_exe) { + Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id); + + if (cursorGroup) { + Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor; + CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); + CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); + return; } } diff --git a/graphics/module.mk b/graphics/module.mk index c962f0617d..cb3a07e691 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -23,7 +23,8 @@ MODULE_OBJS := \ surface.o \ thumbnail.o \ VectorRenderer.o \ - VectorRendererSpec.o + VectorRendererSpec.o \ + wincursor.o ifdef USE_SCALERS MODULE_OBJS += \ diff --git a/graphics/wincursor.cpp b/graphics/wincursor.cpp new file mode 100644 index 0000000000..68b4023c0a --- /dev/null +++ b/graphics/wincursor.cpp @@ -0,0 +1,235 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "common/debug.h" +#include "common/file.h" +#include "common/memstream.h" +#include "common/str.h" +#include "common/stream.h" +#include "common/winexe_ne.h" + +#include "graphics/wincursor.h" + +namespace Graphics { + +WinCursor::WinCursor() { + _width = 0; + _height = 0; + _hotspotX = 0; + _hotspotY = 0; + _surface = 0; + _keyColor = 0; + memset(_palette, 0, 256 * 3); +} + +WinCursor::~WinCursor() { + clear(); +} + +uint16 WinCursor::getWidth() const { + return _width; +} + +uint16 WinCursor::getHeight() const { + return _height; +} + +uint16 WinCursor::getHotspotX() const { + return _hotspotX; +} + +uint16 WinCursor::getHotspotY() const { + return _hotspotY; +} + +byte WinCursor::getKeyColor() const { + return _keyColor; +} + +bool WinCursor::readFromStream(Common::SeekableReadStream &stream) { + clear(); + + _hotspotX = stream.readUint16LE(); + _hotspotY = stream.readUint16LE(); + + // Check header size + if (stream.readUint32LE() != 40) + return false; + + // Check dimensions + _width = stream.readUint32LE(); + _height = stream.readUint32LE() / 2; + + // Color planes + if (stream.readUint16LE() != 1) + return false; + // Bits per pixel + if (stream.readUint16LE() != 1) + return false; + // Compression + if (stream.readUint32LE() != 0) + return false; + + // Image size + X resolution + Y resolution + stream.skip(12); + + uint32 numColors = stream.readUint32LE(); + + 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; + + // 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(); + stream.readByte(); + } + + // Reading the bitmap data + 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); + + _surface = new byte[_width * _height]; + byte *dest = _surface + _width * (_height - 1); + + 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]; + + for (int k = 0; k < 8; k++, rowDest++, p <<= 1, m <<= 1) { + if ((m & 0x80) != 0x80) { + if ((p & 0x80) == 0x80) + *rowDest = 2; + else + *rowDest = 1; + } else + *rowDest = _keyColor; + } + } + + dest -= _width; + srcP += _width / 8; + srcM += _width / 8; + } + + delete[] initialSource; + return true; +} + +void WinCursor::clear() { + delete[] _surface; _surface = 0; +} + +WinCursorGroup::WinCursorGroup() { +} + +WinCursorGroup::~WinCursorGroup() { + for (uint32 i = 0; i < cursors.size(); i++) + delete cursors[i].cursor; +} + +WinCursorGroup *WinCursorGroup::createCursorGroup(Common::NEResources &exe, const Common::WinResourceID &id) { + Common::SeekableReadStream *stream = exe.getResource(Common::kNEGroupCursor, id); + + if (!stream || stream->size() <= 6) + return 0; + + stream->skip(4); + uint32 cursorCount = stream->readUint16LE(); + if ((uint32)stream->size() < (6 + cursorCount * 16)) + return 0; + + WinCursorGroup *group = new WinCursorGroup(); + group->cursors.reserve(cursorCount); + + for (uint32 i = 0; i < cursorCount; i++) { + stream->readUint16LE(); // width + stream->readUint16LE(); // height + + // Plane count + if (stream->readUint16LE() != 1) { + delete stream; + delete group; + return 0; + } + + // Bit count + if (stream->readUint16LE() != 1) { + delete stream; + delete group; + return 0; + } + + stream->readUint32LE(); // data size + uint32 cursorId = stream->readUint32LE(); + + Common::SeekableReadStream *cursorStream = exe.getResource(Common::kNECursor, cursorId); + if (!cursorStream) { + delete stream; + delete group; + return 0; + } + + WinCursor *cursor = new WinCursor(); + if (!cursor->readFromStream(*cursorStream)) { + delete stream; + delete cursorStream; + delete cursor; + delete group; + return 0; + } + + delete cursorStream; + + CursorItem item; + item.id = cursorId; + item.cursor = cursor; + group->cursors.push_back(item); + } + + delete stream; + return group; +} + +} // End of namespace Graphics diff --git a/graphics/wincursor.h b/graphics/wincursor.h new file mode 100644 index 0000000000..3e2fc55bb8 --- /dev/null +++ b/graphics/wincursor.h @@ -0,0 +1,94 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef GRAPHICS_WINCURSOR_H +#define GRAPHICS_WINCURSOR_H + +#include "common/array.h" +#include "common/winexe.h" + +namespace Common { + class NEResources; + class PEResources; + class SeekableReadStream; +} + +namespace Graphics { + +/** A Windows cursor. */ +class WinCursor { +public: + WinCursor(); + ~WinCursor(); + + /** Return the cursor's width. */ + uint16 getWidth() const; + /** Return the cursor's height. */ + uint16 getHeight() const; + /** Return the cursor's hotspot's x coordinate. */ + uint16 getHotspotX() const; + /** Return the cursor's hotspot's y coordinate. */ + uint16 getHotspotY() const; + /** Return the cursor's transparent key. */ + byte getKeyColor() const; + + const byte *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + + /** Read the cursor's data out of a stream. */ + bool readFromStream(Common::SeekableReadStream &stream); + +private: + byte *_surface; + byte _palette[256 * 3]; + + uint16 _width; ///< The cursor's width. + uint16 _height; ///< The cursor's height. + uint16 _hotspotX; ///< The cursor's hotspot's x coordinate. + uint16 _hotspotY; ///< The cursor's hotspot's y coordinate. + byte _keyColor; ///< The cursor's transparent key + + /** Clear the cursor. */ + void clear(); +}; + +struct WinCursorGroup { + WinCursorGroup(); + ~WinCursorGroup(); + + struct CursorItem { + Common::WinResourceID id; + WinCursor *cursor; + }; + + Common::Array<CursorItem> cursors; + + static WinCursorGroup *createCursorGroup(Common::NEResources &exe, const Common::WinResourceID &id); + //static WinCursorGroup *createCursorGroup(Common::PEResources &exe, const Common::WinResourceID &id); +}; + +} // End of namespace Graphics + +#endif |