[Scummvm-git-logs] scummvm master -> 8b1124de8f865e54cd165e53f82aa87f7d66f764

dreammaster noreply at scummvm.org
Thu Jul 2 19:57:02 UTC 2026


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

Summary:
8b1124de8f MADS: PHANTOM: MPSArchive class for directly using installer archives


Commit: 8b1124de8f865e54cd165e53f82aa87f7d66f764
    https://github.com/scummvm/scummvm/commit/8b1124de8f865e54cd165e53f82aa87f7d66f764
Author: Paul Gilbert (dreammaster at scummvm.org)
Date: 2026-07-03T05:56:39+10:00

Commit Message:
MADS: PHANTOM: MPSArchive class for directly using installer archives

Changed paths:
  A engines/mads/madsv2/core/mps_archive.cpp
  A engines/mads/madsv2/core/mps_archive.h
    engines/mads/detection_tables.h
    engines/mads/madsv2/dragonsphere/dragonsphere.cpp
    engines/mads/madsv2/engine.cpp
    engines/mads/madsv2/engine.h
    engines/mads/madsv2/forest/forest.cpp
    engines/mads/madsv2/phantom/phantom.cpp
    engines/mads/module.mk


diff --git a/engines/mads/detection_tables.h b/engines/mads/detection_tables.h
index 33e67a4c352..d88d80fef28 100644
--- a/engines/mads/detection_tables.h
+++ b/engines/mads/detection_tables.h
@@ -177,6 +177,21 @@ static const MADSGameDescription gameDescriptions[] = {
 		0
 	},
 
