XPlor/tests/PS3/autotest_cod5_ps3.cpp

185 lines
5.7 KiB
C++
Raw Permalink Normal View History

2025-04-04 20:40:12 -04:00
#include <QtTest/QtTest>
#include <QDirIterator>
#include <QFileInfo>
#include "autotest_cod.h"
#include "compression.h"
class AutoTest_COD5_PS3 : public AutoTest_COD {
Q_OBJECT
const QString EXPORT_DIR = "./exports/cod5/PS3";
private slots:
void initTestCase();
2025-04-04 20:40:12 -04:00
void testDecompression_data();
void testDecompression();
2025-04-04 20:40:12 -04:00
void testCompression_data();
void testCompression();
void testFactory_data();
void testFactory();
2025-04-04 20:40:12 -04:00
void cleanupTestCase();
};
void AutoTest_COD5_PS3::initTestCase() {
// Ensure the exports directory exists.
createDirectory(EXPORT_DIR);
}
void AutoTest_COD5_PS3::testDecompression_data() {
AutoTest_COD::testDecompression_data();
2025-04-04 20:40:12 -04:00
}
void AutoTest_COD5_PS3::testDecompression() {
QFETCH(QString, fastFilePath);
2025-04-04 20:40:12 -04:00
QFile testFastFile(fastFilePath);
2025-04-04 20:40:12 -04:00
QVERIFY2(testFastFile.open(QIODevice::ReadOnly),
qPrintable("Failed to open test fastfile: " + fastFilePath));
2025-04-04 20:40:12 -04:00
const QByteArray testFFData = testFastFile.readAll();
testFastFile.close();
// Validate header
QVERIFY2(testFFData.size() > 12, "FastFile too small to contain header");
QByteArray header = testFFData.left(8);
QVERIFY2(header == "IWffu100", "Invalid FastFile header!");
QDataStream headerStream(testFFData.mid(8, 6));
headerStream.setByteOrder(QDataStream::BigEndian);
qint32 version;
qint16 identifier;
headerStream >> version >> identifier;
QVERIFY2(version == 387, "Unsupported game version");
QByteArray decompressed;
int pos = 12;
// Loop until EOF or invalid chunk
while (pos <= testFFData.size()) {
// Read 2-byte BIG-ENDIAN chunk size
quint16 chunkSize;
QDataStream chunkStream(testFFData.mid(pos, 2));
chunkStream.setByteOrder(QDataStream::BigEndian);
chunkStream >> chunkSize;
pos += 2;
if (chunkSize == 0 || pos + chunkSize > testFFData.size()) {
qWarning() << "Invalid or incomplete chunk detected, stopping.";
break;
}
const QByteArray compressedChunk = testFFData.mid(pos, chunkSize);
decompressed.append(Compression::DecompressDeflate(compressedChunk));
pos += chunkSize;
2025-04-23 00:09:35 -04:00
}
2025-04-04 20:40:12 -04:00
// Write decompressed .zone file
QFileInfo fi(fastFilePath);
2025-04-04 20:40:12 -04:00
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(decompressed);
2025-04-04 20:40:12 -04:00
outputFile.close();
}
void AutoTest_COD5_PS3::testCompression_data() {
AutoTest_COD::testCompression_data();
2025-04-04 20:40:12 -04:00
}
void AutoTest_COD5_PS3::testCompression() {
QFETCH(QString, zoneFilePath);
2025-04-04 20:40:12 -04:00
QFile zoneFile(zoneFilePath);
QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath));
2025-04-04 20:40:12 -04:00
QByteArray decompressedData = zoneFile.readAll();
zoneFile.close();
QFileInfo fi(zoneFilePath);
2025-04-04 20:40:12 -04:00
QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff");
QFile originalFile(originalFFPath);
QVERIFY2(originalFile.open(QIODevice::ReadOnly), qPrintable("Failed to open original .ff file: " + originalFFPath));
QByteArray originalFFData = originalFile.readAll();
originalFile.close();
QByteArray header = originalFFData.left(12);
QByteArray recompressedData = header;
// Split decompressed data into chunks (optional: same size as original or fixed 0x4000)
const int chunkSize = 0x4000;
int offset = 0;
while (offset < decompressedData.size()) {
QByteArray chunk = decompressedData.mid(offset, chunkSize);
offset += chunk.size();
QByteArray compressedChunk = Compression::CompressDeflate(chunk);
quint16 length = static_cast<quint16>(compressedChunk.size());
2025-04-04 20:40:12 -04:00
// Write 2-byte big-endian chunk size
recompressedData.append(static_cast<char>((length >> 8) & 0xFF));
recompressedData.append(static_cast<char>(length & 0xFF));
2025-04-04 20:40:12 -04:00
// Write compressed chunk
recompressedData.append(compressedChunk);
2025-04-04 20:40:12 -04:00
}
// No terminator chunk needed if original didn't have one
2025-04-04 20:40:12 -04:00
// Save new file
2025-04-04 20:40:12 -04:00
QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff");
QFile recompressedFile(recompressedFilePath);
QVERIFY2(recompressedFile.open(QIODevice::WriteOnly), qPrintable("Failed to write recompressed file."));
recompressedFile.write(recompressedData);
recompressedFile.close();
// Validate byte-for-byte match
2025-04-04 20:40:12 -04:00
QCOMPARE(recompressedData, originalFFData);
}
void AutoTest_COD5_PS3::testFactory_data() {
AutoTest_COD::testFactory_data();
}
void AutoTest_COD5_PS3::testFactory() {
QFETCH(QString, fastFilePath);
const QString testName = "Factory ingest: " + fastFilePath;
std::shared_ptr<FastFile> fastFile = FastFileFactory::Create(fastFilePath);
const QString game = fastFile->GetGame();
bool correctGame = game == "COD5";
if (!correctGame) {
recordResult(testName, false);
}
QVERIFY2(correctGame
, qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath));
const QString platform = fastFile->GetPlatform();
bool correctPlatform = platform == "PS3";
if (!correctPlatform) {
recordResult(testName, false);
}
QVERIFY2(correctPlatform
, qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath));
recordResult(testName, true);
}
2025-04-04 20:40:12 -04:00
void AutoTest_COD5_PS3::cleanupTestCase() {
// Any cleanup if necessary.
}
// Don't generate a main() function
#include "autotest_cod5_ps3.moc"