Remove specific zonefile code
This commit is contained in:
parent
9d6fa35f50
commit
3b61ff5a05
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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;
|
||||
}
|
||||
@ -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
|
||||
@ -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/../
|
||||
@ -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
|
||||
Loading…
x
Reference in New Issue
Block a user