191 lines
6.2 KiB
C++
191 lines
6.2 KiB
C++
#include <QtTest/QtTest>
|
|
#include <QDirIterator>
|
|
#include <QFileInfo>
|
|
|
|
#include "autotest_cod.h"
|
|
#include "compression.h"
|
|
#include "encryption.h"
|
|
#include "fastfile.h"
|
|
|
|
class AutoTest_COD7_360 : public AutoTest_COD {
|
|
Q_OBJECT
|
|
|
|
const QString EXPORT_DIR = "./exports/cod7/360";
|
|
|
|
private slots:
|
|
void initTestCase();
|
|
|
|
void testDecompression_data();
|
|
void testDecompression();
|
|
|
|
void testCompression_data();
|
|
void testCompression();
|
|
|
|
void testFactory_data();
|
|
void testFactory();
|
|
|
|
void cleanupTestCase();
|
|
};
|
|
|
|
void AutoTest_COD7_360::initTestCase() {
|
|
// Ensure the exports directory exists.
|
|
createDirectory(EXPORT_DIR);
|
|
}
|
|
|
|
void AutoTest_COD7_360::testDecompression_data() {
|
|
AutoTest_COD::testDecompression_data();
|
|
}
|
|
|
|
void AutoTest_COD7_360::testDecompression() {
|
|
QFETCH(QString, fastFilePath);
|
|
|
|
const QString testName = "Decompress: " + fastFilePath;
|
|
|
|
// Open the original .ff file.
|
|
QFile testFastFile(fastFilePath);
|
|
QVERIFY2(testFastFile.open(QIODevice::ReadOnly),
|
|
qPrintable("Failed to open test fastfile: " + fastFilePath));
|
|
const QByteArray testFFData = testFastFile.readAll();
|
|
testFastFile.close();
|
|
|
|
QByteArray decompressedData;
|
|
QByteArray key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d");
|
|
|
|
// Create a QDataStream on the input data.
|
|
QDataStream fastFileStream(testFFData);
|
|
fastFileStream.setByteOrder(QDataStream::BigEndian);
|
|
fastFileStream.skipRawData(16);
|
|
|
|
// Read the 8-byte magic.
|
|
QByteArray fileMagic(8, Qt::Uninitialized);
|
|
fastFileStream.readRawData(fileMagic.data(), 8);
|
|
QVERIFY2(fileMagic == "PHEEBs71",
|
|
qPrintable("Invalid fast file magic: " + fileMagic));
|
|
fastFileStream.skipRawData(4);
|
|
|
|
// Read IV table name (32 bytes).
|
|
QByteArray fileName(32, Qt::Uninitialized);
|
|
fastFileStream.readRawData(fileName.data(), 32);
|
|
|
|
const QByteArray testZoneData = decompressedData;
|
|
|
|
// Verify the decompressed data via its embedded zone size.
|
|
QDataStream zoneStream(testZoneData);
|
|
zoneStream.setByteOrder(QDataStream::BigEndian);
|
|
quint32 zoneSize;
|
|
zoneStream >> zoneSize;
|
|
if (fabs(zoneSize - testZoneData.size()) != 36) {
|
|
qDebug() << "Zone Size: " << zoneSize;
|
|
qDebug() << "Test zone Size: " << testZoneData.size();
|
|
qDebug() << "Difference: " << fabs(zoneSize - testZoneData.size());
|
|
}
|
|
QVERIFY2(zoneSize + 36 == testZoneData.size(),
|
|
qPrintable("Decompression validation failed for: " + fastFilePath));
|
|
|
|
// Write the decompressed zone data to the exports folder with a .zone extension.
|
|
QFileInfo fi(fastFilePath);
|
|
QString outputFileName = fi.completeBaseName() + ".zone";
|
|
QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName);
|
|
QFile outputFile(outputFilePath);
|
|
QVERIFY2(outputFile.open(QIODevice::WriteOnly),
|
|
qPrintable("Failed to open output file for writing: " + outputFilePath));
|
|
outputFile.write(testZoneData);
|
|
outputFile.close();
|
|
}
|
|
|
|
void AutoTest_COD7_360::testCompression_data() {
|
|
AutoTest_COD::testCompression_data();
|
|
}
|
|
|
|
void AutoTest_COD7_360::testCompression() {
|
|
QFETCH(QString, zoneFilePath);
|
|
|
|
const QString testName = "Compress: " + zoneFilePath;
|
|
|
|
// Open the original .zone file (decompressed zone data).
|
|
QFile zoneFile(zoneFilePath);
|
|
QVERIFY2(zoneFile.open(QIODevice::ReadOnly),
|
|
qPrintable("Failed to open zone file: " + zoneFilePath));
|
|
const QByteArray zoneData = zoneFile.readAll();
|
|
zoneFile.close();
|
|
|
|
QByteArray compressedData;
|
|
//QByteArray key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d");
|
|
|
|
// Read the original fastfile header to recover metadata (filename, IV table, etc.)
|
|
QString ffPath = zoneFilePath;
|
|
ffPath.replace(".zone", ".ff");
|
|
QFile originalFF(ffPath);
|
|
QVERIFY2(originalFF.open(QIODevice::ReadOnly),
|
|
qPrintable("Failed to open original fastfile: " + ffPath));
|
|
QByteArray header = originalFF.read(0x13C); // Everything up to section data
|
|
originalFF.seek(24); // IV Table starts at 24 (after magic + skip + filename)
|
|
QByteArray fileName(32, Qt::Uninitialized);
|
|
originalFF.read(fileName.data(), 32);
|
|
originalFF.close();
|
|
|
|
// Rebuild sections from zone data
|
|
QDataStream zoneStream(zoneData);
|
|
zoneStream.setByteOrder(QDataStream::BigEndian);
|
|
quint32 zoneSize;
|
|
zoneStream >> zoneSize;
|
|
|
|
//QByteArray remainingData = zoneData.mid(4); // exclude size field
|
|
|
|
QDataStream fastFileStreamOut(&compressedData, QIODevice::WriteOnly);
|
|
fastFileStreamOut.setByteOrder(QDataStream::BigEndian);
|
|
|
|
// Write 0 section size terminator
|
|
fastFileStreamOut << static_cast<qint32>(0);
|
|
|
|
// Combine with header
|
|
QByteArray fullFastFile = header + compressedData;
|
|
|
|
// Save re-encoded fastfile
|
|
QFileInfo fi(zoneFilePath);
|
|
QString outputFileName = fi.completeBaseName() + "_recompressed.ff";
|
|
QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName);
|
|
QFile outputFile(outputFilePath);
|
|
QVERIFY2(outputFile.open(QIODevice::WriteOnly),
|
|
qPrintable("Failed to open output file for writing: " + outputFilePath));
|
|
outputFile.write(fullFastFile);
|
|
outputFile.close();
|
|
}
|
|
|
|
void AutoTest_COD7_360::testFactory_data() {
|
|
AutoTest_COD::testFactory_data();
|
|
}
|
|
|
|
void AutoTest_COD7_360::testFactory() {
|
|
QFETCH(QString, fastFilePath);
|
|
|
|
const QString testName = "Factory ingest: " + fastFilePath;
|
|
|
|
FastFile* fastFile = FastFile::Open(fastFilePath);
|
|
|
|
const QString game = fastFile->GetGame();
|
|
bool correctGame = game == "COD7";
|
|
if (!correctGame) {
|
|
recordResult(testName, false);
|
|
}
|
|
QVERIFY2(correctGame
|
|
, qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath));
|
|
|
|
const QString platform = fastFile->GetPlatform();
|
|
bool correctPlatform = platform == "360";
|
|
if (!correctPlatform) {
|
|
recordResult(testName, false);
|
|
}
|
|
QVERIFY2(correctPlatform
|
|
, qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath));
|
|
|
|
recordResult(testName, true);
|
|
}
|
|
|
|
void AutoTest_COD7_360::cleanupTestCase() {
|
|
// Any cleanup if necessary.
|
|
}
|
|
|
|
// Don't generate a main() function
|
|
#include "autotest_cod7_360.moc"
|