Remove specific zonefile code

This commit is contained in:
njohnson 2025-12-31 18:11:48 -05:00
parent 9d6fa35f50
commit 3b61ff5a05
74 changed files with 0 additions and 5873 deletions

View File

@ -1,112 +0,0 @@
#include "fastfile_cod10_360.h"
#include "zonefile_cod10_360.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD10_360::FastFile_COD10_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD10_360::FastFile_COD10_360(const QByteArray& aData)
: FastFile_COD10_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD10_360::FastFile_COD10_360(const QString aFilePath)
: FastFile_COD10_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD10_360::~FastFile_COD10_360() {
}
QByteArray FastFile_COD10_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD10_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD10_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
decompressedData = Encryption::DecryptFile(aData, fileName, "0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD10_360* zoneFile = new ZoneFile_COD10_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD10_360_H
#define FASTFILE_COD10_360_H
#include "fastfile.h"
class FastFile_COD10_360 : public FastFile
{
public:
FastFile_COD10_360();
FastFile_COD10_360(const QByteArray& aData);
FastFile_COD10_360(const QString aFilePath);
~FastFile_COD10_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD10_360_H

View File

@ -1,150 +0,0 @@
#include "fastfile_cod11_360.h"
#include "zonefile_cod11_360.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD11_360::FastFile_COD11_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD11_360::FastFile_COD11_360(const QByteArray& aData)
: FastFile_COD11_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD11_360::FastFile_COD11_360(const QString aFilePath)
: FastFile_COD11_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD11_360::~FastFile_COD11_360() {
}
QByteArray FastFile_COD11_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD11_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first();
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
enum DB_CompressorType : qint32
{
DB_COMPRESSOR_INVALID = 0x0,
DB_COMPRESSOR_ZLIB = 0x1,
DB_COMPRESSOR_LZX = 0x2,
DB_COMPRESSOR_PASSTHROUGH = 0x3,
};
bool FastFile_COD11_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Prepare data stream for parsing
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::BigEndian);
// Verify magic header
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
quint32 version = fastFileStream.ParseUInt32();
fastFileStream.skipRawData(1);
DB_CompressorType compressorType = (DB_CompressorType)fastFileStream.ParseInt8();
fastFileStream.skipRawData(10);
qint32 blockCount = fastFileStream.ParseInt32();
if (version != 1838)
{
qWarning() << "Invalid fast file version:" << version << "!";
return false;
}
if (blockCount > 17280)
{
qWarning() << "Fast file has too many blocks:" << blockCount << "> 17280!";
return false;
}
fastFileStream.skipRawData(12 * blockCount);
qint32 startPos = fastFileStream.ParseInt32();
Q_UNUSED(startPos);
qint32 endPos = fastFileStream.ParseInt32();
Q_UNUSED(endPos);
if (fileMagic == "S1ffu100")
{
QByteArray compressedData = aData.mid(fastFileStream.device()->pos());
if (compressorType == DB_COMPRESSOR_ZLIB)
{
decompressedData = Compression::DecompressZLIB(compressedData);
}
else if (compressorType == DB_COMPRESSOR_LZX)
{
decompressedData = Compression::DecompressXMem(compressedData, 0, 0x80000, 0);
}
}
else if (fileMagic == "S1ff0100")
{
}
else
{
qWarning() << "Invalid fast file magic:" << fileMagic << "!";
return false;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with decompressed data
ZoneFile_COD11_360* zoneFile = new ZoneFile_COD11_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD11_360_H
#define FASTFILE_COD11_360_H
#include "fastfile.h"
class FastFile_COD11_360 : public FastFile
{
public:
FastFile_COD11_360();
FastFile_COD11_360(const QByteArray &aData);
FastFile_COD11_360(const QString aFilePath);
~FastFile_COD11_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD11_360_H

View File

@ -1,150 +0,0 @@
#include "fastfile_cod12_360.h"
#include "zonefile_cod12_360.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD12_360::FastFile_COD12_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD12_360::FastFile_COD12_360(const QByteArray& aData)
: FastFile_COD12_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD12_360::FastFile_COD12_360(const QString aFilePath)
: FastFile_COD12_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD12_360::~FastFile_COD12_360() {
}
QByteArray FastFile_COD12_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD12_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first();
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD12_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Prepare data stream for parsing
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Skip header magic
fastFileStream.skipRawData(8);
quint32 version;
fastFileStream >> version;
quint8 unknownFlag, compressionFlag, platformFlag, encryptionFlag;
fastFileStream >> unknownFlag >> compressionFlag >> platformFlag >> encryptionFlag;
if (compressionFlag != 1) {
qDebug() << "Invalid fastfile compression: " << compressionFlag;
return false;
} else if (platformFlag != 4) {
qDebug() << "Invalid platform: " << platformFlag;
return false;
} else if (encryptionFlag != 0) {
qDebug() << "Decryption not supported yet!";
return false;
}
fastFileStream.skipRawData(128);
quint64 size;
fastFileStream >> size;
fastFileStream.skipRawData(432);
int consumed = 0;
while(consumed < size)
{
// Read Block Header
quint32 compressedSize, decompressedSize, blockSize, blockPosition;
fastFileStream >> compressedSize >> decompressedSize >> blockSize >> blockPosition;
// Validate the block position, it should match
if(blockPosition != fastFileStream.device()->pos() - 16)
{
qDebug() << "Block Position does not match Stream Position.";
return false;
}
// Check for padding blocks
if(decompressedSize == 0)
{
fastFileStream.device()->read((((fastFileStream.device()->pos()) + ((0x800000) - 1)) & ~((0x800000) - 1)) - fastFileStream.device()->pos());
continue;
}
fastFileStream.device()->read(2);
QByteArray compressedData(compressedSize - 2, Qt::Uninitialized);
qDebug() << "Data position: " << fastFileStream.device()->pos() << " - Size: " << compressedSize;
fastFileStream.readRawData(compressedData.data(), compressedSize - 2);
decompressedData.append(Compression::DecompressDeflate(compressedData));
consumed += decompressedSize;
// Sinze Fast Files are aligns, we must skip the full block
fastFileStream.device()->seek(blockPosition + 16 + blockSize);
}
// Output for verification/testing
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with decompressed data
ZoneFile_COD12_360* zoneFile = new ZoneFile_COD12_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD12_360_H
#define FASTFILE_COD12_360_H
#include "fastfile.h"
class FastFile_COD12_360 : public FastFile
{
public:
FastFile_COD12_360();
FastFile_COD12_360(const QByteArray &aData);
FastFile_COD12_360(const QString aFilePath);
~FastFile_COD12_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD12_360_H

View File

@ -1,90 +0,0 @@
#include "fastfile_cod2_360.h"
#include "utils.h"
#include "compression.h"
#include "zonefile_cod2_360.h"
#include <QFile>
#include <QDebug>
FastFile_COD2_360::FastFile_COD2_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD2_360::FastFile_COD2_360(const QByteArray& aData)
: FastFile_COD2_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD2_360::FastFile_COD2_360(const QString aFilePath)
: FastFile_COD2_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD2_360::~FastFile_COD2_360() {
}
QByteArray FastFile_COD2_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD2_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
SetStem(aFilePath.section("/", -1, -1));
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << GetStem();
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD2_360::Load(const QByteArray aData) {
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
Utils::ReadUntilHex(&fastFileStream, "78");
QByteArray compressedData = aData.mid(fastFileStream.device()->pos());
QByteArray decompressedData = Compression::DecompressZLIB(compressedData);
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD2_360* zoneFile = new ZoneFile_COD2_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD2_360_H
#define FASTFILE_COD2_360_H
#include "fastfile.h"
class FastFile_COD2_360 : public FastFile
{
public:
FastFile_COD2_360();
FastFile_COD2_360(const QByteArray& aData);
FastFile_COD2_360(const QString aFilePath);
~FastFile_COD2_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD2_360_H

View File

@ -1,139 +0,0 @@
#include "fastfile_cod4_360.h"
#include "zonefile_cod4_360.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD4_360::FastFile_COD4_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD4_360::FastFile_COD4_360(const QByteArray& aData)
: FastFile_COD4_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD4_360::FastFile_COD4_360(const QString aFilePath)
: FastFile_COD4_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD4_360::~FastFile_COD4_360() {
}
QByteArray FastFile_COD4_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD4_360::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
QString fastFileStem = aFilePath.split('/').last().replace(".ff", "");
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD4_360::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
const QString header = aData.left(8);
if (header == "IWffu100") {
// For COD5, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(12));
} else if (header == "IWff0100") {
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData.mid(12));
fastFileStream.setByteOrder(XDataStream::LittleEndian);
QByteArray magic(8, Qt::Uninitialized);
fastFileStream.readRawData(magic.data(), 8);
if (magic != "IWffs100") {
qDebug() << "Found invalid signed header: " << magic;
return false;
}
fastFileStream.skipRawData(4);
QByteArray rsaSigChecksum(32, Qt::Uninitialized);
fastFileStream.readRawData(rsaSigChecksum.data(), 32);
QByteArray rsaSig(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSig.data(), 256);
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
fastFileStream.skipRawData(4);
QByteArray bigSigBlock(7856, Qt::Uninitialized);
fastFileStream.readRawData(bigSigBlock.data(), 7856);
QVector<QByteArray> sigBlocks = QVector<QByteArray>();
QByteArray compressedData;
for (int i = 0; i < (aData.size() / 202000) + 1; i++)
{
QByteArray newSigBlocks;
for (int j = 0; j < 256; j++) {
QByteArray newSigBlock(32, Qt::Uninitialized);
fastFileStream.readRawData(newSigBlock.data(), 32);
sigBlocks.append(newSigBlock);
}
newSigBlocks.append(newSigBlocks);
for (int j = 0; j < 256; j++) {
QByteArray compressedChunk(8192, Qt::Uninitialized);
fastFileStream.readRawData(compressedChunk.data(), 8192);
compressedData.append(compressedChunk);
}
}
decompressedData = Compression::DecompressZLIB(compressedData);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD4_360* zoneFile = new ZoneFile_COD4_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD4_360_H
#define FASTFILE_COD4_360_H
#include "fastfile.h"
class FastFile_COD4_360 : public FastFile
{
public:
FastFile_COD4_360();
FastFile_COD4_360(const QByteArray &aData);
FastFile_COD4_360(const QString aFilePath);
~FastFile_COD4_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD4_360_H

View File

@ -1,91 +0,0 @@
#include "fastfile_cod5_360.h"
#include "zonefile_cod5_360.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD5_360::FastFile_COD5_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD5_360::FastFile_COD5_360(const QByteArray& aData)
: FastFile_COD5_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD5_360::FastFile_COD5_360(const QString aFilePath)
: FastFile_COD5_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD5_360::~FastFile_COD5_360() {
}
QByteArray FastFile_COD5_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD5_360::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
QString fastFileStem = aFilePath.split('/').last().replace(".ff", "");
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD5_360::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
// For COD5, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(12));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD5_360* zoneFile = new ZoneFile_COD5_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD5_360_H
#define FASTFILE_COD5_360_H
#include "fastfile.h"
class FastFile_COD5_360 : public FastFile
{
public:
FastFile_COD5_360();
FastFile_COD5_360(const QByteArray &aData);
FastFile_COD5_360(const QString aFilePath);
~FastFile_COD5_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD5_360_H

View File

@ -1,124 +0,0 @@
#include "fastfile_cod6_360.h"
#include "zonefile_cod6_360.h"
#include "compression.h"
#include "encryption.h"
#include "utils.h"
#include <QFile>
#include <QDebug>
FastFile_COD6_360::FastFile_COD6_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD6_360::FastFile_COD6_360(const QByteArray& aData)
: FastFile_COD6_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD6_360::FastFile_COD6_360(const QString aFilePath)
: FastFile_COD6_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD6_360::~FastFile_COD6_360() {
}
QByteArray FastFile_COD6_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD6_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD6_360::Load(const QByteArray aData) {
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::BigEndian);
QByteArray magic(8, Qt::Uninitialized);
fastFileStream.readRawData(magic.data(), 8);
quint32 version = fastFileStream.ParseUInt32();
if (version != 269)
{
qDebug() << QString("Invalid version: %1!").arg(version);
return false;
}
bool localPatch = fastFileStream.ParseBool();
Q_UNUSED(localPatch);
quint8 compressor = fastFileStream.ParseUInt8();
Q_UNUSED(compressor);
// Skip fastfile date/time
fastFileStream.skipRawData(11);
quint32 hashCount = fastFileStream.ParseUInt32();
fastFileStream.skipRawData(12 * hashCount);
fastFileStream.skipRawData(8);
QByteArray decompressedData;
if (magic == "IWff0100")
{
}
else if (magic == "IWffu100")
{
quint32 zlibSize = aData.size() - fastFileStream.device()->pos();
QByteArray zlibData(zlibSize, Qt::Uninitialized);
fastFileStream.readRawData(zlibData.data(), zlibSize);
decompressedData = Compression::DecompressZLIB(zlibData);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD6_360* zoneFile = new ZoneFile_COD6_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD6_360_H
#define FASTFILE_COD6_360_H
#include "fastfile.h"
class FastFile_COD6_360 : public FastFile
{
public:
FastFile_COD6_360();
FastFile_COD6_360(const QByteArray& aData);
FastFile_COD6_360(const QString aFilePath);
~FastFile_COD6_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD6_360_H

View File

@ -1,149 +0,0 @@
#include "fastfile_cod7_360.h"
#include "zonefile_cod7_360.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD7_360::FastFile_COD7_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD7_360::FastFile_COD7_360(const QByteArray& aData)
: FastFile_COD7_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD7_360::FastFile_COD7_360(const QString aFilePath)
: FastFile_COD7_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD7_360::~FastFile_COD7_360() {
}
QByteArray FastFile_COD7_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD7_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD7_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::BigEndian);
fastFileStream.skipRawData(16);
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Build the IV table from the fileName.
QByteArray ivTable = Encryption::InitIVTable(fileName);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
QByteArray key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d");
// Now the stream should be positioned at 0x13C, where sections begin.
int sectionIndex = 0;
while (true) {
qint32 sectionSize = 0;
fastFileStream >> sectionSize;
qDebug() << "Section index:" << sectionIndex << "Size:" << sectionSize
<< "Pos:" << fastFileStream.device()->pos();
if (sectionSize == 0)
break;
// Read the section data.
QByteArray sectionData;
sectionData.resize(sectionSize);
fastFileStream.readRawData(sectionData.data(), sectionSize);
// Compute the IV for this section.
QByteArray iv = Encryption::GetIV(ivTable, sectionIndex);
// Decrypt the section using Salsa20.
QByteArray decData = Encryption::salsa20DecryptSection(sectionData, key, iv);
// Compute SHA1 hash of the decrypted data.
QByteArray sectionHash = QCryptographicHash::hash(decData, QCryptographicHash::Sha1);
// Update the IV table based on the section hash.
Encryption::UpdateIVTable(ivTable, sectionIndex, sectionHash);
// Build a compressed data buffer by prepending the two-byte zlib header.
QByteArray compressedData;
compressedData.append(char(0x78));
compressedData.append(char(0x01));
compressedData.append(decData);
decompressedData.append(Compression::DecompressZLIB(compressedData));
sectionIndex++;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD7_360* zoneFile = new ZoneFile_COD7_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD7_360_H
#define FASTFILE_COD7_360_H
#include "fastfile.h"
class FastFile_COD7_360 : public FastFile
{
public:
FastFile_COD7_360();
FastFile_COD7_360(const QByteArray& aData);
FastFile_COD7_360(const QString aFilePath);
~FastFile_COD7_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD7_360_H

View File

@ -1,147 +0,0 @@
#include "fastfile_cod7_5_360.h"
#include "zonefile_cod7_360.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD7_5_360::FastFile_COD7_5_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD7_5_360::FastFile_COD7_5_360(const QByteArray& aData)
: FastFile_COD7_5_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD7_5_360::FastFile_COD7_5_360(const QString aFilePath)
: FastFile_COD7_5_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD7_5_360::~FastFile_COD7_5_360() {
}
QByteArray FastFile_COD7_5_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD7_5_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
enum NX_Language : qint32
{
LANGUAGE_ENGLISH = 0x0,
LANGUAGE_FRENCH = 0x1,
LANGUAGE_GERMAN = 0x2,
LANGUAGE_ITALIAN = 0x3,
LANGUAGE_SPANISH = 0x4,
LANGUAGE_BRITISH = 0x5,
LANGUAGE_RUSSIAN = 0x6,
LANGUAGE_POLISH = 0x7,
LANGUAGE_KOREAN = 0x8,
LANGUAGE_TAIWANESE = 0x9,
LANGUAGE_JAPANESE = 0xA,
LANGUAGE_CHINESE = 0xB,
LANGUAGE_THAI = 0xC,
LANGUAGE_LEET = 0xD,
LANGUAGE_CZECH = 0xE,
MAX_LANGUAGES = 0xF,
};
bool FastFile_COD7_5_360::Load(const QByteArray aData) {
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::BigEndian);
QByteArray magic(8, Qt::Uninitialized);
fastFileStream.readRawData(magic.data(), 8);
quint32 version = fastFileStream.ParseUInt32();
if (version != 357)
{
qDebug() << QString("Invalid version: %1!").arg(version);
return false;
}
bool localPatch = fastFileStream.ParseBool();
Q_UNUSED(localPatch);
quint8 compressor = fastFileStream.ParseUInt8();
Q_UNUSED(compressor);
// Skip fastfile date/time
fastFileStream.skipRawData(8);
NX_Language language = (NX_Language)fastFileStream.ParseInt32();
Q_UNUSED(language);
quint32 hashCount = fastFileStream.ParseUInt32();
fastFileStream.skipRawData(12 * hashCount);
fastFileStream.skipRawData(8);
QByteArray decompressedData;
if (magic == "NXff0100")
{
}
else if (magic == "NXffu100")
{
quint32 zlibSize = aData.size() - fastFileStream.device()->pos();
QByteArray zlibData(zlibSize, Qt::Uninitialized);
fastFileStream.readRawData(zlibData.data(), zlibSize);
decompressedData = Compression::DecompressZLIB(zlibData);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD7_360* zoneFile = new ZoneFile_COD7_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD7_5_360_H
#define FASTFILE_COD7_5_360_H
#include "fastfile.h"
class FastFile_COD7_5_360 : public FastFile
{
public:
FastFile_COD7_5_360();
FastFile_COD7_5_360(const QByteArray& aData);
FastFile_COD7_5_360(const QString aFilePath);
~FastFile_COD7_5_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD7_5_360_H

View File

@ -1,110 +0,0 @@
#include "fastfile_cod8_360.h"
#include "zonefile_cod8_360.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD8_360::FastFile_COD8_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD8_360::FastFile_COD8_360(const QByteArray& aData)
: FastFile_COD8_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD8_360::FastFile_COD8_360(const QString aFilePath)
: FastFile_COD8_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD8_360::~FastFile_COD8_360() {
}
QByteArray FastFile_COD8_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD8_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD8_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
decompressedData = Encryption::DecryptFile(aData, fileName, "0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD8_360* zoneFile = new ZoneFile_COD8_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD8_360_H
#define FASTFILE_COD8_360_H
#include "fastfile.h"
class FastFile_COD8_360 : public FastFile
{
public:
FastFile_COD8_360();
FastFile_COD8_360(const QByteArray& aData);
FastFile_COD8_360(const QString aFilePath);
~FastFile_COD8_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD8_360_H

View File

@ -1,114 +0,0 @@
#include "fastfile_cod9_360.h"
#include "zonefile_cod9_360.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD9_360::FastFile_COD9_360()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD9_360::FastFile_COD9_360(const QByteArray& aData)
: FastFile_COD9_360() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD9_360::FastFile_COD9_360(const QString aFilePath)
: FastFile_COD9_360() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD9_360::~FastFile_COD9_360() {
}
QByteArray FastFile_COD9_360::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD9_360::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD9_360::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
decompressedData = Encryption::DecryptFile(aData, fileName, "0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD9_360* zoneFile = new ZoneFile_COD9_360();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD9_360_H
#define FASTFILE_COD9_360_H
#include "fastfile.h"
class FastFile_COD9_360 : public FastFile
{
public:
FastFile_COD9_360();
FastFile_COD9_360(const QByteArray& aData);
FastFile_COD9_360(const QString aFilePath);
~FastFile_COD9_360();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD9_360_H

View File

@ -1,129 +0,0 @@
#include "fastfile_cod10_pc.h"
#include "zonefile_cod10_pc.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD10_PC::FastFile_COD10_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD10_PC::FastFile_COD10_PC(const QByteArray& aData)
: FastFile_COD10_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD10_PC::FastFile_COD10_PC(const QString aFilePath)
: FastFile_COD10_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD10_PC::~FastFile_COD10_PC() {
}
QByteArray FastFile_COD10_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD10_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD10_PC::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
}
// Select key based on game.
QByteArray key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
//decompressedData = Encryption::decryptFastFile_BO2(aData);
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD10_PC* zoneFile = new ZoneFile_COD10_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD10_PC_H
#define FASTFILE_COD10_PC_H
#include "fastfile.h"
class FastFile_COD10_PC : public FastFile
{
public:
FastFile_COD10_PC();
FastFile_COD10_PC(const QByteArray &aData);
FastFile_COD10_PC(const QString aFilePath);
~FastFile_COD10_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD10_PC_H

View File

@ -1,125 +0,0 @@
#include "fastfile_cod11_pc.h"
#include "zonefile_cod11_pc.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD11_PC::FastFile_COD11_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD11_PC::FastFile_COD11_PC(const QByteArray& aData)
: FastFile_COD11_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD11_PC::FastFile_COD11_PC(const QString aFilePath)
: FastFile_COD11_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD11_PC::~FastFile_COD11_PC() {
}
QByteArray FastFile_COD11_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD11_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD11_PC::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Select key based on game.
QByteArray key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
//decompressedData = Encryption::decryptFastFile_BO2(aData);
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD11_PC* zoneFile = new ZoneFile_COD11_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD11_PC_H
#define FASTFILE_COD11_PC_H
#include "fastfile.h"
class FastFile_COD11_PC : public FastFile
{
public:
FastFile_COD11_PC();
FastFile_COD11_PC(const QByteArray &aData);
FastFile_COD11_PC(const QString aFilePath);
~FastFile_COD11_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD11_PC_H

View File

@ -1,149 +0,0 @@
#include "fastfile_cod12_pc.h"
#include "zonefile_cod12_pc.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD12_PC::FastFile_COD12_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD12_PC::FastFile_COD12_PC(const QByteArray& aData)
: FastFile_COD12_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD12_PC::FastFile_COD12_PC(const QString aFilePath)
: FastFile_COD12_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD12_PC::~FastFile_COD12_PC() {
}
QByteArray FastFile_COD12_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD12_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first();
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD12_PC::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Skip header magic
fastFileStream.skipRawData(8);
quint32 version;
fastFileStream >> version;
quint8 unknownFlag, compressionFlag, platformFlag, encryptionFlag;
fastFileStream >> unknownFlag >> compressionFlag >> platformFlag >> encryptionFlag;
if (compressionFlag != 1) {
qDebug() << "Invalid fastfile compression: " << compressionFlag;
return false;
} else if (platformFlag != 0) {
qDebug() << "Invalid platform: " << platformFlag;
return false;
} else if (encryptionFlag != 0) {
qDebug() << "Decryption not supported yet!";
return false;
}
fastFileStream.skipRawData(128);
quint64 size;
fastFileStream >> size;
fastFileStream.skipRawData(432);
int consumed = 0;
while(consumed < size)
{
// Read Block Header
quint32 compressedSize, decompressedSize, blockSize, blockPosition;
fastFileStream >> compressedSize >> decompressedSize >> blockSize >> blockPosition;
// Validate the block position, it should match
if(blockPosition != fastFileStream.device()->pos() - 16)
{
qDebug() << "Block Position does not match Stream Position.";
return false;
}
// Check for padding blocks
if(decompressedSize == 0)
{
fastFileStream.device()->read((((fastFileStream.device()->pos()) + ((0x800000) - 1)) & ~((0x800000) - 1)) - fastFileStream.device()->pos());
continue;
}
fastFileStream.device()->read(2);
QByteArray compressedData(compressedSize - 2, Qt::Uninitialized);
qDebug() << "Data position: " << fastFileStream.device()->pos() << " - Size: " << compressedSize;
fastFileStream.readRawData(compressedData.data(), compressedSize - 2);
decompressedData.append(Compression::DecompressDeflate(compressedData));
consumed += decompressedSize;
// Sinze Fast Files are aligns, we must skip the full block
fastFileStream.device()->seek(blockPosition + 16 + blockSize);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD12_PC* zoneFile = new ZoneFile_COD12_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD12_PC_H
#define FASTFILE_COD12_PC_H
#include "fastfile.h"
class FastFile_COD12_PC : public FastFile
{
public:
FastFile_COD12_PC();
FastFile_COD12_PC(const QByteArray &aData);
FastFile_COD12_PC(const QString aFilePath);
~FastFile_COD12_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD12_PC_H

View File

@ -1,209 +0,0 @@
#include "fastfile_cod21_pc.h"
#include "zonefile_cod21_pc.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD21_PC::FastFile_COD21_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_SIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD21_PC::FastFile_COD21_PC(const QByteArray& aData)
: FastFile_COD21_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD21_PC::FastFile_COD21_PC(const QString aFilePath)
: FastFile_COD21_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD21_PC::~FastFile_COD21_PC() {
}
QByteArray FastFile_COD21_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD21_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first();
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD21_PC::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
auto dev = fastFileStream.device();
if (dev->bytesAvailable() < 12) {
qWarning() << "Not enough data for block header";
return false;
}
// Skip to start of fastfile
quint64 startIndex = aData.indexOf("IWCIWffs100");
if (startIndex == -1)
{
qDebug() << "Failed to find data start!";
return true;
}
fastFileStream.skipRawData(startIndex + 11);
qDebug() << "Start index: " << startIndex + 11;
// Skip RSA hashes
fastFileStream.skipRawData(32760);
qint32 decompressedDataLen = fastFileStream.ParseInt32();
qDebug() << "Decompressed Data Len: " << decompressedDataLen;
fastFileStream.skipRawData(3);
qint8 compressionType = fastFileStream.ParseInt8();
qDebug() << "Compression Type: " << compressionType;
long decompressedDataCount = 0;
int loopCount = 1;
while (decompressedDataCount < decompressedDataLen)
{
qDebug() << QString("Block Offset: {0:%1}, total: {1:%2}").arg(fastFileStream.device()->pos()).arg(decompressedDataCount);
if (loopCount == 512)
{
// Skip an RSA block
fastFileStream.skipRawData(0x4000);
loopCount = 0;
}
qint32 compLenRaw = fastFileStream.ParseInt32();
qDebug() << "Test: " << fastFileStream.device()->pos();
qint32 compressedLen = (compLenRaw + 3) & ~3;
qint32 decompressedLen = fastFileStream.ParseInt32();
if (dev->bytesAvailable() < compressedLen) {
qDebug() << "Too Much at: " << fastFileStream.device()->pos();
qWarning() << "Not enough data for compressed block. Want"
<< compressedLen << "have" << dev->bytesAvailable();
break;
}
fastFileStream.skipRawData(4); // padding
QByteArray compressedAligned(compressedLen, Qt::Uninitialized);
// Read the full aligned block
if (fastFileStream.readRawData(compressedAligned.data(), compressedLen) != compressedLen) {
qWarning() << "Unexpected EOF while reading aligned compressed block";
//return false;
}
// Only first compLenRaw bytes are real data
QByteArray compressedChunk = compressedAligned.left(compLenRaw);
QByteArray decompressedChunk;
switch (compressionType)
{
// Decompress None
case 1:
decompressedChunk = compressedChunk;
break;
// unknown
case 4:
case 5:
qDebug() << "unimplemented compression type!";
return false;
// Decompress Oodle
case 6:
case 7:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
qDebug() << "Calling Oodle with compLenRaw=" << compLenRaw
<< "aligned=" << compressedLen
<< "decompressedLen=" << decompressedLen;
decompressedChunk = Compression::DecompressOodle(compressedChunk, decompressedLen);
break;
default:
qDebug() << "Unknown type of compression!";
return false;
}
if (decompressedChunk.isNull())
{
qDebug() << "Decompressor returned null!";
continue;
}
if (decompressedDataCount + decompressedLen > decompressedDataLen) {
qWarning() << "Decompressed overrun:" << decompressedDataCount + decompressedLen
<< ">" << decompressedDataLen;
decompressedLen = decompressedDataLen - decompressedDataCount;
decompressedChunk.truncate(decompressedLen);
}
decompressedData.append(decompressedChunk);
decompressedDataCount += decompressedLen;
loopCount++;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// // Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD21_PC* zoneFile = new ZoneFile_COD21_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD21_PC_H
#define FASTFILE_COD21_PC_H
#include "fastfile.h"
class FastFile_COD21_PC : public FastFile
{
public:
FastFile_COD21_PC();
FastFile_COD21_PC(const QByteArray &aData);
FastFile_COD21_PC(const QString aFilePath);
~FastFile_COD21_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD21_PC_H

View File

@ -1,95 +0,0 @@
#include "fastfile_cod4_pc.h"
#include "zonefile_cod4_pc.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD4_PC::FastFile_COD4_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD4_PC::FastFile_COD4_PC(const QByteArray& aData)
: FastFile_COD4_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD4_PC::FastFile_COD4_PC(const QString aFilePath)
: FastFile_COD4_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD4_PC::~FastFile_COD4_PC() {
}
QByteArray FastFile_COD4_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD4_PC::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD" + GetCommonInfo().GetGameString() + " Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD4_PC::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// For COD5, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(12));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD4_PC* zoneFile = new ZoneFile_COD4_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD4_PC_H
#define FASTFILE_COD4_PC_H
#include "fastfile.h"
class FastFile_COD4_PC : public FastFile
{
public:
FastFile_COD4_PC();
FastFile_COD4_PC(const QByteArray &aData);
FastFile_COD4_PC(const QString aFilePath);
~FastFile_COD4_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD4_PC_H

View File

@ -1,95 +0,0 @@
#include "fastfile_cod5_pc.h"
#include "zonefile_cod5_pc.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD5_PC::FastFile_COD5_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD5_PC::FastFile_COD5_PC(const QByteArray& aData)
: FastFile_COD5_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD5_PC::FastFile_COD5_PC(const QString aFilePath)
: FastFile_COD5_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD5_PC::~FastFile_COD5_PC() {
}
QByteArray FastFile_COD5_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD5_PC::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD5_PC::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// For COD5, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(12));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD5_PC* zoneFile = new ZoneFile_COD5_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD5_PC_H
#define FASTFILE_COD5_PC_H
#include "fastfile.h"
class FastFile_COD5_PC : public FastFile
{
public:
FastFile_COD5_PC();
FastFile_COD5_PC(const QByteArray &aData);
FastFile_COD5_PC(const QString aFilePath);
~FastFile_COD5_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD5_PC_H

View File

@ -1,110 +0,0 @@
#include "fastfile_cod6_pc.h"
#include "zonefile_cod6_pc.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD6_PC::FastFile_COD6_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD6_PC::FastFile_COD6_PC(const QByteArray& aData)
: FastFile_COD6_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD6_PC::FastFile_COD6_PC(const QString aFilePath)
: FastFile_COD6_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD6_PC::~FastFile_COD6_PC() {
}
QByteArray FastFile_COD6_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD6_PC::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD6_PC::Load(const QByteArray aData) {
const qint64 zlibOffset = Compression::FindZlibOffset(aData);
qDebug() << "ZLib Offset: " << zlibOffset;
if (zlibOffset == -1)
{
qWarning() << "Z-Lib stream not found";
return false;
}
QByteArray compressed = aData.mid(zlibOffset);
QByteArray decompressedData = Compression::DecompressZLIB(compressed);
if (decompressedData.isEmpty() || decompressedData.size() < 1024)
{
QByteArray stripped = Compression::StripHashBlocks(compressed);
QByteArray retry = Compression::DecompressZLIB(stripped);
if (!retry.isEmpty())
decompressedData.swap(retry);
}
if (decompressedData.isEmpty())
{
qWarning() << "Unable to decompress fast-file";
return false;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD6_PC* zoneFile = new ZoneFile_COD6_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD6_PC_H
#define FASTFILE_COD6_PC_H
#include "fastfile.h"
class FastFile_COD6_PC : public FastFile
{
public:
FastFile_COD6_PC();
FastFile_COD6_PC(const QByteArray &aData);
FastFile_COD6_PC(const QString aFilePath);
~FastFile_COD6_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD6_PC_H

View File

@ -1,100 +0,0 @@
#include "fastfile_cod7_pc.h"
//#include "zonefile_cod7_pc.h"
#include "utils.h"
#include "compression.h"
#include <QFile>
#include <QDebug>
FastFile_COD7_PC::FastFile_COD7_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD7_PC::FastFile_COD7_PC(const QByteArray& aData)
: FastFile_COD7_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD7_PC::FastFile_COD7_PC(const QString aFilePath)
: FastFile_COD7_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD7_PC::~FastFile_COD7_PC() {
}
QByteArray FastFile_COD7_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD7_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD7_PC::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// Assume the first 12 bytes are a header; the rest is zlib-compressed zone data.
const QByteArray compressedData = aData.mid(12);
decompressedData = Compression::DecompressZLIB(compressedData);
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// ZoneFile_COD7_PC* zoneFile = new ZoneFile_COD7_PC();
// zoneFile->SetStem(GetBaseStem() + ".zone");
// zoneFile->SetCommonInfo(&mCommonInfo);
// if (!zoneFile->Load(decompressedData)) {
// qWarning() << "Failed to load ZoneFile!";
// return false;
// }
// SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD7_PC_H
#define FASTFILE_COD7_PC_H
#include "fastfile.h"
class FastFile_COD7_PC : public FastFile
{
public:
FastFile_COD7_PC();
FastFile_COD7_PC(const QByteArray &aData);
FastFile_COD7_PC(const QString aFilePath);
~FastFile_COD7_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD7_PC_H

View File

@ -1,97 +0,0 @@
#include "fastfile_cod8_pc.h"
#include "zonefile_cod8_pc.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD8_PC::FastFile_COD8_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD8_PC::FastFile_COD8_PC(const QByteArray& aData)
: FastFile_COD8_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD8_PC::FastFile_COD8_PC(const QString aFilePath)
: FastFile_COD8_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD8_PC::~FastFile_COD8_PC() {
}
QByteArray FastFile_COD8_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD8_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD8_PC::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
SetVersion(pParseFFVersion(&fastFileStream));
decompressedData = Compression::DecompressZLIB(aData.mid(21));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD8_PC* zoneFile = new ZoneFile_COD8_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD8_PC_H
#define FASTFILE_COD8_PC_H
#include "fastfile.h"
class FastFile_COD8_PC : public FastFile
{
public:
FastFile_COD8_PC();
FastFile_COD8_PC(const QByteArray &aData);
FastFile_COD8_PC(const QString aFilePath);
~FastFile_COD8_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD8_PC_H

View File

@ -1,185 +0,0 @@
#include "fastfile_cod9_pc.h"
#include "zonefile_cod9_pc.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD9_PC::FastFile_COD9_PC()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD9_PC::FastFile_COD9_PC(const QByteArray& aData)
: FastFile_COD9_PC() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD9_PC::FastFile_COD9_PC(const QString aFilePath)
: FastFile_COD9_PC() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD9_PC::~FastFile_COD9_PC() {
}
QByteArray FastFile_COD9_PC::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD9_PC::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD9_PC::Load(const QByteArray aData) {
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
SetVersion(pParseFFVersion(&fastFileStream));
// Validate the fastfile magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV seed name (32 bytes).
QByteArray nameKey(32, Qt::Uninitialized);
fastFileStream.readRawData(nameKey.data(), 32);
// --- Salsa20 + IV setup ---
static QVector<quint32> ivCounter(4, 1);
QByteArray ivTable = Encryption::InitIVTable(nameKey);
ivCounter.fill(1); // reset global counters
// Skip RSA signature (0x100)
fastFileStream.skipRawData(0x100);
// Decrypt + decompress loop
QByteArray finalZone;
int chunkIndex = 0;
while (!fastFileStream.atEnd()) {
quint32 dataLength = 0;
fastFileStream >> dataLength;
if (dataLength == 0)
break;
QByteArray encryptedBlock(dataLength, Qt::Uninitialized);
if (fastFileStream.readRawData(encryptedBlock.data(), dataLength) != dataLength) {
qWarning() << "Unexpected EOF while reading block";
break;
}
// Derive IV for this chunk
QByteArray iv = Encryption::GetIV(ivTable, chunkIndex % 4);
// Salsa20 decryption
QByteArray decryptedBlock = Encryption::salsa20DecryptSection(
encryptedBlock,
QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"),
iv,
64
);
// SHA1 hash of decrypted block
QCryptographicHash sha1(QCryptographicHash::Sha1);
sha1.addData(decryptedBlock);
QByteArray sha1Hash = sha1.result();
// Inflate into buffer
z_stream strm{};
strm.avail_in = static_cast<uInt>(decryptedBlock.size());
strm.next_in = reinterpret_cast<Bytef*>(decryptedBlock.data());
QByteArray decompressedData;
QByteArray buffer(0x10000, Qt::Uninitialized);
inflateInit2(&strm, -15);
int ret;
do {
strm.avail_out = buffer.size();
strm.next_out = reinterpret_cast<Bytef*>(buffer.data());
ret = inflate(&strm, Z_NO_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) {
qWarning() << "inflate failed with code" << ret;
break;
}
int have = buffer.size() - strm.avail_out;
if (have > 0)
decompressedData.append(buffer.constData(), have);
} while (ret != Z_STREAM_END);
inflateEnd(&strm);
finalZone.append(decompressedData);
// Update IV table for next block
Encryption::UpdateIVTable(ivTable, chunkIndex % 4, sha1Hash);
chunkIndex++;
}
// Export decompressed zone
Utils::ExportData(GetBaseStem() + ".zone", finalZone);
// Load zone file
ZoneFile_COD9_PC* zoneFile = new ZoneFile_COD9_PC();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(finalZone)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD9_PC_H
#define FASTFILE_COD9_PC_H
#include "fastfile.h"
class FastFile_COD9_PC : public FastFile
{
public:
FastFile_COD9_PC();
FastFile_COD9_PC(const QByteArray &aData);
FastFile_COD9_PC(const QString aFilePath);
~FastFile_COD9_PC();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD9_PC_H

View File

@ -1,129 +0,0 @@
#include "fastfile_cod10_ps3.h"
#include "zonefile_cod10_ps3.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD10_PS3::FastFile_COD10_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD10_PS3::FastFile_COD10_PS3(const QByteArray& aData)
: FastFile_COD10_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD10_PS3::FastFile_COD10_PS3(const QString aFilePath)
: FastFile_COD10_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD10_PS3::~FastFile_COD10_PS3() {
}
QByteArray FastFile_COD10_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD10_PS3::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD10_PS3::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
}
// Select key based on game.
QByteArray key;
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
}
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
//decompressedData = Encryption::decryptFastFile_BO2(aData);
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD10_PS3* zoneFile = new ZoneFile_COD10_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD10_PS3_H
#define FASTFILE_COD10_PS3_H
#include "fastfile.h"
class FastFile_COD10_PS3 : public FastFile
{
public:
FastFile_COD10_PS3();
FastFile_COD10_PS3(const QByteArray &aData);
FastFile_COD10_PS3(const QString aFilePath);
~FastFile_COD10_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD10_PS3_H

View File

@ -1,149 +0,0 @@
#include "fastfile_cod11_ps3.h"
#include "zonefile_cod11_ps3.h"
#include "encryption.h"
#include "compression.h"
#include <QFile>
#include <QDebug>
FastFile_COD11_PS3::FastFile_COD11_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD11_PS3::FastFile_COD11_PS3(const QByteArray& aData)
: FastFile_COD11_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD11_PS3::FastFile_COD11_PS3(const QString aFilePath)
: FastFile_COD11_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD11_PS3::~FastFile_COD11_PS3() {
}
QByteArray FastFile_COD11_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD11_PS3::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
enum DB_CompressorType : qint32
{
DB_COMPRESSOR_INVALID = 0x0,
DB_COMPRESSOR_ZLIB = 0x1,
DB_COMPRESSOR_LZX = 0x2,
DB_COMPRESSOR_PASSTHROUGH = 0x3,
};
bool FastFile_COD11_PS3::Load(const QByteArray aData) {
QByteArray decompressedData;
// Prepare data stream for parsing
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::BigEndian);
// Verify magic header
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
quint32 version = fastFileStream.ParseUInt32();
fastFileStream.skipRawData(1);
DB_CompressorType compressorType = (DB_CompressorType)fastFileStream.ParseInt8();
fastFileStream.skipRawData(10);
qint32 blockCount = fastFileStream.ParseInt32();
if (version != 1838)
{
qWarning() << "Invalid fast file version:" << version << "!";
return false;
}
if (blockCount > 17280)
{
qWarning() << "Fast file has too many blocks:" << blockCount << "> 17280!";
return false;
}
fastFileStream.skipRawData(12 * blockCount);
qint32 startPos = fastFileStream.ParseInt32();
Q_UNUSED(startPos);
qint32 endPos = fastFileStream.ParseInt32();
Q_UNUSED(endPos);
if (fileMagic == "S1ffu100")
{
QByteArray compressedData = aData.mid(fastFileStream.device()->pos());
if (compressorType == DB_COMPRESSOR_ZLIB)
{
decompressedData = Compression::DecompressZLIB(compressedData);
}
else if (compressorType == DB_COMPRESSOR_LZX)
{
decompressedData = Compression::DecompressXMem(compressedData, 0, 0x80000, 0);
}
}
else if (fileMagic == "S1ff0100")
{
}
else
{
qWarning() << "Invalid fast file magic:" << fileMagic << "!";
return false;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with decompressed data
ZoneFile_COD11_PS3* zoneFile = new ZoneFile_COD11_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD11_PS3_H
#define FASTFILE_COD11_PS3_H
#include "fastfile.h"
class FastFile_COD11_PS3 : public FastFile
{
public:
FastFile_COD11_PS3();
FastFile_COD11_PS3(const QByteArray &aData);
FastFile_COD11_PS3(const QString aFilePath);
~FastFile_COD11_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD11_PS3_H

View File

@ -1,129 +0,0 @@
#include "fastfile_cod12_ps3.h"
#include "zonefile_cod12_ps3.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD12_PS3::FastFile_COD12_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD12_PS3::FastFile_COD12_PS3(const QByteArray& aData)
: FastFile_COD12_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD12_PS3::FastFile_COD12_PS3(const QString aFilePath)
: FastFile_COD12_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD12_PS3::~FastFile_COD12_PS3() {
}
QByteArray FastFile_COD12_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD12_PS3::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD12_PS3::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
}
// Select key based on game.
QByteArray key;
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
}
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
decompressedData = Encryption::decryptFastFile_BO3(aData);
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD12_PS3* zoneFile = new ZoneFile_COD12_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD12_PS3_H
#define FASTFILE_COD12_PS3_H
#include "fastfile.h"
class FastFile_COD12_PS3 : public FastFile
{
public:
FastFile_COD12_PS3();
FastFile_COD12_PS3(const QByteArray &aData);
FastFile_COD12_PS3(const QString aFilePath);
~FastFile_COD12_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD12_PS3_H

View File

@ -1,117 +0,0 @@
#include "fastfile_cod4_ps3.h"
#include "zonefile_cod4_ps3.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD4_PS3::FastFile_COD4_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD4_PS3::FastFile_COD4_PS3(const QByteArray& aData)
: FastFile_COD4_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD4_PS3::FastFile_COD4_PS3(const QString aFilePath)
: FastFile_COD4_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD4_PS3::~FastFile_COD4_PS3() {
}
QByteArray FastFile_COD4_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD4_PS3::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD4_PS3::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
SetVersion(pParseFFVersion(&fastFileStream));
// Loop until EOF or invalid chunk
fastFileStream.setByteOrder(XDataStream::BigEndian);
while (!fastFileStream.atEnd()) {
// Read 2-byte BIG-ENDIAN chunk size
quint16 chunkSize;
fastFileStream >> chunkSize;
if (chunkSize == 0 || fastFileStream.device()->pos() + chunkSize > aData.size()) {
qWarning() << "Invalid or incomplete chunk detected, stopping.";
break;
}
QByteArray compressedChunk(chunkSize, Qt::Uninitialized);
fastFileStream.readRawData(compressedChunk.data(), chunkSize);
QByteArray decompressedChunk = Compression::DecompressDeflate(compressedChunk);
decompressedData.append(decompressedChunk);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD4_PS3* zoneFile = new ZoneFile_COD4_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD4_PS3_H
#define FASTFILE_COD4_PS3_H
#include "fastfile.h"
class FastFile_COD4_PS3 : public FastFile
{
public:
FastFile_COD4_PS3();
FastFile_COD4_PS3(const QByteArray &aData);
FastFile_COD4_PS3(const QString aFilePath);
~FastFile_COD4_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD4_PS3_H

View File

@ -1,117 +0,0 @@
#include "fastfile_cod5_ps3.h"
#include "zonefile_cod5_ps3.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD5_PS3::FastFile_COD5_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD5_PS3::FastFile_COD5_PS3(const QByteArray& aData)
: FastFile_COD5_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD5_PS3::FastFile_COD5_PS3(const QString aFilePath)
: FastFile_COD5_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD5_PS3::~FastFile_COD5_PS3() {
}
QByteArray FastFile_COD5_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD5_PS3::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD5_PS3::Load(const QByteArray aData) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000);
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
SetVersion(pParseFFVersion(&fastFileStream));
// Loop until EOF or invalid chunk
fastFileStream.setByteOrder(XDataStream::BigEndian);
while (!fastFileStream.atEnd()) {
// Read 2-byte BIG-ENDIAN chunk size
quint16 chunkSize;
fastFileStream >> chunkSize;
if (chunkSize == 0 || fastFileStream.device()->pos() + chunkSize > aData.size()) {
qWarning() << "Invalid or incomplete chunk detected, stopping.";
break;
}
QByteArray compressedChunk(chunkSize, Qt::Uninitialized);
fastFileStream.readRawData(compressedChunk.data(), chunkSize);
QByteArray decompressedChunk = Compression::DecompressDeflate(compressedChunk);
decompressedData.append(decompressedChunk);
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD5_PS3* zoneFile = new ZoneFile_COD5_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD5_PS3_H
#define FASTFILE_COD5_PS3_H
#include "fastfile.h"
class FastFile_COD5_PS3 : public FastFile
{
public:
FastFile_COD5_PS3();
FastFile_COD5_PS3(const QByteArray &aData);
FastFile_COD5_PS3(const QString aFilePath);
~FastFile_COD5_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD5_PS3_H

View File

@ -1,110 +0,0 @@
#include "fastfile_cod6_ps3.h"
#include "zonefile_cod6_ps3.h"
#include "utils.h"
#include "compression.h"
#include "statusbarmanager.h"
#include <QFile>
#include <QDebug>
FastFile_COD6_PS3::FastFile_COD6_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD6_PS3::FastFile_COD6_PS3(const QByteArray& aData)
: FastFile_COD6_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD6_PS3::FastFile_COD6_PS3(const QString aFilePath)
: FastFile_COD6_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD6_PS3::~FastFile_COD6_PS3() {
}
QByteArray FastFile_COD6_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD6_PS3::Load(const QString aFilePath) {
StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000);
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD6_PS3::Load(const QByteArray aData) {
const qint64 zlibOffset = Compression::FindZlibOffset(aData);
qDebug() << "ZLib Offset: " << zlibOffset;
if (zlibOffset == -1)
{
qWarning() << "Z-Lib stream not found";
return false;
}
QByteArray compressed = aData.mid(zlibOffset);
QByteArray decompressedData = Compression::DecompressZLIB(compressed);
if (decompressedData.isEmpty() || decompressedData.size() < 1024)
{
QByteArray stripped = Compression::StripHashBlocks(compressed);
QByteArray retry = Compression::DecompressZLIB(stripped);
if (!retry.isEmpty())
decompressedData.swap(retry);
}
if (decompressedData.isEmpty())
{
qWarning() << "Unable to decompress fast-file";
return false;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD6_PS3* zoneFile = new ZoneFile_COD6_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD6_PS3_H
#define FASTFILE_COD6_PS3_H
#include "fastfile.h"
class FastFile_COD6_PS3 : public FastFile
{
public:
FastFile_COD6_PS3();
FastFile_COD6_PS3(const QByteArray &aData);
FastFile_COD6_PS3(const QString aFilePath);
~FastFile_COD6_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD6_PS3_H

View File

@ -1,160 +0,0 @@
#include "fastfile_cod7_ps3.h"
#include "zonefile_cod7_ps3.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD7_PS3::FastFile_COD7_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD7_PS3::FastFile_COD7_PS3(const QByteArray& aData)
: FastFile_COD7_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD7_PS3::FastFile_COD7_PS3(const QString aFilePath)
: FastFile_COD7_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD7_PS3::~FastFile_COD7_PS3() {
}
QByteArray FastFile_COD7_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD7_PS3::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
return true;
}
bool FastFile_COD7_PS3::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
SetVersion(pParseFFVersion(&fastFileStream));
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD7_PS3* zoneFile = new ZoneFile_COD7_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
// Select key based on game.
QByteArray key = "46D3F997F29C9ACE175B0DAE3AB8C0C1B8E423E2E3BF7E3C311EA35245BF193A";
fastFileStream.skipRawData(4);
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Build the IV table from the fileName.
QByteArray ivTable = Encryption::InitIVTable(fileName);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
// Now the stream should be positioned at 0x13C, where sections begin.
int sectionIndex = 0;
while (true) {
qint32 sectionSize = 0;
fastFileStream >> sectionSize;
qDebug() << "Section index:" << sectionIndex << "Size:" << sectionSize
<< "Pos:" << fastFileStream.device()->pos();
if (sectionSize == 0)
break;
// Read the section data.
QByteArray sectionData;
sectionData.resize(sectionSize);
fastFileStream.readRawData(sectionData.data(), sectionSize);
// Compute the IV for this section.
QByteArray iv = Encryption::GetIV(ivTable, sectionIndex);
// Decrypt the section using Salsa20.
QByteArray decData = Encryption::salsa20DecryptSection(sectionData, key, iv);
// Compute SHA1 hash of the decrypted data.
QByteArray sectionHash = QCryptographicHash::hash(decData, QCryptographicHash::Sha1);
// Update the IV table based on the section hash.
Encryption::UpdateIVTable(ivTable, sectionIndex, sectionHash);
// Build a compressed data buffer by prepending the two-byte zlib header.
QByteArray compressedData;
compressedData.append(char(0x78));
compressedData.append(char(0x01));
compressedData.append(decData);
decompressedData.append(Compression::DecompressZLIB(compressedData));
sectionIndex++;
}
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD7_PS3_H
#define FASTFILE_COD7_PS3_H
#include "fastfile.h"
class FastFile_COD7_PS3 : public FastFile
{
public:
FastFile_COD7_PS3();
FastFile_COD7_PS3(const QByteArray &aData);
FastFile_COD7_PS3(const QString aFilePath);
~FastFile_COD7_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD7_PS3_H

View File

@ -1,127 +0,0 @@
#include "fastfile_cod8_ps3.h"
#include "zonefile_cod8_ps3.h"
#include "utils.h"
#include "compression.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD8_PS3::FastFile_COD8_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD8_PS3::FastFile_COD8_PS3(const QByteArray& aData)
: FastFile_COD8_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD8_PS3::FastFile_COD8_PS3(const QString aFilePath)
: FastFile_COD8_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD8_PS3::~FastFile_COD8_PS3() {
}
QByteArray FastFile_COD8_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD8_PS3::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD8_PS3::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
ZoneFile_COD8_PS3* zoneFile = new ZoneFile_COD8_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Select key based on game.
QByteArray key;
fastFileStream.skipRawData(4);
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d");
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PS3) {
key = QByteArray::fromHex("46D3F997F29C9ACE175B0DAE3AB8C0C1B8E423E2E3BF7E3C311EA35245BF193A");
// or
// key = QByteArray::fromHex("0C99B3DDB8D6D0845D1147E470F28A8BF2AE69A8A9F534767B54E9180FF55370");
}
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD8_PS3_H
#define FASTFILE_COD8_PS3_H
#include "fastfile.h"
class FastFile_COD8_PS3 : public FastFile
{
public:
FastFile_COD8_PS3();
FastFile_COD8_PS3(const QByteArray &aData);
FastFile_COD8_PS3(const QString aFilePath);
~FastFile_COD8_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD8_PS3_H

View File

@ -1,137 +0,0 @@
#include "fastfile_cod9_ps3.h"
#include "zonefile_cod9_ps3.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD9_PS3::FastFile_COD9_PS3()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD9_PS3::FastFile_COD9_PS3(const QByteArray& aData)
: FastFile_COD9_PS3() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD9_PS3::FastFile_COD9_PS3(const QString aFilePath)
: FastFile_COD9_PS3() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD9_PS3::~FastFile_COD9_PS3() {
}
QByteArray FastFile_COD9_PS3::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD9_PS3::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD9_PS3::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
}
// Select key based on game.
QByteArray key;
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
}
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
//decompressedData = Compressor::cod9_decryptFastFile(aData);
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
//decompressedData = Encryption::decryptFastFile_BO2(aData);
}
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD9_PS3* zoneFile = new ZoneFile_COD9_PS3();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD9_PS3_H
#define FASTFILE_COD9_PS3_H
#include "fastfile.h"
class FastFile_COD9_PS3 : public FastFile
{
public:
FastFile_COD9_PS3();
FastFile_COD9_PS3(const QByteArray &aData);
FastFile_COD9_PS3(const QString aFilePath);
~FastFile_COD9_PS3();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD9_PS3_H

View File

@ -1,84 +0,0 @@
#include "fastfile_cod4_wii.h"
#include "zonefile_cod4_wii.h"
#include "utils.h"
#include "compression.h"
#include <QFile>
#include <QDebug>
FastFile_COD4_Wii::FastFile_COD4_Wii()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD4_Wii::FastFile_COD4_Wii(const QByteArray& aData)
: FastFile_COD4_Wii() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD4_Wii::FastFile_COD4_Wii(const QString aFilePath)
: FastFile_COD4_Wii() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD4_Wii::~FastFile_COD4_Wii() {
}
QByteArray FastFile_COD4_Wii::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD4_Wii::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD4_Wii::Load(const QByteArray aData) {
// For COD7, simply decompress from offset 12.
QByteArray decompressedData = Compression::DecompressZLIB(aData.mid(12));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD4_Wii* zoneFile = new ZoneFile_COD4_Wii();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD4_WII_H
#define FASTFILE_COD4_WII_H
#include "fastfile.h"
class FastFile_COD4_Wii : public FastFile
{
public:
FastFile_COD4_Wii();
FastFile_COD4_Wii(const QByteArray &aData);
FastFile_COD4_Wii(const QString aFilePath);
~FastFile_COD4_Wii();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD4_WII_H

View File

@ -1,110 +0,0 @@
#include "fastfile_cod7_wii.h"
#include "zonefile_cod7_wii.h"
#include "utils.h"
#include "compression.h"
#include <QFile>
#include <QDebug>
FastFile_COD7_Wii::FastFile_COD7_Wii()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD7_Wii::FastFile_COD7_Wii(const QByteArray& aData)
: FastFile_COD7_Wii() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD7_Wii::FastFile_COD7_Wii(const QString aFilePath)
: FastFile_COD7_Wii() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD7_Wii::~FastFile_COD7_Wii() {
}
QByteArray FastFile_COD7_Wii::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD7_Wii::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD7_Wii::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
// For COD7, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(12));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
QDir workingDir = QDir::currentPath();
workingDir.mkdir("exports");
QFile outputFile("exports/" + GetBaseStem() + ".zone");
if (!outputFile.open(QIODevice::WriteOnly)) {
qDebug() << "Failed to extract IPAK file.";
}
outputFile.write(decompressedData);
outputFile.close();
ZoneFile_COD7_Wii* zoneFile = new ZoneFile_COD7_Wii();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD7_WII_H
#define FASTFILE_COD7_WII_H
#include "fastfile.h"
class FastFile_COD7_Wii : public FastFile
{
public:
FastFile_COD7_Wii();
FastFile_COD7_Wii(const QByteArray &aData);
FastFile_COD7_Wii(const QString aFilePath);
~FastFile_COD7_Wii();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD7_WII_H

View File

@ -1,99 +0,0 @@
#include "fastfile_cod8_wii.h"
#include "zonefile_cod8_wii.h"
#include "utils.h"
#include "compression.h"
#include <QFile>
#include <QDebug>
FastFile_COD8_Wii::FastFile_COD8_Wii()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD8_Wii::FastFile_COD8_Wii(const QByteArray& aData)
: FastFile_COD8_Wii() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD8_Wii::FastFile_COD8_Wii(const QString aFilePath)
: FastFile_COD8_Wii() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD8_Wii::~FastFile_COD8_Wii() {
}
QByteArray FastFile_COD8_Wii::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD8_Wii::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem;
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD8_Wii::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
SetVersion(pParseFFVersion(&fastFileStream));
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
// For COD7, simply decompress from offset 12.
decompressedData = Compression::DecompressZLIB(aData.mid(25));
Utils::ExportData(GetBaseStem() + ".zone", decompressedData);
ZoneFile_COD8_Wii* zoneFile = new ZoneFile_COD8_Wii();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD8_WII_H
#define FASTFILE_COD8_WII_H
#include "fastfile.h"
class FastFile_COD8_Wii : public FastFile
{
public:
FastFile_COD8_Wii();
FastFile_COD8_Wii(const QByteArray &aData);
FastFile_COD8_Wii(const QString aFilePath);
~FastFile_COD8_Wii();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD8_WII_H

View File

@ -1,135 +0,0 @@
#include "fastfile_cod10_wiiu.h"
#include "zonefile_cod10_wiiu.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD10_WiiU::FastFile_COD10_WiiU()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD10_WiiU::FastFile_COD10_WiiU(const QByteArray& aData)
: FastFile_COD10_WiiU() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD10_WiiU::FastFile_COD10_WiiU(const QString aFilePath)
: FastFile_COD10_WiiU() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD10_WiiU::~FastFile_COD10_WiiU() {
}
QByteArray FastFile_COD10_WiiU::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD10_WiiU::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD10_WiiU::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
}
// Select key based on game.
QByteArray key;
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
}
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
//decompressedData = Compressor::cod9_decryptFastFile(aData);
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
//decompressedData = Encryption::decryptFastFile_BO2(aData);
}
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD10_WiiU *zoneFile = new ZoneFile_COD10_WiiU();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD10_WIIU_H
#define FASTFILE_COD10_WIIU_H
#include "fastfile.h"
class FastFile_COD10_WiiU : public FastFile
{
public:
FastFile_COD10_WiiU();
FastFile_COD10_WiiU(const QByteArray &aData);
FastFile_COD10_WiiU(const QString aFilePath);
~FastFile_COD10_WiiU();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD10_WIIU_H

View File

@ -1,135 +0,0 @@
#include "fastfile_cod9_wiiu.h"
#include "zonefile_cod9_wiiu.h"
#include "encryption.h"
#include <QFile>
#include <QDebug>
FastFile_COD9_WiiU::FastFile_COD9_WiiU()
: FastFile() {
SetCompany(COMPANY_INFINITY_WARD);
SetType(FILETYPE_FAST_FILE);
SetSignage(SIGNAGE_UNSIGNED);
SetMagic(0);
SetVersion(0);
}
FastFile_COD9_WiiU::FastFile_COD9_WiiU(const QByteArray& aData)
: FastFile_COD9_WiiU() {
if (!aData.isEmpty()) {
Load(aData);
}
}
FastFile_COD9_WiiU::FastFile_COD9_WiiU(const QString aFilePath)
: FastFile_COD9_WiiU() {
if (!aFilePath.isEmpty()) {
Load(aFilePath);
}
}
FastFile_COD9_WiiU::~FastFile_COD9_WiiU() {
}
QByteArray FastFile_COD9_WiiU::GetBinaryData() const {
return QByteArray();
}
bool FastFile_COD9_WiiU::Load(const QString aFilePath) {
if (aFilePath.isEmpty()) {
return false;
}
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath);
return false;
}
// Decompress fastfile and close
const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0);
SetStem(fastFileStem);
if (!Load(file->readAll())) {
qDebug() << "Error: Failed to load fastfile: " << fastFileStem + ".ff";
return false;
}
file->close();
// Open zone file after decompressing ff and writing
return true;
}
bool FastFile_COD9_WiiU::Load(const QByteArray aData) {
QByteArray decompressedData;
// Create a XDataStream on the input data.
XDataStream fastFileStream(aData);
fastFileStream.setByteOrder(XDataStream::LittleEndian);
// Parse header values.
SetCompany(pParseFFCompany(&fastFileStream));
SetType(pParseFFFileType(&fastFileStream));
SetSignage(pParseFFSignage(&fastFileStream));
SetMagic(pParseFFMagic(&fastFileStream));
quint32 version = pParseFFVersion(&fastFileStream);
SetVersion(version);
// For COD7/COD9, use BigEndian.
fastFileStream.setByteOrder(XDataStream::BigEndian);
if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
fastFileStream.setByteOrder(XDataStream::LittleEndian);
}
// Select key based on game.
QByteArray key;
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3");
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE");
}
// Read the 8-byte magic.
QByteArray fileMagic(8, Qt::Uninitialized);
fastFileStream.readRawData(fileMagic.data(), 8);
if (fileMagic != "PHEEBs71") {
qWarning() << "Invalid fast file magic!";
return false;
}
fastFileStream.skipRawData(4);
// Read IV table name (32 bytes).
QByteArray fileName(32, Qt::Uninitialized);
fastFileStream.readRawData(fileName.data(), 32);
// Skip the RSA signature (256 bytes).
QByteArray rsaSignature(256, Qt::Uninitialized);
fastFileStream.readRawData(rsaSignature.data(), 256);
if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) {
//decompressedData = Compressor::cod9_decryptFastFile(aData);
} else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) {
//decompressedData = Encryption::decryptFastFile_BO2(aData);
}
// For COD9, write out the complete decompressed zone for testing.
QFile testFile("exports/" + GetBaseStem() + ".zone");
if(testFile.open(QIODevice::WriteOnly)) {
testFile.write(decompressedData);
testFile.close();
}
// Load the zone file with the decompressed data (using an Xbox platform flag).
ZoneFile_COD9_WiiU* zoneFile = new ZoneFile_COD9_WiiU();
zoneFile->SetStem(GetBaseStem() + ".zone");
zoneFile->SetCommonInfo(&mCommonInfo);
if (!zoneFile->Load(decompressedData)) {
qWarning() << "Failed to load ZoneFile!";
return false;
}
SetZoneFile(zoneFile);
return true;
}

View File

@ -1,20 +0,0 @@
#ifndef FASTFILE_COD9_WIIU_H
#define FASTFILE_COD9_WIIU_H
#include "fastfile.h"
class FastFile_COD9_WiiU : public FastFile
{
public:
FastFile_COD9_WiiU();
FastFile_COD9_WiiU(const QByteArray &aData);
FastFile_COD9_WiiU(const QString aFilePath);
~FastFile_COD9_WiiU();
QByteArray GetBinaryData() const override;
bool Load(const QString aFilePath) override;
bool Load(const QByteArray aData) override;
};
#endif // FASTFILE_COD9_WIIU_H

View File

@ -1,292 +0,0 @@
#include "fastfile.h"
#include "fastfile_factory.h"
#include "logmanager.h"
#include <QFile>
#include <QDebug>
FastFile::FastFile()
: mCommonInfo(),
mStem(""),
mType(FILETYPE_NONE),
mCompany(COMPANY_NONE),
mSignage(SIGNAGE_NONE),
mMagic(""),
mVersion(0),
mZoneFile(nullptr)
{
}
FastFile::FastFile(const QByteArray &aData) {
Q_UNUSED(aData);
}
FastFile::FastFile(FastFile &fastFile)
: mCommonInfo(fastFile.GetCommonInfo()),
mStem(fastFile.GetStem()),
mType(fastFile.GetType()),
mCompany(fastFile.GetCompany()),
mSignage(fastFile.GetSignage()),
mMagic(fastFile.GetMagic()),
mVersion(fastFile.GetVersion()),
mZoneFile(fastFile.GetZoneFile())
{
}
FastFile::~FastFile() {
}
QString FastFile::GetStem() const {
return mStem;
}
QString FastFile::GetBaseStem() const {
return mStem.split('.').first();
}
FF_FILETYPE FastFile::GetType() const {
return mType;
}
FF_COMPANY FastFile::GetCompany() const {
return mCompany;
}
FF_SIGNAGE FastFile::GetSignage() const {
return mSignage;
}
QString FastFile::GetMagic() const {
return mMagic;
}
quint32 FastFile::GetVersion() const {
return mVersion;
}
const ZoneFile* FastFile::GetZoneFile() const {
return mZoneFile;
}
void FastFile::SetStem(const QString aStem) {
mStem = aStem;
}
void FastFile::SetType(const FF_FILETYPE aType) {
mType = aType;
}
void FastFile::SetCompany(const FF_COMPANY aCompany) {
mCompany = aCompany;
}
void FastFile::SetSignage(const FF_SIGNAGE aSignage) {
mSignage = aSignage;
}
void FastFile::SetMagic(const QString aMagic) {
mMagic = aMagic;
}
void FastFile::SetVersion(const quint32 aVersion) {
mVersion = aVersion;
}
void FastFile::SetZoneFile(const ZoneFile* aZoneFile) {
mZoneFile = aZoneFile;
}
FF_COMPANY FastFile::pParseFFCompany(XDataStream *afastFileStream, quint32 &aCompanyInt) {
LogManager::instance().addEntry("Parsing company into reference...");
// Check for null datastream ptr
if (!afastFileStream) { return COMPANY_NONE; }
// Parse company
QByteArray companyData(2, Qt::Uninitialized);
afastFileStream->readRawData(companyData.data(), 2);
aCompanyInt = companyData.toUInt();
if (companyData == "IW") {
return COMPANY_INFINITY_WARD;
} else if (companyData == "TA") {
return COMPANY_TREYARCH;
} else if (companyData == "Sl") {
return COMPANY_SLEDGEHAMMER;
} else if (companyData == "NX") {
return COMPANY_NEVERSOFT;
}
LogManager::instance().addEntry(QString("Failed to find company, found '%1'!").arg(companyData));
return COMPANY_NONE;
}
FF_COMPANY FastFile::pParseFFCompany(XDataStream *afastFileStream) {
LogManager::instance().addEntry("Parsing company...");
// Check for null datastream ptr
if (!afastFileStream) { return COMPANY_NONE; }
// Parse company
QByteArray companyData(2, Qt::Uninitialized);
afastFileStream->readRawData(companyData.data(), 2);
if (companyData == "IW") {
return COMPANY_INFINITY_WARD;
} else if (companyData == "TA") {
return COMPANY_TREYARCH;
} else if (companyData == "Sl") {
} else if (companyData == "NX") {
return COMPANY_NEVERSOFT;
}
LogManager::instance().addEntry(QString("Failed to find company, found '%1'!").arg(companyData));
return COMPANY_NONE;
}
FF_FILETYPE FastFile::pParseFFFileType(XDataStream *afastFileStream) {
// Parse filetype
QByteArray fileTypeData(2, Qt::Uninitialized);
afastFileStream->readRawData(fileTypeData.data(), 2);
if (fileTypeData == "ff") {
return FILETYPE_FAST_FILE;
}
LogManager::instance().addEntry("Failed to find file type!");
return FILETYPE_NONE;
}
FF_SIGNAGE FastFile::pParseFFSignage(XDataStream *afastFileStream) {
// Parse filetype
QByteArray signedData(1, Qt::Uninitialized);
afastFileStream->readRawData(signedData.data(), 1);
if (signedData == "u") {
return SIGNAGE_UNSIGNED;
} else if (signedData == "0" || signedData == "x") {
return SIGNAGE_SIGNED;
}
LogManager::instance().addEntry("Failed to determine signage of fastfile!");
return SIGNAGE_NONE;
}
QString FastFile::pParseFFMagic(XDataStream *afastFileStream) {
// Parse magic
QByteArray magicData(3, Qt::Uninitialized);
afastFileStream->readRawData(magicData.data(), 3);
if (magicData == "100") {
return magicData;
}
LogManager::instance().addEntry("Magic invalid!");
return "";
}
quint32 FastFile::pParseFFVersion(XDataStream *afastFileStream) {
// Parse version
quint32 version;
*afastFileStream >> version;
qDebug() << QString("Found version: '%1'").arg(version);
return version;
}
QString FastFile::pCalculateFFPlatform(quint32 aVersion) {
switch (aVersion) {
case 387: // PC World at War
case 473: // PC Black Ops 1
case 1: // PC Modern Warfare 3
case 147: // PC Black Ops 2
return "PC";
case 3640721408: // Xbox 360 Black Ops 1
case 2449473536: // Xbox 360 Black Ops 2
return "360";
case 3707830272: // Wii Black Ops 1
return "Wii";
}
return "NONE";
}
QString FastFile::pCalculateFFGame(quint32 aVersion) {
QString result = "NONE";
switch (aVersion) {
case 387: // PC World at War
result = "COD5";
break;
case 473: // PC Black Ops 1
break;
case 3640721408: // Xbox 360 Black Ops 1
case 3707830272: // Wii Black Ops 1
result = "COD7";
break;
case 1: // PC Modern Warfare 3
result = "COD8";
break;
case 147: // PC Black Ops 2
case 2449473536: // Xbox 360 Black Ops 2
result = "COD9";
break;
}
qDebug() << QString("Found game: '%1'").arg(result);
return result;
}
FastFile* FastFile::Open(const QString &aFilePath) {
LogManager::instance().addEntry("Processing Fastfile...");
if (aFilePath.isEmpty()) {
LogManager::instance().addError("Attempted to open file w/no name!");
return nullptr;
}
LogManager::instance().addEntry("File Path: " + aFilePath);
// Check fastfile can be read
QFile *file = new QFile(aFilePath);
if (!file->open(QIODevice::ReadOnly)) {
LogManager::instance().addError(QString("File failed to open: %1").arg(file->errorString()));
return nullptr;
}
LogManager::instance().addEntry("File opened");
const QByteArray data = file->readAll();
LogManager::instance().addEntry("Contents read in");
LogManager::instance().addEntry(QString("- Size: %1 B").arg(data.size()));
file->close();
LogManager::instance().addEntry("File closed");
const QString fastFileStem = aFilePath.section("/", -1, -1);
LogManager::instance().addEntry(QString("Stem: %1").arg(fastFileStem));
FastFile* fastFile = FastFileFactory::Create(data, fastFileStem);
fastFile->SetStem(fastFileStem);
return fastFile;
}
XCommonInfo FastFile::GetCommonInfo() const
{
return mCommonInfo;
}
void FastFile::SetCommonInfo(const XCommonInfo &newCommonInfo)
{
mCommonInfo = newCommonInfo;
}
bool FastFile::Debug() const
{
return mDebug;
}
void FastFile::SetDebug(bool aDebug)
{
mDebug = aDebug;
}
bool FastFile::ExportFastFile(const QString aFastFilePath) const {
QFile fastFile(aFastFilePath);
if (!fastFile.open(QIODevice::WriteOnly)) {
LogManager::instance().addEntry("Failed to write fast file! " +
fastFile.errorString());
return false;
}
fastFile.write(GetBinaryData());
fastFile.close();
return true;
}

View File

@ -1,78 +0,0 @@
#ifndef FASTFILE_H
#define FASTFILE_H
#include "enums.h"
#include "zonefile.h"
#include "xcommoninfo.h"
#include "utils.h"
#include <QString>
#include <QCryptographicHash>
class ZoneFile;
class FastFile
{
public:
FastFile();
FastFile(const QByteArray& aData);
FastFile(FastFile &fastFile);
~FastFile();
virtual bool Load(const QString aFilePath) = 0;
virtual bool Load(const QByteArray aData) = 0;
virtual bool ExportFastFile(const QString aFastFilePath) const;
virtual QByteArray GetBinaryData() const = 0;
virtual QString GetStem() const;
virtual QString GetBaseStem() const;
virtual FF_FILETYPE GetType() const;
virtual FF_COMPANY GetCompany() const;
virtual FF_SIGNAGE GetSignage() const;
virtual QString GetMagic() const;
virtual quint32 GetVersion() const;
virtual const ZoneFile *GetZoneFile() const;
virtual void SetStem(const QString aStem);
virtual void SetType(const FF_FILETYPE aType);
virtual void SetCompany(const FF_COMPANY aCompany);
virtual void SetSignage(const FF_SIGNAGE aSignage);
virtual void SetMagic(const QString aMagic);
virtual void SetVersion(const quint32 aVersion);
virtual void SetZoneFile(const ZoneFile* aZoneFile);
static FF_COMPANY pParseFFCompany(XDataStream *afastFileStream, quint32 &aCompanyInt);
static FF_COMPANY pParseFFCompany(XDataStream *afastFileStream);
static FF_FILETYPE pParseFFFileType(XDataStream *afastFileStream);
static FF_SIGNAGE pParseFFSignage(XDataStream *afastFileStream);
static QString pParseFFMagic(XDataStream *afastFileStream);
static quint32 pParseFFVersion(XDataStream *afastFileStream);
static QString pCalculateFFPlatform(quint32 aVersion);
static QString pCalculateFFGame(quint32 aVersion);
static FastFile* Open(const QString& aFilePath);
XCommonInfo GetCommonInfo() const;
void SetCommonInfo(const XCommonInfo &newCommonInfo);
bool Debug() const;
void SetDebug(bool aDebug);
protected:
XCommonInfo mCommonInfo;
private:
QString mStem;
FF_FILETYPE mType;
FF_COMPANY mCompany;
FF_SIGNAGE mSignage;
QString mMagic;
quint32 mVersion;
const ZoneFile* mZoneFile;
bool mDebug;
};
#endif // FASTFILE_H

View File

@ -1,41 +0,0 @@
QT += core widgets
TEMPLATE = lib
CONFIG += staticlib c++17
SOURCES += $$files($$PWD/*.cpp, true)
HEADERS += $$files($$PWD/*.h, true)
LIBS += \
-L$$OUT_PWD/../libs/core -lcore \
-L$$OUT_PWD/../libs/core -lxassets \
-L$$OUT_PWD/../libs/compression -lcompression \
-L$$OUT_PWD/../libs/encryption -lencryption \
-L$$OUT_PWD/../libs/zonefile -lzonefile
INCLUDEPATH += \
$$PWD/../core \
$$PWD/../compression \
$$PWD/../encryption \
$$PWD/../xassets \
$$PWD/../zonefile \
$$PWD/../zonefile/360 \
$$PWD/../zonefile/PC \
$$PWD/../zonefile/PS3 \
$$PWD/../zonefile/Wii \
$$PWD/../zonefile/PS3 \
$$PWD/../zonefile/WiiU
DEPENDPATH += \
$$PWD/../core \
$$PWD/../compression \
$$PWD/../encryption \
$$PWD/../xassets \
$$PWD/../zonefile \
$$PWD/../zonefile/360 \
$$PWD/../zonefile/PC \
$$PWD/../zonefile/PS3 \
$$PWD/../zonefile/Wii \
$$PWD/../zonefile/PS3 \
$$PWD/../zonefile/WiiU
DESTDIR = $$OUT_PWD/../

View File

@ -1,354 +0,0 @@
#ifndef FASTFILE_FACTORY_H
#define FASTFILE_FACTORY_H
#include "360/fastfile_cod2_360.h"
//#include "360/fastfile_cod3_360.h"
#include "360/fastfile_cod4_360.h"
#include "360/fastfile_cod5_360.h"
#include "360/fastfile_cod6_360.h"
#include "360/fastfile_cod7_360.h"
#include "360/fastfile_cod7_5_360.h"
#include "360/fastfile_cod8_360.h"
#include "360/fastfile_cod9_360.h"
#include "360/fastfile_cod10_360.h"
#include "360/fastfile_cod11_360.h"
#include "360/fastfile_cod12_360.h"
//#include "PS3/fastfile_cod3_ps3.h"
#include "PC/fastfile_cod21_pc.h"
#include "PS3/fastfile_cod4_ps3.h"
#include "PS3/fastfile_cod5_ps3.h"
#include "PS3/fastfile_cod6_ps3.h"
#include "PS3/fastfile_cod7_ps3.h"
#include "PS3/fastfile_cod8_ps3.h"
#include "PS3/fastfile_cod9_ps3.h"
#include "PS3/fastfile_cod10_ps3.h"
#include "PS3/fastfile_cod11_ps3.h"
#include "PS3/fastfile_cod12_ps3.h"
//#include "PC/fastfile_cod3_pc.h"
#include "PC/fastfile_cod4_pc.h"
#include "PC/fastfile_cod5_pc.h"
#include "PC/fastfile_cod6_pc.h"
#include "PC/fastfile_cod7_pc.h"
#include "PC/fastfile_cod8_pc.h"
#include "PC/fastfile_cod9_pc.h"
#include "PC/fastfile_cod10_pc.h"
#include "PC/fastfile_cod11_pc.h"
#include "PC/fastfile_cod12_pc.h"
#include "Wii/fastfile_cod4_wii.h"
#include "Wii/fastfile_cod7_wii.h"
#include "Wii/fastfile_cod8_wii.h"
#include "WiiU/fastfile_cod9_wiiu.h"
#include "WiiU/fastfile_cod10_wiiu.h"
#include <QByteArray>
#include <QString>
#include <QFile>
#include <QDebug>
class FastFile;
class FastFileFactory {
public:
static FastFile* Create(const QString& aFilePath, XPlatform aPlatform = PLATFORM_NONE, XGame aGame = GAME_NONE) {
QFile fastFile(aFilePath);
if (!fastFile.open(QIODevice::ReadOnly)) {
qDebug() << "Factory failed to open fast file: " << aFilePath;
return nullptr;
}
const QString stem = aFilePath.split('/').last().split('.').first();
const QByteArray data = fastFile.readAll();
FastFile* resultFF = nullptr;
if (aPlatform == PLATFORM_NONE) {
aPlatform = pGetPlatform(data);
}
if (aGame == GAME_NONE) {
aGame = pGetGame(data);
}
if (aPlatform == PLATFORM_XBOX) {
if (aGame == GAME_COD2) {
resultFF = new FastFile_COD2_360(aFilePath);
} else if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_360(aFilePath);
} else if (aGame == GAME_COD5) {
resultFF = new FastFile_COD5_360(aFilePath);
} else if (aGame == GAME_COD6) {
resultFF = new FastFile_COD6_360(aFilePath);
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_360(aFilePath);
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_360(aFilePath);
} else if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_360(aFilePath);
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_360(aFilePath);
} else if (aGame == GAME_COD11) {
resultFF = new FastFile_COD11_360(aFilePath);
} else if (aGame == GAME_COD12) {
resultFF = new FastFile_COD12_360(aFilePath);
}
} else if (aPlatform == PLATFORM_PC) {
if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_PC(aFilePath);
} else if (aGame == GAME_COD5) {
resultFF = new FastFile_COD5_PC(aFilePath);
} else if (aGame == GAME_COD6) {
resultFF = new FastFile_COD6_PC(aFilePath);
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_PC(aFilePath);
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_PC(aFilePath);
} else if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_PC(aFilePath);
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_PC(aFilePath);
} else if (aGame == GAME_COD11) {
resultFF = new FastFile_COD11_PC(aFilePath);
} else if (aGame == GAME_COD12) {
resultFF = new FastFile_COD12_PC(aFilePath);
}
} else if (aPlatform == PLATFORM_PS3) {
if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_PS3(aFilePath);
} else if (aGame == GAME_COD5) {
resultFF = new FastFile_COD5_PS3(aFilePath);
} else if (aGame == GAME_COD6) {
resultFF = new FastFile_COD6_PS3(aFilePath);
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_PS3(aFilePath);
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_PS3(aFilePath);
} else if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_PS3(aFilePath);
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_PS3(aFilePath);
} else if (aGame == GAME_COD11) {
resultFF = new FastFile_COD11_PS3(aFilePath);
} else if (aGame == GAME_COD12) {
resultFF = new FastFile_COD12_PS3(aFilePath);
}
} else if (aPlatform == PLATFORM_WII) {
if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_Wii(aFilePath);
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_Wii(aFilePath);
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_Wii(aFilePath);
}
} else if (aPlatform == PLATFORM_WIIU) {
if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_WiiU(aFilePath);
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_WiiU(aFilePath);
}
}
if (resultFF)
{
resultFF->SetCommonInfo(XCommonInfo(aGame, aPlatform));
}
return resultFF;
}
static FastFile* Create(const QByteArray& aData, const QString aStem = "no_name", XPlatform aPlatform = PLATFORM_NONE, XGame aGame = GAME_NONE) {
FastFile* resultFF = nullptr;
if (aPlatform == PLATFORM_NONE) {
aPlatform = pGetPlatform(aData);
}
if (aGame == GAME_NONE) {
aGame = pGetGame(aData);
}
if (aPlatform == PLATFORM_XBOX) {
if (aGame == GAME_COD2) {
resultFF = new FastFile_COD2_360();
} else if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_360();
} else if (aGame == GAME_COD5) {
resultFF = new FastFile_COD5_360();
} else if (aGame == GAME_COD6) {
resultFF = new FastFile_COD6_360();
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_360();
} else if (aGame == GAME_COD7_5) {
resultFF = new FastFile_COD7_5_360();
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_360();
} else if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_360();
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_360();
} else if (aGame == GAME_COD11) {
resultFF = new FastFile_COD11_360();
} else if (aGame == GAME_COD12) {
resultFF = new FastFile_COD12_360();
}
} else if (aPlatform == PLATFORM_PC) {
if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_PC();
} else if (aGame == GAME_COD5) {
resultFF = new FastFile_COD5_PC();
} else if (aGame == GAME_COD6) {
resultFF = new FastFile_COD6_PC();
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_PC();
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_PC();
} else if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_PC();
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_PC();
} else if (aGame == GAME_COD11) {
resultFF = new FastFile_COD11_PC();
} else if (aGame == GAME_COD12) {
resultFF = new FastFile_COD12_PC();
} else if (aGame == GAME_COD21) {
resultFF = new FastFile_COD21_PC();
}
} else if (aPlatform == PLATFORM_PS3) {
if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_PS3();
} else if (aGame == GAME_COD5) {
resultFF = new FastFile_COD5_PS3();
} else if (aGame == GAME_COD6) {
resultFF = new FastFile_COD6_PS3();
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_PS3();
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_PS3();
} else if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_PS3();
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_PS3();
} else if (aGame == GAME_COD11) {
resultFF = new FastFile_COD11_PS3();
} else if (aGame == GAME_COD12) {
resultFF = new FastFile_COD12_PS3();
}
} else if (aPlatform == PLATFORM_WII) {
if (aGame == GAME_COD4) {
resultFF = new FastFile_COD4_Wii();
} else if (aGame == GAME_COD7) {
resultFF = new FastFile_COD7_Wii();
} else if (aGame == GAME_COD8) {
resultFF = new FastFile_COD8_Wii();
}
} else if (aPlatform == PLATFORM_WIIU) {
if (aGame == GAME_COD9) {
resultFF = new FastFile_COD9_WiiU();
} else if (aGame == GAME_COD10) {
resultFF = new FastFile_COD10_WiiU();
}
}
if (resultFF) {
resultFF->SetStem(aStem);
resultFF->SetCommonInfo(XCommonInfo(aGame, aPlatform));
resultFF->Load(aData);
}
return resultFF;
}
private:
static QStringList pGetDataSections(const QByteArray& aData) {
QStringList sections;
sections << aData.mid(0, 2).toHex().toUpper();
sections << aData.mid(2, 2).toHex().toUpper();
sections << aData.mid(4, 2).toHex().toUpper();
sections << aData.mid(6, 2).toHex().toUpper();
sections << aData.mid(8, 2).toHex().toUpper();
sections << aData.mid(10, 2).toHex().toUpper();
sections << aData.mid(12, 2).toHex().toUpper();
sections << aData.mid(14, 2).toHex().toUpper();
return sections;
}
static XPlatform pGetPlatform(const QByteArray& aData) {
const QStringList sections = pGetDataSections(aData);
if (pGetGame(aData) == GAME_COD21)
{
return PLATFORM_PC;
}
else if (sections[0] == "0000" || sections[0] == "4E58") {
return PLATFORM_XBOX;
}
else if (sections[4] == "0000") {
if (sections[5] == "0001" && sections[6] == "78DA") {
return PLATFORM_XBOX;
} else if (sections[5] == "0001" && sections[6] == "4957") {
return PLATFORM_XBOX;
} else if (sections[5] == "0183" && sections[6] == "7801") {
return PLATFORM_XBOX;
} else if (sections[5] == "01D9" && sections[6] == "0000") {
return PLATFORM_XBOX;
} else if (sections[6] == "0101" && sections[7] == "CA3E") {
return PLATFORM_XBOX;
} else if (sections[6] == "0000" && sections[7] == "0001") {
return PLATFORM_XBOX;
} else if (sections[6] == "0101" && sections[7] == "CC76") {
return PLATFORM_XBOX;
} else if (sections[6] == "0101" && sections[7] == "0101") {
return PLATFORM_XBOX;
} else if (sections[2] == "7831") {
return PLATFORM_XBOX;
} else if (sections[0] == "5331" && sections[2] == "7531") {
return PLATFORM_XBOX;
} else if (sections[2] == "3030" && sections[3] == "3030") {
return PLATFORM_XBOX;
} else if (sections[5] == "01A2" && sections[6] == "7801") {
return PLATFORM_WII;
} else if (sections[5] == "01DD" && sections[6] == "7801") {
return PLATFORM_WII;
} else if (sections[5] == "006B") {
return PLATFORM_WII;
}
} else if (sections[5] == "0000") {
return PLATFORM_PC;
}else if (sections[5] == "0094" || sections[6] == "0100") {
return PLATFORM_WIIU;
}
return PLATFORM_PS3;
}
static XGame pGetGame(const QByteArray& aData) {
const QStringList sections = pGetDataSections(aData);
if (sections[0] == "0000") {
return GAME_COD2;
} else if (sections[4] == "0500" || sections[5] == "01A2" || sections[5] == "0001") {
return GAME_COD4;
} else if (sections[4] == "8301" || sections[5] == "0183") {
return GAME_COD5;
} else if (sections[4] == "1401" || sections[5] == "010D") {
return GAME_COD6;
} else if (sections[4] == "D901" || sections[5] == "01DD" || sections[5] == "01D9") {
return GAME_COD7;
} else if (sections[0] == "4E58") {
return GAME_COD7_5;
} else if (sections[4] == "0100" || sections[5] == "006B" || sections[5] == "0070") {
return GAME_COD8;
} else if (sections[4] == "9300" || sections[5] == "0092"
|| sections[5] == "0094") {
return GAME_COD9;
} else if (sections[4] == "3502" || sections[5] == "022E") {
return GAME_COD10;
} else if (sections[0] == "5331") {
return GAME_COD11;
} else if (sections[2] == "3030") {
return GAME_COD12;
} else if (sections[2] == "6131" || sections[2] == "6431") {
return GAME_COD21;
}
return GAME_NONE;
}
};
#endif // FASTFILE_FACTORY_H