24 #include "modreader.h" 26 #include "datastreamoperatorwrapper.h" 27 #include "wadseeker/zip/unarchive.h" 30 #include <QDataStream> 33 #include <QTemporaryDir> 35 QSharedPointer<ModReader> ModReader::create(
const QString &path)
38 if (f.suffix().compare(
"wad", Qt::CaseInsensitive) == 0)
40 return QSharedPointer<ModReader>(
new WadReader(path));
42 else if (f.suffix().compare(
"zip", Qt::CaseInsensitive) == 0 ||
43 f.suffix().compare(
"7z", Qt::CaseInsensitive) == 0)
47 else if (f.suffix().compare(
"pk3", Qt::CaseInsensitive) == 0 ||
48 f.suffix().compare(
"pk7", Qt::CaseInsensitive) == 0)
50 return QSharedPointer<ModReader>(
new PkReader(path));
52 return QSharedPointer<ModReader> ();
60 QList<DirectoryEntry> directory;
70 WadReader::~WadReader()
77 if (f.open(QIODevice::ReadOnly))
79 QDataStream streamUnwrapped(&f);
80 streamUnwrapped.setByteOrder(QDataStream::LittleEndian);
83 QString isIwadText = stream.
readRaw(4);
84 d->isIwad = (isIwadText ==
"IWAD");
87 int directoryPosition = stream.readQInt32();
92 dirEntry.position = stream.readQInt32();
93 dirEntry.size = stream.readQInt32();
94 dirEntry.name = stream.
readRaw(8);
95 d->directory << dirEntry;
117 names << dirEntry.name;
119 QStringList maps = getClassicMaps(names);
120 maps << getUdmfMaps(names);
124 QStringList WadReader::getClassicMaps(
const QStringList &names)
127 QStringList initialMandatoryLumps = {
"THINGS",
"LINEDEFS",
"SIDEDEFS",
"VERTEXES"};
128 QStringList extraMandatoryLumps = {
"SECTORS",
"REJECT"};
130 for (
int mainIter = 0; mainIter < names.size() - (initialMandatoryLumps.size() + extraMandatoryLumps.size()); ++mainIter)
132 bool allInitsFound =
true;
133 for (
int subInitIter = 0; subInitIter < initialMandatoryLumps.size(); ++subInitIter)
135 allInitsFound &= (names[mainIter + subInitIter + 1] == initialMandatoryLumps[subInitIter]);
141 int extrasChecked = 0;
143 for (
int subExtraIter = 0; mainIter + subExtraIter + 1 < names.size(); ++subExtraIter)
145 if (extrasChecked == extraMandatoryLumps.size())
147 maps << names[mainIter];
150 if (names[mainIter + subExtraIter + 1] == extraMandatoryLumps[extrasChecked])
158 QStringList WadReader::getUdmfMaps(
const QStringList &names)
161 QString firstLump =
"TEXTMAP";
162 QString lastLump =
"ENDMAP";
163 unsigned char lumpAmount = 2;
165 for (
int mainIter = 0; mainIter < names.size() - lumpAmount; ++mainIter)
167 if (names[mainIter + 1] == firstLump)
169 for (
int checkIter = lumpAmount; mainIter + checkIter < names.size(); ++checkIter)
171 if (names[mainIter + checkIter] == lastLump)
173 maps << names[mainIter];
174 mainIter += checkIter;
184 DClass<CompressedReader>
187 QScopedPointer<UnArchive> archive;
189 QStringList directory;
197 d->archive.reset(
nullptr);
200 CompressedReader::~CompressedReader()
206 d->archive.reset(UnArchive::openArchive(d->filepath));
207 if (!d->archive.isNull())
209 d->directory = d->archive->files();
218 return getAllMapsRootDir();
221 QStringList CompressedReader::getAllMapsRootDir()
223 QStringList rootPaths;
225 QTemporaryDir tempDir;
227 if (tempDir.isValid())
229 for (QString dirEntry : d->directory)
231 if (!dirEntry.contains(
"/"))
233 QString extractedFilePath = tempDir.path() + QDir::separator() + dirEntry;
234 QSharedPointer<ModReader> modReader = ModReader::create(extractedFilePath);
235 if (!modReader.isNull() && !d->archive.isNull() &&
236 d->archive->extract(d->archive->findFileEntry(dirEntry), extractedFilePath))
239 mapList << modReader->getAllMaps();
254 QStringList rootPaths;
255 for (
const QString &dirEntry : d->directory)
257 QFileInfo fileInfo(dirEntry);
258 if (dirEntry.startsWith(
"maps/", Qt::CaseInsensitive) &&
259 fileInfo.suffix().compare(
"wad", Qt::CaseInsensitive) == 0)
261 mapList << fileInfo.baseName();
264 mapList << getAllMapsRootDir();
File reader for PK3/7 format.
QStringList getAllMaps() override
Get a list of the maps that this WAD contains.
File reader for the WAD format.
CompressedReader(const QString &path)
Construct a new reader to manage the compressed file.
Wraps around QDataStream stream operators to provide cleaner reading interface.
QStringList getAllMaps() override
Get a list of the maps that this PK3/7 contains.
bool isIwad() override
returns whether or not this is a IWAD.
bool load() override
loads the compressed file set in the constructor.
int skipRawData(int len)
Reads and discards specified amount of data.
bool load() override
loads the WAD set in the constructor.
Contains an entry of a WAD directory.
bool hasRemaining() const
Returns true if there is any data remaining in the stream.
File reader for generic compression file formats. Current formats: ZIP, 7Z.
QByteArray readRaw(qint64 length)
Reads specified amount of raw bytes.
QStringList getAllMaps() override
Get a list of the maps that this compressed file contains.
QList< DirectoryEntry > getDirectory()
Get all the directory of the WAD.