aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Sandulenko2013-05-01 15:15:08 +0300
committerEugene Sandulenko2013-09-06 14:48:06 +0300
commitc69415112f790091ba1a9545462078ae3960c72a (patch)
treeb74302d4e40c6438271b7c696856ccddad0dadbe
parent26e6f5086046ad824c6338fc78ea49f9d71f0dbd (diff)
downloadscummvm-rg350-c69415112f790091ba1a9545462078ae3960c72a.tar.gz
scummvm-rg350-c69415112f790091ba1a9545462078ae3960c72a.tar.bz2
scummvm-rg350-c69415112f790091ba1a9545462078ae3960c72a.zip
FULLPIPE: Implemented NMI archive parser
-rw-r--r--engines/fullpipe/fullpipe.cpp4
-rw-r--r--engines/fullpipe/ngiarchive.cpp181
-rw-r--r--engines/fullpipe/ngiarchive.h42
3 files changed, 227 insertions, 0 deletions
diff --git a/engines/fullpipe/fullpipe.cpp b/engines/fullpipe/fullpipe.cpp
index 23bae97f1e..5be5338f86 100644
--- a/engines/fullpipe/fullpipe.cpp
+++ b/engines/fullpipe/fullpipe.cpp
@@ -22,11 +22,13 @@
#include "base/plugins.h"
+#include "common/archive.h"
#include "common/config-manager.h"
#include "engines/util.h"
#include "fullpipe/fullpipe.h"
+#include "fullpipe/ngiarchive.h"
namespace Fullpipe {
@@ -53,6 +55,8 @@ Common::Error FullpipeEngine::run() {
_isSaveAllowed = false;
+ Common::Archive *arch = makeNGIArchive("3896.nl");
+
return Common::kNoError;
}
diff --git a/engines/fullpipe/ngiarchive.cpp b/engines/fullpipe/ngiarchive.cpp
new file mode 100644
index 0000000000..801d020495
--- /dev/null
+++ b/engines/fullpipe/ngiarchive.cpp
@@ -0,0 +1,181 @@
+/* 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.
+ *
+ */
+
+#include "fullpipe/fullpipe.h"
+#include "common/archive.h"
+
+#include "common/file.h"
+#include "common/hash-str.h"
+#include "common/memstream.h"
+#include "common/bufferedstream.h"
+#include "common/textconsole.h"
+
+#include "fullpipe/ngiarchive.h"
+
+namespace Fullpipe {
+
+#define NGI_FILENAME_MAX 13
+
+struct NgiHeader {
+ int32 pos;
+ int32 extVal;
+ int32 flags;
+ int32 size;
+ char filename[NGI_FILENAME_MAX];
+};
+
+typedef Common::HashMap<Common::String, NgiHeader*, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> NgiHeadersMap;
+
+class NGIArchive : public Common::Archive {
+ NgiHeadersMap _headers;
+ Common::String _ngiFilename;
+
+public:
+ NGIArchive(const Common::String &name);
+ virtual ~NGIArchive();
+
+ // Archive implementation
+ virtual bool hasFile(const Common::String &name) const;
+ virtual int listMembers(Common::ArchiveMemberList &list) const;
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+};
+
+NGIArchive::NGIArchive(const Common::String &filename) : _ngiFilename(filename) {
+ Common::File ngiFile;
+
+ if (!ngiFile.open(_ngiFilename)) {
+ warning("NGIArchive::NGIArchive(): Could not find the archive file");
+ return;
+ }
+
+ ngiFile.seek(4, SEEK_SET);
+
+ unsigned int count = ngiFile.readUint16LE(); // How many entries?
+
+ ngiFile.seek(20, SEEK_SET);
+
+ unsigned int key = ngiFile.readUint16LE();
+
+ byte key1, key2;
+
+ key1 = key & 0xff;
+ key2 = (key >> 8) & 0xff;
+
+ int fatSize = count * 32;
+
+ ngiFile.seek(32, SEEK_SET);
+
+ byte *fat = (byte *)calloc(fatSize, 1);
+
+ ngiFile.read(fat, fatSize);
+
+ for (int i = 0; i < fatSize; i++) {
+ key1 = (key1 << 1) ^ key2;
+ key2 = (key2 >> 1) ^ key1;
+
+ fat[i] ^= key1;
+ }
+
+ NgiHeader header;
+ NgiHeader *head;
+
+ for (uint i = 0; i < count; i++) {
+ memcpy(header.filename, &fat[i * 32], 12);
+ header.filename[12] = 0;
+ header.flags = READ_LE_UINT32(&fat[i * 32 + 16]);
+ header.extVal = READ_LE_UINT32(&fat[i * 32 + 20]);
+ header.pos = READ_LE_UINT32(&fat[i * 32 + 24]);
+ header.size = READ_LE_UINT32(&fat[i * 32 + 28]);
+
+ if (header.flags & 0x1e0) {
+ warning("File has flags: %.8x\n", header.flags & 0x1e0);
+ }
+
+ head = new NgiHeader(header);
+
+ _headers[header.filename] = head;
+ }
+
+ free(fat);
+
+ debug(0, "NGIArchive::NGIArchive(%s): Located %d files", filename.c_str(), _headers.size());
+}
+
+NGIArchive::~NGIArchive() {
+ debug(0, "NGIArchive Destructor Called");
+ NgiHeadersMap::iterator it = _headers.begin();
+ for ( ; it != _headers.end(); ++it) {
+ delete it->_value;
+ }
+}
+
+bool NGIArchive::hasFile(const Common::String &name) const {
+ return _headers.contains(name);
+}
+
+ int NGIArchive::listMembers(Common::ArchiveMemberList &list) const {
+ int matches = 0;
+
+ NgiHeadersMap::const_iterator it = _headers.begin();
+ for ( ; it != _headers.end(); ++it) {
+ list.push_back(Common::ArchiveMemberList::value_type(new Common::GenericArchiveMember(it->_value->filename, this)));
+ matches++;
+ }
+
+ return matches;
+}
+
+const Common::ArchiveMemberPtr NGIArchive::getMember(const Common::String &name) const {
+ if (!hasFile(name))
+ return Common::ArchiveMemberPtr();
+
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(name, this));
+}
+
+Common::SeekableReadStream *NGIArchive::createReadStreamForMember(const Common::String &name) const {
+ if (!_headers.contains(name)) {
+ return 0;
+ }
+
+ NgiHeader *hdr = _headers[name];
+
+ Common::File archiveFile;
+ archiveFile.open(_ngiFilename);
+ archiveFile.seek(hdr->pos, SEEK_SET);
+
+ // TODO: It would be good if ArjFile could decompress files in a streaming
+ // mode, so it would not need to pre-allocate the entire output.
+ byte *data = (byte *)malloc(hdr->size);
+ assert(data);
+
+ int32 len = archiveFile.read(data, hdr->size);
+ assert(len == hdr->size);
+
+ return new Common::MemoryReadStream(data, hdr->size, DisposeAfterUse::YES);
+}
+
+Common::Archive *makeNGIArchive(const Common::String &name) {
+ return new NGIArchive(name);
+}
+
+} // End of namespace Fullpipe
diff --git a/engines/fullpipe/ngiarchive.h b/engines/fullpipe/ngiarchive.h
new file mode 100644
index 0000000000..ee977c6140
--- /dev/null
+++ b/engines/fullpipe/ngiarchive.h
@@ -0,0 +1,42 @@
+/* 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.
+ *
+ */
+
+#ifndef FULLPIPE_NGIARCHIVE_H
+#define FULLPIPE_NGIARCHIVE_H
+
+#include "common/str.h"
+
+namespace Fullpipe {
+
+class Archive;
+
+/**
+ * This factory method creates an Archive instance corresponding to the content
+ * of the NGI compressed file with the given name.
+ *
+ * May return 0 in case of a failure.
+ */
+Common::Archive *makeNGIArchive(const Common::String &name);
+
+} // End of namespace Fullpipe
+
+#endif