[Scummvm-git-logs] scummvm-tools master -> 2317d8fdc062ad55b0e7f7f4d758162e342b8c00

sev- sev at scummvm.org
Tue Sep 10 11:17:50 CEST 2019


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm-tools' repo located at https://github.com/scummvm/scummvm-tools .

Summary:
2317d8fdc0 TOOLS: Added HDB extraction tool


Commit: 2317d8fdc062ad55b0e7f7f4d758162e342b8c00
    https://github.com/scummvm/scummvm-tools/commit/2317d8fdc062ad55b0e7f7f4d758162e342b8c00
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2019-08-13T00:07:21+02:00

Commit Message:
TOOLS: Added HDB extraction tool

Changed paths:
  A engines/hdb/extract_hdb.cpp
  A engines/hdb/extract_hdb.h
    Makefile.common
    README
    tools.cpp


diff --git a/Makefile.common b/Makefile.common
index 08a95c4..e782d4c 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -172,6 +172,7 @@ tools_OBJS := \
 	engines/bladerunner/pack_bladerunner.o \
 	engines/gob/compress_gob.o \
 	engines/gob/extract_fascination_cd.o \
+	engines/hdb/extract_hdb.o \
 	engines/kyra/compress_kyra.o \
 	engines/queen/compress_queen.o \
 	engines/saga/compress_saga.o \
diff --git a/README b/README
index ab47190..84b0cc5 100644
--- a/README
+++ b/README
@@ -92,6 +92,12 @@ Extraction Tools:
                 Example of usage:
                 ./scummvm-tools-cli --tool extract_gob_stk [-o outputdir] <infile>
 
+        extract_hdb
+               Extracts Hyperspace Delivery Boy! archives.
+
+               Example of usage:
+                ./scummvm-tools-cli --tool extract_hdb [-o outputdir] <hyperspace.msd>
+
         extract_kyra
                 Unpacks .PAK files from Kyrandia games.
 
