From aa9a41545ad331acb37dde0790adfa8298b1f8b5 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Thu, 2 Jan 2020 21:23:35 +0000 Subject: COMMON: Add a common base class for the Windows resource classes --- common/winexe.cpp | 82 +++++++++++++++++++++++++++++++++++ common/winexe.h | 40 +++++++++++++++++ common/winexe_ne.cpp | 82 ----------------------------------- common/winexe_ne.h | 7 +-- common/winexe_pe.cpp | 15 ------- common/winexe_pe.h | 4 +- devtools/create_titanic/winexe.cpp | 14 ++++++ devtools/create_titanic/winexe.h | 35 +++++++++++++++ devtools/create_titanic/winexe_pe.cpp | 14 ------ devtools/create_titanic/winexe_pe.h | 4 +- 10 files changed, 177 insertions(+), 120 deletions(-) diff --git a/common/winexe.cpp b/common/winexe.cpp index fc389f6ea6..fd1d565036 100644 --- a/common/winexe.cpp +++ b/common/winexe.cpp @@ -20,6 +20,8 @@ * */ +#include "common/file.h" +#include "common/memstream.h" #include "common/str.h" #include "common/winexe.h" @@ -78,4 +80,84 @@ 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); +} + } // End of namespace Common diff --git a/common/winexe.h b/common/winexe.h index 9aeea379ed..cdbc0f6d13 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,44 @@ 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 getIDList(const WinResourceID &type) const = 0; + + /** Return a list of languages for a given type and ID. */ + virtual const Array getLangList(const WinResourceID &type, const WinResourceID &id) const { + Array 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); + } +}; + } // 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 a79b0c4d50..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(); diff --git a/common/winexe_pe.h b/common/winexe_pe.h index 875ec898ad..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); diff --git a/devtools/create_titanic/winexe.cpp b/devtools/create_titanic/winexe.cpp index c23bd84a89..49be23dbd4 100644 --- a/devtools/create_titanic/winexe.cpp +++ b/devtools/create_titanic/winexe.cpp @@ -80,4 +80,18 @@ String WinResourceID::toString() const { return ""; } +bool WinResources::loadFromEXE(const String &fileName) { + if (fileName.empty()) + return false; + + File *file = new File(); + + if (!file->open(fileName.c_str())) { + delete file; + return false; + } + + return loadFromEXE(file); +} + } // End of namespace Common diff --git a/devtools/create_titanic/winexe.h b/devtools/create_titanic/winexe.h index 102f1494fd..6bfe2a25a0 100644 --- a/devtools/create_titanic/winexe.h +++ b/devtools/create_titanic/winexe.h @@ -23,6 +23,7 @@ #ifndef COMMON_WINEXE_H #define COMMON_WINEXE_H +#include "file.h" #include "hash-str.h" #include "str.h" @@ -90,6 +91,40 @@ 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); + + virtual bool loadFromEXE(File *stream) = 0; + + /** Return a list of IDs for a given type. */ + virtual const Array getIDList(const WinResourceID &type) const = 0; + + /** Return a list of languages for a given type and ID. */ + virtual const Array getLangList(const WinResourceID &type, const WinResourceID &id) const { + Array array; + return array; + }; + + /** Return a stream to the specified resource, taking the first language found (or 0 if non-existent). */ + virtual File *getResource(const WinResourceID &type, const WinResourceID &id) = 0; + + /** Return a stream to the specified resource (or 0 if non-existent). */ + virtual File *getResource(const WinResourceID &type, const WinResourceID &id, const WinResourceID &lang) { + return getResource(type, id); + } +}; + } // End of namespace Common #endif diff --git a/devtools/create_titanic/winexe_pe.cpp b/devtools/create_titanic/winexe_pe.cpp index 9d35f592fc..f55740f692 100644 --- a/devtools/create_titanic/winexe_pe.cpp +++ b/devtools/create_titanic/winexe_pe.cpp @@ -44,20 +44,6 @@ void PEResources::clear() { delete _exe; _exe = 0; } -bool PEResources::loadFromEXE(const String &fileName) { - if (fileName.empty()) - return false; - - File *file = new File(); - - if (!file->open(fileName.c_str())) { - delete file; - return false; - } - - return loadFromEXE(file); -} - bool PEResources::loadFromEXE(File *stream) { clear(); diff --git a/devtools/create_titanic/winexe_pe.h b/devtools/create_titanic/winexe_pe.h index f72b6fbb04..6ab7ae847a 100644 --- a/devtools/create_titanic/winexe_pe.h +++ b/devtools/create_titanic/winexe_pe.h @@ -38,7 +38,7 @@ class SeekableReadStream; * A class able to load resources from a Windows Portable Executable, such * as cursors, bitmaps, and sounds. */ -class PEResources { +class PEResources : WinResources { public: PEResources(); ~PEResources(); @@ -47,7 +47,7 @@ public: void clear(); /** Load from an EXE file. */ - bool loadFromEXE(const String &fileName); + using WinResources::loadFromEXE; bool loadFromEXE(File *stream); -- cgit v1.2.3