aboutsummaryrefslogtreecommitdiff
path: root/engines/agos/installshield_cab.cpp
diff options
context:
space:
mode:
authorTravis Howell2011-08-28 00:40:55 +1000
committerMatthew Hoops2011-08-27 11:00:24 -0400
commit5346ac18b7e33a603aa2743fa57f430d96cdbc33 (patch)
tree2ad2a778bea8b850cd68438448283e16aa90ff1f /engines/agos/installshield_cab.cpp
parentf91f0f275660cfa3362036f583619b4ef7d343fd (diff)
downloadscummvm-rg350-5346ac18b7e33a603aa2743fa57f430d96cdbc33.tar.gz
scummvm-rg350-5346ac18b7e33a603aa2743fa57f430d96cdbc33.tar.bz2
scummvm-rg350-5346ac18b7e33a603aa2743fa57f430d96cdbc33.zip
AGOS: Integrate InstallShield support.
Diffstat (limited to 'engines/agos/installshield_cab.cpp')
-rw-r--r--engines/agos/installshield_cab.cpp126
1 files changed, 73 insertions, 53 deletions
diff --git a/engines/agos/installshield_cab.cpp b/engines/agos/installshield_cab.cpp
index a8b5d0fba2..f7b49a64c5 100644
--- a/engines/agos/installshield_cab.cpp
+++ b/engines/agos/installshield_cab.cpp
@@ -46,59 +46,80 @@
#include "agos/installshield_cab.h"
#include "common/debug.h"
+#include "common/file.h"
#include "common/memstream.h"
#include "common/zlib.h"
namespace AGOS {
-InstallShieldCabinet::InstallShieldCabinet() : Common::Archive() {
- _stream = 0;
-}
+class InstallShieldCabinet : public Common::Archive {
+ Common::String _installShieldFilename;
+
+public:
+ InstallShieldCabinet(const Common::String &filename);
+ ~InstallShieldCabinet();
+
+ // Common::Archive API implementation
+ bool hasFile(const Common::String &name);
+ int listMembers(Common::ArchiveMemberList &list);
+ Common::ArchiveMemberPtr getMember(const Common::String &name);
+ Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+
+private:
+ struct FileEntry {
+ uint32 uncompressedSize;
+ uint32 compressedSize;
+ uint32 offset;
+ uint16 flags;
+ };
+
+ typedef Common::HashMap<Common::String, FileEntry, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> FileMap;
+ FileMap _map;
+};
InstallShieldCabinet::~InstallShieldCabinet() {
- close();
+ _map.clear();
}
-bool InstallShieldCabinet::open(const Common::String &filename) {
- close();
+InstallShieldCabinet::InstallShieldCabinet(const Common::String &filename) : _installShieldFilename(filename) {
+ Common::File installShieldFile;
- _stream = SearchMan.createReadStreamForMember(filename);
-
- if (!_stream)
- return false;
+ if (!installShieldFile.open(_installShieldFilename)) {
+ warning("InstallShieldCabinet::InstallShieldCabinet(): Could not find the archive file %s", _installShieldFilename.c_str());
+ return;
+ }
// Note that we only support a limited subset of cabinet files
// Only single cabinet files and ones without data shared between
// cabinets.
// Check for the magic uint32
- if (_stream->readUint32LE() != 0x28635349) {
- close();
- return false;
+ if (installShieldFile.readUint32LE() != 0x28635349) {
+ warning("InstallShieldCabinet::InstallShieldCabinet(): Magic ID doesn't match");
+ return;
}
- uint32 version = _stream->readUint32LE();
+ uint32 version = installShieldFile.readUint32LE();
if (version != 0x01000004) {
warning("Unsupported CAB version %08x", version);
- close();
- return false;
+ return;
}
- /* uint32 volumeInfo = */ _stream->readUint32LE();
- uint32 cabDescriptorOffset = _stream->readUint32LE();
- /* uint32 cabDescriptorSize = */ _stream->readUint32LE();
+ /* uint32 volumeInfo = */ installShieldFile.readUint32LE();
+ uint32 cabDescriptorOffset = installShieldFile.readUint32LE();
+ /* uint32 cabDescriptorSize = */ installShieldFile.readUint32LE();
- _stream->seek(cabDescriptorOffset);
+ installShieldFile.seek(cabDescriptorOffset);
- _stream->skip(12);
- uint32 fileTableOffset = _stream->readUint32LE();
- _stream->skip(4);
- uint32 fileTableSize = _stream->readUint32LE();
- uint32 fileTableSize2 = _stream->readUint32LE();
- uint32 directoryCount = _stream->readUint32LE();
- _stream->skip(8);
- uint32 fileCount = _stream->readUint32LE();
+ installShieldFile.skip(12);
+ uint32 fileTableOffset = installShieldFile.readUint32LE();
+ installShieldFile.skip(4);
+ uint32 fileTableSize = installShieldFile.readUint32LE();
+ uint32 fileTableSize2 = installShieldFile.readUint32LE();
+ uint32 directoryCount = installShieldFile.readUint32LE();
+ installShieldFile.skip(8);
+ uint32 fileCount = installShieldFile.readUint32LE();
if (fileTableSize != fileTableSize2)
warning("file table sizes do not match");
@@ -106,49 +127,42 @@ bool InstallShieldCabinet::open(const Common::String &filename) {
// We're ignoring file groups and components since we
// should not need them. Moving on to the files...
- _stream->seek(cabDescriptorOffset + fileTableOffset);
+ installShieldFile.seek(cabDescriptorOffset + fileTableOffset);
uint32 fileTableCount = directoryCount + fileCount;
uint32 *fileTableOffsets = new uint32[fileTableCount];
for (uint32 i = 0; i < fileTableCount; i++)
- fileTableOffsets[i] = _stream->readUint32LE();
+ fileTableOffsets[i] = installShieldFile.readUint32LE();
for (uint32 i = directoryCount; i < fileCount + directoryCount; i++) {
- _stream->seek(cabDescriptorOffset + fileTableOffset + fileTableOffsets[i]);
- uint32 nameOffset = _stream->readUint32LE();
- /* uint32 directoryIndex = */ _stream->readUint32LE();
+ installShieldFile.seek(cabDescriptorOffset + fileTableOffset + fileTableOffsets[i]);
+ uint32 nameOffset = installShieldFile.readUint32LE();
+ /* uint32 directoryIndex = */ installShieldFile.readUint32LE();
// First read in data needed by us to get at the file data
FileEntry entry;
- entry.flags = _stream->readUint16LE();
- entry.uncompressedSize = _stream->readUint32LE();
- entry.compressedSize = _stream->readUint32LE();
- _stream->skip(20);
- entry.offset = _stream->readUint32LE();
+ entry.flags = installShieldFile.readUint16LE();
+ entry.uncompressedSize = installShieldFile.readUint32LE();
+ entry.compressedSize = installShieldFile.readUint32LE();
+ installShieldFile.skip(20);
+ entry.offset = installShieldFile.readUint32LE();
// Then let's get the string
- _stream->seek(cabDescriptorOffset + fileTableOffset + nameOffset);
+ installShieldFile.seek(cabDescriptorOffset + fileTableOffset + nameOffset);
Common::String fileName;
- char c = _stream->readByte();
+ char c = installShieldFile.readByte();
while (c) {
fileName += c;
- c = _stream->readByte();
+ c = installShieldFile.readByte();
}
-
_map[fileName] = entry;
}
delete[] fileTableOffsets;
-
- return true;
-}
-
-void InstallShieldCabinet::close() {
- delete _stream; _stream = 0;
- _map.clear();
}
bool InstallShieldCabinet::hasFile(const Common::String &name) {
+ warning("hasFile: Filename %s", name.c_str());
return _map.contains(name);
}
@@ -164,23 +178,25 @@ Common::ArchiveMemberPtr InstallShieldCabinet::getMember(const Common::String &n
}
Common::SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(const Common::String &name) const {
- if (!_stream || !_map.contains(name))
+ if (!_map.contains(name))
return 0;
const FileEntry &entry = _map[name];
- _stream->seek(entry.offset);
+ Common::File archiveFile;
+ archiveFile.open(_installShieldFilename);
+ archiveFile.seek(entry.offset);
if (!(entry.flags & 0x04)) {
// Not compressed
- return _stream->readStream(entry.uncompressedSize);
+ return archiveFile.readStream(entry.uncompressedSize);
}
#ifdef USE_ZLIB
byte *src = (byte *)malloc(entry.compressedSize);
byte *dst = (byte *)malloc(entry.uncompressedSize);
- _stream->read(src, entry.compressedSize);
+ archiveFile.read(src, entry.compressedSize);
bool result = Common::inflateZlibHeaderless(dst, entry.uncompressedSize, src, entry.compressedSize);
free(src);
@@ -198,4 +214,8 @@ Common::SeekableReadStream *InstallShieldCabinet::createReadStreamForMember(cons
#endif
}
+Common::Archive *makeInstallShieldArchive(const Common::String &name) {
+ return new InstallShieldCabinet(name);
+}
+
} // End of namespace AGOS