+	{
+		// Return of the Phantom CD Installer
+		{
+			"phantom",
+			"CD Installer",
+			AD_ENTRY2s("mpslabs.001", "6f891664a0b09a00e45eaa3ee9b24669", 633998, "mpslabs.idx", "156a856072f4eb66b1f9b337358225e9", 4048),
+			Common::EN_ANY,
+			Common::kPlatformDOS,
+			ADGF_UNSTABLE | ADGF_CD | GF_INSTALLER,
+			GUIO3(GUIO_NOMIDI, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ORIGINAL_SAVELOAD)
+		},
+		GType_Phantom,
+		0
+	},
+
 	{
 		// Return of the Phantom DOS English Demo
 		{
@@ -226,12 +241,12 @@ static const MADSGameDescription gameDescriptions[] = {
 		// Dragonsphere Microprose DOS English
 		{
 			"dragonsphere",
-			0,
+			"CD Installer",
 			AD_ENTRY2s("mpslabs.001", "0d2143364be8e12b9807e111ffbe4fb5", 771220,
 				"mpslabs.idx", "db604f6e665516c59bebe60b404abe44", 4636),
 			Common::EN_ANY,
 			Common::kPlatformDOS,
-			GF_INSTALLER | ADGF_UNSTABLE,
+			ADGF_UNSTABLE | ADGF_CD | GF_INSTALLER,
 			GUIO3(GUIO_NOMIDI, GAMEOPTION_EASY_MOUSE, GAMEOPTION_ORIGINAL_SAVELOAD)
 		},
 		GType_Dragonsphere,
diff --git a/engines/mads/madsv2/core/mps_archive.cpp b/engines/mads/madsv2/core/mps_archive.cpp
new file mode 100644
index 00000000000..965ca739860
--- /dev/null
+++ b/engines/mads/madsv2/core/mps_archive.cpp
@@ -0,0 +1,128 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "common/file.h"
+#include "common/compression/unzip.h"
+#include "mads/madsv2/core/mps_archive.h"
+
+namespace MADS {
+namespace MADSV2 {
+
+static constexpr int HEADER_SIZE = 30;
+static constexpr int ENTRY_SIZE = 98;
+
+MpsArchive *MpsArchive::open(const char *baseName) {
+	Common::File indexFile, dataFile;
+	Common::String indexFilename = Common::String::format("%s.idx", baseName);
+	Common::String dataFilename;
+
+	if (!indexFile.open(indexFilename.c_str()))
+		error("Could not open %s", indexFilename.c_str());
+
+	indexFile.skip(2);
+	int totalFiles = indexFile.readUint16LE();
+	int numZips = indexFile.readUint16LE();
+
+	if (indexFile.readString('\0', 13) != "MPSLABS")
+		error("Invalid mpslabs index file");
+
+	// The mpslabs.idx file consists of a 30 byte header, followed by 98 byte
+	// entries for all the files. However, this is followed by extra entries
+	// specifying overall wad files within the msplabs.00? files, which are
+	// basically just bog-standard zip files
+	MpsArchive *result = new MpsArchive();
+	indexFile.seek(HEADER_SIZE + totalFiles * ENTRY_SIZE);
+	byte entry[ENTRY_SIZE];
+	int currentNum = -1;
+
+	for (int zipNum = 0; zipNum < numZips; ++zipNum) {
+		// Read the next entry
+		indexFile.read(entry, ENTRY_SIZE);
+		const int mpsNum = READ_LE_UINT16(entry + 0x54);
+		const int offset = READ_LE_UINT32(entry + 0x56);
+		const int size = READ_LE_UINT32(entry + 0x5a);
+
+		// Ensure the correct mpslabs .00? file is open
+		if (mpsNum != currentNum) {
+			currentNum = mpsNum;
+			dataFilename = Common::String::format("%s.%03d", baseName, mpsNum);
+			if (!dataFile.open(dataFilename.c_str()))
+				error("Could not open %s", dataFilename.c_str());
+		}
+
+		// Get the section within the archive
+		dataFile.seek(offset);
+		Common::SeekableReadStream *zipStream = dataFile.readStream(size);
+		Common::Archive *zip = Common::makeZipArchive(zipStream);
+
+		if (!zip)
+			error("Could not decompress data archive");
+
+		// Add the archive to the list
+		result->_zips.push_back(zip);
+	}
+
+	return result;
+}
+
+MpsArchive::~MpsArchive() {
+	for (Common::Archive *zip : _zips)
+		delete zip;
+}
+
+bool MpsArchive::hasFile(const Common::Path &path) const {
+	for (const Common::Archive *zip : _zips) {
+		if (zip->hasFile(path))
+			return true;
+	}
+
+	return false;
+}
+
+int MpsArchive::listMembers(Common::ArchiveMemberList &list) const {
+	int total = 0;
+	for (const Common::Archive *zip : _zips)
+		total += zip->listMembers(list);
+
+	return total;
+}
+
+const Common::ArchiveMemberPtr MpsArchive::getMember(const Common::Path &path) const {
+	for (const Common::Archive *zip : _zips) {
+		if (zip->hasFile(path))
+			return zip->getMember(path);
+	}
+
+	return nullptr;
+}
+
+Common::SeekableReadStream *MpsArchive::createReadStreamForMember(const Common::Path &path) const {
+	for (const Common::Archive *zip : _zips) {
+		Common::SeekableReadStream *result = zip->createReadStreamForMember(path);
+		if (result)
+			return result;
+	}
+
+	return nullptr;
+}
+
+} // namespace MADSV2
+} // namespace MADS
diff --git a/engines/mads/madsv2/core/mps_archive.h b/engines/mads/madsv2/core/mps_archive.h
new file mode 100644
index 00000000000..978a1fa4b79
--- /dev/null
+++ b/engines/mads/madsv2/core/mps_archive.h
@@ -0,0 +1,50 @@
+/* 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 3 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MADS_CORE_MPS_ARCHIVE_H
+#define MADS_CORE_MPS_ARCHIVE_H
+
+#include "common/archive.h"
+#include "mads/madsv2/core/general.h"
+
+namespace MADS {
+namespace MADSV2 {
+
+
+class MpsArchive : public Common::Archive {
+private:
+	Common::Array<Common::Archive *> _zips;
+
+public:
+	static MpsArchive *open(const char *baseName = "mpslabs");
+	MpsArchive() {}
+	~MpsArchive() override;
+
+	bool hasFile(const Common::Path &path) const override;
+	int listMembers(Common::ArchiveMemberList &list) const override;
+	const Common::ArchiveMemberPtr getMember(const Common::Path &path) const override;
+	Common::SeekableReadStream *createReadStreamForMember(const Common::Path &path) const override;
+};
+
+} // namespace MADSV2
+} // namespace MADS
+
+#endif
diff --git a/engines/mads/madsv2/dragonsphere/dragonsphere.cpp b/engines/mads/madsv2/dragonsphere/dragonsphere.cpp
index 00f952aa103..3a0d4b998e6 100644
--- a/engines/mads/madsv2/dragonsphere/dragonsphere.cpp
+++ b/engines/mads/madsv2/dragonsphere/dragonsphere.cpp
@@ -29,6 +29,7 @@
 #include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
 #include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mps_archive.h"
 #include "mads/madsv2/core/object.h"
 #include "mads/madsv2/core/pal.h"
 #include "mads/madsv2/core/rail.h"
@@ -65,7 +66,7 @@ Common::Error DragonsphereEngine::run() {
 
 	// Set up to read mpslabs installer archive if needed
 	if (_gameDescription->desc.flags & GF_INSTALLER) {
-		Common::Archive *arch = MpsInstaller::open("MPSLABS");
+		MpsArchive *arch = MpsArchive::open();
 		if (arch)
 			SearchMan.add("mpslabs", arch);
 	}
diff --git a/engines/mads/madsv2/engine.cpp b/engines/mads/madsv2/engine.cpp
index e0ed335888c..bccdec2eac3 100644
--- a/engines/mads/madsv2/engine.cpp
+++ b/engines/mads/madsv2/engine.cpp
@@ -89,6 +89,13 @@ MADSV2Engine::~MADSV2Engine() {
 	delete _soundManager;
 }
 
+void MADSV2Engine::initializePath(const Common::FSNode &gamePath) {
+	MADSEngine::initializePath(gamePath);
+	Common::FSNode folder = gamePath.getChild("resource");
+	if (folder.exists())
+		SearchMan.addDirectory(folder);
+}
+
 void MADSV2Engine::initGlobals() {
 	init_anim();
 	init_attr();
diff --git a/engines/mads/madsv2/engine.h b/engines/mads/madsv2/engine.h
index 6db62148dc5..c3e9cdd6b95 100644
--- a/engines/mads/madsv2/engine.h
+++ b/engines/mads/madsv2/engine.h
@@ -65,6 +65,8 @@ public:
 public:
 	MADSV2Engine(OSystem *syst, const MADSGameDescription *gameDesc);
 	~MADSV2Engine() override;
+	void initializePath(const Common::FSNode &gamePath) override;
+
 	void readConfigFile();
 
 	Graphics::Screen *getScreen() const {
diff --git a/engines/mads/madsv2/forest/forest.cpp b/engines/mads/madsv2/forest/forest.cpp
index 61840529d5f..27b5c0c432b 100644
--- a/engines/mads/madsv2/forest/forest.cpp
+++ b/engines/mads/madsv2/forest/forest.cpp
@@ -30,6 +30,7 @@
 #include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
 #include "mads/madsv2/core/matte.h"
+#include "mads/madsv2/core/mps_archive.h"
 #include "mads/madsv2/core/object.h"
 #include "mads/madsv2/core/pal.h"
 #include "mads/madsv2/core/rail.h"
@@ -79,7 +80,7 @@ Common::Error ForestEngine::run() {
 
 	// Set up to read mpslabs installer archive if needed
 	if (_gameDescription->desc.flags & GF_INSTALLER) {
-		Common::Archive *arch = MpsInstaller::open("MPSLABS");
+		MpsArchive *arch = MpsArchive::open();
 		if (arch)
 			SearchMan.add("mpslabs", arch);
 	}
diff --git a/engines/mads/madsv2/phantom/phantom.cpp b/engines/mads/madsv2/phantom/phantom.cpp
index dde1c9c8139..62904d8c891 100644
--- a/engines/mads/madsv2/phantom/phantom.cpp
+++ b/engines/mads/madsv2/phantom/phantom.cpp
@@ -29,6 +29,7 @@
 #include "mads/madsv2/core/imath.h"
 #include "mads/madsv2/core/inter.h"
 #include "mads/madsv2/core/kernel.h"
+#include "mads/madsv2/core/mps_archive.h"
 #include "mads/madsv2/core/object.h"
 #include "mads/madsv2/core/pal.h"
 #include "mads/madsv2/core/screen.h"
@@ -56,6 +57,13 @@ Common::Error PhantomEngine::run() {
 	// Create a debugger console
 	setDebugger(new Console());
 
+	// Set up to read mpslabs installer archive if needed
+	if (_gameDescription->desc.flags & GF_INSTALLER) {
+		MpsArchive *arch = MpsArchive::open();
+		if (arch)
+			SearchMan.add("mpslabs", arch);
+	}
+
 	// Set up sound manager
 	_soundManager = new PhantomSoundManager(_mixer, _soundFlag);
 	_soundManager->validate();
diff --git a/engines/mads/module.mk b/engines/mads/module.mk
index 0ae9a6e3841..a727553beca 100644
--- a/engines/mads/module.mk
+++ b/engines/mads/module.mk
@@ -96,6 +96,7 @@ MODULE_OBJS += \
 	madsv2/core/mcga.o \
 	madsv2/core/mem.o \
 	madsv2/core/mouse.o \
+	madsv2/core/mps_archive.o \
 	madsv2/core/object.o \
 	madsv2/core/pack.o \
 	madsv2/core/pal.o \




More information about the Scummvm-git-logs mailing list