[Scummvm-git-logs] scummvm master -> 2f256f8a9f0e05a39db81660eabe81af27ad8f7a
bluegr
noreply at scummvm.org
Sun Mar 8 14:42:52 UTC 2026
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
977fccd097 TINSEL: Add support for PSX .LFI/.LFD archive files
2f256f8a9f TINSEL Add debugger command for dumping PSX files
Commit: 977fccd097781c865779a97e156c793419f01756
https://github.com/scummvm/scummvm/commit/977fccd097781c865779a97e156c793419f01756
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-03-08T16:42:47+02:00
Commit Message:
TINSEL: Add support for PSX .LFI/.LFD archive files
DW1 German and Japanese store all their resource files in two files
on PSX CDs. Now we support these archive files instead of requiring
users to manually extract the resource files.
Changed paths:
A engines/tinsel/psx_archive.cpp
A engines/tinsel/psx_archive.h
engines/tinsel/detection_tables.h
engines/tinsel/module.mk
engines/tinsel/tinsel.cpp
engines/tinsel/tinsel.h
diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h
index 888f16d866a..135f79f8466 100644
--- a/engines/tinsel/detection_tables.h
+++ b/engines/tinsel/detection_tables.h
@@ -440,7 +440,8 @@ static const TinselGameDescription gameDescriptions[] = {
{
"dw",
"CD",
- AD_ENTRY1s("dw.scn", "0b34bb57cd3961e4528e4bce48cc0ab9", 339764),
+ AD_ENTRY2s("discwld.lfi", "10588d11b85d490f1337af9b5aa5ee3d", 10100,
+ "discwld.lfd", "ddd05e47488065f88ca116c6572318c8", 511459328),
Common::DE_DEU,
Common::kPlatformPSX,
ADGF_CD,
@@ -456,7 +457,8 @@ static const TinselGameDescription gameDescriptions[] = {
{
"dw",
"CD",
- AD_ENTRY1s("dw.scn", "bd2e47010565998641ec45a9c9285be0", 328048),
+ AD_ENTRY2s("discwld.lfi", "10588d11b85d490f1337af9b5aa5ee3d", 10120,
+ "discwld.lfd", "ddd05e47488065f88ca116c6572318c8", 550049792),
Common::JA_JPN,
Common::kPlatformPSX,
ADGF_CD | ADGF_UNSTABLE,
diff --git a/engines/tinsel/module.mk b/engines/tinsel/module.mk
index d583bcb5641..58f2b8db975 100644
--- a/engines/tinsel/module.mk
+++ b/engines/tinsel/module.mk
@@ -35,6 +35,7 @@ MODULE_OBJS := \
pdisplay.o \
play.o \
polygons.o \
+ psx_archive.o \
saveload.o \
savescn.o \
scene.o \
diff --git a/engines/tinsel/psx_archive.cpp b/engines/tinsel/psx_archive.cpp
new file mode 100644
index 00000000000..0e5e3c81609
--- /dev/null
+++ b/engines/tinsel/psx_archive.cpp
@@ -0,0 +1,112 @@
+/* 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 "engines/tinsel/psx_archive.h"
+
+#include "common/file.h"
+#include "common/ptr.h"
+#include "common/stream.h"
+#include "common/substream.h"
+
+namespace Tinsel {
+
+PsxArchive::PsxArchive() : Common::Archive() {
+}
+
+PsxArchive::~PsxArchive() {
+ close();
+}
+
+bool PsxArchive::open(const Common::Path &indexFilePath, const Common::Path &dataFilePath, uint16 tinselVersion) {
+ close();
+
+ // open index file
+ Common::ScopedPtr<Common::SeekableReadStream> indexStream(SearchMan.createReadStreamForMember(indexFilePath));
+ if (!indexStream) {
+ return false;
+ }
+
+ // read file entries from index file.
+ // c[12] file name, zero terminated unless 12 characters
+ // u32LE file size
+ // u32LE file offset, shifted right 11 bits in DW1
+ int fileCount = indexStream->size() / (12 + 4 + 4);
+ for (int i = 0; i < fileCount; i++) {
+ int entryPos = indexStream->pos();
+ Common::String fileName = indexStream->readString('\0', 12);
+ indexStream->seek(entryPos + 12);
+
+ FileEntry fileEntry;
+ fileEntry.size = indexStream->readUint32LE();
+ fileEntry.offset = indexStream->readUint32LE();
+ if (tinselVersion == 1) {
+ fileEntry.offset <<= 11;
+ }
+ _map[Common::Path(fileName)] = fileEntry;
+ }
+
+ // verify data file exists
+ _dataFilePath = dataFilePath;
+ if (!SearchMan.hasFile(_dataFilePath)) {
+ close();
+ return false;
+ }
+ return true;
+}
+
+void PsxArchive::close() {
+ _dataFilePath.clear();
+ _map.clear();
+}
+
+bool PsxArchive::hasFile(const Common::Path &path) const {
+ return _map.contains(path);
+}
+
+int PsxArchive::listMembers(Common::ArchiveMemberList &list) const {
+ for (const auto &file : _map) {
+ list.push_back(getMember(file._key));
+ }
+
+ return _map.size();
+}
+
+const Common::ArchiveMemberPtr PsxArchive::getMember(const Common::Path &path) const {
+ return Common::ArchiveMemberPtr(new Common::GenericArchiveMember(path, *this));
+}
+
+Common::SeekableReadStream *PsxArchive::createReadStreamForMember(const Common::Path &path) const {
+ if (!_map.contains(path))
+ return nullptr;
+
+ // open data file
+ Common::File *dataFile = new Common::File();
+ if (!dataFile->open(_dataFilePath)) {
+ delete dataFile;
+ return nullptr;
+ }
+
+ // return a substream using offset and size from index
+ const FileEntry &entry = _map[path];
+ return new Common::SeekableSubReadStream(dataFile, entry.offset, entry.offset + entry.size, DisposeAfterUse::YES);
+}
+
+} // End of namespace Tinsel
diff --git a/engines/tinsel/psx_archive.h b/engines/tinsel/psx_archive.h
new file mode 100644
index 00000000000..603bb0c6834
--- /dev/null
+++ b/engines/tinsel/psx_archive.h
@@ -0,0 +1,65 @@
+/* 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 TINSEL_PSX_ARCHIVE_H
+#define TINSEL_PSX_ARCHIVE_H
+
+#include "common/archive.h"
+#include "common/scummsys.h"
+#include "common/hashmap.h"
+
+namespace Tinsel {
+
+// PSX Index / Data archive format
+//
+// Several PSX versions store all resource files in a single uncompressed
+// data file. A separate index file contains the names, offsets, and sizes.
+// Used in DW1 German, DW1 Japanese, and all DW2 versions.
+
+class PsxArchive : public Common::Archive {
+public:
+ PsxArchive();
+ ~PsxArchive() override;
+
+ bool open(const Common::Path &indexFilePath, const Common::Path &dataFilePath, uint16 tinselVersion);
+ void close();
+
+ // Common::Archive API implementation
+ 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;
+
+private:
+ struct FileEntry {
+ uint32 size;
+ uint32 offset;
+ };
+
+ Common::Path _dataFilePath;
+
+ typedef Common::HashMap<Common::Path, FileEntry, Common::Path::IgnoreCase_Hash, Common::Path::IgnoreCase_EqualTo> FileMap;
+ FileMap _map;
+};
+
+} // End of namespace Tinsel
+
+#endif
diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp
index f4807ac6df6..45027874ac7 100644
--- a/engines/tinsel/tinsel.cpp
+++ b/engines/tinsel/tinsel.cpp
@@ -57,6 +57,7 @@
#include "tinsel/object.h"
#include "tinsel/pid.h"
#include "tinsel/polygons.h"
+#include "tinsel/psx_archive.h"
#include "tinsel/savescn.h"
#include "tinsel/scn.h"
#include "tinsel/sound.h"
@@ -990,6 +991,9 @@ void TinselEngine::initializePath(const Common::FSNode &gamePath) {
if (TinselV1PSX) {
// Add subfolders needed for PSX versions of Discworld 1
SearchMan.addDirectory(gamePath, 0, 3, true);
+
+ // Add PSX archive if it exists (German, Japanese)
+ addPsxArchive("discwld.lfi", "discwld.lfd");
} else {
// Add DW2 subfolder to search path in case user is running directly from the CDs
SearchMan.addSubDirectoryMatching(gamePath, "dw2");
@@ -1429,4 +1433,13 @@ const char *TinselEngine::getSceneFile(LANGUAGE lang) {
return _sceneFiles[lang];
}
+void TinselEngine::addPsxArchive(const char *indexFileName, const char *dataFileName) {
+ PsxArchive *psxArchive = new PsxArchive();
+ if (psxArchive->open(indexFileName, dataFileName, TinselVersion)) {
+ SearchMan.add(dataFileName, psxArchive);
+ } else {
+ delete psxArchive;
+ }
+}
+
} // End of namespace Tinsel
diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h
index 9665804d02d..9643e3a9495 100644
--- a/engines/tinsel/tinsel.h
+++ b/engines/tinsel/tinsel.h
@@ -231,6 +231,7 @@ private:
void ChopDrivers();
void ProcessKeyEvent(const Common::Event &event);
bool pollEvent();
+ void addPsxArchive(const char *indexFileName, const char *dataFileName);
public:
const Common::String getTargetName() const { return _targetName; }
Commit: 2f256f8a9f0e05a39db81660eabe81af27ad8f7a
https://github.com/scummvm/scummvm/commit/2f256f8a9f0e05a39db81660eabe81af27ad8f7a
Author: sluicebox (22204938+sluicebox at users.noreply.github.com)
Date: 2026-03-08T16:42:47+02:00
Commit Message:
TINSEL Add debugger command for dumping PSX files
Changed paths:
engines/tinsel/debugger.cpp
engines/tinsel/debugger.h
diff --git a/engines/tinsel/debugger.cpp b/engines/tinsel/debugger.cpp
index 4a02d5b2c2d..66f3719d35e 100644
--- a/engines/tinsel/debugger.cpp
+++ b/engines/tinsel/debugger.cpp
@@ -24,6 +24,7 @@
#include "tinsel/dialogs.h"
#include "tinsel/handle.h"
#include "tinsel/pcode.h"
+#include "tinsel/psx_archive.h"
#include "tinsel/scene.h"
#include "tinsel/sound.h"
#include "tinsel/music.h"
@@ -78,6 +79,7 @@ Console::Console() : GUI::Debugger() {
registerCmd("globals", WRAP_METHOD(Console, cmd_globals));
registerCmd("global", WRAP_METHOD(Console, cmd_global));
registerCmd("g", WRAP_METHOD(Console, cmd_global)); // alias
+ registerCmd("psxdump", WRAP_METHOD(Console, cmd_psxdump));
}
Console::~Console() {
@@ -222,6 +224,44 @@ bool Console::cmd_global(int argc, const char **argv) {
return true;
}
+bool Console::cmd_psxdump(int argc, const char **argv) {
+ if (argc != 2) {
+ debugPrintf("Dumps PSX resource files to disk\n");
+ debugPrintf("usage: %s <file>\n", argv[0]);
+ debugPrintf(" <file> may be '*' to dump all files\n");
+ return true;
+ }
+
+ if (!TinselV1PSX) {
+ return true;
+ }
+
+ PsxArchive psxArchive;
+ if (!psxArchive.open("discwld.lfi", "discwld.lfd", TinselVersion)) {
+ return true;
+ }
+
+ bool dumpAll = !strcmp(argv[1], "*");
+ Common::ArchiveMemberList members;
+ psxArchive.listMembers(members);
+ Common::sort(members.begin(), members.end(), Common::ArchiveMemberListComparator());
+ for (auto &member : members) {
+ if (dumpAll || member->getName().equalsIgnoreCase(argv[1])) {
+ Common::Path path = member->getPathInArchive();
+ Common::ScopedPtr<Common::SeekableReadStream> resource(psxArchive.createReadStreamForMember(path));
+ if (resource) {
+ Common::DumpFile dumpFile;
+ if (dumpFile.open(member->getPathInArchive())) {
+ debugPrintf("Writing %s to disk\n", member->getName().c_str());
+ dumpFile.writeStream(resource.get());
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
// Noir:
bool Console::cmd_add_clue(int argc, const char **argv) {
if (argc < 2) {
diff --git a/engines/tinsel/debugger.h b/engines/tinsel/debugger.h
index 77e6f3ee099..2e7ac9f4174 100644
--- a/engines/tinsel/debugger.h
+++ b/engines/tinsel/debugger.h
@@ -46,6 +46,7 @@ private:
bool cmd_string(int argc, const char **argv);
bool cmd_globals(int argc, const char **argv);
bool cmd_global(int argc, const char **argv);
+ bool cmd_psxdump(int argc, const char **argv);
};
} // End of namespace Tinsel
More information about the Scummvm-git-logs
mailing list