aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/str.cpp6
-rw-r--r--common/winexe.cpp105
-rw-r--r--common/winexe.h42
-rw-r--r--common/winexe_ne.cpp82
-rw-r--r--common/winexe_ne.h7
-rw-r--r--common/winexe_pe.cpp49
-rw-r--r--common/winexe_pe.h22
7 files changed, 180 insertions, 133 deletions
diff --git a/common/str.cpp b/common/str.cpp
index 0082dc1bec..ad9e17806e 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -1097,7 +1097,7 @@ size_t strnlen(const char *src, size_t maxSize) {
String toPrintable(const String &in, bool keepNewLines) {
Common::String res;
- const char *tr = "\x01\x02\x03\x04\x05\x06" "a"
+ const char *tr = "\x01\x01\x02\x03\x04\x05\x06" "a"
//"\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f";
"b" "t" "n" "v" "f" "r\x0e\x0f"
"\x10\x11\x12\x13\x14\x15\x16\x17"
@@ -1117,10 +1117,10 @@ String toPrintable(const String &in, bool keepNewLines) {
res += '\\';
if (*p < 0x20) {
- if (tr[*p + 1] < 0x20)
+ if (tr[*p] < 0x20)
res += Common::String::format("x%02x", *p);
else
- res += tr[*p + 1];
+ res += tr[*p];
} else {
res += *p; // We will escape it
}
diff --git a/common/winexe.cpp b/common/winexe.cpp
index fc389f6ea6..ad6ff96505 100644
--- a/common/winexe.cpp
+++ b/common/winexe.cpp
@@ -20,8 +20,12 @@
*
*/
+#include "common/file.h"
+#include "common/memstream.h"
#include "common/str.h"
#include "common/winexe.h"
+#include "common/winexe_ne.h"
+#include "common/winexe_pe.h"
namespace Common {
@@ -78,4 +82,105 @@ String WinResourceID::toString() const {
return "";
}
+bool WinResources::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 WinResources::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() != MKTAG('S','Z','D','D'))
+ 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);
+}
+
+
+WinResources *WinResources::createFromEXE(const String &fileName) {
+ WinResources *exe;
+
+ // First try loading via the NE code
+ exe = new Common::NEResources();
+ if (exe->loadFromEXE(fileName)) {
+ return exe;
+ }
+ delete exe;
+
+ // Then try loading via the PE code
+ exe = new Common::PEResources();
+ if (exe->loadFromEXE(fileName)) {
+ return exe;
+ }
+ delete exe;
+
+ return nullptr;
+}
+
} // End of namespace Common
diff --git a/common/winexe.h b/common/winexe.h
index 9aeea379ed..2b81a33261 100644
--- a/common/winexe.h
+++ b/common/winexe.h
@@ -28,6 +28,8 @@
namespace Common {
+class SeekableReadStream;
+
/** The default Windows resources. */
enum WinResourceType {
kWinCursor = 0x01,
@@ -90,6 +92,46 @@ struct WinResourceID_EqualTo {
bool operator()(const WinResourceID &id1, const WinResourceID &id2) const { return id1 == id2; }
};
+/**
+ * A class able to load resources from a Windows Executable, such
+ * as cursors, bitmaps, and sounds.
+ */
+class WinResources {
+public:
+ virtual ~WinResources() {};
+
+ /** Clear all information. */
+ virtual void clear() = 0;
+
+ /** Load from an EXE file. */
+ virtual bool loadFromEXE(const String &fileName);
+
+ /** Load from a Windows compressed EXE file. */
+ virtual bool loadFromCompressedEXE(const String &fileName);
+
+ /** Load from a stream. */
+ virtual bool loadFromEXE(SeekableReadStream *stream) = 0;
+
+ /** Return a list of IDs for a given type. */
+ virtual const Array<WinResourceID> getIDList(const WinResourceID &type) const = 0;
+
+ /** Return a list of languages for a given type and ID. */
+ virtual const Array<WinResourceID> getLangList(const WinResourceID &type, const WinResourceID &id) const {
+ Array<WinResourceID> array;
+ return array;
+ }
+
+ /** Return a stream to the specified resource, taking the first language found (or 0 if non-existent). */
+ virtual SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &id) = 0;
+
+ /** Return a stream to the specified resource (or 0 if non-existent). */
+ virtual SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &id, const WinResourceID &lang) {
+ return getResource(type, id);
+ }
+
+ static WinResources *createFromEXE(const String &fileName);
+};
+
} // End of namespace Common
#endif
diff --git a/common/winexe_ne.cpp b/common/winexe_ne.cpp
index 2d46cb2554..66b5e0911a 100644
--- a/common/winexe_ne.cpp
+++ b/common/winexe_ne.cpp
@@ -21,8 +21,6 @@
*/
#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"
@@ -46,20 +44,6 @@ void NEResources::clear() {
_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();
@@ -80,72 +64,6 @@ bool NEResources::loadFromEXE(SeekableReadStream *stream) {
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() != MKTAG('S','Z','D','D'))
- 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;
diff --git a/common/winexe_ne.h b/common/winexe_ne.h
index 1a845864b2..118629abe1 100644
--- a/common/winexe_ne.h
+++ b/common/winexe_ne.h
@@ -38,7 +38,7 @@ class SeekableReadStream;
*
* See http://en.wikipedia.org/wiki/New_Executable for more info.
*/
-class NEResources {
+class NEResources : public WinResources {
public:
NEResources();
~NEResources();
@@ -47,10 +47,7 @@ public:
void clear();
/** Load from an EXE file. */
- bool loadFromEXE(const String &fileName);
-
- /** Load from a Windows compressed EXE file. */
- bool loadFromCompressedEXE(const String &fileName);
+ using WinResources::loadFromEXE;
/** Load from a stream. */
bool loadFromEXE(SeekableReadStream *stream);
diff --git a/common/winexe_pe.cpp b/common/winexe_pe.cpp
index 042c347c47..5e962dd139 100644
--- a/common/winexe_pe.cpp
+++ b/common/winexe_pe.cpp
@@ -23,7 +23,6 @@
#include "common/array.h"
#include "common/debug.h"
#include "common/endian.h"
-#include "common/file.h"
#include "common/str.h"
#include "common/stream.h"
#include "common/winexe_pe.h"
@@ -44,20 +43,6 @@ void PEResources::clear() {
delete _exe; _exe = nullptr;
}
-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();
@@ -151,7 +136,7 @@ void PEResources::parseResourceLevel(Section &section, uint32 offset, int level)
if (level == 0)
_curType = id;
else if (level == 1)
- _curName = id;
+ _curID = id;
else if (level == 2)
_curLang = id;
@@ -166,9 +151,9 @@ void PEResources::parseResourceLevel(Section &section, uint32 offset, int level)
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);
+ _curID.toString().c_str(), _curLang.toString().c_str(), resource.offset, resource.size);
- _resources[_curType][_curName][_curLang] = resource;
+ _resources[_curType][_curID][_curLang] = resource;
}
_exe->seek(lastOffset);
@@ -187,32 +172,32 @@ const Array<WinResourceID> PEResources::getTypeList() const {
return array;
}
-const Array<WinResourceID> PEResources::getNameList(const WinResourceID &type) const {
+const Array<WinResourceID> PEResources::getIDList(const WinResourceID &type) const {
Array<WinResourceID> array;
if (!_exe || !_resources.contains(type))
return array;
- const NameMap &nameMap = _resources[type];
+ const IDMap &idMap = _resources[type];
- for (NameMap::const_iterator it = nameMap.begin(); it != nameMap.end(); it++)
+ for (IDMap::const_iterator it = idMap.begin(); it != idMap.end(); it++)
array.push_back(it->_key);
return array;
}
-const Array<WinResourceID> PEResources::getLangList(const WinResourceID &type, const WinResourceID &name) const {
+const Array<WinResourceID> PEResources::getLangList(const WinResourceID &type, const WinResourceID &id) const {
Array<WinResourceID> array;
if (!_exe || !_resources.contains(type))
return array;
- const NameMap &nameMap = _resources[type];
+ const IDMap &idMap = _resources[type];
- if (!nameMap.contains(name))
+ if (!idMap.contains(id))
return array;
- const LangMap &langMap = nameMap[name];
+ const LangMap &langMap = idMap[id];
for (LangMap::const_iterator it = langMap.begin(); it != langMap.end(); it++)
array.push_back(it->_key);
@@ -220,27 +205,27 @@ const Array<WinResourceID> PEResources::getLangList(const WinResourceID &type, c
return array;
}
-SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name) {
- Array<WinResourceID> langList = getLangList(type, name);
+SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &id) {
+ Array<WinResourceID> langList = getLangList(type, id);
if (langList.empty())
return nullptr;
- const Resource &resource = _resources[type][name][langList[0]];
+ const Resource &resource = _resources[type][id][langList[0]];
_exe->seek(resource.offset);
return _exe->readStream(resource.size);
}
-SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang) {
+SeekableReadStream *PEResources::getResource(const WinResourceID &type, const WinResourceID &id, const WinResourceID &lang) {
if (!_exe || !_resources.contains(type))
return nullptr;
- const NameMap &nameMap = _resources[type];
+ const IDMap &idMap = _resources[type];
- if (!nameMap.contains(name))
+ if (!idMap.contains(id))
return nullptr;
- const LangMap &langMap = nameMap[name];
+ const LangMap &langMap = idMap[id];
if (!langMap.contains(lang))
return nullptr;
diff --git a/common/winexe_pe.h b/common/winexe_pe.h
index 6f92cde6dc..79b913043a 100644
--- a/common/winexe_pe.h
+++ b/common/winexe_pe.h
@@ -37,7 +37,7 @@ class SeekableReadStream;
* A class able to load resources from a Windows Portable Executable, such
* as cursors, bitmaps, and sounds.
*/
-class PEResources {
+class PEResources : public WinResources {
public:
PEResources();
~PEResources();
@@ -46,7 +46,7 @@ public:
void clear();
/** Load from an EXE file. */
- bool loadFromEXE(const String &fileName);
+ using WinResources::loadFromEXE;
/** Load from a stream. */
bool loadFromEXE(SeekableReadStream *stream);
@@ -54,17 +54,17 @@ public:
/** 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 IDs for a given type. */
+ const Array<WinResourceID> getIDList(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 list of languages for a given type and ID. */
+ const Array<WinResourceID> getLangList(const WinResourceID &type, const WinResourceID &id) 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);
+ SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &id);
/** Return a stream to the specified resource (or 0 if non-existent). */
- SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &name, const WinResourceID &lang);
+ SeekableReadStream *getResource(const WinResourceID &type, const WinResourceID &id, const WinResourceID &lang);
private:
struct Section {
@@ -78,7 +78,7 @@ private:
SeekableReadStream *_exe;
void parseResourceLevel(Section &section, uint32 offset, int level);
- WinResourceID _curType, _curName, _curLang;
+ WinResourceID _curType, _curID, _curLang;
struct Resource {
uint32 offset;
@@ -86,8 +86,8 @@ private:
};
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;
+ typedef HashMap<WinResourceID, LangMap, WinResourceID_Hash, WinResourceID_EqualTo> IDMap;
+ typedef HashMap<WinResourceID, IDMap, WinResourceID_Hash, WinResourceID_EqualTo> TypeMap;
TypeMap _resources;
};