[Scummvm-cvs-logs] SF.net SVN: scummvm:[54557] scummvm/trunk/common

mthreepwood at users.sourceforge.net mthreepwood at users.sourceforge.net
Sun Nov 28 23:55:00 CET 2010


Revision: 54557
          http://scummvm.svn.sourceforge.net/scummvm/?rev=54557&view=rev
Author:   mthreepwood
Date:     2010-11-28 22:55:00 +0000 (Sun, 28 Nov 2010)

Log Message:
-----------
COMMON: Add support for loading NE resources and cursors

Needed for Mohawk (and Hugo Win eventually). Based on DrMcCoy's excellent Dark Seed II code.

Modified Paths:
--------------
    scummvm/trunk/common/module.mk

Added Paths:
-----------
    scummvm/trunk/common/ne_exe.cpp
    scummvm/trunk/common/ne_exe.h

Modified: scummvm/trunk/common/module.mk
===================================================================
--- scummvm/trunk/common/module.mk	2010-11-28 22:25:00 UTC (rev 54556)
+++ scummvm/trunk/common/module.mk	2010-11-28 22:55:00 UTC (rev 54557)
@@ -16,6 +16,7 @@
 	memorypool.o \
 	md5.o \
 	mutex.o \
+	ne_exe.o \
 	random.o \
 	rational.o \
 	str.o \

Added: scummvm/trunk/common/ne_exe.cpp
===================================================================
--- scummvm/trunk/common/ne_exe.cpp	                        (rev 0)
+++ scummvm/trunk/common/ne_exe.cpp	2010-11-28 22:55:00 UTC (rev 54557)
@@ -0,0 +1,612 @@
+/* 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 * 4);
+}
+
+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[8] = 0xff;
+	_palette[9] = 0xff;
+	_palette[10] = 0xff;
+
+	// Reading the palette
+	bitmap->seek(40);
+	for (uint32 i = 0 ; i < numColors; i++) {
+		_palette[(i + 1) * 4 + 2] = bitmap->readByte();
+		_palette[(i + 1) * 4 + 1] = bitmap->readByte();
+		_palette[(i + 1) * 4 + 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


Property changes on: scummvm/trunk/common/ne_exe.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/common/ne_exe.h
===================================================================
--- scummvm/trunk/common/ne_exe.h	                        (rev 0)
+++ scummvm/trunk/common/ne_exe.h	2010-11-28 22:55:00 UTC (rev 54557)
@@ -0,0 +1,207 @@
+/* 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_NE_EXE_H
+#define COMMON_NE_EXE_H
+
+#include "common/array.h"
+#include "common/file.h"
+#include "common/list.h"
+
+namespace Common {
+
+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 * 4];
+
+	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,
+	kNEBitmap = 0x8002,
+	kNEIcon = 0x8003,
+	kNEMenu = 0x8004,
+	kNEDialog = 0x8005,
+	kNEString = 0x8006,
+	kNEFontDir = 0x8007,
+	kNEFont = 0x8008,
+	kNEAccelerator = 0x8009,
+	kNERCData = 0x800A,
+	kNEMessageTable = 0x800B,
+	kNEGroupCursor = 0x800C,
+	kNEGroupIcon = 0x800D,
+	kNEVersion = 0x8010,
+	kNEDlgInclude = 0x8011,
+	kNEPlugPlay = 0x8013,
+	kNEVXD = 0x8014,
+	kNEAniCursor = 0x8015,
+	kNEAniIcon = 0x8016,
+	kNEHTML = 0x8017,
+	kNEManifest = 0x8018
+};
+
+/** A class able to load resources from a New Executable. */
+class NEResources {
+public:
+	NEResources();
+	~NEResources();
+
+	/** Clear all information. */
+	void clear();
+
+	/** Load from an EXE file. */
+	bool loadFromEXE(const String &fileName);
+
+	/** Load from a Windows compressed EXE file. */
+	bool loadFromCompressedEXE(const String &fileName);
+
+	/** 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;
+
+	/** Return a stream to the specified resource (or 0 if non-existent). */
+	SeekableReadStream *getResource(uint16 type, NEResourceID id);
+
+private:
+	/** A resource. */
+	struct Resource {
+		NEResourceID id;
+
+		uint16 type; ///< Type of the resource.
+
+		uint32 offset; ///< Offset within the EXE.
+		uint32 size;   ///< Size of the data.
+
+		uint16 flags;
+		uint16 handle;
+		uint16 usage;
+	};
+
+	SeekableReadStream *_exe;        ///< Current file.
+
+	/** 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;
+
+	/** Read a resource string. */
+	static String getResourceString(SeekableReadStream &exe, uint32 offset);
+};
+
+} // End of namespace Common
+
+#endif // COMMON_NE_EXE_H


Property changes on: scummvm/trunk/common/ne_exe.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list