diff options
author | sylvaintv | 2011-03-08 00:54:40 +0100 |
---|---|---|
committer | sylvaintv | 2011-03-08 00:54:40 +0100 |
commit | b2a72da6518b30a58a1257ff7217185ae5683628 (patch) | |
tree | 41e5d532124466b09a396ec4b043ec74e1b9ea56 /common | |
parent | 53d6a4f831c9e7c7de594cdaed3c8546b41ea2e2 (diff) | |
parent | 9fb28410b5ea27fa8e79ac5f0ac4ce70ae4cf3c6 (diff) | |
download | scummvm-rg350-b2a72da6518b30a58a1257ff7217185ae5683628.tar.gz scummvm-rg350-b2a72da6518b30a58a1257ff7217185ae5683628.tar.bz2 scummvm-rg350-b2a72da6518b30a58a1257ff7217185ae5683628.zip |
Merge branch 'master' of github.com:scummvm/scummvm
Diffstat (limited to 'common')
-rw-r--r-- | common/macresman.cpp | 138 | ||||
-rw-r--r-- | common/macresman.h | 11 | ||||
-rw-r--r-- | common/module.mk | 4 | ||||
-rw-r--r-- | common/ne_exe.cpp | 612 | ||||
-rw-r--r-- | common/winexe.cpp | 84 | ||||
-rw-r--r-- | common/winexe.h | 74 | ||||
-rw-r--r-- | common/winexe_ne.cpp | 291 | ||||
-rw-r--r-- | common/winexe_ne.h (renamed from common/ne_exe.h) | 100 | ||||
-rw-r--r-- | common/winexe_pe.cpp | 255 | ||||
-rw-r--r-- | common/winexe_pe.h | 122 |
10 files changed, 907 insertions, 784 deletions
diff --git a/common/macresman.cpp b/common/macresman.cpp index 4fd4e72ee3..e7d4a30789 100644 --- a/common/macresman.cpp +++ b/common/macresman.cpp @@ -550,118 +550,110 @@ void MacResManager::readMap() { } } -void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, int *w, int *h, - int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize) { - MemoryReadStream dis(data, datasize); - int i, b; - byte imageByte; - byte *iconData; - int pixelsPerByte, bpp; - int ctSize; - byte bitmask; - int iconRowBytes, iconBounds[4]; - 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 +void MacResManager::convertCrsrCursor(SeekableReadStream *data, byte **cursor, int &w, int &h, int &hotspotX, + int &hotspotY, int &keycolor, bool colored, byte **palette, int &palSize) { + + data->readUint16BE(); // type + data->readUint32BE(); // offset to pixel map + data->readUint32BE(); // offset to pixel data + data->readUint32BE(); // expanded cursor data + data->readUint16BE(); // expanded data depth + data->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); + *cursor = new byte[16 * 16]; + for (int i = 0; i < 32; i++) { + byte imageByte = data->readByte(); + for (int 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++) + for (int i = 0; i < 32; i++) { + byte imageByte = data->readByte(); + for (int b = 0; b < 8; b++) if ((imageByte & (0x80 >> b)) == 0) - cursor[0][i*8+b] = 0xff; + cursor[0][i * 8 + b] = 0xff; } - *hotspot_y = dis.readUint16BE(); - *hotspot_x = dis.readUint16BE(); - *w = *h = 16; - *keycolor = 0xff; + hotspotY = data->readUint16BE(); + hotspotX = data->readUint16BE(); + w = h = 16; + keycolor = 0xff; // Use b/w cursor on backends which don't support cursor palettes if (!colored) return; - dis.readUint32BE(); // reserved - dis.readUint32BE(); // cursorID + data->readUint32BE(); // reserved + data->readUint32BE(); // cursorID // Color version of cursor - dis.readUint32BE(); // baseAddr + data->readUint32BE(); // baseAddr // Keep only lowbyte for now - dis.readByte(); - iconRowBytes = dis.readByte(); + data->readByte(); + int iconRowBytes = data->readByte(); if (!iconRowBytes) return; - iconBounds[0] = dis.readUint16BE(); - iconBounds[1] = dis.readUint16BE(); - iconBounds[2] = dis.readUint16BE(); - iconBounds[3] = dis.readUint16BE(); + int iconBounds[4]; + iconBounds[0] = data->readUint16BE(); + iconBounds[1] = data->readUint16BE(); + iconBounds[2] = data->readUint16BE(); + iconBounds[3] = data->readUint16BE(); - dis.readUint16BE(); // pmVersion - dis.readUint16BE(); // packType - dis.readUint32BE(); // packSize + data->readUint16BE(); // pmVersion + data->readUint16BE(); // packType + data->readUint32BE(); // packSize - dis.readUint32BE(); // hRes - dis.readUint32BE(); // vRes + data->readUint32BE(); // hRes + data->readUint32BE(); // vRes - dis.readUint16BE(); // pixelType - dis.readUint16BE(); // pixelSize - dis.readUint16BE(); // cmpCount - dis.readUint16BE(); // cmpSize + data->readUint16BE(); // pixelType + data->readUint16BE(); // pixelSize + data->readUint16BE(); // cmpCount + data->readUint16BE(); // cmpSize - dis.readUint32BE(); // planeByte - dis.readUint32BE(); // pmTable - dis.readUint32BE(); // reserved + data->readUint32BE(); // planeByte + data->readUint32BE(); // pmTable + data->readUint32BE(); // reserved // Pixel data for cursor - iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]); - iconData = (byte *)malloc(iconDataSize); - dis.read(iconData, iconDataSize); + int iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]); + byte *iconData = new byte[iconDataSize]; + data->read(iconData, iconDataSize); // Color table - dis.readUint32BE(); // ctSeed - dis.readUint16BE(); // ctFlag - ctSize = dis.readUint16BE() + 1; + data->readUint32BE(); // ctSeed + data->readUint16BE(); // ctFlag + uint16 ctSize = data->readUint16BE() + 1; - *palette = (byte *)malloc(ctSize * 3); + *palette = new byte[ctSize * 3]; // 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] + data->readUint16BE(); // colorID[c] - palette[0][c * 3 + 0] = dis.readByte(); - dis.readByte(); + palette[0][c * 3 + 0] = data->readByte(); + data->readByte(); - palette[0][c * 3 + 1] = dis.readByte(); - dis.readByte(); + palette[0][c * 3 + 1] = data->readByte(); + data->readByte(); - palette[0][c * 3 + 2] = dis.readByte(); - dis.readByte(); + palette[0][c * 3 + 2] = data->readByte(); + data->readByte(); } - *palSize = ctSize; + palSize = ctSize; - pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes; - bpp = 8 / pixelsPerByte; + int pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes; + int bpp = 8 / pixelsPerByte; // build a mask to make sure the pixels are properly shifted out - bitmask = 0; + int bitmask = 0; for (int m = 0; m < bpp; m++) { bitmask <<= 1; bitmask |= 1; @@ -669,16 +661,16 @@ void MacResManager::convertCrsrCursor(byte *data, int datasize, byte **cursor, i // Extract pixels from bytes for (int j = 0; j < iconDataSize; j++) - for (b = 0; b < pixelsPerByte; b++) { + for (int 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); + delete[] iconData; - assert(datasize - dis.pos() == 0); + assert(data->size() - data->pos() == 0); } } // End of namespace Common diff --git a/common/macresman.h b/common/macresman.h index 1cbebbcf4b..2ad0b608a1 100644 --- a/common/macresman.h +++ b/common/macresman.h @@ -154,14 +154,13 @@ public: /** * Convert cursor from crsr format to format suitable for feeding to CursorMan - * @param data Pointer to the cursor data - * @param datasize Size of the cursor data + * @param data Pointer to the cursor datax * @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 hotspotX Storage for cursor hotspot X coordinate + * @param hotspotY 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 @@ -169,8 +168,8 @@ public: * The memory will be malloc()'ed * @param palSize Pointer to integer where the palette size will be stored. */ - static void convertCrsrCursor(byte *data, int datasize, byte **cursor, int *w, int *h, - int *hotspot_x, int *hotspot_y, int *keycolor, bool colored, byte **palette, int *palSize); + static void convertCrsrCursor(SeekableReadStream *data, byte **cursor, int &w, int &h, int &hotspotX, + int &hotspotY, int &keycolor, bool colored, byte **palette, int &palSize); /** * Return list of resource IDs with specified type ID diff --git a/common/module.mk b/common/module.mk index a4cea5c23f..a57de6a4b8 100644 --- a/common/module.mk +++ b/common/module.mk @@ -17,7 +17,6 @@ MODULE_OBJS := \ memorypool.o \ md5.o \ mutex.o \ - ne_exe.o \ random.o \ rational.o \ str.o \ @@ -29,6 +28,9 @@ MODULE_OBJS := \ unarj.o \ unzip.o \ util.o \ + winexe.o \ + winexe_ne.o \ + winexe_pe.o \ xmlparser.o \ zlib.o diff --git a/common/ne_exe.cpp b/common/ne_exe.cpp deleted file mode 100644 index 34bb551b06..0000000000 --- a/common/ne_exe.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* 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/ne_exe.h" -#include "common/str.h" -#include "common/stream.h" - -namespace Common { - -NECursor::NECursor() { - _width = 0; - _height = 0; - _hotspotX = 0; - _hotspotY = 0; - _surface = 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; -} - -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 = 0; - } - } - - dest -= width; - srcP += width / 8; - srcM += width / 8; - } - - delete bitmap; - delete[] initialSource; - return true; -} - -void NECursor::clear() { - delete[] _surface; _surface = 0; -} - -NEResourceID &NEResourceID::operator=(String string) { - _name = string; - _idType = kIDTypeString; - return *this; -} - -NEResourceID &NEResourceID::operator=(uint16 x) { - _id = x; - _idType = kIDTypeNumerical; - return *this; -} - -bool NEResourceID::operator==(const String &x) const { - return _idType == kIDTypeString && _name.equalsIgnoreCase(x); -} - -bool NEResourceID::operator==(const uint16 &x) const { - return _idType == kIDTypeNumerical && _id == x; -} - -bool NEResourceID::operator==(const NEResourceID &x) const { - if (_idType != x._idType) - return false; - if (_idType == kIDTypeString) - return _name.equalsIgnoreCase(x._name); - if (_idType == kIDTypeNumerical) - return _id == x._id; - return true; -} - -String NEResourceID::getString() const { - if (_idType != kIDTypeString) - return ""; - - return _name; -} - -uint16 NEResourceID::getID() const { - if (_idType != kIDTypeNumerical) - return 0xffff; - - return _idType; -} - -String NEResourceID::toString() const { - if (_idType == kIDTypeString) - return _name; - else if (_idType == kIDTypeNumerical) - return String::format("%04x", _id); - - return ""; -} - -NEResources::NEResources() { - _exe = 0; -} - -NEResources::~NEResources() { - clear(); -} - -void NEResources::clear() { - if (_exe) { - delete _exe; - _exe = 0; - } - - _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) { - if (fileName.empty()) - return false; - - File *file = new File(); - - if (!file->open(fileName)) { - delete file; - return false; - } - - return loadFromEXE(file); -} - -bool NEResources::loadFromEXE(SeekableReadStream *stream) { - clear(); - - if (!stream) - return false; - - _exe = stream; - - uint32 offsetResourceTable = getResourceTableOffset(); - if (offsetResourceTable == 0xFFFFFFFF) - return false; - if (offsetResourceTable == 0) - return true; - - if (!readResourceTable(offsetResourceTable)) - return false; - - if (!readCursors()) - return false; - - return true; -} - -bool NEResources::loadFromCompressedEXE(const String &fileName) { - // Based on http://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html - - File file; - - if (!file.open(fileName)) - return false; - - // First part of the signature - if (file.readUint32BE() != MKID_BE('SZDD')) - return false; - - // Second part of the signature - if (file.readUint32BE() != 0x88F02733) - return false; - - // Compression mode must be 'A' - if (file.readByte() != 'A') - return false; - - file.readByte(); // file name character change - uint32 unpackedLength = file.readUint32LE(); - - byte *window = new byte[0x1000]; - int pos = 0x1000 - 16; - memset(window, 0x20, 0x1000); // Initialize to all spaces - - byte *unpackedData = (byte *)malloc(unpackedLength); - byte *dataPos = unpackedData; - - // Apply simple LZSS decompression - for (;;) { - byte controlByte = file.readByte(); - - if (file.eos()) - break; - - for (byte i = 0; i < 8; i++) { - if (controlByte & (1 << i)) { - *dataPos++ = window[pos++] = file.readByte(); - pos &= 0xFFF; - } else { - int matchPos = file.readByte(); - int matchLen = file.readByte(); - matchPos |= (matchLen & 0xF0) << 4; - matchLen = (matchLen & 0xF) + 3; - while (matchLen--) { - *dataPos++ = window[pos++] = window[matchPos++]; - pos &= 0xFFF; - matchPos &= 0xFFF; - } - } - - } - } - - delete[] window; - SeekableReadStream *stream = new MemoryReadStream(unpackedData, unpackedLength); - - return loadFromEXE(stream); -} - -uint32 NEResources::getResourceTableOffset() { - if (!_exe) - return 0xFFFFFFFF; - - if (!_exe->seek(0)) - return 0xFFFFFFFF; - - // 'MZ' - if (_exe->readUint16BE() != 0x4D5A) - return 0xFFFFFFFF; - - if (!_exe->seek(60)) - return 0xFFFFFFFF; - - uint32 offsetSegmentEXE = _exe->readUint16LE(); - if (!_exe->seek(offsetSegmentEXE)) - return 0xFFFFFFFF; - - // 'NE' - if (_exe->readUint16BE() != 0x4E45) - return 0xFFFFFFFF; - - if (!_exe->seek(offsetSegmentEXE + 36)) - return 0xFFFFFFFF; - - uint32 offsetResourceTable = _exe->readUint16LE(); - if (offsetResourceTable == 0) - // No resource table - return 0; - - // Offset relative to the segment _exe header - offsetResourceTable += offsetSegmentEXE; - if (!_exe->seek(offsetResourceTable)) - return 0xFFFFFFFF; - - return offsetResourceTable; -} - -static const char *s_resTypeNames[] = { - "", "cursor", "bitmap", "icon", "menu", "dialog", "string", - "font_dir", "font", "accelerator", "rc_data", "msg_table", - "group_cursor", "group_icon", "version", "dlg_include", - "plug_play", "vxd", "ani_cursor", "ani_icon", "html", - "manifest" -}; - -bool NEResources::readResourceTable(uint32 offset) { - if (!_exe) - return false; - - if (!_exe->seek(offset)) - return false; - - uint32 align = 1 << _exe->readUint16LE(); - - uint16 typeID = _exe->readUint16LE(); - while (typeID != 0) { - uint16 resCount = _exe->readUint16LE(); - - _exe->skip(4); // reserved - - for (int i = 0; i < resCount; i++) { - Resource res; - - // Resource properties - res.offset = _exe->readUint16LE() * align; - res.size = _exe->readUint16LE() * align; - res.flags = _exe->readUint16LE(); - uint16 id = _exe->readUint16LE(); - res.handle = _exe->readUint16LE(); - res.usage = _exe->readUint16LE(); - - res.type = typeID; - - if ((id & 0x8000) == 0) - res.id = getResourceString(*_exe, offset + id); - else - res.id = id & 0x7FFF; - - if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames))) - debug(2, "Found resource %s %s", s_resTypeNames[typeID & 0x7FFF], res.id.toString().c_str()); - else - debug(2, "Found resource %04x %s", typeID, res.id.toString().c_str()); - - _resources.push_back(res); - } - - typeID = _exe->readUint16LE(); - } - - return true; -} - -String NEResources::getResourceString(SeekableReadStream &exe, uint32 offset) { - uint32 curPos = exe.pos(); - - if (!exe.seek(offset)) { - exe.seek(curPos); - return ""; - } - - uint8 length = exe.readByte(); - - String string; - for (uint16 i = 0; i < length; i++) - string += (char)exe.readByte(); - - exe.seek(curPos); - return string; -} - -const NEResources::Resource *NEResources::findResource(uint16 type, NEResourceID id) const { - for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) - if (it->type == type && it->id == id) - return &*it; - - return 0; -} - -SeekableReadStream *NEResources::getResource(uint16 type, NEResourceID id) { - const Resource *res = findResource(type, id); - - if (!res) - return 0; - - _exe->seek(res->offset); - return _exe->readStream(res->size); -} - -const Array<NEResourceID> NEResources::getIDList(uint16 type) const { - Array<NEResourceID> idArray; - - for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) - if (it->type == type) - idArray.push_back(it->id); - - 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.cpp b/common/winexe.cpp new file mode 100644 index 0000000000..9602e84c88 --- /dev/null +++ b/common/winexe.cpp @@ -0,0 +1,84 @@ +/* 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/str.h" +#include "common/winexe.h" + +namespace Common { + +WinResourceID &WinResourceID::operator=(const String &x) { + _name = x; + _idType = kIDTypeString; + return *this; +} + +WinResourceID &WinResourceID::operator=(uint32 x) { + _id = x; + _idType = kIDTypeNumerical; + return *this; +} + +bool WinResourceID::operator==(const String &x) const { + return _idType == kIDTypeString && _name.equalsIgnoreCase(x); +} + +bool WinResourceID::operator==(const uint32 &x) const { + return _idType == kIDTypeNumerical && _id == x; +} + +bool WinResourceID::operator==(const WinResourceID &x) const { + if (_idType != x._idType) + return false; + if (_idType == kIDTypeString) + return _name.equalsIgnoreCase(x._name); + if (_idType == kIDTypeNumerical) + return _id == x._id; + return true; +} + +String WinResourceID::getString() const { + if (_idType != kIDTypeString) + return ""; + + return _name; +} + +uint32 WinResourceID::getID() const { + if (_idType != kIDTypeNumerical) + return 0xffffffff; + + return _id; +} + +String WinResourceID::toString() const { + if (_idType == kIDTypeString) + return _name; + else if (_idType == kIDTypeNumerical) + return String::format("%08x", _id); + + return ""; +} + +} // End of namespace Common diff --git a/common/winexe.h b/common/winexe.h new file mode 100644 index 0000000000..af0d70c555 --- /dev/null +++ b/common/winexe.h @@ -0,0 +1,74 @@ +/* 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 COMMON_WINEXE_H +#define COMMON_WINEXE_H + +#include "common/hash-str.h" + +namespace Common { + +class String; + +class WinResourceID { +public: + WinResourceID() { _idType = kIDTypeNull; } + WinResourceID(String x) { _idType = kIDTypeString; _name = x; } + WinResourceID(uint32 x) { _idType = kIDTypeNumerical; _id = x; } + + WinResourceID &operator=(const String &x); + WinResourceID &operator=(uint32 x); + + bool operator==(const String &x) const; + bool operator==(const uint32 &x) const; + bool operator==(const WinResourceID &x) const; + + String getString() const; + uint32 getID() const; + String toString() const; + +private: + /** An ID Type. */ + enum IDType { + kIDTypeNull, ///< No type set + kIDTypeNumerical, ///< A numerical ID. + kIDTypeString ///< A string ID. + } _idType; + + String _name; ///< The resource's string ID. + uint32 _id; ///< The resource's numerical ID. +}; + +struct WinResourceID_Hash { + uint operator()(const WinResourceID &id) const { return hashit(id.toString()); } +}; + +struct WinResourceID_EqualTo { + bool operator()(const WinResourceID &id1, const WinResourceID &id2) const { return id1 == id2; } +}; + +} // End of namespace Common + +#endif diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp new file mode 100644 index 0000000000..24e51f1c9e --- /dev/null +++ b/common/winexe_ne.cpp @@ -0,0 +1,291 @@ +/* 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" + +namespace Common { + +NEResources::NEResources() { + _exe = 0; +} + +NEResources::~NEResources() { + clear(); +} + +void NEResources::clear() { + if (_exe) { + delete _exe; + _exe = 0; + } + + _resources.clear(); +} + +bool NEResources::loadFromEXE(const String &fileName) { + if (fileName.empty()) + return false; + + File *file = new File(); + + if (!file->open(fileName)) { + delete file; + return false; + } + + return loadFromEXE(file); +} + +bool NEResources::loadFromEXE(SeekableReadStream *stream) { + clear(); + + if (!stream) + return false; + + _exe = stream; + + uint32 offsetResourceTable = getResourceTableOffset(); + if (offsetResourceTable == 0xFFFFFFFF) + return false; + if (offsetResourceTable == 0) + return true; + + if (!readResourceTable(offsetResourceTable)) + return false; + + return true; +} + +bool NEResources::loadFromCompressedEXE(const String &fileName) { + // Based on http://www.cabextract.org.uk/libmspack/doc/szdd_kwaj_format.html + + // TODO: Merge this with with loadFromEXE() so the handling of the compressed + // EXE's is transparent + + File file; + + if (!file.open(fileName)) + return false; + + // First part of the signature + if (file.readUint32BE() != MKID_BE('SZDD')) + return false; + + // Second part of the signature + if (file.readUint32BE() != 0x88F02733) + return false; + + // Compression mode must be 'A' + if (file.readByte() != 'A') + return false; + + file.readByte(); // file name character change + uint32 unpackedLength = file.readUint32LE(); + + byte *window = new byte[0x1000]; + int pos = 0x1000 - 16; + memset(window, 0x20, 0x1000); // Initialize to all spaces + + byte *unpackedData = (byte *)malloc(unpackedLength); + assert(unpackedData); + byte *dataPos = unpackedData; + + // Apply simple LZSS decompression + for (;;) { + byte controlByte = file.readByte(); + + if (file.eos()) + break; + + for (byte i = 0; i < 8; i++) { + if (controlByte & (1 << i)) { + *dataPos++ = window[pos++] = file.readByte(); + pos &= 0xFFF; + } else { + int matchPos = file.readByte(); + int matchLen = file.readByte(); + matchPos |= (matchLen & 0xF0) << 4; + matchLen = (matchLen & 0xF) + 3; + while (matchLen--) { + *dataPos++ = window[pos++] = window[matchPos++]; + pos &= 0xFFF; + matchPos &= 0xFFF; + } + } + + } + } + + delete[] window; + SeekableReadStream *stream = new MemoryReadStream(unpackedData, unpackedLength); + + return loadFromEXE(stream); +} + +uint32 NEResources::getResourceTableOffset() { + if (!_exe) + return 0xFFFFFFFF; + + if (!_exe->seek(0)) + return 0xFFFFFFFF; + + // 'MZ' + if (_exe->readUint16BE() != 0x4D5A) + return 0xFFFFFFFF; + + if (!_exe->seek(60)) + return 0xFFFFFFFF; + + uint32 offsetSegmentEXE = _exe->readUint16LE(); + if (!_exe->seek(offsetSegmentEXE)) + return 0xFFFFFFFF; + + // 'NE' + if (_exe->readUint16BE() != 0x4E45) + return 0xFFFFFFFF; + + if (!_exe->seek(offsetSegmentEXE + 36)) + return 0xFFFFFFFF; + + uint32 offsetResourceTable = _exe->readUint16LE(); + if (offsetResourceTable == 0) + // No resource table + return 0; + + // Offset relative to the segment _exe header + offsetResourceTable += offsetSegmentEXE; + if (!_exe->seek(offsetResourceTable)) + return 0xFFFFFFFF; + + return offsetResourceTable; +} + +static const char *s_resTypeNames[] = { + "", "cursor", "bitmap", "icon", "menu", "dialog", "string", + "font_dir", "font", "accelerator", "rc_data", "msg_table", + "group_cursor", "group_icon", "version", "dlg_include", + "plug_play", "vxd", "ani_cursor", "ani_icon", "html", + "manifest" +}; + +bool NEResources::readResourceTable(uint32 offset) { + if (!_exe) + return false; + + if (!_exe->seek(offset)) + return false; + + uint32 align = 1 << _exe->readUint16LE(); + + uint16 typeID = _exe->readUint16LE(); + while (typeID != 0) { + uint16 resCount = _exe->readUint16LE(); + + _exe->skip(4); // reserved + + for (int i = 0; i < resCount; i++) { + Resource res; + + // Resource properties + res.offset = _exe->readUint16LE() * align; + res.size = _exe->readUint16LE() * align; + res.flags = _exe->readUint16LE(); + uint16 id = _exe->readUint16LE(); + res.handle = _exe->readUint16LE(); + res.usage = _exe->readUint16LE(); + + res.type = typeID; + + if ((id & 0x8000) == 0) + res.id = getResourceString(*_exe, offset + id); + else + res.id = id & 0x7FFF; + + if (typeID & 0x8000 && ((typeID & 0x7FFF) < ARRAYSIZE(s_resTypeNames))) + debug(2, "Found resource %s %s", s_resTypeNames[typeID & 0x7FFF], res.id.toString().c_str()); + else + debug(2, "Found resource %04x %s", typeID, res.id.toString().c_str()); + + _resources.push_back(res); + } + + typeID = _exe->readUint16LE(); + } + + return true; +} + +String NEResources::getResourceString(SeekableReadStream &exe, uint32 offset) { + uint32 curPos = exe.pos(); + + if (!exe.seek(offset)) { + exe.seek(curPos); + return ""; + } + + uint8 length = exe.readByte(); + + String string; + for (uint16 i = 0; i < length; i++) + string += (char)exe.readByte(); + + exe.seek(curPos); + return string; +} + +const NEResources::Resource *NEResources::findResource(uint16 type, WinResourceID id) const { + for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) + if (it->type == type && it->id == id) + return &*it; + + return 0; +} + +SeekableReadStream *NEResources::getResource(uint16 type, WinResourceID id) { + const Resource *res = findResource(type, id); + + if (!res) + return 0; + + _exe->seek(res->offset); + return _exe->readStream(res->size); +} + +const Array<WinResourceID> NEResources::getIDList(uint16 type) const { + Array<WinResourceID> idArray; + + for (List<Resource>::const_iterator it = _resources.begin(); it != _resources.end(); ++it) + if (it->type == type) + idArray.push_back(it->id); + + return idArray; +} + +} // End of namespace Common diff --git a/common/ne_exe.h b/common/winexe_ne.h index 545c8e5eff..c1d04080ba 100644 --- a/common/ne_exe.h +++ b/common/winexe_ne.h @@ -23,11 +23,12 @@ * */ -#ifndef COMMON_NE_EXE_H -#define COMMON_NE_EXE_H +#ifndef COMMON_WINEXE_NE_H +#define COMMON_WINEXE_NE_H #include "common/array.h" #include "common/list.h" +#include "common/winexe.h" namespace Common { @@ -35,80 +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; - - 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. - - /** Clear the cursor. */ - void clear(); -}; - -class NEResourceID { -public: - NEResourceID() { _idType = kIDTypeNull; } - NEResourceID(String x) { _idType = kIDTypeString; _name = x; } - NEResourceID(uint16 x) { _idType = kIDTypeNumerical; _id = x; } - - NEResourceID &operator=(String string); - NEResourceID &operator=(uint16 x); - - bool operator==(const String &x) const; - bool operator==(const uint16 &x) const; - bool operator==(const NEResourceID &x) const; - - String getString() const; - uint16 getID() const; - String toString() const; - -private: - /** An ID Type. */ - enum IDType { - kIDTypeNull, ///< No type set - kIDTypeNumerical, ///< A numerical ID. - kIDTypeString ///< A string ID. - } _idType; - - String _name; ///< The resource's string ID. - uint16 _id; ///< The resource's numerical ID. -}; - -/** A New Executable cursor group. */ -struct NECursorGroup { - NEResourceID id; - Array<NECursor *> cursors; ///< The cursors. -}; - /** The default Windows resources. */ enum NEResourceType { kNECursor = 0x8001, @@ -157,19 +84,16 @@ 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<NEResourceID> getIDList(uint16 type) const; + const Array<WinResourceID> getIDList(uint16 type) const; /** Return a stream to the specified resource (or 0 if non-existent). */ - SeekableReadStream *getResource(uint16 type, NEResourceID id); + SeekableReadStream *getResource(uint16 type, WinResourceID id); private: /** A resource. */ struct Resource { - NEResourceID id; + WinResourceID id; uint16 type; ///< Type of the resource. @@ -186,21 +110,13 @@ 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, NEResourceID id) const; + const Resource *findResource(uint16 type, WinResourceID id) const; /** Read a resource string. */ static String getResourceString(SeekableReadStream &exe, uint32 offset); @@ -208,4 +124,4 @@ private: } // End of namespace Common -#endif // COMMON_NE_EXE_H +#endif diff --git a/common/winexe_pe.cpp b/common/winexe_pe.cpp new file mode 100644 index 0000000000..456093f5b4 --- /dev/null +++ b/common/winexe_pe.cpp @@ -0,0 +1,255 @@ +/* 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_pe.h" + +namespace Common { + +PEResources::PEResources() { + _exe = 0; +} + +PEResources::~PEResources() { + clear(); +} + +void PEResources::clear() { + _sections.clear(); + _resources.clear(); + delete _exe; _exe = 0; +} + +bool PEResources::loadFromEXE(const String &fileName) { + if (fileName.empty()) + return false; + + File *file = new File(); + + if (!file->open(fileName)) { + delete file; + return false; + } + + return loadFromEXE(file); +} + +bool PEResources::loadFromEXE(SeekableReadStream *stream) { + clear(); + + if (!stream) + return false; + + if (stream->readUint16BE() != 'MZ') + return false; + + stream->skip(58); + + uint32 peOffset = stream->readUint32LE(); + + if (!peOffset || peOffset >= (uint32)stream->size()) + return false; + + stream->seek(peOffset); + + if (stream->readUint32BE() != MKID_BE('PE\0\0')) + return false; + + stream->skip(2); + uint16 sectionCount = stream->readUint16LE(); + stream->skip(12); + uint16 optionalHeaderSize = stream->readUint16LE(); + stream->skip(optionalHeaderSize + 2); + + // Read in all the sections + for (uint16 i = 0; i < sectionCount; i++) { + char sectionName[9]; + stream->read(sectionName, 8); + sectionName[8] = 0; + + Section section; + stream->skip(4); + section.virtualAddress = stream->readUint32LE(); + section.size = stream->readUint32LE(); + section.offset = stream->readUint32LE(); + stream->skip(16); + + _sections[sectionName] = section; + } + + // Currently, we require loading a resource section + if (!_sections.contains(".rsrc")) { + clear(); + return false; + } + + _exe = stream; + + Section &resSection = _sections[".rsrc"]; + parseResourceLevel(resSection, resSection.offset, 0); + + return true; +} + +void PEResources::parseResourceLevel(Section §ion, uint32 offset, int level) { + _exe->seek(offset + 12); + + uint16 namedEntryCount = _exe->readUint16LE(); + uint16 intEntryCount = _exe->readUint16LE(); + + for (uint32 i = 0; i < namedEntryCount + intEntryCount; i++) { + uint32 value = _exe->readUint32LE(); + + WinResourceID id; + + if (value & 0x80000000) { + value &= 0x7fffffff; + + uint32 startPos = _exe->pos(); + _exe->seek(section.offset + (value & 0x7fffffff)); + + // Read in the name, truncating from unicode to ascii + Common::String name; + uint16 nameLength = _exe->readUint16LE(); + while (nameLength--) + name += (char)(_exe->readUint16LE() & 0xff); + + _exe->seek(startPos); + + id = name; + } else { + id = value; + } + + uint32 nextOffset = _exe->readUint32LE(); + uint32 lastOffset = _exe->pos(); + + if (level == 0) + _curType = id; + else if (level == 1) + _curName = id; + else if (level == 2) + _curLang = id; + + if (level < 2) { + // Time to dive down further + parseResourceLevel(section, section.offset + (nextOffset & 0x7fffffff), level + 1); + } else { + _exe->seek(section.offset + nextOffset); + + Resource resource; + resource.offset = _exe->readUint32LE() + section.offset - section.virtualAddress; + resource.size = _exe->readUint32LE(); + + debug(4, "Found resource '%s' '%s' '%s' at %d of size %d", _curType.toString().c_str(), + _curName.toString().c_str(), _curLang.toString().c_str(), resource.offset, resource.size); + + _resources[_curType][_curName][_curLang] = resource; + } + + _exe->seek(lastOffset); + } +} + +const Array<WinResourceID> PEResources::getTypeList() const { + Array<WinResourceID> array; + + if (!_exe) + return array; + + for (TypeMap::const_iterator it = _resources.begin(); it != _resources.end(); it++) + array.push_back(it->_key); + + return array; +} + +const Array<WinResourceID> PEResources::getNameList(const WinResourceID &type) const { + Array<WinResourceID> array; + + if (!_exe || !_resources.contains(type)) + return array; + + const NameMap &nameMap = _resources[type]; + + for (NameMap::const_iterator it = nameMap.begin(); it != nameMap.end(); it++) + array.push_back(it->_key); + + return array; +} + +const Array<WinResourceID> PEResources::getLangList(const WinResourceID &type, const WinResourceID &name) const { + Array<WinResourceID> array; + + if (!_exe || !_resources.contains(type)) + return array; + + const NameMap &nameMap = _resources[type]; + + if (!nameMap.contains(name)) + return array; + + const LangMap &langMap = nameMap[name]; + + for (LangMap::const_iterator it = langMap.begin(); it != langMap.end(); it++) + array.push_back(it->_key); + + return array; +} + +SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name) { + Array<WinResourceID> langList = getLangList(type, name); + + if (langList.empty()) + return 0; + + const Resource &resource = _resources[type][name][langList[0]]; + _exe->seek(resource.offset); + return _exe->readStream(resource.size); +} + +SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang) { + if (!_exe || !_resources.contains(type)) + return 0; + + const NameMap &nameMap = _resources[type]; + + if (!nameMap.contains(name)) + return 0; + + const LangMap &langMap = nameMap[name]; + + if (!langMap.contains(lang)) + return 0; + + const Resource &resource = langMap[lang]; + _exe->seek(resource.offset); + return _exe->readStream(resource.size); +} + +} // End of namespace Common diff --git a/common/winexe_pe.h b/common/winexe_pe.h new file mode 100644 index 0000000000..5298e993ad --- /dev/null +++ b/common/winexe_pe.h @@ -0,0 +1,122 @@ +/* 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 COMMON_WINEXE_PE_H +#define COMMON_WINEXE_PE_H + +#include "common/array.h" +#include "common/hashmap.h" +#include "common/winexe.h" + +namespace Common { + +class SeekableReadStream; +class String; + +/** The default Windows PE resources. */ +enum PEResourceType { + kPECursor = 0x01, + kPEBitmap = 0x02, + kPEIcon = 0x03, + kPEMenu = 0x04, + kPEDialog = 0x05, + kPEString = 0x06, + kPEFontDir = 0x07, + kPEFont = 0x08, + kPEAccelerator = 0x09, + kPERCData = 0x0A, + kPEMessageTable = 0x0B, + kPEGroupCursor = 0x0C, + kPEGroupIcon = 0x0E, + kPEVersion = 0x10, + kPEDlgInclude = 0x11, + kPEPlugPlay = 0x13, + kPEVXD = 0x14, + kPEAniCursor = 0x15, + kPEAniIcon = 0x16 +}; + +/** + * A class able to load resources from a Windows Portable Executable, such + * as cursors, bitmaps, and sounds. + */ +class PEResources { +public: + PEResources(); + ~PEResources(); + + /** Clear all information. */ + void clear(); + + /** Load from an EXE file. */ + bool loadFromEXE(const String &fileName); + + /** Load from a stream. */ + bool loadFromEXE(SeekableReadStream *stream); + + /** Return a list of resource types. */ + const Array<WinResourceID> getTypeList() const; + + /** Return a list of names for a given type. */ + const Array<WinResourceID> getNameList(const WinResourceID &type) const; + + /** Return a list of languages for a given type and name. */ + const Array<WinResourceID> getLangList(const WinResourceID &type, const WinResourceID &name) const; + + /** Return a stream to the specified resource, taking the first language found (or 0 if non-existent). */ + SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &name); + + /** Return a stream to the specified resource (or 0 if non-existent). */ + SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang); + +private: + struct Section { + uint32 virtualAddress; + uint32 size; + uint32 offset; + }; + + HashMap<String, Section, IgnoreCase_Hash, IgnoreCase_EqualTo> _sections; + + SeekableReadStream *_exe; + + void parseResourceLevel(Section §ion, uint32 offset, int level); + WinResourceID _curType, _curName, _curLang; + + struct Resource { + uint32 offset; + uint32 size; + }; + + typedef HashMap<WinResourceID, Resource, WinResourceID_Hash, WinResourceID_EqualTo> LangMap; + typedef HashMap<WinResourceID, LangMap, WinResourceID_Hash, WinResourceID_EqualTo> NameMap; + typedef HashMap<WinResourceID, NameMap, WinResourceID_Hash, WinResourceID_EqualTo> TypeMap; + + TypeMap _resources; +}; + +} // End of namespace Common + +#endif |