aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
Diffstat (limited to 'engines')
-rw-r--r--engines/zvision/zfsArchive.cpp29
-rw-r--r--engines/zvision/zfsArchive.h28
2 files changed, 45 insertions, 12 deletions
diff --git a/engines/zvision/zfsArchive.cpp b/engines/zvision/zfsArchive.cpp
index a3111d7705..59e65f1713 100644
--- a/engines/zvision/zfsArchive.cpp
+++ b/engines/zvision/zfsArchive.cpp
@@ -55,16 +55,17 @@ ZfsArchive::~ZfsArchive() {
}
void ZfsArchive::readHeaders(Common::SeekableReadStream *stream) {
- ZfsHeader header;
-
// Don't do a straight struct cast since we can't guarantee endianness
- header.magic = stream->readUint32LE();
- header.unknown1 = stream->readUint32LE();
- header.unknown2 = stream->readUint32LE();
- header.filesPerBlock = stream->readUint32LE();
- header.fileCount = stream->readUint32LE();
- header.xorKey = stream->readUint32LE();
- header.fileSectionOffset = stream->readUint32LE();
+ _header.magic = stream->readUint32LE();
+ _header.unknown1 = stream->readUint32LE();
+ _header.maxNameLength = stream->readUint32LE();
+ _header.filesPerBlock = stream->readUint32LE();
+ _header.fileCount = stream->readUint32LE();
+ _header.xorKey[0] = stream->readByte();
+ _header.xorKey[1] = stream->readByte();
+ _header.xorKey[2] = stream->readByte();
+ _header.xorKey[3] = stream->readByte();
+ _header.fileSectionOffset = stream->readUint32LE();
uint32 nextOffset;
@@ -73,7 +74,7 @@ void ZfsArchive::readHeaders(Common::SeekableReadStream *stream) {
nextOffset = stream->readUint32LE();
// Read in each entry header
- for (int i = 0; i < header.filesPerBlock; i++) {
+ for (int i = 0; i < _header.filesPerBlock; i++) {
ZfsEntryHeader entryHeader;
entryHeader.name = readEntryName(stream);
@@ -135,10 +136,18 @@ Common::SeekableReadStream *ZfsArchive::createReadStreamForMember(const Common::
byte* buffer = new byte[entryHeader->size];
zfsArchive.read(buffer, entryHeader->size);
+ // Decrypt the data in place
+ if (_header.xorKey != 0)
+ unXor(buffer, entryHeader->size, _header.xorKey);
return new Common::MemoryReadStream(buffer, entryHeader->size, DisposeAfterUse::YES);
}
+void ZfsArchive::unXor(byte *buffer, int length, const byte *xorKey) const {
+ for (uint32 i = 0; i < length; i++)
+ buffer[i] ^= xorKey[i % 4];
+}
+
} // End namespace ZVision
diff --git a/engines/zvision/zfsArchive.h b/engines/zvision/zfsArchive.h
index 96c002f815..718b26c836 100644
--- a/engines/zvision/zfsArchive.h
+++ b/engines/zvision/zfsArchive.h
@@ -32,10 +32,10 @@ namespace ZVision {
struct ZfsHeader {
uint32 magic;
uint32 unknown1;
- uint32 unknown2;
+ uint32 maxNameLength;
uint32 filesPerBlock;
uint32 fileCount;
- uint32 xorKey;
+ byte xorKey[4];
uint32 fileSectionOffset;
};
@@ -85,10 +85,34 @@ public:
private:
const Common::String _fileName;
+ ZfsHeader _header;
ZfsEntryHeaderMap _entryHeaders;
+ /**
+ * Parses the zfs file into file entry headers that can be used later
+ * to get the entry data.
+ *
+ * @param stream The contents of the zfs file
+ */
void readHeaders(Common::SeekableReadStream *stream);
+
+ /**
+ * Entry names are contained within a 16 byte block. This reads the block
+ * and converts it the name to a Common::String
+ *
+ * @param stream The zfs file stream
+ * @return The entry file name
+ */
Common::String readEntryName(Common::SeekableReadStream *stream) const;
+
+ /**
+ * ZFS file entries can be encrypted using XOR encoding. This method
+ * decodes the buffer in place using the supplied xorKey.
+ *
+ * @param buffer The data to decode
+ * @param length Length of buffer
+ */
+ void unXor(byte *buffer, int length, const byte *xorKey) const;
};
} // End of namespace Common