aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2010-01-11 20:41:07 +0000
committerEugene Sandulenko2010-01-11 20:41:07 +0000
commit80ee1de8e4d1d7e56e703c86ca28377b02d6d59f (patch)
tree1032b3870e38ff622f1152b08615b0f545360c97
parent3145ee5379044785fde3bc897b46f236d5797be9 (diff)
downloadscummvm-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.cpp393
-rw-r--r--common/macresman.h127
-rw-r--r--common/module.mk1
-rw-r--r--engines/scumm/he/resource_he.cpp303
-rw-r--r--engines/scumm/he/resource_he.h41
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