diff options
author | Eugene Sandulenko | 2010-01-11 20:41:07 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-01-11 20:41:07 +0000 |
commit | 80ee1de8e4d1d7e56e703c86ca28377b02d6d59f (patch) | |
tree | 1032b3870e38ff622f1152b08615b0f545360c97 | |
parent | 3145ee5379044785fde3bc897b46f236d5797be9 (diff) | |
download | scummvm-rg350-80ee1de8e4d1d7e56e703c86ca28377b02d6d59f.tar.gz scummvm-rg350-80ee1de8e4d1d7e56e703c86ca28377b02d6d59f.tar.bz2 scummvm-rg350-80ee1de8e4d1d7e56e703c86ca28377b02d6d59f.zip |
Move Mac Binary resource loader to common class. Plug tons of memory leaks along the way.
svn-id: r47258
-rw-r--r-- | common/macresman.cpp | 393 | ||||
-rw-r--r-- | common/macresman.h | 127 | ||||
-rw-r--r-- | common/module.mk | 1 | ||||
-rw-r--r-- | engines/scumm/he/resource_he.cpp | 303 | ||||
-rw-r--r-- | engines/scumm/he/resource_he.h | 41 |
5 files changed, 532 insertions, 333 deletions
diff --git a/common/macresman.cpp b/common/macresman.cpp new file mode 100644 index 0000000000..af9d89268a --- /dev/null +++ b/common/macresman.cpp @@ -0,0 +1,393 @@ +/* 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/scummsys.h" +#include "common/debug.h" +#include "common/file.h" +#include "common/util.h" + +#include "common/macresman.h" + +namespace Common { + +MacResManager::MacResManager(Common::String fileName) : _fileName(fileName), _resOffset(-1) { + _resFile.open(_fileName); + + if (!_resFile.isOpen()) { + error("Cannot open file %s", _fileName.c_str()); + } + + if (!init()) + error("Resource fork is missing in file '%s'", _fileName.c_str()); +} + +MacResManager::~MacResManager() { + for (int i = 0; i < _resMap.numTypes; i++) { + for (int j = 0; j < _resTypes[i].items; j++) { + if (_resLists[i][j].nameOffset != -1) { + delete _resLists[i][j].name; + } + } + delete _resLists[i]; + } + + delete _resLists; + delete _resTypes; + + _resFile.close(); +} + +#define MBI_INFOHDR 128 +#define MBI_ZERO1 0 +#define MBI_NAMELEN 1 +#define MBI_ZERO2 74 +#define MBI_ZERO3 82 +#define MBI_DFLEN 83 +#define MBI_RFLEN 87 +#define MAXNAMELEN 63 + +bool MacResManager::init() { + byte infoHeader[MBI_INFOHDR]; + int32 data_size, rsrc_size; + int32 data_size_pad, rsrc_size_pad; + int filelen; + + filelen = _resFile.size(); + _resFile.read(infoHeader, MBI_INFOHDR); + + // Maybe we have MacBinary? + if (infoHeader[MBI_ZERO1] == 0 && infoHeader[MBI_ZERO2] == 0 && + infoHeader[MBI_ZERO3] == 0 && infoHeader[MBI_NAMELEN] <= MAXNAMELEN) { + + // Pull out fork lengths + data_size = READ_BE_UINT32(infoHeader + MBI_DFLEN); + rsrc_size = READ_BE_UINT32(infoHeader + MBI_RFLEN); + + data_size_pad = (((data_size + 127) >> 7) << 7); + rsrc_size_pad = (((rsrc_size + 127) >> 7) << 7); + + // Length check + int sumlen = MBI_INFOHDR + data_size_pad + rsrc_size_pad; + + if (sumlen == filelen) + _resOffset = MBI_INFOHDR + data_size_pad; + } + + if (_resOffset == -1) // MacBinary check is failed + _resOffset = 0; // Maybe we have dumped fork? + + _resFile.seek(_resOffset); + + _dataOffset = _resFile.readUint32BE() + _resOffset; + _mapOffset = _resFile.readUint32BE() + _resOffset; + _dataLength = _resFile.readUint32BE(); + _mapLength = _resFile.readUint32BE(); + + // do sanity check + if (_dataOffset >= filelen || _mapOffset >= filelen || + _dataLength + _mapLength > filelen) { + _resOffset = -1; + return false; + } + + debug(7, "got header: data %d [%d] map %d [%d]", + _dataOffset, _dataLength, _mapOffset, _mapLength); + + readMap(); + + return true; +} + +MacResIDArray MacResManager::getResIDArray(const char *typeID) { + int typeNum = -1; + MacResIDArray res; + + for (int i = 0; i < _resMap.numTypes; i++) + if (strcmp(_resTypes[i].id, typeID) == 0) { + typeNum = i; + break; + } + + if (typeNum == -1) + return res; + + res.resize(_resTypes[typeNum].items); + + for (int i = 0; i < _resTypes[typeNum].items; i++) + res[i] = _resLists[typeNum][i].id; + + return res; +} + +char *MacResManager::getResName(const char *typeID, int16 resID) { + int i; + int typeNum = -1; + + for (i = 0; i < _resMap.numTypes; i++) + if (strcmp(_resTypes[i].id, typeID) == 0) { + typeNum = i; + break; + } + + if (typeNum == -1) + return NULL; + + for (i = 0; i < _resTypes[typeNum].items; i++) + if (_resLists[typeNum][i].id == resID) + return _resLists[typeNum][i].name; + + return NULL; +} + +byte *MacResManager::getResource(const char *typeID, int16 resID, int *size) { + int i; + int typeNum = -1; + int resNum = -1; + byte *buf; + int len; + + for (i = 0; i < _resMap.numTypes; i++) + if (strcmp(_resTypes[i].id, typeID) == 0) { + typeNum = i; + break; + } + + if (typeNum == -1) + return NULL; + + for (i = 0; i < _resTypes[typeNum].items; i++) + if (_resLists[typeNum][i].id == resID) { + resNum = i; + break; + } + + if (resNum == -1) + return NULL; + + _resFile.seek(_dataOffset + _resLists[typeNum][resNum].dataOffset); + + len = _resFile.readUint32BE(); + buf = (byte *)malloc(len); + + _resFile.read(buf, len); + + *size = len; + + return buf; +} + +void MacResManager::readMap() { + int i, j, len; + + _resFile.seek(_mapOffset + 22); + + _resMap.resAttr = _resFile.readUint16BE(); + _resMap.typeOffset = _resFile.readUint16BE(); + _resMap.nameOffset = _resFile.readUint16BE(); + _resMap.numTypes = _resFile.readUint16BE(); + _resMap.numTypes++; + + _resFile.seek(_mapOffset + _resMap.typeOffset + 2); + _resTypes = new ResType[_resMap.numTypes]; + + for (i = 0; i < _resMap.numTypes; i++) { + _resFile.read(_resTypes[i].id, 4); + _resTypes[i].id[4] = 0; + _resTypes[i].items = _resFile.readUint16BE(); + _resTypes[i].offset = _resFile.readUint16BE(); + _resTypes[i].items++; + + debug(8, "resType: <%s> items: %d offset: %d (0x%x)", _resTypes[i].id, _resTypes[i].items, _resTypes[i].offset, _resTypes[i].offset); + } + + _resLists = new ResPtr[_resMap.numTypes]; + + for (i = 0; i < _resMap.numTypes; i++) { + _resLists[i] = new Resource[_resTypes[i].items]; + _resFile.seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset); + + for (j = 0; j < _resTypes[i].items; j++) { + ResPtr resPtr = _resLists[i] + j; + + resPtr->id = _resFile.readUint16BE(); + resPtr->nameOffset = _resFile.readUint16BE(); + resPtr->dataOffset = _resFile.readUint32BE(); + _resFile.readUint32BE(); + resPtr->name = 0; + + resPtr->attr = resPtr->dataOffset >> 24; + resPtr->dataOffset &= 0xFFFFFF; + } + + for (j = 0; j < _resTypes[i].items; j++) { + if (_resLists[i][j].nameOffset != -1) { + _resFile.seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset); + + len = _resFile.readByte(); + _resLists[i][j].name = new char[len + 1]; + _resLists[i][j].name[len] = 0; + _resFile.read(_resLists[i][j].name, len); + } + } + } +} + +void MacResManager::convertCursor(byte *data, int datasize, byte **cursor, int *w, int *h, + int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize) { + Common::MemoryReadStream dis(data, datasize); + int i, b; + byte imageByte; + byte *iconData; + int numBytes; + int pixelsPerByte, bpp; + int ctSize; + byte bitmask; + int iconRowBytes, iconBounds[4]; + int ignored; + int iconDataSize; + + dis.readUint16BE(); // type + dis.readUint32BE(); // offset to pixel map + dis.readUint32BE(); // offset to pixel data + dis.readUint32BE(); // expanded cursor data + dis.readUint16BE(); // expanded data depth + dis.readUint32BE(); // reserved + + // Grab B/W icon data + *cursor = (byte *)malloc(16 * 16); + for (i = 0; i < 32; i++) { + imageByte = dis.readByte(); + for (b = 0; b < 8; b++) + cursor[0][i*8+b] = (byte)((imageByte & (0x80 >> b)) > 0? 0x0F: 0x00); + } + + // Apply mask data + for (i = 0; i < 32; i++) { + imageByte = dis.readByte(); + for (b = 0; b < 8; b++) + if ((imageByte & (0x80 >> b)) == 0) + cursor[0][i*8+b] = 0xff; + } + + *hotspot_y = dis.readUint16BE(); + *hotspot_x = dis.readUint16BE(); + *w = *h = 16; + + // Use b/w cursor on backends which don't support cursor palettes + if (!colored) + return; + + dis.readUint32BE(); // reserved + dis.readUint32BE(); // cursorID + + // Color version of cursor + dis.readUint32BE(); // baseAddr + + // Keep only lowbyte for now + dis.readByte(); + iconRowBytes = dis.readByte(); + + if (!iconRowBytes) + return; + + iconBounds[0] = dis.readUint16BE(); + iconBounds[1] = dis.readUint16BE(); + iconBounds[2] = dis.readUint16BE(); + iconBounds[3] = dis.readUint16BE(); + + dis.readUint16BE(); // pmVersion + dis.readUint16BE(); // packType + dis.readUint32BE(); // packSize + + dis.readUint32BE(); // hRes + dis.readUint32BE(); // vRes + + dis.readUint16BE(); // pixelType + dis.readUint16BE(); // pixelSize + dis.readUint16BE(); // cmpCount + dis.readUint16BE(); // cmpSize + + dis.readUint32BE(); // planeByte + dis.readUint32BE(); // pmTable + dis.readUint32BE(); // reserved + + // Pixel data for cursor + iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]); + iconData = (byte *)malloc(iconDataSize); + dis.read(iconData, iconDataSize); + + // Color table + dis.readUint32BE(); // ctSeed + dis.readUint16BE(); // ctFlag + ctSize = dis.readUint16BE() + 1; + + *palette = (byte *)malloc(ctSize * 4); + + // Read just high byte of 16-bit color + for (int c = 0; c < ctSize; c++) { + // We just use indices 0..ctSize, so ignore color ID + dis.readUint16BE(); // colorID[c] + + palette[0][c * 4 + 0] = dis.readByte(); + ignored = dis.readByte(); + + palette[0][c * 4 + 1] = dis.readByte(); + ignored = dis.readByte(); + + palette[0][c * 4 + 2] = dis.readByte(); + ignored = dis.readByte(); + + palette[0][c * 4 + 3] = 0; + } + + *palSize = ctSize; + + numBytes = (iconBounds[2] - iconBounds[0]) * (iconBounds[3] - iconBounds[1]); + + pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes; + bpp = 8 / pixelsPerByte; + + // build a mask to make sure the pixels are properly shifted out + bitmask = 0; + for (int m = 0; m < bpp; m++) { + bitmask <<= 1; + bitmask |= 1; + } + + // Extract pixels from bytes + for (int j = 0; j < iconDataSize; j++) + for (b = 0; b < pixelsPerByte; b++) { + int idx = j * pixelsPerByte + (pixelsPerByte - 1 - b); + + if (cursor[0][idx] != 0xff) // if mask is not there + cursor[0][idx] = (byte)((iconData[j] >> (b * bpp)) & bitmask); + } + + free(iconData); + + assert(datasize - dis.pos() == 0); +} + +} // End of namespace Common diff --git a/common/macresman.h b/common/macresman.h new file mode 100644 index 0000000000..fd4557f92c --- /dev/null +++ b/common/macresman.h @@ -0,0 +1,127 @@ +/* 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/array.h" +#include "common/file.h" + +#ifndef COMMON_MACRESMAN_H +#define COMMON_MACRESMAN_H + +namespace Common { + +typedef Common::Array<int16> MacResIDArray; + +/** + * Class for reading Mac Binary files. + * Is able to read dumped resource forks too. + */ +class MacResManager { + +public: + MacResManager(Common::String fileName); + ~MacResManager(); + + /** + * Read resource from the Mac Binary file + * @param typeID FourCC with type ID + * @param resID Resource ID to fetch + * @param size Pointer to int where loaded data size will be stored + * @return Pointer to memory with loaded resource. Malloc()'ed + */ + byte *getResource(const char *typeID, int16 resID, int *size); + + char *getResName(const char *typeID, int16 resID); + /** + * Convert cursor from Mac format to format suitable for feeding to CursorMan + * @param data Pointer to the cursor data + * @param datasize Size of the cursor data + * @param cursor Pointer to memory where result cursor will be stored. The memory + * block will be malloc()'ed + * @param w Pointer to int where the cursor width will be stored + * @param h Pointer to int where the cursor height will be stored + * @param hotspot_x Storage for cursor hotspot X coordinate + * @param hotspot_Y Storage for cursor hotspot Y coordinate + * @param keycolor Pointer to int where the transpared color value will be stored + * @param colored If set to true then colored cursor will be returned (if any). + * b/w version will be used otherwise + * @param palette Pointer to memory where the cursor palette will be stored. + * The memory will be malloc()'ed + * @param palSize Pointer to integer where the palette size will be stored. + */ + void convertCursor(byte *data, int datasize, byte **cursor, int *w, int *h, + int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize); + + /** + * Return list of resource IDs with specified type ID + */ + MacResIDArray getResIDArray(const char *typeID); + + Common::String getFileName() { return _fileName; } + +private: + int extractResource(int id, byte **buf); + bool init(); + void readMap(); + + struct ResMap { + int16 resAttr; + int16 typeOffset; + int16 nameOffset; + int16 numTypes; + }; + + struct ResType { + char id[5]; + int16 items; + int16 offset; + }; + + struct Resource { + int16 id; + int16 nameOffset; + byte attr; + int32 dataOffset; + char *name; + }; + + typedef Resource *ResPtr; + +private: + int _resOffset; + int32 _dataOffset; + int32 _dataLength; + int32 _mapOffset; + int32 _mapLength; + ResMap _resMap; + ResType *_resTypes; + ResPtr *_resLists; + + Common::String _fileName; + Common::File _resFile; +}; + +} // End of namespace Common + +#endif diff --git a/common/module.mk b/common/module.mk index a619b5c54f..23d7b326f0 100644 --- a/common/module.mk +++ b/common/module.mk @@ -11,6 +11,7 @@ MODULE_OBJS := \ file.o \ fs.o \ hashmap.o \ + macresman.o \ memorypool.o \ md5.o \ mutex.o \ diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 824f998def..9fc9dd4baf 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -1140,7 +1140,7 @@ void Win32ResExtractor::fix_win32_image_data_directory(Win32ImageDataDirectory * MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) { - _resOffset = -1; + _resMgr = NULL; } int MacResExtractor::extractResource(int id, byte **buf) { @@ -1172,18 +1172,13 @@ int MacResExtractor::extractResource(int id, byte **buf) { if (!in.isOpen()) { error("Cannot open file %s", _fileName.c_str()); } + in.close(); - // we haven't calculated it - if (_resOffset == -1) { - if (!init(in)) - error("Resource fork is missing in file '%s'", _fileName.c_str()); - in.close(); - in.open(_fileName); - } + if (_resMgr == NULL) + _resMgr = new Common::MacResManager(_fileName); - *buf = getResource(in, "crsr", 1000 + id, &size); - in.close(); + *buf = _resMgr->getResource("crsr", 1000 + id, &size); if (*buf == NULL) error("There is no cursor ID #%d", 1000 + id); @@ -1191,295 +1186,11 @@ int MacResExtractor::extractResource(int id, byte **buf) { return size; } -#define MBI_INFOHDR 128 -#define MBI_ZERO1 0 -#define MBI_NAMELEN 1 -#define MBI_ZERO2 74 -#define MBI_ZERO3 82 -#define MBI_DFLEN 83 -#define MBI_RFLEN 87 -#define MAXNAMELEN 63 - -bool MacResExtractor::init(Common::File &in) { - byte infoHeader[MBI_INFOHDR]; - int32 data_size, rsrc_size; - int32 data_size_pad, rsrc_size_pad; - int filelen; - - filelen = in.size(); - in.read(infoHeader, MBI_INFOHDR); - - // Maybe we have MacBinary? - if (infoHeader[MBI_ZERO1] == 0 && infoHeader[MBI_ZERO2] == 0 && - infoHeader[MBI_ZERO3] == 0 && infoHeader[MBI_NAMELEN] <= MAXNAMELEN) { - - // Pull out fork lengths - data_size = READ_BE_UINT32(infoHeader + MBI_DFLEN); - rsrc_size = READ_BE_UINT32(infoHeader + MBI_RFLEN); - - data_size_pad = (((data_size + 127) >> 7) << 7); - rsrc_size_pad = (((rsrc_size + 127) >> 7) << 7); - - // Length check - int sumlen = MBI_INFOHDR + data_size_pad + rsrc_size_pad; - - if (sumlen == filelen) - _resOffset = MBI_INFOHDR + data_size_pad; - } - - if (_resOffset == -1) // MacBinary check is failed - _resOffset = 0; // Maybe we have dumped fork? - - in.seek(_resOffset); - - _dataOffset = in.readUint32BE() + _resOffset; - _mapOffset = in.readUint32BE() + _resOffset; - _dataLength = in.readUint32BE(); - _mapLength = in.readUint32BE(); - - // do sanity check - if (_dataOffset >= filelen || _mapOffset >= filelen || - _dataLength + _mapLength > filelen) { - _resOffset = -1; - return false; - } - - debug(7, "got header: data %d [%d] map %d [%d]", - _dataOffset, _dataLength, _mapOffset, _mapLength); - - readMap(in); - - return true; -} - -byte *MacResExtractor::getResource(Common::File &in, const char *typeID, int16 resID, int *size) { - int i; - int typeNum = -1; - int resNum = -1; - byte *buf; - int len; - - for (i = 0; i < _resMap.numTypes; i++) - if (strcmp(_resTypes[i].id, typeID) == 0) { - typeNum = i; - break; - } - - if (typeNum == -1) - return NULL; - - for (i = 0; i < _resTypes[typeNum].items; i++) - if (_resLists[typeNum][i].id == resID) { - resNum = i; - break; - } - - if (resNum == -1) - return NULL; - - in.seek(_dataOffset + _resLists[typeNum][resNum].dataOffset); - - len = in.readUint32BE(); - buf = (byte *)malloc(len); - - in.read(buf, len); - - *size = len; - - return buf; -} - -void MacResExtractor::readMap(Common::File &in) { - int i, j, len; - - in.seek(_mapOffset + 22); - - _resMap.resAttr = in.readUint16BE(); - _resMap.typeOffset = in.readUint16BE(); - _resMap.nameOffset = in.readUint16BE(); - _resMap.numTypes = in.readUint16BE(); - _resMap.numTypes++; - - in.seek(_mapOffset + _resMap.typeOffset + 2); - _resTypes = new ResType[_resMap.numTypes]; - - for (i = 0; i < _resMap.numTypes; i++) { - in.read(_resTypes[i].id, 4); - _resTypes[i].id[4] = 0; - _resTypes[i].items = in.readUint16BE(); - _resTypes[i].offset = in.readUint16BE(); - _resTypes[i].items++; - } - - _resLists = new ResPtr[_resMap.numTypes]; - - for (i = 0; i < _resMap.numTypes; i++) { - _resLists[i] = new Resource[_resTypes[i].items]; - in.seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset); - - for (j = 0; j < _resTypes[i].items; j++) { - ResPtr resPtr = _resLists[i] + j; - - resPtr->id = in.readUint16BE(); - resPtr->nameOffset = in.readUint16BE(); - resPtr->dataOffset = in.readUint32BE(); - in.readUint32BE(); - resPtr->name = 0; - - resPtr->attr = resPtr->dataOffset >> 24; - resPtr->dataOffset &= 0xFFFFFF; - } - - for (j = 0; j < _resTypes[i].items; j++) { - if (_resLists[i][j].nameOffset != -1) { - in.seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset); - - len = in.readByte(); - _resLists[i][j].name = new byte[len + 1]; - _resLists[i][j].name[len] = 0; - in.read(_resLists[i][j].name, len); - } - } - } -} - int MacResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize) { - Common::MemoryReadStream dis(data, datasize); - int i, b; - byte imageByte; - byte *iconData; - int numBytes; - int pixelsPerByte, bpp; - int ctSize; - byte bitmask; - int iconRowBytes, iconBounds[4]; - int ignored; - int iconDataSize; - - dis.readUint16BE(); // type - dis.readUint32BE(); // offset to pixel map - dis.readUint32BE(); // offset to pixel data - dis.readUint32BE(); // expanded cursor data - dis.readUint16BE(); // expanded data depth - dis.readUint32BE(); // reserved - - // Grab B/W icon data - *cursor = (byte *)malloc(16 * 16); - for (i = 0; i < 32; i++) { - imageByte = dis.readByte(); - for (b = 0; b < 8; b++) - cursor[0][i*8+b] = (byte)((imageByte & - (0x80 >> b)) > 0? 0x0F: 0x00); - } - - // Apply mask data - for (i = 0; i < 32; i++) { - imageByte = dis.readByte(); - for (b = 0; b < 8; b++) - if ((imageByte & (0x80 >> b)) == 0) - cursor[0][i*8+b] = 0xff; - } - - *hotspot_y = dis.readUint16BE(); - *hotspot_x = dis.readUint16BE(); - *w = *h = 16; - - // Use b/w cursor on backends which don't support cursor palettes - if (!_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette)) - return 1; - - dis.readUint32BE(); // reserved - dis.readUint32BE(); // cursorID - - // Color version of cursor - dis.readUint32BE(); // baseAddr - - // Keep only lowbyte for now - dis.readByte(); - iconRowBytes = dis.readByte(); - - if (!iconRowBytes) - return 1; - - iconBounds[0] = dis.readUint16BE(); - iconBounds[1] = dis.readUint16BE(); - iconBounds[2] = dis.readUint16BE(); - iconBounds[3] = dis.readUint16BE(); - - dis.readUint16BE(); // pmVersion - dis.readUint16BE(); // packType - dis.readUint32BE(); // packSize - - dis.readUint32BE(); // hRes - dis.readUint32BE(); // vRes - - dis.readUint16BE(); // pixelType - dis.readUint16BE(); // pixelSize - dis.readUint16BE(); // cmpCount - dis.readUint16BE(); // cmpSize - - dis.readUint32BE(); // planeByte - dis.readUint32BE(); // pmTable - dis.readUint32BE(); // reserved - - // Pixel data for cursor - iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]); - iconData = (byte *)malloc(iconDataSize); - dis.read(iconData, iconDataSize); - - // Color table - dis.readUint32BE(); // ctSeed - dis.readUint16BE(); // ctFlag - ctSize = dis.readUint16BE() + 1; - - *palette = (byte *)malloc(ctSize * 4); - - // Read just high byte of 16-bit color - for (int c = 0; c < ctSize; c++) { - // We just use indices 0..ctSize, so ignore color ID - dis.readUint16BE(); // colorID[c] - - palette[0][c * 4 + 0] = dis.readByte(); - ignored = dis.readByte(); - - palette[0][c * 4 + 1] = dis.readByte(); - ignored = dis.readByte(); - - palette[0][c * 4 + 2] = dis.readByte(); - ignored = dis.readByte(); - - palette[0][c * 4 + 3] = 0; - } - - *palSize = ctSize; - - numBytes = - (iconBounds[2] - iconBounds[0]) * - (iconBounds[3] - iconBounds[1]); - - pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes; - bpp = 8 / pixelsPerByte; - - // build a mask to make sure the pixels are properly shifted out - bitmask = 0; - for (int m = 0; m < bpp; m++) { - bitmask <<= 1; - bitmask |= 1; - } - - // Extract pixels from bytes - for (int j = 0; j < iconDataSize; j++) - for (b = 0; b < pixelsPerByte; b++) { - int idx = j * pixelsPerByte + (pixelsPerByte - 1 - b); - - if (cursor[0][idx] != 0xff) // if mask is not there - cursor[0][idx] = (byte)((iconData[j] >> (b * bpp)) & bitmask); - } - - free(iconData); - assert(datasize - dis.pos() == 0); + _resMgr->convertCursor(data, datasize, cursor, w, h, hotspot_x, hotspot_y, keycolor, + _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette), palette, palSize); return 1; } diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h index cbe19a4fdf..4567c598a3 100644 --- a/engines/scumm/he/resource_he.h +++ b/engines/scumm/he/resource_he.h @@ -26,6 +26,8 @@ #ifndef SCUMM_HE_RESOURCE_HE_H #define SCUMM_HE_RESOURCE_HE_H +#include "common/macresman.h" + namespace Scumm { #define WINRES_ID_MAXLEN (256) @@ -419,48 +421,13 @@ class MacResExtractor : public ResExtractor { public: MacResExtractor(ScummEngine_v70he *scumm); ~MacResExtractor() { } - void setCursor(int id) ; private: + Common::MacResManager *_resMgr; + int extractResource(int id, byte **buf); - bool init(Common::File &in); - void readMap(Common::File &in); - byte *getResource(Common::File &in, const char *typeID, int16 resID, int *size); int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize); - - struct ResMap { - int16 resAttr; - int16 typeOffset; - int16 nameOffset; - int16 numTypes; - }; - - struct ResType { - char id[5]; - int16 items; - int16 offset; - }; - - struct Resource { - int16 id; - int16 nameOffset; - byte attr; - int32 dataOffset; - byte *name; - }; - - typedef Resource *ResPtr; - -private: - int _resOffset; - int32 _dataOffset; - int32 _dataLength; - int32 _mapOffset; - int32 _mapLength; - ResMap _resMap; - ResType *_resTypes; - ResPtr *_resLists; }; } // End of namespace Scumm |