[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