diff --git a/engines/hdb/extract_hdb.cpp b/engines/hdb/extract_hdb.cpp
new file mode 100644
index 0000000..ec2ce0b
--- /dev/null
+++ b/engines/hdb/extract_hdb.cpp
@@ -0,0 +1,168 @@
+/* ScummVM Tools
+ *
+ * ScummVM Tools 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "extract_hdb.h"
+#include <zlib.h>
+
+
+ExtractHDB::ExtractHDB(const std::string &name) : Tool(name, TOOLTYPE_EXTRACTION) {
+	ToolInput input;
+	input.format = "*.*";
+	_inputPaths.push_back(input);
+
+	_outputToDirectory = true;
+
+	_shorthelp = "Used to extract Hyperspace Delivery Boy! archive files.";
+	_helptext = "\nUsage: " + getName() + " [-o /path/to/output/dir/] <inputfile>\n";
+
+	_compressed = false;
+}
+
+void ExtractHDB::execute() {
+	Common::Filename filename = _inputPaths[0].path;
+
+	if (!openMPC(filename))
+		error("Unable to open %s", filename.getFullName().c_str());
+
+	Common::File fOut;
+	for (Common::Array<MPCEntry *>::iterator it = _dir.begin(); it != _dir.end(); it++) {
+		byte *buffer = (byte *)malloc((*it)->length);
+
+		_mpcFile.seek((*it)->offset, SEEK_SET);
+
+		_mpcFile.read_noThrow(buffer, (*it)->length);
+
+		_outputPath.setFullName((*it)->filename);
+
+		fOut.open(_outputPath, "wb");
+
+		if (_compressed) {
+			byte *buffer2 = (byte *)calloc((*it)->ulength, 1);
+			unsigned long len = (*it)->ulength;
+
+			print("... decompressing %s", (*it)->filename);
+
+			if (uncompress(buffer2, &len, buffer, (*it)->length) != Z_OK) {
+				print("Error uncompressing file %s", (*it)->filename);
+
+				fOut.write(buffer, (*it)->length);
+			} else if (len != (*it)->ulength) {
+				print("Size mismatch for %s: %d <> %d", (*it)->filename, len, (*it)->ulength);
+
+				fOut.write(buffer, (*it)->length);
+			} else {
+				fOut.write(buffer2, (*it)->ulength);
+			}
+
+			free(buffer2);
+		} else {
+			print("... %s", (*it)->filename);
+			fOut.write(buffer, (*it)->length);
+		}
+
+		fOut.close();
+
+		free(buffer);
+	}
+
+	_mpcFile.close();
+}
+
+InspectionMatch ExtractHDB::inspectInput(const Common::Filename &filename) {
+	// Accept either 'vol.cat' or 'vol.dat'
+	std::string file = filename.getFullName();
+	if (
+		scumm_stricmp(file.c_str(), "hyperspace.mpc") == 0 ||
+		scumm_stricmp(file.c_str(), "hyperspace.msd") == 0 ||
+		scumm_stricmp(file.c_str(), "hyperdemo.mpc") == 0 ||
+		scumm_stricmp(file.c_str(), "hyperdemo.msd") == 0
+	)
+		return IMATCH_PERFECT;
+	return IMATCH_AWFUL;
+}
+
+bool ExtractHDB::openMPC(Common::Filename &filename) {
+	uint32 offset;
+
+	_mpcFile.open(filename, "rb");
+	if (!_mpcFile.isOpen()) {
+		error("FileMan::openMPC(): Error reading the MSD/MPC file %s", filename.getFullName().c_str());
+		return false;
+	}
+
+	_dataHeader.id = _mpcFile.readUint32BE();
+
+	if (_dataHeader.id == 'MPCC') {
+		print("COMPRESSED MPC FILE");
+		return false;
+	} else if (_dataHeader.id == 'MPCU') {
+		print("Unpacking uncompressed MPC file...");
+		// we're fine
+	} else if (_dataHeader.id == 'MSDC') {
+		print("Unpacking compressed MSD file...");
+		_compressed = true;
+		// we're fine
+	} else if (_dataHeader.id == 'MSDU') {
+		print("UNCOMPRESSED MSD FILE");
+		return false;
+	} else {
+		error("Invalid MPC/MSD File.");
+		return false;
+	}
+
+	// read the directory
+	offset = _mpcFile.readUint32LE();
+	_mpcFile.seek((int32)offset, SEEK_SET);
+
+	// Note: The MPC archive format assumes the offset to be uint32,
+	// but Common::File::seek() takes the offset as int32.
+
+	_dataHeader.dirSize = _mpcFile.readUint32LE();
+
+	print("MPCU: Read %d entries", _dataHeader.dirSize);
+
+	for (uint32 fileIndex = 0; fileIndex < _dataHeader.dirSize; fileIndex++) {
+		MPCEntry *dirEntry = new MPCEntry();
+
+		for (int i = 0; i < 64; i++) {
+			dirEntry->filename[i] = _mpcFile.readByte();
+		}
+
+		dirEntry->offset = _mpcFile.readUint32LE();
+		dirEntry->length = _mpcFile.readUint32LE();
+		dirEntry->ulength = _mpcFile.readUint32LE();
+		dirEntry->type = (DataType)_mpcFile.readUint32LE();
+
+		_dir.push_back(dirEntry);
+	}
+
+	return true;
+}
+
+#ifdef STANDALONE_MAIN
+int main(int argc, char *argv[]) {
+	ExtractHDB hdb(argv[0]);
+	return hdb.run(argc, argv);
+}
+#endif
diff --git a/engines/hdb/extract_hdb.h b/engines/hdb/extract_hdb.h
new file mode 100644
index 0000000..8917c07
--- /dev/null
+++ b/engines/hdb/extract_hdb.h
@@ -0,0 +1,71 @@
+/* ScummVM Tools
+ *
+ * ScummVM Tools 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 EXTRACT_HDB_H
+#define EXTRACT_HDB_H
+
+#include "tool.h"
+#include "common/array.h"
+
+enum DataType {
+	TYPE_ERROR,
+	TYPE_BINARY,
+	TYPE_TILE32,
+	TYPE_FONT,
+	TYPE_ICON32,
+	TYPE_PIC,
+
+	ENDOFTYPES
+};
+
+struct MPCEntry {
+	char	filename[64];	// filename
+	int32	offset;			// offset in MSD file of data
+	int32	length;			// compressed length of data
+	int32	ulength;		// uncompressed length
+	DataType	type;		// type of data
+};
+
+#define MPCIterator Common::Array<MPCEntry *>::iterator
+
+class ExtractHDB : public Tool {
+public:
+	ExtractHDB(const std::string &name = "extract_hdb");
+
+	virtual void execute();
+
+	virtual InspectionMatch inspectInput(const Common::Filename &filename);
+
+protected:
+	bool openMPC(Common::Filename &filename);
+
+	Common::File _mpcFile;
+
+	struct {
+		uint32 id;
+		uint32 dirSize;
+	} _dataHeader;
+
+	Common::Array<MPCEntry *> _dir;
+	bool _compressed;
+};
+
+#endif
diff --git a/tools.cpp b/tools.cpp
index b45cc6d..2ae1c08 100644
--- a/tools.cpp
+++ b/tools.cpp
@@ -54,6 +54,7 @@
 #include "engines/cruise/extract_cruise_pc.h"
 #include "engines/gob/extract_gob_stk.h"
 #include "engines/gob/extract_fascination_cd.h"
+#include "engines/hdb/extract_hdb.h"
 #include "engines/kyra/extract_kyra.h"
 #include "engines/prince/extract_prince.h"
 #include "engines/prince/pack_prince.h"
@@ -96,6 +97,7 @@ Tools::Tools() {
 	_tools.push_back(new ExtractCruisePC());
 	_tools.push_back(new ExtractGobStk());
 	_tools.push_back(new ExtractFascinationCD());
+	_tools.push_back(new ExtractHDB());
 	_tools.push_back(new ExtractKyra());
 	_tools.push_back(new ExtractPrince());
 	_tools.push_back(new PackPrince());





More information about the Scummvm-git-logs mailing list