diff --git a/XPlor.pro b/XPlor.pro index 642f704..4cf1c89 100644 --- a/XPlor.pro +++ b/XPlor.pro @@ -4,3 +4,7 @@ SUBDIRS += libs \ app \ tools \ tests + +tests.depends = libs +app.depends = libs +tools.depends = libs diff --git a/XPlor.pro.user.40d992c b/XPlor.pro.user.40d992c deleted file mode 100644 index 861b133..0000000 --- a/XPlor.pro.user.40d992c +++ /dev/null @@ -1,625 +0,0 @@ - - - - - - EnvironmentId - {40d992cb-ac11-4385-a22b-016f1b4251a7} - - - ProjectExplorer.Project.ActiveTarget - 0 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 0 - 80 - true - true - 1 - 0 - false - true - false - 2 - true - true - 0 - 8 - true - false - 1 - true - true - true - *.md, *.MD, Makefile - false - true - true - - - - ProjectExplorer.Project.PluginSettings - - - true - false - true - true - true - true - - false - - Unchecked - - - 0 - true - - true - true - Builtin.DefaultTidyAndClazy - 16 - true - - - - true - - - true - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Desktop Qt 6.8.2 MSVC2022 64bit - Desktop Qt 6.8.2 MSVC2022 64bit - qt.qt6.682.win64_msvc2022_64_kit - 0 - 0 - 0 - - 0 - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_MSVC2022_64bit-Debug - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Debug - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Debug - Qt4ProjectManager.Qt4BuildConfiguration - 2 - - - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_MSVC2022_64bit-Release - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Release - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Release - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - - 0 - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_MSVC2022_64bit-Profile - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Profile - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Profile - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - 0 - - 3 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 - - Qt4ProjectManager.Qt4RunConfiguration: - G:/Projects/Qt/XPlor/app/app.pro - false - true - true - true - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Debug/app - - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 - - Qt4ProjectManager.Qt4RunConfiguration: - G:/Projects/Qt/XPlor/tests/tests.pro - false - true - true - true - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_MSVC2022_64bit-Debug/tests - - 2 - - - - ProjectExplorer.Project.Target.1 - - Desktop - Desktop Qt 6.8.2 llvm-mingw 64-bit - Desktop Qt 6.8.2 llvm-mingw 64-bit - qt.qt6.682.win64_llvm_mingw_kit - 0 - 0 - 1 - - 0 - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_llvm_mingw_64_bit-Debug - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_llvm_mingw_64_bit-Debug - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Debug - Qt4ProjectManager.Qt4BuildConfiguration - 2 - - - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_llvm_mingw_64_bit-Release - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_llvm_mingw_64_bit-Release - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Release - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - - 0 - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_2_llvm_mingw_64_bit-Profile - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_2_llvm_mingw_64_bit-Profile - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Profile - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - 0 - - 3 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 - - Qt4ProjectManager.Qt4RunConfiguration: - G:/Projects/Qt/XPlor/app/app.pro - false - true - true - true - - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 - - Qt4ProjectManager.Qt4RunConfiguration: - G:/Projects/Qt/XPlor/tests/tests.pro - false - true - true - true - - 2 - - - - ProjectExplorer.Project.Target.2 - - Desktop - Desktop Qt 6.8.1 MSVC2022 64bit - Desktop Qt 6.8.1 MSVC2022 64bit - qt.qt6.681.win64_msvc2022_64_kit - 0 - 0 - 0 - - 0 - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_1_MSVC2022_64bit-Debug - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Debug - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Debug - Qt4ProjectManager.Qt4BuildConfiguration - 2 - - - G:\Projects\Qt\XPlor\build\Desktop_Qt_6_8_1_MSVC2022_64bit-Release - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Release - - - true - QtProjectManager.QMakeBuildStep - false - - - - true - Qt4ProjectManager.MakeStep - - 2 - Build - Build - ProjectExplorer.BuildSteps.Build - - - - true - Qt4ProjectManager.MakeStep - clean - - 1 - Clean - Clean - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Release - Qt4ProjectManager.Qt4BuildConfiguration - 0 - 0 - - 2 - - - 0 - Deploy - Deploy - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 - - Qt4ProjectManager.Qt4RunConfiguration: - G:/Projects/Qt/XPlor/app/app.pro - false - true - true - true - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Debug/app - - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph "dwarf,4096" -F 250 - - Qt4ProjectManager.Qt4RunConfiguration: - G:/Projects/Qt/XPlor/tests/tests.pro - false - true - true - true - G:/Projects/Qt/XPlor/build/Desktop_Qt_6_8_1_MSVC2022_64bit-Debug/tests - - 2 - - - - ProjectExplorer.Project.TargetCount - 3 - - - ProjectExplorer.Project.Updater.FileVersion - 22 - - - Version - 22 - - diff --git a/app/app.pro b/app/app.pro index 011daaf..618e6e4 100644 --- a/app/app.pro +++ b/app/app.pro @@ -19,6 +19,8 @@ SOURCES += \ preferenceeditor.cpp \ soundviewer.cpp \ stringtableviewer.cpp \ + rumblegraphviewer.cpp \ + rumblefileviewer.cpp \ techsetviewer.cpp \ xtreewidget.cpp \ xtreewidgetitem.cpp \ @@ -37,6 +39,8 @@ HEADERS += \ preferenceeditor.h \ soundviewer.h \ stringtableviewer.h \ + rumblegraphviewer.h \ + rumblefileviewer.h \ techsetviewer.h \ xtreewidget.h \ xtreewidgetitem.h \ @@ -55,21 +59,13 @@ FORMS += \ preferenceeditor.ui \ soundviewer.ui \ stringtableviewer.ui \ + rumblegraphviewer.ui \ + rumblefileviewer.ui \ techsetviewer.ui \ zonefileviewer.ui RESOURCES += ../data/data.qrc -app.depends += \ - libs/core \ - libs/compression \ - libs/encryption \ - libs/fastfile \ - libs/ddsfile \ - libs/ipakfile \ - libs/iwifile \ - libs/zonefile - LIBS += \ -L$$PWD/../third_party/devil_sdk/lib/ -lDevIL -lILU -lILUT \ -L$$PWD/../third_party/zlib/lib/ -lzlib \ diff --git a/app/fastfileviewer.cpp b/app/fastfileviewer.cpp index 2fb29bb..62e7044 100644 --- a/app/fastfileviewer.cpp +++ b/app/fastfileviewer.cpp @@ -18,7 +18,7 @@ FastFileViewer::~FastFileViewer() void FastFileViewer::SetFastFile(std::shared_ptr aFastFile) { mFastFile.swap(aFastFile); - ui->label_Title->setText(mFastFile->GetStem() + ".ff"); + ui->label_Title->setText(mFastFile->GetStem()); ui->comboBox_Company->setCurrentIndex(mFastFile->GetCompany()); ui->comboBox_FileType->setCurrentIndex(mFastFile->GetType()); ui->checkBox_Signed->setChecked(mFastFile->GetSignage() == SIGNAGE_SIGNED); diff --git a/app/localstringviewer.cpp b/app/localstringviewer.cpp index 6550668..891b1e4 100644 --- a/app/localstringviewer.cpp +++ b/app/localstringviewer.cpp @@ -10,6 +10,7 @@ LocalStringViewer::LocalStringViewer(QWidget *parent) ui->setupUi(this); ui->tableWidget_Strings->setColumnCount(2); + ui->tableWidget_Strings->setRowCount(0); ui->tableWidget_Strings->setColumnWidth(0, 200); ui->tableWidget_Strings->horizontalHeader()->setStretchLastSection(true); } @@ -37,10 +38,12 @@ void LocalStringViewer::SetFileNotes(const QString aFileNotes) { } void LocalStringViewer::AddLocalString(LocalString aLocalString) { - mLocalStrings << aLocalString; + mLocalStrings.append(aLocalString); ui->tableWidget_Strings->setRowCount(mLocalStrings.size()); + ui->groupBox_LocalStrViewer->setTitle(QString("Entries (%1)").arg(mLocalStrings.size())); + QTableWidgetItem *aliasItem = new QTableWidgetItem(aLocalString.alias); QTableWidgetItem *stringItem = new QTableWidgetItem(aLocalString.string); @@ -53,7 +56,7 @@ void LocalStringViewer::SetZoneFile(std::shared_ptr aZoneFile) { ui->tableWidget_Strings->clear(); ui->label_Title->setText(aZoneFile->GetStem().section('.', 0, 0) + ".str"); - for (LocalString localStr : aZoneFile->GetAssetMap().localStrings) { + for (const LocalString &localStr : aZoneFile->GetAssetMap().localStrings) { AddLocalString(localStr); } } diff --git a/app/localstringviewer.ui b/app/localstringviewer.ui index bdd547e..f8ccfa8 100644 --- a/app/localstringviewer.ui +++ b/app/localstringviewer.ui @@ -142,7 +142,7 @@ - + 400 diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp index 475cb32..07605bc 100644 --- a/app/mainwindow.cpp +++ b/app/mainwindow.cpp @@ -1,13 +1,19 @@ #include "mainwindow.h" #include "aboutdialog.h" #include "fastfile.h" +#include "highlighter_gsc.h" +#include "highlighter_cfg.h" +#include "highlighter_shock.h" +#include "highlighter_rumble.h" #include "materialviewer.h" #include "preferenceeditor.h" +#include "rumblefileviewer.h" +#include "rumblegraphviewer.h" #include "soundviewer.h" #include "stringtableviewer.h" #include "techsetviewer.h" #include "ui_mainwindow.h" -#include "compression.h" +#include "fastfile_factory.h" #include "iwifile.h" #include "ddsfile.h" #include "statusbarmanager.h" @@ -143,9 +149,13 @@ MainWindow::MainWindow(QWidget *parent) }); connect(mTreeWidget, &XTreeWidget::RawFileSelected, this, [this](std::shared_ptr rawFile, const QString aParentName) { - QPlainTextEdit *scriptEditor = new QPlainTextEdit(this); + QTabWidget *rawTabWidget = new QTabWidget(this); + rawTabWidget->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); + + QPlainTextEdit *scriptEditor = new QPlainTextEdit(rawTabWidget); scriptEditor->setAcceptDrops(false); scriptEditor->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); + scriptEditor->setFont(QFont("Consolas")); if (rawFile->contents.isEmpty()) { scriptEditor->setPlainText("EMPTY"); @@ -156,15 +166,52 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = rawFile->path.split('/').last(); for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete scriptEditor; return; } } - QScrollArea *scrollArea = new QScrollArea(ui->tabWidget); - scrollArea->layout()->addWidget(scriptEditor); + const int tabStopSpaces = 4; + QFontMetrics metrics(scriptEditor->font()); + scriptEditor->setTabStopDistance(tabStopSpaces * metrics.horizontalAdvance(' ')); - ui->tabWidget->addTab(scrollArea, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_GSCFile.png")); + QSyntaxHighlighter *highlighter; + if (fileStem.contains(".gsc")) { + highlighter = new Highlighter_GSC(scriptEditor->document()); + } else if (fileStem.contains(".cfg")) { + highlighter = new Highlighter_CFG(scriptEditor->document()); + } else if (fileStem.contains(".rmb")) { + highlighter = new Highlighter_Rumble(scriptEditor->document()); + + RumbleGraphViewer *rmbGraphViewer = new RumbleGraphViewer(this); + rmbGraphViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); + rmbGraphViewer->SetRumbleGraphFile(rawFile); + + rawTabWidget->addTab(rmbGraphViewer, "UI Editor"); + rawTabWidget->addTab(scriptEditor, "Text Editor"); + + ui->tabWidget->addTab(rawTabWidget, fileStem); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_RUMBLE)); + ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); + return; + } else if (fileStem.contains(".shock")) { + highlighter = new Highlighter_Shock(scriptEditor->document()); + } else if (rawFile->contents.left(6) == "RUMBLE") { + RumbleFileViewer *rmbFileViewer = new RumbleFileViewer(this); + rmbFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); + rmbFileViewer->SetRumbleFile(rawFile); + + rawTabWidget->addTab(rmbFileViewer, "UI Editor"); + rawTabWidget->addTab(scriptEditor, "Text Editor"); + + ui->tabWidget->addTab(rawTabWidget, fileStem); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_RUMBLE)); + ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); + return; + } + + ui->tabWidget->addTab(scriptEditor, fileStem); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_RAW_FILE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -177,12 +224,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = image->materialName; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete mImageWidget; return; } } ui->tabWidget->addTab(mImageWidget, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Image.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_IMAGE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -190,24 +238,6 @@ MainWindow::MainWindow(QWidget *parent) Q_UNUSED(menu); }); - connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](std::shared_ptr ddsFile, const QString aParentName) { - DDSViewer *ddsViewer = new DDSViewer(this); - ddsViewer->setAcceptDrops(false); - ddsViewer->SetDDSFile(ddsFile); - ddsViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - - QString fileStem = ddsFile->fileStem + ".dds"; - for (int i = 0; i < ui->tabWidget->count(); i++) { - if (ui->tabWidget->tabText(i) == fileStem) { - return; - } - } - - ui->tabWidget->addTab(ddsViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_DDSFile.png")); - ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); - }); - connect(mTreeWidget, &XTreeWidget::MaterialSelected, this, [this](std::shared_ptr material, const QString aParentName) { MaterialViewer *matViewer = new MaterialViewer(this); matViewer->setAcceptDrops(false); @@ -217,12 +247,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = material->name; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete matViewer; return; } } ui->tabWidget->addTab(matViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Material.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_MATERIAL)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -235,12 +266,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = ddsFile->fileStem + ".dds"; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete ddsViewer; return; } } ui->tabWidget->addTab(ddsViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_DDSFile.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_IMAGE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -253,12 +285,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = iwiFile->fileStem + ".iwi"; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete iwiViewer; return; } } ui->tabWidget->addTab(iwiViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_IWIFile.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_IMAGE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -268,15 +301,16 @@ MainWindow::MainWindow(QWidget *parent) fastFileViewer->SetFastFile(aFastFile); fastFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - QString fileStem = aFastFile->GetStem() + ".ff"; + QString fileStem = aFastFile->GetStem(); for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete fastFileViewer; return; } } ui->tabWidget->addTab(fastFileViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_FastFile.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_FAST_FILE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -286,9 +320,10 @@ MainWindow::MainWindow(QWidget *parent) zoneFileViewer->SetZoneFile(aZoneFile); zoneFileViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - QString fileStem = aZoneFile->GetStem() + ".zone"; + QString fileStem = aZoneFile->GetBaseStem() + ".zone"; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete zoneFileViewer; return; } } @@ -306,7 +341,7 @@ MainWindow::MainWindow(QWidget *parent) scrollArea->setWidget(containerWidget); ui->tabWidget->addTab(scrollArea, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_ZoneFile.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_ZONE_FILE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -319,12 +354,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = aZoneFile->GetStem() + ".str"; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete localStrViewer; return; } } ui->tabWidget->addTab(localStrViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_String.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_LOCAL_STRING)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -337,12 +373,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = aTechSet->name; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete techSetViewer; return; } } ui->tabWidget->addTab(techSetViewer, aTechSet->name); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_TechSetFile.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_TECH_SET)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -355,12 +392,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = aStrTable->name; for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete strTableViewer; return; } } ui->tabWidget->addTab(strTableViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_StringTable.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_STRING_TABLE)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -373,12 +411,13 @@ MainWindow::MainWindow(QWidget *parent) QString fileStem = aSound->path.split('/').last(); for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { + delete soundViewer; return; } } ui->tabWidget->addTab(soundViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, QIcon(":/icons/icons/Icon_Sound.png")); + ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, ZoneFile::AssetTypeToIcon(ASSET_SOUND)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -475,13 +514,13 @@ void MainWindow::Reset() { and opens the selected file. */ bool MainWindow::OpenFastFile(const QString aFastFilePath) { - const QString fastFileStem = aFastFilePath.section("/", -1, -1).section('.', 0, 0); + const QString fastFileStem = aFastFilePath.section("/", -1, -1); if (mTreeWidget->HasFastFile(fastFileStem)) { LogManager::instance().addError("Can't add duplicate file!"); return false; } - std::shared_ptr fastFile = FastFile::Open(aFastFilePath); + std::shared_ptr fastFile = FastFileFactory::Create(aFastFilePath); fastFile->SetStem(fastFileStem); mTreeWidget->AddFastFile(fastFile); diff --git a/app/materialviewer.cpp b/app/materialviewer.cpp index 1a97977..08064e6 100644 --- a/app/materialviewer.cpp +++ b/app/materialviewer.cpp @@ -20,18 +20,11 @@ void MaterialViewer::SetMaterial(std::shared_ptr aMaterial) { ui->lineEdit_Name->setText(aMaterial->name); ui->lineEdit_RefPtr->setText(ToHexStr(aMaterial->refNamePtr)); ui->lineEdit_RefName->setText(aMaterial->refName); - ui->lineEdit_Unknowns->setText(ToHexStr(aMaterial->unknownA[0]) - + ToHexStr(aMaterial->unknownA[1]) - + ToHexStr(aMaterial->unknownA[2]) - + ToHexStr(aMaterial->unknownA[3]) - + ToHexStr(aMaterial->unknownA[4]) - + ToHexStr(aMaterial->unknownA[5]) - + ToHexStr(aMaterial->unknownA[6]) - + ToHexStr(aMaterial->unknownA[7]) - + ToHexStr(aMaterial->unknownA[8]) - + ToHexStr(aMaterial->unknownA[9]) - + ToHexStr(aMaterial->unknownA[10]) - + ToHexStr(aMaterial->unknownA[11])); + QString unknownStr = ""; + foreach (quint32 unknownPtr, aMaterial->pointers) { + unknownStr += ToHexStr(unknownPtr) + "\n"; + } + ui->lineEdit_Unknowns->setText(unknownStr); ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[0])); ui->lineEdit_StateA->setText(ToHexStr(aMaterial->stateBits[1])); ui->spinBox_TextureCount->setValue(aMaterial->textureCount); diff --git a/app/rumblefileviewer.cpp b/app/rumblefileviewer.cpp new file mode 100644 index 0000000..a6483f2 --- /dev/null +++ b/app/rumblefileviewer.cpp @@ -0,0 +1,58 @@ +#include "rumblefileviewer.h" +#include "ui_rumblefileviewer.h" + +RumbleFileViewer::RumbleFileViewer(QWidget *parent) + : QWidget(parent) + , ui(new Ui::RumbleFileViewer) + , mPropertyCount() + , mRumbleFile(nullptr) { + ui->setupUi(this); + + ui->tableWidget_Properties->setColumnCount(2); + ui->tableWidget_Properties->setRowCount(0); + ui->tableWidget_Properties->setColumnWidth(0, 200); + ui->tableWidget_Properties->horizontalHeader()->setStretchLastSection(true); +} + +RumbleFileViewer::~RumbleFileViewer() { + delete ui; +} + +void RumbleFileViewer::SetRumbleFile(std::shared_ptr aRumbleFile) { + mRumbleFile = aRumbleFile; + + ui->tableWidget_Properties->clear(); + + const QString magic = aRumbleFile->contents.left(6); + if (magic != "RUMBLE") { + qDebug() << "Rumble file has invalid magic: " << magic; + return; + } + + int firstIndex = 0; + int secondIndex = 0; + int thirdIndex = 0; + + int startIndex = 0; + for (int i = 0; i < aRumbleFile->contents.count("\\") / 2; i++) { + ui->tableWidget_Properties->setRowCount(i + 1); + ui->spinBox_Entries->setValue(i + 1); + + firstIndex = aRumbleFile->contents.indexOf("\\", startIndex); + secondIndex = aRumbleFile->contents.indexOf("\\", firstIndex + 1); + thirdIndex = aRumbleFile->contents.indexOf("\\", secondIndex + 1); + if (thirdIndex == -1) { + thirdIndex = aRumbleFile->contents.size(); + } + + const QString keyStr = aRumbleFile->contents.mid(firstIndex + 1, secondIndex - firstIndex - 1); + QTableWidgetItem *keyItem = new QTableWidgetItem(keyStr); + ui->tableWidget_Properties->setItem(i, 0, keyItem); + + const QString valStr = aRumbleFile->contents.mid(secondIndex + 1, thirdIndex - secondIndex - 1); + QTableWidgetItem *valueItem = new QTableWidgetItem(valStr); + ui->tableWidget_Properties->setItem(i, 1, valueItem); + + startIndex = thirdIndex; + } +} diff --git a/app/rumblefileviewer.h b/app/rumblefileviewer.h new file mode 100644 index 0000000..eb21e23 --- /dev/null +++ b/app/rumblefileviewer.h @@ -0,0 +1,28 @@ +#ifndef RUMBLEFILEVIEWER_H +#define RUMBLEFILEVIEWER_H + +#include "asset_structs.h" +#include "zonefile.h" +#include + +namespace Ui { +class RumbleFileViewer; +} + +class RumbleFileViewer : public QWidget +{ + Q_OBJECT + +public: + explicit RumbleFileViewer(QWidget *parent = nullptr); + ~RumbleFileViewer(); + + void SetRumbleFile(std::shared_ptr aRumbleFile); + +private: + Ui::RumbleFileViewer *ui; + quint32 mPropertyCount; + std::shared_ptr mRumbleFile; +}; + +#endif // RUMBLEFILEVIEWER_H diff --git a/app/rumblefileviewer.ui b/app/rumblefileviewer.ui new file mode 100644 index 0000000..e9d0174 --- /dev/null +++ b/app/rumblefileviewer.ui @@ -0,0 +1,153 @@ + + + RumbleFileViewer + + + + 0 + 0 + 841 + 457 + + + + + 841 + 457 + + + + Form + + + + + + + Roboto + 16 + true + + + + Rumble File Viewer + + + + + + + + + + + + 325 + 398 + + + + + 325 + 16777215 + + + + + Roboto + 9 + + + + Header + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + false + + + 10000 + + + 1 + + + + + + + Entries: + + + + + + + + + + + + + 400 + 400 + + + + + Roboto + 9 + + + + Properties + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 0 + + + + + + + + + diff --git a/app/rumblegraphviewer.cpp b/app/rumblegraphviewer.cpp new file mode 100644 index 0000000..ca3dc8e --- /dev/null +++ b/app/rumblegraphviewer.cpp @@ -0,0 +1,54 @@ +#include "rumblegraphviewer.h" +#include "ui_rumblegraphviewer.h" + +RumbleGraphViewer::RumbleGraphViewer(QWidget *parent) + : QWidget(parent) + , ui(new Ui::RumbleGraphViewer), + mEntryCount(), + mRumbleGraphFile(nullptr) { + ui->setupUi(this); + + ui->tableWidget_Entries->setColumnCount(2); + ui->tableWidget_Entries->setHorizontalHeaderLabels({ "X", "Y" }); + ui->tableWidget_Entries->setRowCount(0); + ui->tableWidget_Entries->setColumnWidth(0, 200); + ui->tableWidget_Entries->horizontalHeader()->setStretchLastSection(true); +} + +RumbleGraphViewer::~RumbleGraphViewer() { + delete ui; +} + +void RumbleGraphViewer::SetRumbleGraphFile(const std::shared_ptr aRawFile) { + mRumbleGraphFile = aRawFile; + + QDataStream rawFileStream(mRumbleGraphFile->contents.toLatin1()); + + QByteArray magic(15, Qt::Uninitialized); + rawFileStream.readRawData(magic.data(), 15); + + rawFileStream.skipRawData(4); + + char sectionChar; + rawFileStream >> sectionChar; + int sectionCount = sectionChar - '0'; + ui->tableWidget_Entries->setRowCount(sectionCount); + ui->spinBox_Entries->setValue(sectionCount); + ui->groupBox_LocalStrViewer->setTitle(QString("Entries (%1)").arg(sectionCount)); + + rawFileStream.skipRawData(2); + + for (int i = 0; i < sectionCount; i++) { + QByteArray xVal(6, Qt::Uninitialized), yVal(6, Qt::Uninitialized); + rawFileStream.readRawData(xVal.data(), 6); + rawFileStream.skipRawData(1); + rawFileStream.readRawData(yVal.data(), 6); + rawFileStream.skipRawData(2); + + QTableWidgetItem *xItem = new QTableWidgetItem(xVal); + QTableWidgetItem *yItem = new QTableWidgetItem(yVal); + + ui->tableWidget_Entries->setItem(i, 0, xItem); + ui->tableWidget_Entries->setItem(i, 1, yItem); + } +} diff --git a/app/rumblegraphviewer.h b/app/rumblegraphviewer.h new file mode 100644 index 0000000..6f8e498 --- /dev/null +++ b/app/rumblegraphviewer.h @@ -0,0 +1,30 @@ +#ifndef RUMBLEGRAPHVIEWER_H +#define RUMBLEGRAPHVIEWER_H + +#include "asset_structs.h" +#include "zonefile.h" +#include + +namespace Ui { +class RumbleGraphViewer; +} + +class RumbleGraphViewer : public QWidget +{ + Q_OBJECT + +public: + explicit RumbleGraphViewer(QWidget *parent = nullptr); + ~RumbleGraphViewer(); + + void SetEntryCount(quint32 aCount); + void SetRumbleGraphFile(const std::shared_ptr aRawFile); + void SetZoneFile(std::shared_ptr aZoneFile); + +private: + Ui::RumbleGraphViewer *ui; + quint32 mEntryCount; + std::shared_ptr mRumbleGraphFile; +}; + +#endif // RUMBLEGRAPHVIEWER_H diff --git a/app/rumblegraphviewer.ui b/app/rumblegraphviewer.ui new file mode 100644 index 0000000..36ab973 --- /dev/null +++ b/app/rumblegraphviewer.ui @@ -0,0 +1,153 @@ + + + RumbleGraphViewer + + + + 0 + 0 + 841 + 457 + + + + + 841 + 457 + + + + Form + + + + + + + Roboto + 16 + true + + + + Rumble Graph File + + + + + + + + + + + + 325 + 398 + + + + + 325 + 16777215 + + + + + Roboto + 9 + + + + Header + + + + + + Entry Count: + + + + + + + false + + + 10000 + + + 0 + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + 400 + 400 + + + + + Roboto + 9 + + + + Entries + + + + + + + 0 + 0 + + + + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 0 + + + + + + + + + diff --git a/app/xtreewidget.cpp b/app/xtreewidget.cpp index 043f5e4..dc00cd9 100644 --- a/app/xtreewidget.cpp +++ b/app/xtreewidget.cpp @@ -16,6 +16,7 @@ XTreeWidget::XTreeWidget(QWidget *parent) header()->hide(); setMinimumWidth(350); setSortingEnabled(true); + setIconSize(QSize(16, 16)); header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); @@ -38,36 +39,44 @@ XTreeWidget::~XTreeWidget() { void XTreeWidget::AddFastFile(std::shared_ptr aFastFile) { XTreeWidgetItem *fastFileItem = new XTreeWidgetItem(this); - fastFileItem->setText(0, aFastFile->GetStem() + ".ff"); - fastFileItem->setIcon(0, QIcon(":/icons/icons/Icon_FastFile.png")); + fastFileItem->setText(0, aFastFile->GetStem()); + fastFileItem->setIcon(0, Utils::CreateAssetIcon("FF")); if (aFastFile->GetPlatform() == "PC") { - fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_PC.png")); + fastFileItem->setIcon(1, Utils::CreateAssetIcon("PC")); } else if (aFastFile->GetPlatform() == "360") { - fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_Xbox.png")); + fastFileItem->setIcon(1, Utils::CreateAssetIcon("360")); + } else if (aFastFile->GetPlatform() == "PS3") { + fastFileItem->setIcon(1, Utils::CreateAssetIcon("PS3")); } else if (aFastFile->GetPlatform() == "Wii") { - fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_Wii.png")); + fastFileItem->setIcon(1, Utils::CreateAssetIcon("WII")); } else if (aFastFile->GetPlatform() == "WiiU") { - fastFileItem->setIcon(1, QIcon(":/icons/icons/Icon_WiiU.png")); + fastFileItem->setIcon(1, Utils::CreateAssetIcon("WU")); } if (aFastFile->GetGame() == "COD2") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD2.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(2)); } if (aFastFile->GetGame() == "COD4") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD4.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(4)); } else if (aFastFile->GetGame() == "COD5") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD5.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(5)); } else if (aFastFile->GetGame() == "COD6") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD6.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(6)); } else if (aFastFile->GetGame() == "COD7") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD7.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(7)); } else if (aFastFile->GetGame() == "COD8") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD8.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(8)); } else if (aFastFile->GetGame() == "COD9") { - fastFileItem->setIcon(2, QIcon(":/icons/icons/Icon_COD9.png")); + fastFileItem->setIcon(2, Utils::CreateGameIcon(9)); + } else if (aFastFile->GetGame() == "COD10") { + fastFileItem->setIcon(2, Utils::CreateGameIcon(10)); + } else if (aFastFile->GetGame() == "COD11") { + fastFileItem->setIcon(2, Utils::CreateGameIcon(11)); + } else if (aFastFile->GetGame() == "COD12") { + fastFileItem->setIcon(2, Utils::CreateGameIcon(12)); } AddZoneFile(aFastFile->GetZoneFile(), fastFileItem); - mFastFiles[aFastFile->GetStem().section(".", 0, 0)] = aFastFile; + mFastFiles[aFastFile->GetStem()] = aFastFile; resizeColumnToContents(1); setSortingEnabled(true); @@ -81,42 +90,52 @@ void XTreeWidget::AddZoneFile(std::shared_ptr aZoneFile, XTreeWidgetIt } else { zoneItem = new XTreeWidgetItem(this); } - zoneItem->setIcon(0, QIcon(":/icons/icons/Icon_ZoneFile.png")); - zoneItem->setText(0, aZoneFile->GetStem() + ".zone"); + zoneItem->setIcon(0, ZoneFile::AssetTypeToIcon(ASSET_ZONE_FILE)); + zoneItem->setText(0, aZoneFile->GetBaseStem() + ".zone"); auto assetMap = aZoneFile->GetAssetMap(); if (!assetMap.localStrings.isEmpty()) { + QIcon localStrIcon = ZoneFile::AssetTypeToIcon(ASSET_LOCAL_STRING); + XTreeWidgetItem *localStrRoot = new XTreeWidgetItem(zoneItem); localStrRoot->setText(0, "String Files"); - localStrRoot->setIcon(0, QIcon(":/icons/icons/Icon_StringFile.png")); + localStrRoot->setIcon(0, localStrIcon); + localStrRoot->SetCategory(CATEGORY_TYPE); XTreeWidgetItem *localStrItem = new XTreeWidgetItem(localStrRoot); localStrItem->setText(0, aZoneFile->GetStem().section('.', 0, 0) + ".str"); - localStrItem->setIcon(0, QIcon(":/icons/icons/Icon_StringFile.png")); + localStrItem->setIcon(0, localStrIcon); } if (!assetMap.techSets.isEmpty()) { + QIcon techSetIcon = ZoneFile::AssetTypeToIcon(ASSET_TECH_SET); + XTreeWidgetItem *techSetRoot = new XTreeWidgetItem(zoneItem); techSetRoot->setText(0, "Tech Sets"); - techSetRoot->setIcon(0, QIcon(":/icons/icons/Icon_TechSetFile.png")); + techSetRoot->setIcon(0, techSetIcon); + techSetRoot->SetCategory(CATEGORY_TYPE); for (TechSet techSet : assetMap.techSets) { XTreeWidgetItem *techSetItem = new XTreeWidgetItem(techSetRoot); techSetItem->setText(0, techSet.name); - techSetItem->setIcon(0, QIcon(":/icons/icons/Icon_TechSetFile.png")); + techSetItem->setIcon(0, techSetIcon); } } if (!assetMap.rawFiles.isEmpty()) { + QIcon rawFileIcon = ZoneFile::AssetTypeToIcon(ASSET_RAW_FILE); + XTreeWidgetItem *rawFileRoot = new XTreeWidgetItem(zoneItem); rawFileRoot->setText(0, "Raw Files"); - rawFileRoot->setIcon(0, QIcon(":/icons/icons/Icon_GSCFile.png")); + rawFileRoot->setIcon(0, rawFileIcon); + rawFileRoot->SetCategory(CATEGORY_TYPE); for (RawFile rawFile : assetMap.rawFiles) { if (!rawFile.length) { continue; } XTreeWidgetItem *tempItem = rawFileRoot; - for (const QString &pathPart : rawFile.path.split('/')) { + const QStringList pathParts = rawFile.path.split('/'); + for (const QString &pathPart : pathParts) { bool childFound = false; for (int i = 0; i < tempItem->childCount(); i++) { QTreeWidgetItem *rawChildItem = tempItem->child(i); @@ -129,25 +148,30 @@ void XTreeWidget::AddZoneFile(std::shared_ptr aZoneFile, XTreeWidgetIt } } - if (pathPart.contains(".gsc")) { + const QString rawFileStr = QString("%1 [%2-%3]").arg(pathPart).arg(rawFile.startPos).arg(rawFile.endPos); + //rawFileStr = pathPart; + if (pathPart == pathParts.last()) { XTreeWidgetItem *rawFileItem = new XTreeWidgetItem(tempItem); - rawFileItem->setText(0, pathPart); + rawFileItem->setText(0, rawFileStr); tempItem = rawFileItem; } else if (!childFound) { tempItem = new XTreeWidgetItem(tempItem); - tempItem->setText(0, pathPart); + tempItem->setText(0, rawFileStr); } } - tempItem->setIcon(0, QIcon(":/icons/icons/Icon_GSCFile.png")); + tempItem->setIcon(0, rawFileIcon); } } if (!assetMap.menuFiles.isEmpty()) { + QIcon menuFileIcon = ZoneFile::AssetTypeToIcon(ASSET_MENU); + XTreeWidgetItem *menuRoot = new XTreeWidgetItem(zoneItem); menuRoot->setText(0, "Menu Files"); - menuRoot->setIcon(0, QIcon(":/icons/icons/Icon_MenuFile.png")); + menuRoot->setIcon(0, menuFileIcon); + menuRoot->SetCategory(CATEGORY_TYPE); int menuIndex = 1; for (MenuFile menuFile : assetMap.menuFiles) { @@ -155,65 +179,80 @@ void XTreeWidget::AddZoneFile(std::shared_ptr aZoneFile, XTreeWidgetIt menuFileRoot->setText(0, QString("Menu %1").arg(menuIndex)); for (Menu menu : menuFile.menuDefs) { XTreeWidgetItem *menuItem = new XTreeWidgetItem(menuFileRoot); - menuItem->setText(0, menu.name); - menuItem->setIcon(0, QIcon(":/icons/icons/Icon_MenuFile.png")); + menuItem->setText(0, menu.filePath); + menuItem->setIcon(0, menuFileIcon); } menuIndex++; } } if (!assetMap.images.isEmpty()) { + QIcon imageIcon = ZoneFile::AssetTypeToIcon(ASSET_IMAGE); + XTreeWidgetItem *imageRoot = new XTreeWidgetItem(zoneItem); imageRoot->setText(0, "Images"); - imageRoot->setIcon(0, QIcon(":/icons/icons/Icon_Image.png")); + imageRoot->setIcon(0, imageIcon); + imageRoot->SetCategory(CATEGORY_TYPE); for (Image image : assetMap.images) { XTreeWidgetItem *imageItem = new XTreeWidgetItem(imageRoot); imageItem->setText(0, image.materialName); - imageItem->setIcon(0, QIcon(":/icons/icons/Icon_Image.png")); + imageItem->setIcon(0, imageIcon); } } if (!assetMap.models.isEmpty()) { + QIcon modelIcon = ZoneFile::AssetTypeToIcon(ASSET_MODEL); + XTreeWidgetItem *modelsRoot = new XTreeWidgetItem(zoneItem); modelsRoot->setText(0, "Models"); - modelsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Model.png")); + modelsRoot->setIcon(0, modelIcon); + modelsRoot->SetCategory(CATEGORY_TYPE); for (Model model: assetMap.models) { XTreeWidgetItem *modelItem = new XTreeWidgetItem(modelsRoot); modelItem->setText(0, model.modelName); - modelItem->setIcon(0, QIcon(":/icons/icons/Icon_Model.png")); + modelItem->setIcon(0, modelIcon); } } if (!assetMap.materials.isEmpty()) { + QIcon materialIcon = ZoneFile::AssetTypeToIcon(ASSET_MATERIAL); + XTreeWidgetItem *materialsRoot = new XTreeWidgetItem(zoneItem); materialsRoot->setText(0, "Materials"); - materialsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Material.png")); + materialsRoot->setIcon(0, materialIcon); + materialsRoot->SetCategory(CATEGORY_TYPE); for (Material material: assetMap.materials) { XTreeWidgetItem *materialItem = new XTreeWidgetItem(materialsRoot); materialItem->setText(0, material.name); - materialItem->setIcon(0, QIcon(":/icons/icons/Icon_Material.png")); + materialItem->setIcon(0, materialIcon); } } if (!assetMap.stringTables.isEmpty()) { + QIcon stringTableIcon = ZoneFile::AssetTypeToIcon(ASSET_STRING_TABLE); + XTreeWidgetItem *strTableRoot = new XTreeWidgetItem(zoneItem); strTableRoot->setText(0, "String Tables"); - strTableRoot->setIcon(0, QIcon(":/icons/icons/Icon_StringTable.png")); + strTableRoot->setIcon(0, stringTableIcon); + strTableRoot->SetCategory(CATEGORY_TYPE); for (StringTable strTable: assetMap.stringTables) { XTreeWidgetItem *modelItem = new XTreeWidgetItem(strTableRoot); modelItem->setText(0, strTable.name); - modelItem->setIcon(0, QIcon(":/icons/icons/Icon_StringTable.png")); + modelItem->setIcon(0, stringTableIcon); } } if (!assetMap.sounds.isEmpty()) { + QIcon soundIcon = ZoneFile::AssetTypeToIcon(ASSET_SOUND); + XTreeWidgetItem *soundsRoot = new XTreeWidgetItem(zoneItem); soundsRoot->setText(0, "Sounds"); - soundsRoot->setIcon(0, QIcon(":/icons/icons/Icon_Sound.png")); + soundsRoot->setIcon(0, soundIcon); + soundsRoot->SetCategory(CATEGORY_TYPE); for (SoundAsset soundAsset : assetMap.sounds) { for (Sound sound : soundAsset.sounds) { XTreeWidgetItem *tempItem = soundsRoot; @@ -245,16 +284,16 @@ void XTreeWidget::AddZoneFile(std::shared_ptr aZoneFile, XTreeWidgetIt } } - tempItem->setIcon(0, QIcon(":/icons/icons/Icon_Sound.png")); + tempItem->setIcon(0, soundIcon); } } } - mZoneFiles[aZoneFile->GetStem().section(".", 0, 0)] = aZoneFile; + mZoneFiles[aZoneFile->GetBaseStem() + ".zone"] = aZoneFile; } void XTreeWidget::CloseFastFile(const QString aFFName) { - const QString fileStem = aFFName.section(".", 0, 0); + const QString fileStem = aFFName; emit ItemClosed(fileStem); } @@ -355,7 +394,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { iwiFile->SaveJPG(); }); } else if (activeText.contains(".ff")) { - const QString fileStem = activeText.replace(".zone", ""); + const QString fileStem = activeText; QMenu *closeMultipleAction = new QMenu("Close Multiple Tabs"); @@ -379,7 +418,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { auto childItem = invisibleRootItem()->child(i); if (childItem == activeItem) { continue; } - const QString fileStem = childItem->text(0).replace(".ff", ""); + const QString fileStem = childItem->text(0); if (!mFastFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; return; @@ -401,7 +440,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { auto childItem = invisibleRootItem()->child(i); if (childItem == activeItem) { return; } - const QString fileStem = childItem->text(0).replace(".ff", ""); + const QString fileStem = childItem->text(0); if (!mFastFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; return; @@ -428,7 +467,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { continue; } - const QString fileStem = childItem->text(0).replace(".ff", ""); + const QString fileStem = childItem->text(0); if (!mFastFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Fast File map!"; return; @@ -448,7 +487,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { connect(closeAction, &QAction::triggered, this, [this, &activeItem, &activeText](bool checked) { Q_UNUSED(checked); - const QString fileStem = activeItem->text(0).replace(".ff", ""); + const QString fileStem = activeItem->text(0); mFastFiles.remove(fileStem); CloseFastFile(activeText); @@ -482,7 +521,7 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { fastFile->GetZoneFile()->SaveZoneFile(zoneFilePath); }); } else if (activeText.contains(".zone")) { - const QString fileStem = activeText.replace(".zone", ""); + const QString fileStem = activeText; if (!mZoneFiles.contains(fileStem)) { qDebug() << "Error: Could not find " << fileStem << " in Zone File map!"; return; @@ -612,63 +651,39 @@ void XTreeWidget::ItemSelectionChanged() { QString selectedText = selectedItem->text(0); emit ItemSelected(selectedText); - const QString fileStem = selectedText.section(".", 0, 0); - XTreeWidgetItem *parentItem = dynamic_cast(selectedItem->parent()); if (selectedText.contains(".dds")) { - if (!mDDSFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in DDS map!"); + if (!mDDSFiles.contains(selectedText)) { + LogManager::instance().addError("Could not find " + selectedText + " in DDS map!"); return; } - std::shared_ptr ddsFile = mDDSFiles[fileStem]; - emit DDSFileSelected(ddsFile, fileStem); + std::shared_ptr ddsFile = mDDSFiles[selectedText]; + emit DDSFileSelected(ddsFile, selectedText); } else if (selectedText.contains(".iwi")) { - if (!mIWIFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in IWI map!"); + if (!mIWIFiles.contains(selectedText)) { + LogManager::instance().addError("Could not find " + selectedText + " in IWI map!"); return; } - emit IWIFileSelected(mIWIFiles[fileStem], fileStem); + emit IWIFileSelected(mIWIFiles[selectedText], selectedText); } else if (selectedText.contains(".ff")) { - if (!mFastFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in Fast File map!"); + if (!mFastFiles.contains(selectedText)) { + LogManager::instance().addError("Could not find " + selectedText + " in Fast File map!"); return; } - emit FastFileSelected(mFastFiles[fileStem], fileStem); + emit FastFileSelected(mFastFiles[selectedText], selectedText); } else if (selectedText.contains(".zone")) { - if (!mZoneFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); + if (!mZoneFiles.contains(selectedText)) { + LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!"); return; } - emit ZoneFileSelected(mZoneFiles[fileStem], fileStem); + emit ZoneFileSelected(mZoneFiles[selectedText], selectedText); } else if (selectedText.contains(".str")) { - if (!mZoneFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); + if (!mZoneFiles.contains(selectedText.replace(".str", ".zone"))) { + LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!"); return; } - emit LocalStringSelected(mZoneFiles[fileStem], fileStem); - } else if (selectedText.contains(".gsc")) { - XTreeWidgetItem *zoneRoot = selectedItem; - if (!zoneRoot) { return; } - - while (!zoneRoot->text(0).contains(".zone")) { - zoneRoot = dynamic_cast(zoneRoot->parent()); - if (!zoneRoot) { return; } - } - - const QString fileStem = zoneRoot->text(0).section('.', 0, 0); - if (!mZoneFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); - return; - } - - QVector rawFiles = mZoneFiles[fileStem]->GetAssetMap().rawFiles; - for (RawFile rawFile : rawFiles) { - if (rawFile.path.contains(selectedText)) { - emit RawFileSelected(std::make_shared(rawFile), fileStem); - return; - } - } + emit LocalStringSelected(mZoneFiles[selectedText], selectedText); } else if (parentItem && (parentItem->text(0) == "Images")) { XTreeWidgetItem *grandpaItem = dynamic_cast(parentItem->parent()); if (grandpaItem && grandpaItem->text(0).contains(".zone")) { @@ -738,6 +753,32 @@ void XTreeWidget::ItemSelectionChanged() { } } } + } else if (selectedItem->GetCategory() != CATEGORY_TYPE) { + XTreeWidgetItem *zoneRoot = selectedItem; + + bool zoneChild = false; + while (zoneRoot) { + zoneRoot = dynamic_cast(zoneRoot->parent()); + if (zoneRoot->text(0).contains("Raw Files")) { + zoneChild = true; + break; + } + } + if (!zoneChild) { return; } + const QString fileStem = zoneRoot->parent()->text(0); + + if (!mZoneFiles.contains(fileStem)) { + LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); + return; + } + + QVector rawFiles = mZoneFiles[fileStem]->GetAssetMap().rawFiles; + for (RawFile rawFile : rawFiles) { + if (rawFile.path.split('/').last() == selectedText) { + emit RawFileSelected(std::make_shared(rawFile), fileStem); + return; + } + } } } @@ -778,7 +819,7 @@ void XTreeWidget::AddIWIFile(std::shared_ptr aIWIFile) { } XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this); - iwiItem->setIcon(0, QIcon(":/icons/icons/Icon_IWIFile.png")); + iwiItem->setIcon(0, ZoneFile::AssetTypeToIcon(ASSET_IMAGE)); iwiItem->setText(0, iwiFileName); mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile; } @@ -794,7 +835,7 @@ void XTreeWidget::AddDDSFile(std::shared_ptr aDDSFile) { } XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this); - ddsItem->setIcon(0, QIcon(":/icons/icons/Icon_DDSFile.png")); + ddsItem->setIcon(0, ZoneFile::AssetTypeToIcon(ASSET_IMAGE)); ddsItem->setText(0, ddsFileName); mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile; } diff --git a/app/xtreewidget.h b/app/xtreewidget.h index 37e3761..5026fca 100644 --- a/app/xtreewidget.h +++ b/app/xtreewidget.h @@ -8,8 +8,10 @@ #include "fastfile.h" #include "xtreewidgetitem.h" #include "zonefile.h" +#include "utils.h" #include +#include class XTreeWidget : public QTreeWidget { diff --git a/app/xtreewidgetitem.cpp b/app/xtreewidgetitem.cpp index eae4ee9..bed2d07 100644 --- a/app/xtreewidgetitem.cpp +++ b/app/xtreewidgetitem.cpp @@ -1,15 +1,29 @@ #include "xtreewidgetitem.h" XTreeWidgetItem::XTreeWidgetItem(QTreeWidget *parent, bool group) - : QTreeWidgetItem(parent), isGroup(group) { + : QTreeWidgetItem(parent) + , isGroup(group) + , mCategory(CATEGORY_NONE) { } XTreeWidgetItem::XTreeWidgetItem(QTreeWidgetItem *parent, bool group) - : QTreeWidgetItem(parent), isGroup(group) { + : QTreeWidgetItem(parent) + , isGroup(group) + , mCategory(CATEGORY_NONE) { } +void XTreeWidgetItem::SetCategory(TREE_CATEGORY category) +{ + mCategory = category; +} + +TREE_CATEGORY XTreeWidgetItem::GetCategory() +{ + return mCategory; +} + bool XTreeWidgetItem::operator<(const QTreeWidgetItem &other) const { // Attempt to cast the other item to our custom type. const XTreeWidgetItem* otherItem = dynamic_cast(&other); diff --git a/app/xtreewidgetitem.h b/app/xtreewidgetitem.h index e189d04..ff1f544 100644 --- a/app/xtreewidgetitem.h +++ b/app/xtreewidgetitem.h @@ -4,6 +4,12 @@ #include #include +enum TREE_CATEGORY { + CATEGORY_NONE = 0x00, + CATEGORY_FILE = 0x01, + CATEGORY_TYPE = 0x02 +}; + // Custom item class class XTreeWidgetItem : public QTreeWidgetItem { @@ -15,9 +21,15 @@ public: XTreeWidgetItem(QTreeWidget *parent, bool group = false); XTreeWidgetItem(QTreeWidgetItem *parent, bool group = false); + void SetCategory(TREE_CATEGORY category); + TREE_CATEGORY GetCategory(); + // Override the less-than operator to customize sorting. bool operator<(const QTreeWidgetItem &other) const override; XTreeWidgetItem &operator =(const XTreeWidgetItem &other); + +private: + TREE_CATEGORY mCategory; }; diff --git a/app/zonefileviewer.cpp b/app/zonefileviewer.cpp index 12c48a3..52d736e 100644 --- a/app/zonefileviewer.cpp +++ b/app/zonefileviewer.cpp @@ -1,34 +1,86 @@ #include "zonefileviewer.h" #include "ui_zonefileviewer.h" +#include "statusbarmanager.h" + ZoneFileViewer::ZoneFileViewer(QWidget *parent) : QWidget(parent) , ui(new Ui::ZoneFileViewer) { ui->setupUi(this); - aZoneFile = nullptr; + mZoneFile = nullptr; - ui->tableWidget_RecordCounts->setColumnCount(4); - ui->tableWidget_RecordCounts->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count", "Icon" }); + ui->tableWidget_RecordCounts->setColumnCount(3); + ui->tableWidget_RecordCounts->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count" }); ui->tableWidget_RecordCounts->horizontalHeader()->setStretchLastSection(true); - ui->tableWidget_RecordOrder->setColumnCount(4); - ui->tableWidget_RecordOrder->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count", "Icon" }); + ui->tableWidget_RecordOrder->setColumnCount(3); + ui->tableWidget_RecordOrder->setHorizontalHeaderLabels({ "Identifier", "Asset", "Count" }); ui->tableWidget_RecordOrder->horizontalHeader()->setStretchLastSection(true); + + connect(ui->lineEdit_TagSearch, &QLineEdit::textChanged, this, &ZoneFileViewer::SortTags); + connect(ui->tableWidget_RecordCounts, &QTableWidget::itemSelectionChanged, this, &ZoneFileViewer::HighlightRecordInOrder); + connect(ui->listWidget_Tags, &QListWidget::currentTextChanged, this, [this](const QString &aCurrentText) { + StatusBarManager::instance().updateStatus(QString("Selected tag '%1' with index %2").arg(aCurrentText).arg(mZoneFile->GetTags().indexOf(aCurrentText))); + }); } ZoneFileViewer::~ZoneFileViewer() { delete ui; } +void ZoneFileViewer::HighlightRecordInOrder() { + ui->tableWidget_RecordOrder->clearSelection(); + + foreach (auto selectedItem, ui->tableWidget_RecordCounts->selectedItems()) { + int selectedRow = selectedItem->row(); + const QString assetId = ui->tableWidget_RecordCounts->item(selectedRow, 0)->text(); + + for (int i = 0; i < ui->tableWidget_RecordOrder->rowCount(); i++) { + const QString testAssetId = ui->tableWidget_RecordOrder->item(i, 0)->text(); + if (testAssetId != assetId) { continue; } + + ui->tableWidget_RecordOrder->selectRow(i); + ui->tableWidget_RecordOrder->item(i, 0)->setSelected(true); + ui->tableWidget_RecordOrder->item(i, 1)->setSelected(true); + ui->tableWidget_RecordOrder->item(i, 2)->setSelected(true); + ui->tableWidget_RecordOrder->item(i, 3)->setSelected(true); + } + } +} + +void ZoneFileViewer::SortTags(const QString &aSearchText) { + ui->listWidget_Tags->clear(); + + const QStringList tags = mZoneFile->GetTags(); + if (aSearchText.isEmpty()) { + ui->listWidget_Tags->addItems(tags); + return; + } + + QStringList sortedTags; + foreach (const QString tag, tags) { + if (tag.contains(aSearchText)) { + sortedTags << tag; + } + } + + StatusBarManager::instance().updateStatus(QString("Found %1 tags.").arg(sortedTags.size())); + ui->listWidget_Tags->addItems(sortedTags); +} + void ZoneFileViewer::SetZoneFile(std::shared_ptr aZoneFile) { + mZoneFile = aZoneFile; + ui->tableWidget_RecordCounts->clearContents(); ui->tableWidget_RecordOrder->clearContents(); ui->listWidget_Tags->clear(); - const QStringList tags = aZoneFile->GetTags(); + const QStringList tags = mZoneFile->GetTags(); ui->listWidget_Tags->addItems(tags); - ui->label_Title->setText(aZoneFile->GetStem() + ".zone"); + ui->label_Title->setText(mZoneFile->GetBaseStem() + ".zone"); + + ui->groupBox_Tags->setTitle(QString("Tags (%1)").arg(tags.size())); if (tags.isEmpty()) { ui->groupBox_Tags->hide(); @@ -36,88 +88,67 @@ void ZoneFileViewer::SetZoneFile(std::shared_ptr aZoneFile) { ui->groupBox_Tags->show(); } - QString lastAsset = ""; - QString lastRecord = ""; - QIcon assetIcon; - int consecutiveCount = 1; - int consecutiveIndex = 0; - const QStringList records = aZoneFile->GetRecords(); QMap recordCounts = QMap(); - for (const QString &record : records) { - lastRecord = record; - if (record == "ffffffff") { break; } + QVector> assetOccurances = QVector>(); + for (const QString &record : mZoneFile->GetRecords()) { if (!recordCounts.contains(record)) { recordCounts[record] = 0; } recordCounts[record]++; - QString assetType = aZoneFile->AssetTypeToString(record); + if (!assetOccurances.isEmpty() && assetOccurances.last().first == record) { + assetOccurances.last().second++; + continue; + } + + QPair assetOccurance(record, 1); + assetOccurances << assetOccurance; + } + ui->tableWidget_RecordOrder->setRowCount(assetOccurances.size()); + + int assetIndex = 0; + foreach (auto assetOccurance, assetOccurances) { + const QString record = assetOccurance.first; + AssetType assetType = mZoneFile->AssetStrToEnum(record); + int assetCount = assetOccurance.second; + + QIcon assetIcon = mZoneFile->AssetTypeToIcon(assetType); if (assetIcon.isNull()) { qDebug() << "Icon is null for record: " << record; } - if (lastAsset.isEmpty()) { - lastAsset = assetType; - lastRecord = record; - } else if (lastAsset == assetType) { - consecutiveCount++; - } else { - ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1); + QTableWidgetItem *recordItem = new QTableWidgetItem(record.toUpper()); + QTableWidgetItem *recordStrItem = new QTableWidgetItem(mZoneFile->AssetEnumToStr(assetType)); + QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(assetCount)); + recordItem->setIcon(assetIcon); - QTableWidgetItem *recordItem = new QTableWidgetItem(lastRecord.toUpper()); - QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset); - QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount)); - QTableWidgetItem *recordIconItem = new QTableWidgetItem(); - assetIcon = aZoneFile->AssetStrToIcon(lastAsset); - recordIconItem->setIcon(assetIcon); + ui->tableWidget_RecordOrder->setItem(assetIndex, 0, recordItem); + ui->tableWidget_RecordOrder->setItem(assetIndex, 1, recordStrItem); + ui->tableWidget_RecordOrder->setItem(assetIndex, 2, recordCountItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordStrItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 2, recordCountItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 3, recordIconItem); - - consecutiveCount = 1; - consecutiveIndex++; - lastAsset = assetType; - lastRecord = record; - } + assetIndex++; } - ui->tableWidget_RecordOrder->setRowCount(consecutiveIndex + 1); - - QTableWidgetItem *recordItem = new QTableWidgetItem(lastRecord.toUpper()); - QTableWidgetItem *recordStrItem = new QTableWidgetItem(lastAsset); - QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(consecutiveCount)); - QTableWidgetItem *recordIconItem = new QTableWidgetItem(); - assetIcon = aZoneFile->AssetStrToIcon(lastAsset); - recordIconItem->setIcon(assetIcon); - - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 0, recordItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 1, recordStrItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 2, recordCountItem); - ui->tableWidget_RecordOrder->setItem(consecutiveIndex, 3, recordIconItem); int recordIndex = 0; for (const QString &record : recordCounts.keys()) { int recordCount = recordCounts[record]; - QString assetType = aZoneFile->AssetTypeToString(record); - assetIcon = aZoneFile->AssetStrToIcon(assetType); + AssetType assetType = mZoneFile->AssetStrToEnum(record); + QIcon assetIcon = mZoneFile->AssetTypeToIcon(assetType); if (assetIcon.isNull()) { qDebug() << "Icon is null for record: " << record; } ui->tableWidget_RecordCounts->setRowCount(recordIndex + 1); - QTableWidgetItem *recordCountStrItem = new QTableWidgetItem(assetType); QTableWidgetItem *recordItem = new QTableWidgetItem(record.toUpper()); + QTableWidgetItem *recordCountStrItem = new QTableWidgetItem(mZoneFile->AssetEnumToStr(assetType)); QTableWidgetItem *recordCountItem = new QTableWidgetItem(QString::number(recordCount)); - QTableWidgetItem *recordIconItem = new QTableWidgetItem(); - recordIconItem->setIcon(assetIcon); + recordItem->setIcon(assetIcon); ui->tableWidget_RecordCounts->setItem(recordIndex, 0, recordItem); ui->tableWidget_RecordCounts->setItem(recordIndex, 1, recordCountStrItem); ui->tableWidget_RecordCounts->setItem(recordIndex, 2, recordCountItem); - ui->tableWidget_RecordCounts->setItem(recordIndex, 3, recordIconItem); recordIndex++; } diff --git a/app/zonefileviewer.h b/app/zonefileviewer.h index e335d2c..998d319 100644 --- a/app/zonefileviewer.h +++ b/app/zonefileviewer.h @@ -19,9 +19,15 @@ public: ~ZoneFileViewer(); void SetZoneFile(std::shared_ptr aZoneFile); + +public slots: + void SortTags(const QString &aSearchText); + + void HighlightRecordInOrder(); + private: Ui::ZoneFileViewer *ui; - std::shared_ptr aZoneFile; + std::shared_ptr mZoneFile; }; #endif // ZONEFILEVIEWER_H diff --git a/app/zonefileviewer.ui b/app/zonefileviewer.ui index 7b0755a..1845ca1 100644 --- a/app/zonefileviewer.ui +++ b/app/zonefileviewer.ui @@ -61,7 +61,14 @@ - + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + true + + @@ -73,7 +80,20 @@ - + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + true + + + QAbstractItemView::SelectionMode::SingleSelection + + + QAbstractItemView::SelectionBehavior::SelectRows + + @@ -85,7 +105,17 @@ - + + + QAbstractItemView::EditTrigger::NoEditTriggers + + + true + + + QAbstractItemView::SelectionMode::NoSelection + + diff --git a/bink.h b/bink.h deleted file mode 100644 index ab7c0de..0000000 --- a/bink.h +++ /dev/null @@ -1,396 +0,0 @@ -/* xoreos - A reimplementation of BioWare's Aurora engine - * - * xoreos is the legal property of its developers, whose names - * can be found in the AUTHORS file distributed with this source - * distribution. - * - * xoreos is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 3 - * of the License, or (at your option) any later version. - * - * xoreos is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with xoreos. If not, see . - */ - -/** @file - * Decoding RAD Game Tools' Bink videos. - */ - -/* Based on the Bink implementation in FFmpeg (, - * which is released under the terms of version 2 or later of the GNU - * Lesser General Public License. - * - * The original copyright notes in the files - * - libavformat/bink.c - * - libavcodec/bink.c - * - libavcodec/binkdata.h - * - libavcodec/binkdsp.c - * - libavcodec/binkdsp.h - * - libavcodec/binkaudio.c - * read as follows: - * - * Bink demuxer - * Copyright (c) 2008-2010 Peter Ross (pross@xvid.org) - * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) - * - * Bink video decoder - * Copyright (c) 2009 Konstantin Shishkov - * Copyright (C) 2011 Peter Ross - * - * Bink video decoder - * Copyright (C) 2009 Konstantin Shishkov - * - * Bink DSP routines - * Copyright (c) 2009 Konstantin Shishkov - * - * Bink Audio decoder - * Copyright (c) 2007-2011 Peter Ross (pross@xvid.org) - * Copyright (c) 2009 Daniel Verkamp (daniel@drv.nu) - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef VIDEO_BINK_H -#define VIDEO_BINK_H - -#include -#include - -#include "src/common/types.h" -#include "src/common/rational.h" - -#include "src/video/decoder.h" - -namespace Common { - class SeekableReadStream; - class BitStream; - class Huffman; - - class RDFT; - class DCT; -} - -namespace Sound { - class PacketizedAudioStream; -} - -namespace Video { - -/** A decoder for RAD Game Tools' Bink videos. */ -class Bink : public VideoDecoder { -public: - Bink(Common::SeekableReadStream *bink); - ~Bink(); - -protected: - void decodeNextTrackFrame(VideoTrack &track); - void checkAudioBuffer(AudioTrack &track, const Common::Timestamp &endTime); - -private: - static const int kAudioChannelsMax = 2; - static const int kAudioBlockSizeMax = (kAudioChannelsMax << 11); - - enum AudioCodec { - kAudioCodecDCT, - kAudioCodecRDFT - }; - - /** An audio track. */ - struct AudioInfo { - uint16_t flags; - - uint32_t sampleRate; - uint8_t channels; - - uint32_t outSampleRate; - uint8_t outChannels; - - AudioCodec codec; - - bool first; - - uint32_t frameLen; - uint32_t overlapLen; - - uint32_t blockSize; - - uint32_t bandCount; - uint32_t *bands; - - float root; - - float coeffs[16 * kAudioBlockSizeMax]; - int16_t prevCoeffs[kAudioBlockSizeMax]; - - float *coeffsPtr[kAudioChannelsMax]; - - Common::RDFT *rdft; - Common::DCT *dct; - - AudioInfo(); - AudioInfo(const AudioInfo &audioInfo) = default; - ~AudioInfo(); - }; - - /** A video frame. */ - struct VideoFrame { - bool keyFrame; - - uint32_t offset; - uint32_t size; - - Common::BitStream *bits; - - VideoFrame(); - VideoFrame(const VideoFrame &videoFrame) = default; - ~VideoFrame(); - }; - - std::unique_ptr _bink; - - std::vector _audioTracks; ///< All audio tracks. - std::vector _frames; ///< All video frames. - - uint32_t _audioTrack; ///< Audio track to use. - - /** Load a Bink file. */ - void load(); - - class BinkVideoTrack : public FixedRateVideoTrack { - public: - BinkVideoTrack(uint32_t width, uint32_t height, uint32_t frameCount, const Common::Rational &frameRate, bool swapPlanes, bool hasAlpha, uint32_t id); - - uint32_t getWidth() const { return _width; } - uint32_t getHeight() const { return _height; } - int getCurFrame() const { return _curFrame; } - int getFrameCount() const { return _frameCount; } - - /** Decode a video packet. */ - void decodePacket(Graphics::Surface &surface, VideoFrame &frame); - - protected: - Common::Rational getFrameRate() const { return _frameRate; } - - private: - /** A decoder state. */ - struct DecodeContext { - VideoFrame *video; - - uint32_t planeIdx; - - uint32_t blockX; - uint32_t blockY; - - byte *dest; - byte *prev; - - byte *destStart, *destEnd; - byte *prevStart, *prevEnd; - - uint32_t pitch; - - int coordMap[64]; - int coordScaledMap1[64]; - int coordScaledMap2[64]; - int coordScaledMap3[64]; - int coordScaledMap4[64]; - }; - - /** IDs for different data types used in Bink video codec. */ - enum Source { - kSourceBlockTypes = 0, ///< 8x8 block types. - kSourceSubBlockTypes , ///< 16x16 block types (a subset of 8x8 block types). - kSourceColors , ///< Pixel values used for different block types. - kSourcePattern , ///< 8-bit values for 2-color pattern fill. - kSourceXOff , ///< X components of motion value. - kSourceYOff , ///< Y components of motion value. - kSourceIntraDC , ///< DC values for intrablocks with DCT. - kSourceInterDC , ///< DC values for interblocks with DCT. - kSourceRun , ///< Run lengths for special fill block. - - kSourceMAX - }; - - /** Bink video block types. */ - enum BlockType { - kBlockSkip = 0, ///< Skipped block. - kBlockScaled , ///< Block has size 16x16. - kBlockMotion , ///< Block is copied from previous frame with some offset. - kBlockRun , ///< Block is composed from runs of colors with custom scan order. - kBlockResidue , ///< Motion block with some difference added. - kBlockIntra , ///< Intra DCT block. - kBlockFill , ///< Block is filled with single color. - kBlockInter , ///< Motion block with DCT applied to the difference. - kBlockPattern , ///< Block is filled with two colors following custom pattern. - kBlockRaw ///< Uncoded 8x8 block. - }; - - /** Data structure for decoding and translating Huffman'd data. */ - struct Huffman { - int index; ///< Index of the Huffman codebook to use. - byte symbols[16]; ///< Huffman symbol => Bink symbol translation list. - - Huffman(); - }; - - /** Data structure used for decoding a single Bink data type. */ - struct Bundle { - int countLengths[2]; ///< Lengths of number of entries to decode (in bits). - int countLength; ///< Length of number of entries to decode (in bits) for the current plane. - - Huffman huffman; ///< Huffman codebook. - - std::unique_ptr data; ///< Buffer for decoded symbols. - - byte *dataEnd; ///< Pointer to the data end end. - byte *curDec; ///< Pointer to the data that wasn't yet decoded. - byte *curPtr; ///< Pointer to the data that wasn't yet read. - - Bundle(); - }; - - uint32_t _width; - uint32_t _height; - - int _curFrame; ///< Current Frame. - int _frameCount; - - Common::Rational _frameRate; ///< The frame rate of the video. - - bool _swapPlanes; ///< Are the planes ordered (A)YVU instead of (A)YUV? - bool _hasAlpha; ///< Do video frames have alpha? - - uint32_t _id; ///< The BIK FourCC. - - Bundle _bundles[kSourceMAX]; ///< Bundles for decoding all data types. - - std::unique_ptr _huffman[16]; ///< The 16 Huffman codebooks used in Bink decoding. - - /** Huffman codebooks to use for decoding high nibbles in color data types. */ - Huffman _colHighHuffman[16]; - /** Value of the last decoded high nibble in color data types. */ - int _colLastVal; - - std::unique_ptr _curPlanes[4]; ///< The 4 color planes, YUVA, current frame. - std::unique_ptr _oldPlanes[4]; ///< The 4 color planes, YUVA, last frame. - - /** Initialize the bundles. */ - void initBundles(); - - /** Initialize the Huffman decoders. */ - void initHuffman(); - - /** Decode a video packet. */ - void videoPacket(VideoFrame &video); - - /** Decode a plane. */ - void decodePlane(VideoFrame &video, int planeIdx, bool isChroma); - - /** Read/Initialize a bundle for decoding a plane. */ - void readBundle(VideoFrame &video, Source source); - - /** Read the symbols for a Huffman code. */ - void readHuffman(VideoFrame &video, Huffman &huffman); - /** Merge two Huffman symbol lists. */ - void mergeHuffmanSymbols(VideoFrame &video, byte *dst, const byte *src, int size); - - /** Read and translate a symbol out of a Huffman code. */ - byte getHuffmanSymbol(VideoFrame &video, Huffman &huffman); - - /** Get a direct value out of a bundle. */ - int32_t getBundleValue(Source source); - /** Read a count value out of a bundle. */ - uint32_t readBundleCount(VideoFrame &video, Bundle &bundle); - - // Handle the block types - void blockSkip (DecodeContext &ctx); - void blockScaledSkip (DecodeContext &ctx); - void blockScaledRun (DecodeContext &ctx); - void blockScaledIntra (DecodeContext &ctx); - void blockScaledFill (DecodeContext &ctx); - void blockScaledPattern(DecodeContext &ctx); - void blockScaledRaw (DecodeContext &ctx); - void blockScaled (DecodeContext &ctx); - void blockMotion (DecodeContext &ctx); - void blockRun (DecodeContext &ctx); - void blockResidue (DecodeContext &ctx); - void blockIntra (DecodeContext &ctx); - void blockFill (DecodeContext &ctx); - void blockInter (DecodeContext &ctx); - void blockPattern (DecodeContext &ctx); - void blockRaw (DecodeContext &ctx); - - // Read the bundles - void readRuns (VideoFrame &video, Bundle &bundle); - void readMotionValues(VideoFrame &video, Bundle &bundle); - void readBlockTypes (VideoFrame &video, Bundle &bundle); - void readPatterns (VideoFrame &video, Bundle &bundle); - void readColors (VideoFrame &video, Bundle &bundle); - void readDCS (VideoFrame &video, Bundle &bundle, int startBits, bool hasSign); - void readDCTCoeffs (VideoFrame &video, int16_t *block, bool isIntra); - void readResidue (VideoFrame &video, int16_t *block, int masksCount); - - // Bink video IDCT - void IDCT(int16_t *block); - void IDCTPut(DecodeContext &ctx, int16_t *block); - void IDCTAdd(DecodeContext &ctx, int16_t *block); - }; - - class BinkAudioTrack : public AudioTrack { - public: - BinkAudioTrack(size_t index, AudioInfo &audio); - ~BinkAudioTrack(); - - bool canBufferData() const; - - /** Decode audio data up to endTime. */ - void decodeAudio(Common::SeekableReadStream& bink, const std::vector& frames, const std::vector& audioTracks, const Common::Timestamp& endTime); - - protected: - Sound::AudioStream *getAudioStream() const; - - private: - size_t _index; - AudioInfo &_info; - Sound::PacketizedAudioStream *_audioStream; - uint32_t _curFrame; - Common::Timestamp _audioBuffered; - - float getFloat(Common::BitStream &bits); - - /** Decode an audio block. */ - void audioBlock(Common::BitStream &bits, int16_t *out); - /** Decode a DCT'd audio block. */ - void audioBlockDCT(Common::BitStream &bits); - /** Decode a RDFT'd audio block. */ - void audioBlockRDFT(Common::BitStream &bits); - - void readAudioCoeffs(Common::BitStream &bits, float *coeffs); - - static void floatToInt16Interleave(int16_t *dst, const float **src, uint32_t length, uint8_t channels); - }; - - void initAudioTrack(AudioInfo &audio); -}; - -} // End of namespace Video - -#endif // VIDEO_BINK_H diff --git a/data/Data.qrc b/data/Data.qrc index e1c377a..8929957 100644 --- a/data/Data.qrc +++ b/data/Data.qrc @@ -1,26 +1,4 @@ - - obj/defaultactor_LOD0.XMODEL_BIN - obj/defaultactor_LOD0.XMODEL_EXPORT - obj/defaultactor_LOD0.bin - obj/defaultactor_LOD0.cast - obj/defaultactor_LOD0.gltf - obj/defaultactor_LOD0.ma - obj/defaultactor_LOD0.mesh.ascii - obj/defaultactor_LOD0.obj - obj/defaultactor_LOD0.semodel - obj/defaultactor_LOD0.smd - obj/defaultactor_LOD0_BIND.mel - obj/defaultactor_LOD0_cosmetics.mel - obj/diffusemap.png - obj/mtl_body_default_character.mtl - obj/mtl_body_default_character_images.txt - obj/normalmap.png - - - d3dbsp/asset_viewer.d3dbsp - d3dbsp/barebones.d3dbsp - images/XPlor.png images/copy.svg @@ -34,28 +12,6 @@ images/save.svg - icons/Icon_COD4.png - icons/Icon_COD5.png - icons/Icon_COD6.png - icons/Icon_COD7.png - icons/Icon_COD8.png - icons/Icon_COD9.png - icons/Icon_DDSFile.png - icons/Icon_FastFile.png - icons/Icon_IWIFile.png - icons/Icon_PC.png - icons/Icon_Playstation.png - icons/Icon_Xbox.png - icons/Icon_ZoneFile.png - icons/Icon_GSCFile.png - icons/Icon_StringFile.png - icons/Icon_TechSetFile.png - icons/Icon_WAVFile.png - icons/Icon_MenuFile.png - icons/Icon_Image.png - icons/Icon_Model.png - icons/Icon_StringTable.png - icons/Icon_Sound.png icons/Icon_Pause.png icons/Icon_Play.png icons/Icon_SkipBack.png @@ -71,21 +27,5 @@ icons/Icon_Paste.png icons/Icon_Save.png icons/Icon_OpenFile.png - icons/Icon_COD2.png - icons/Icon_Material.png - icons/Icon_Animation.png - icons/Icon_BSP.png - icons/Icon_ColMapSp.png - icons/Icon_Effect.png - icons/Icon_GameMapSp.png - icons/Icon_Font.png - icons/Icon_FXMap.png - icons/Icon_LightDef.png - icons/Icon_Weapon.png - icons/Icon_RawFile.png - icons/Icon_Destructible.png - icons/Icon_PhysPreset.png - icons/Icon_Wii.png - icons/Icon_WiiU.png diff --git a/data/icons/Icon.psd b/data/icons/Icon.psd new file mode 100644 index 0000000..d4a51db Binary files /dev/null and b/data/icons/Icon.psd differ diff --git a/data/icons/Icon_Animation.png b/data/icons/Icon_Animation.png deleted file mode 100644 index 0dc0e31..0000000 Binary files a/data/icons/Icon_Animation.png and /dev/null differ diff --git a/data/icons/Icon_BSP.png b/data/icons/Icon_BSP.png deleted file mode 100644 index 4a3ab1d..0000000 Binary files a/data/icons/Icon_BSP.png and /dev/null differ diff --git a/data/icons/Icon_COD2.png b/data/icons/Icon_COD2.png deleted file mode 100644 index 470c389..0000000 Binary files a/data/icons/Icon_COD2.png and /dev/null differ diff --git a/data/icons/Icon_COD4.png b/data/icons/Icon_COD4.png deleted file mode 100644 index fa0df53..0000000 Binary files a/data/icons/Icon_COD4.png and /dev/null differ diff --git a/data/icons/Icon_COD5.png b/data/icons/Icon_COD5.png deleted file mode 100644 index 81b926a..0000000 Binary files a/data/icons/Icon_COD5.png and /dev/null differ diff --git a/data/icons/Icon_COD6.png b/data/icons/Icon_COD6.png deleted file mode 100644 index aecb4b0..0000000 Binary files a/data/icons/Icon_COD6.png and /dev/null differ diff --git a/data/icons/Icon_COD7.png b/data/icons/Icon_COD7.png deleted file mode 100644 index d237f37..0000000 Binary files a/data/icons/Icon_COD7.png and /dev/null differ diff --git a/data/icons/Icon_COD8.png b/data/icons/Icon_COD8.png deleted file mode 100644 index 57f6d45..0000000 Binary files a/data/icons/Icon_COD8.png and /dev/null differ diff --git a/data/icons/Icon_COD9.png b/data/icons/Icon_COD9.png deleted file mode 100644 index ac82d59..0000000 Binary files a/data/icons/Icon_COD9.png and /dev/null differ diff --git a/data/icons/Icon_ColMapSp.png b/data/icons/Icon_ColMapSp.png deleted file mode 100644 index 085e84d..0000000 Binary files a/data/icons/Icon_ColMapSp.png and /dev/null differ diff --git a/data/icons/Icon_DDSFile.png b/data/icons/Icon_DDSFile.png deleted file mode 100644 index d9aa7eb..0000000 Binary files a/data/icons/Icon_DDSFile.png and /dev/null differ diff --git a/data/icons/Icon_Destructible.png b/data/icons/Icon_Destructible.png deleted file mode 100644 index 06f5eb1..0000000 Binary files a/data/icons/Icon_Destructible.png and /dev/null differ diff --git a/data/icons/Icon_Effect.png b/data/icons/Icon_Effect.png deleted file mode 100644 index ba41f66..0000000 Binary files a/data/icons/Icon_Effect.png and /dev/null differ diff --git a/data/icons/Icon_FXMap.png b/data/icons/Icon_FXMap.png deleted file mode 100644 index f434048..0000000 Binary files a/data/icons/Icon_FXMap.png and /dev/null differ diff --git a/data/icons/Icon_FastFile.png b/data/icons/Icon_FastFile.png deleted file mode 100644 index 8221e33..0000000 Binary files a/data/icons/Icon_FastFile.png and /dev/null differ diff --git a/data/icons/Icon_Font.png b/data/icons/Icon_Font.png deleted file mode 100644 index 1af47b2..0000000 Binary files a/data/icons/Icon_Font.png and /dev/null differ diff --git a/data/icons/Icon_GSCFile.png b/data/icons/Icon_GSCFile.png deleted file mode 100644 index 9a5fad0..0000000 Binary files a/data/icons/Icon_GSCFile.png and /dev/null differ diff --git a/data/icons/Icon_GameMapSp.png b/data/icons/Icon_GameMapSp.png deleted file mode 100644 index 6b72e9a..0000000 Binary files a/data/icons/Icon_GameMapSp.png and /dev/null differ diff --git a/data/icons/Icon_IWIFile.png b/data/icons/Icon_IWIFile.png deleted file mode 100644 index 0a9e2fd..0000000 Binary files a/data/icons/Icon_IWIFile.png and /dev/null differ diff --git a/data/icons/Icon_Image.png b/data/icons/Icon_Image.png deleted file mode 100644 index 5f31b19..0000000 Binary files a/data/icons/Icon_Image.png and /dev/null differ diff --git a/data/icons/Icon_LightDef.png b/data/icons/Icon_LightDef.png deleted file mode 100644 index 20689ba..0000000 Binary files a/data/icons/Icon_LightDef.png and /dev/null differ diff --git a/data/icons/Icon_Material.png b/data/icons/Icon_Material.png deleted file mode 100644 index 2e9d2e8..0000000 Binary files a/data/icons/Icon_Material.png and /dev/null differ diff --git a/data/icons/Icon_MenuFile.png b/data/icons/Icon_MenuFile.png deleted file mode 100644 index 7d40946..0000000 Binary files a/data/icons/Icon_MenuFile.png and /dev/null differ diff --git a/data/icons/Icon_Model.png b/data/icons/Icon_Model.png deleted file mode 100644 index c5e0355..0000000 Binary files a/data/icons/Icon_Model.png and /dev/null differ diff --git a/data/icons/Icon_PC.png b/data/icons/Icon_PC.png deleted file mode 100644 index b71e03d..0000000 Binary files a/data/icons/Icon_PC.png and /dev/null differ diff --git a/data/icons/Icon_PhysPreset.png b/data/icons/Icon_PhysPreset.png deleted file mode 100644 index 5e4339f..0000000 Binary files a/data/icons/Icon_PhysPreset.png and /dev/null differ diff --git a/data/icons/Icon_Playstation.png b/data/icons/Icon_Playstation.png deleted file mode 100644 index c706d53..0000000 Binary files a/data/icons/Icon_Playstation.png and /dev/null differ diff --git a/data/icons/Icon_RawFile.png b/data/icons/Icon_RawFile.png deleted file mode 100644 index 1281b71..0000000 Binary files a/data/icons/Icon_RawFile.png and /dev/null differ diff --git a/data/icons/Icon_Sound.png b/data/icons/Icon_Sound.png deleted file mode 100644 index f55c471..0000000 Binary files a/data/icons/Icon_Sound.png and /dev/null differ diff --git a/data/icons/Icon_StringFile.png b/data/icons/Icon_StringFile.png deleted file mode 100644 index ac3e25f..0000000 Binary files a/data/icons/Icon_StringFile.png and /dev/null differ diff --git a/data/icons/Icon_StringTable.png b/data/icons/Icon_StringTable.png deleted file mode 100644 index 9ca4722..0000000 Binary files a/data/icons/Icon_StringTable.png and /dev/null differ diff --git a/data/icons/Icon_TechSetFile.png b/data/icons/Icon_TechSetFile.png deleted file mode 100644 index 96fc774..0000000 Binary files a/data/icons/Icon_TechSetFile.png and /dev/null differ diff --git a/data/icons/Icon_WAVFile.png b/data/icons/Icon_WAVFile.png deleted file mode 100644 index f7e43e8..0000000 Binary files a/data/icons/Icon_WAVFile.png and /dev/null differ diff --git a/data/icons/Icon_Weapon.png b/data/icons/Icon_Weapon.png deleted file mode 100644 index 76e98e7..0000000 Binary files a/data/icons/Icon_Weapon.png and /dev/null differ diff --git a/data/icons/Icon_Wii.png b/data/icons/Icon_Wii.png deleted file mode 100644 index efed38a..0000000 Binary files a/data/icons/Icon_Wii.png and /dev/null differ diff --git a/data/icons/Icon_WiiU.png b/data/icons/Icon_WiiU.png deleted file mode 100644 index a827c6a..0000000 Binary files a/data/icons/Icon_WiiU.png and /dev/null differ diff --git a/data/icons/Icon_Xbox.png b/data/icons/Icon_Xbox.png deleted file mode 100644 index c25da9a..0000000 Binary files a/data/icons/Icon_Xbox.png and /dev/null differ diff --git a/data/icons/Icon_ZoneFile.png b/data/icons/Icon_ZoneFile.png deleted file mode 100644 index f9e8daf..0000000 Binary files a/data/icons/Icon_ZoneFile.png and /dev/null differ diff --git a/data/obj/defaultactor_LOD0.gltf b/data/obj/defaultactor_LOD0.gltf index b1c0e0d..f31bc03 100644 --- a/data/obj/defaultactor_LOD0.gltf +++ b/data/obj/defaultactor_LOD0.gltf @@ -234,7 +234,7 @@ "WEIGHTS_0": 6 }, "indices": 1, - "material": 0, + ASSET_MATERIAL: 0, "mode": 4 } ] @@ -250,7 +250,7 @@ "WEIGHTS_0": 12 }, "indices": 7, - "material": 0, + ASSET_MATERIAL: 0, "mode": 4 } ] diff --git a/data/obj/diffusemap.png b/data/obj/diffusemap.png deleted file mode 100644 index de266f3..0000000 Binary files a/data/obj/diffusemap.png and /dev/null differ diff --git a/data/obj/normalmap.png b/data/obj/normalmap.png deleted file mode 100644 index 486181e..0000000 Binary files a/data/obj/normalmap.png and /dev/null differ diff --git a/enums.h b/enums.h deleted file mode 100644 index 734e146..0000000 --- a/enums.h +++ /dev/null @@ -1,670 +0,0 @@ -#ifndef ENUMS_H -#define ENUMS_H - -#include "qtypes.h" -enum LUMP_TYPE -{ - LUMP_MATERIALS = 0x0, - LUMP_LIGHTBYTES = 0x1, - LUMP_LIGHTGRIDENTRIES = 0x2, - LUMP_LIGHTGRIDCOLORS = 0x3, - LUMP_PLANES = 0x4, - LUMP_BRUSHSIDES = 0x5, - LUMP_BRUSHSIDEEDGECOUNTS = 0x6, - LUMP_BRUSHEDGES = 0x7, - LUMP_BRUSHES = 0x8, - LUMP_TRIANGLES = 0x9, - LUMP_DRAWVERTS = 0xA, - LUMP_DRAWINDICES = 0xB, - LUMP_CULLGROUPS = 0xC, - LUMP_CULLGROUPINDICES = 0xD, - LUMP_OBSOLETE_1 = 0xE, - LUMP_OBSOLETE_2 = 0xF, - LUMP_OBSOLETE_3 = 0x10, - LUMP_OBSOLETE_4 = 0x11, - LUMP_OBSOLETE_5 = 0x12, - LUMP_PORTALVERTS = 0x13, - LUMP_OBSOLETE_6 = 0x14, - LUMP_UINDS = 0x15, - LUMP_BRUSHVERTSCOUNTS = 0x16, - LUMP_BRUSHVERTS = 0x17, - LUMP_AABBTREES = 0x18, - LUMP_CELLS = 0x19, - LUMP_PORTALS = 0x1A, - LUMP_NODES = 0x1B, - LUMP_LEAFS = 0x1C, - LUMP_LEAFBRUSHES = 0x1D, - LUMP_LEAFSURFACES = 0x1E, - LUMP_COLLISIONVERTS = 0x1F, - LUMP_COLLISIONTRIS = 0x20, - LUMP_COLLISIONEDGEWALKABLE = 0x21, - LUMP_COLLISIONBORDERS = 0x22, - LUMP_COLLISIONPARTITIONS = 0x23, - LUMP_COLLISIONAABBS = 0x24, - LUMP_MODELS = 0x25, - LUMP_VISIBILITY = 0x26, - LUMP_ENTITIES = 0x27, - LUMP_PATHCONNECTIONS = 0x28, - LUMP_REFLECTION_PROBES = 0x29, - LUMP_VERTEX_LAYER_DATA = 0x2A, - LUMP_PRIMARY_LIGHTS = 0x2B, - LUMP_LIGHTGRIDHEADER = 0x2C, - LUMP_LIGHTGRIDROWS = 0x2D, - LUMP_OBSOLETE_10 = 0x2E, - - //Obsolete in BO1///////////////// - LUMP_UNLAYERED_TRIANGLES = 0x2F, - LUMP_UNLAYERED_DRAWVERTS = 0x30, - LUMP_UNLAYERED_DRAWINDICES = 0x31, - LUMP_UNLAYERED_CULLGROUPS = 0x32, - LUMP_UNLAYERED_AABBTREES = 0x33, - ////////////////////////////////// - - LUMP_WATERHEADER = 0x34, - LUMP_WATERCELLS = 0x35, - LUMP_WATERCELLDATA = 0x36, - LUMP_BURNABLEHEADER = 0x37, - LUMP_BURNABLECELLS = 0x38, - LUMP_BURNABLECELLDATA = 0x39, - LUMP_SIMPLELIGHTMAPBYTES = 0x3A, - LUMP_LODCHAINS = 0x3B, - LUMP_LODINFOS = 0x3C, - LUMP_LODSURFACES = 0x3D, - LUMP_LIGHTREGIONS = 0x3E, - LUMP_LIGHTREGION_HULLS = 0x3F, - LUMP_LIGHTREGION_AXES = 0x40, - LUMP_WIILIGHTGRID = 0x41, - LUMP_LIGHTGRID2D_LIGHTS = 0x42, - LUMP_LIGHTGRID2D_INDICES = 0x43, - LUMP_LIGHTGRID2D_POINTS = 0x44, - LUMP_LIGHTGRID2D_CELLS = 0x45, - LUMP_LIGHT_CORONAS = 0x46, - - //BO Specific///////////////////////// - LUMP_SHADOWMAP_VOLUMES = 0x47, - LUMP_SHADOWMAP_VOLUME_PLANES = 0x48, - LUMP_EXPOSURE_VOLUMES = 0x49, - LUMP_EXPOSURE_VOLUME_PLANES = 0x4A, - LUMP_OCCLUDERS = 0x4B, - LUMP_OUTDOORBOUNDS = 0x4C, - LUMP_HERO_ONLY_LIGHTS = 0x4D, - ////////////////////////////////////// - - INFO_LUMP_TYPE_COUNT -}; - -enum BSPVERSION_TYPE -{ - BSPVERSION_COD_WAW = 31, - BSPVERSION_COD_BO = 45 -}; - -enum MENU_ITEM_TYPE { - ITEM_TYPE_TEXT = 0, // simple text - ITEM_TYPE_BUTTON = 1, // button, basically text with a border - ITEM_TYPE_RADIOBUTTON = 2, // toggle button, may be grouped - ITEM_TYPE_CHECKBOX = 3, // check box - ITEM_TYPE_EDITFIELD = 4, // editable text, associated with a dvar - ITEM_TYPE_COMBO = 5, // drop down list - ITEM_TYPE_LISTBOX = 6, // scrollable list - ITEM_TYPE_MODEL = 7, // model - ITEM_TYPE_OWNERDRAW = 8, // owner draw, name specs what it is - ITEM_TYPE_NUMERICFIELD = 9, // editable text, associated with a dvar - ITEM_TYPE_SLIDER = 10, // mouse speed, volume, etc. - ITEM_TYPE_YESNO = 11, // yes no dvar setting - ITEM_TYPE_MULTI = 12, // multiple list setting, enumerated - ITEM_TYPE_DVARENUM = 13, // multiple list setting, enumerated from a dvar - ITEM_TYPE_BIND = 14, // bind - ITEM_TYPE_MENUMODEL = 15, // special menu model - ITEM_TYPE_VALIDFILEFIELD = 16, // text must be valid for use in a dos filename - ITEM_TYPE_DECIMALFIELD = 17, // editable text, associated with a dvar, which allows decimal input - ITEM_TYPE_UPREDITFIELD = 18, // editable text, associated with a dvar - ITEM_TYPE_GAME_MESSAGE_WINDOW = 19, // game message window - ITEM_TYPE_SCALEFORM = 20, // Flash movie for Scaleform GFx - ITEM_TYPE_BIND2 = 21, // bind2 -}; - -enum MENU_ITEM_H_ALIGN { - ITEM_ALIGN_LEFT = 0, // aligns left of text to left of containing rectangle - ITEM_ALIGN_CENTER = 1, // aligns center of text to center of containing rectangle - ITEM_ALIGN_RIGHT = 2, // aligns right of text to right of containing rectangle - ITEM_ALIGN_X_MASK = 3, -}; - -enum MENU_ITEM_V_ALIGN { - ITEM_ALIGN_LEGACY = 0, // aligns bottom of text to top of containing rectangle - ITEM_ALIGN_TOP = 4, // aligns top of text to top of containing rectangle - ITEM_ALIGN_MIDDLE = 8, // aligns middle of text to middle of containing rectangle - ITEM_ALIGN_BOTTOM = 12, // aligns bottom of text to bottom of containing rectangle - ITEM_ALIGN_Y_MASK = 12, -}; - -enum MENU_ITEM_ALIGN { - ITEM_ALIGN_LEGACY_LEFT = 0, - ITEM_ALIGN_LEGACY_CENTER = 1, - ITEM_ALIGN_LEGACY_RIGHT = 2, - ITEM_ALIGN_TOP_LEFT = 4, - ITEM_ALIGN_TOP_CENTER = 5, - ITEM_ALIGN_TOP_RIGHT = 6, - ITEM_ALIGN_MIDDLE_LEFT = 8, - ITEM_ALIGN_MIDDLE_CENTER = 9, - ITEM_ALIGN_MIDDLE_RIGHT = 10, - ITEM_ALIGN_BOTTOM_LEFT = 12, - ITEM_ALIGN_BOTTOM_CENTER = 13, - ITEM_ALIGN_BOTTOM_RIGHT = 14 -}; - -enum MENU_ITEM_TEXTSTYLE { - ITEM_TEXTSTYLE_NORMAL = 0, // normal text - ITEM_TEXTSTYLE_BLINK = 1, // fast blinking - ITEM_TEXTSTYLE_SHADOWED = 3, // drop shadow ( need a color for this ) - ITEM_TEXTSTYLE_SHADOWEDMORE = 6, // drop shadow ( need a color for this ) - ITEM_TEXTSTYLE_MONOSPACE = 128 -}; - -enum MENU_WINDOW_BORDER { - WINDOW_BORDER_NONE = 0, // no border - WINDOW_BORDER_FULL = 1, // full border based on border color ( single pixel ) - WINDOW_BORDER_HORZ = 2, // horizontal borders only - WINDOW_BORDER_VERT = 3, // vertical borders only - WINDOW_BORDER_KCGRADIENT = 4, // horizontal border using the gradient bars - WINDOW_BORDER_RAISED = 5, // darken the bottom and right sides of the border - WINDOW_BORDER_SUNKEN = 6 // darken the top and left sides of the border -}; - -enum MENU_WINDOW_STYLE { - WINDOW_STYLE_EMPTY = 0, // no background - WINDOW_STYLE_FILLED = 1, // filled with background color - WINDOW_STYLE_GRADIENT = 2, // gradient bar based on background color - WINDOW_STYLE_SHADER = 3, // shader based on background color - WINDOW_STYLE_TEAMCOLOR = 4, // team color - WINDOW_STYLE_DVAR_SHADER = 5, // draws the shader specified by the dvar - WINDOW_STYLE_LOADBAR = 6, // shader based on background color -}; - -enum MENU_MODE { - MODE_BOTTOMUP_ALIGN_TOP = 0, // text appears on bottom of list and moves up to specified Y coordinate as old text fades out - MODE_BOTTOMUP_ALIGN_BOTTOM = 1, // text appears on bottom of list and moves away from specified Y coordinate as new text pushes it up - MODE_TOPDOWN_ALIGN_TOP = 2, // text appears on top of list and moves away from specified Y coordinate as new text pushes it down - MODE_TOPDOWN_ALIGN_BOTTOM = 3 // text appears on top of list and moves down to specified Y coordinate as old text fades out -}; - -enum MENU_BOOL { - MENU_TRUE = 1, - MENU_FALSE = 0 -}; - -enum MENU_ORIENTATION { - HUD_VERTICAL = 0x00, - HUD_HORIZONTAL = 0x01 -}; - -enum MENU_RANGETYPE { - RANGETYPE_ABSOLUTE = 0, - RANGETYPE_RELATIVE = 1 -}; - -// list box element types -enum MENU_LIST_BOX { - LISTBOX_TEXT = 0x00, - LISTBOX_IMAGE = 0x01 -}; - -// list feeders -enum MENU_FEEDERS { - FEEDER_HEADS = 0x00, // model heads - FEEDER_MAPS = 0x01, // text maps based on game type - FEEDER_SERVERS = 0x02, // servers - FEEDER_CLAN_MEMBERS = 0x03, // clan names - FEEDER_ALLMAPS = 0x04, // all maps available, in graphic format - FEEDER_REDTEAM_LIST = 0x05, // red team members - FEEDER_BLUETEAM_LIST = 0x06, // blue team members - FEEDER_PLAYER_LIST = 0x07, // players - FEEDER_TEAM_LIST = 0x08, // team members for team voting - FEEDER_MODS = 0x09, // team members for team voting - FEEDER_DEMOS = 0x0a, // team members for team voting - FEEDER_SCOREBOARD = 0x0b, // team members for team voting - FEEDER_Q3HEADS = 0x0c, // model heads - FEEDER_SERVERSTATUS = 0x0d, // server status - FEEDER_FINDPLAYER = 0x0e, // find player - FEEDER_CINEMATICS = 0x0f, // cinematics - FEEDER_SAVEGAMES = 0x10, // savegames - FEEDER_PICKSPAWN = 0x11, // pickspawn - FEEDER_LOBBY_MEMBERS = 0x12, // list of players in your party - FEEDER_LOBBY_MEMBERS_TALK = 0x13, // icon for whether they are speaking or not - FEEDER_MUTELIST = 0x14, // list of musted players - FEEDER_PLAYERSTALKING = 0x15, // list of players who are currently talking - FEEDER_SPLITSCREENPLAYERS = 0x16, // list of all players who are playing splitscreen - FEEDER_LOBBY_MEMBERS_READY = 0x17, // icon for whether they are ready or not - FEEDER_PLAYER_PROFILES = 0x18, // player profiles - FEEDER_PARTY_MEMBERS = 0x19, // list of players in your party - FEEDER_PARTY_MEMBERS_TALK = 0x1a, // icon for whether they are speaking or not - FEEDER_PARTY_MEMBERS_READY = 0x1b, // icon for whether they are ready or not - FEEDER_PLAYLISTS = 0x1c, // list of all playlists - FEEDER_GAMEMODES = 0x1d, // list of all game type modes, including any player custom modes - FEEDER_CATEGORIES = 0x1e, // list of all categories - FEEDER_LEADERBOARD = 0x1f, // list of rows for a leaderboard - FEEDER_MYTEAM_MEMBERS = 0x20, // list of marine team members - FEEDER_MYTEAM_MEMBERS_TALK = 0x21, // icon for whether they are speaking - FEEDER_ENEMY_MEMBERS = 0x22, // list of opfor team members - FEEDER_ENEMY_MEMBERS_TALK = 0x23, // icon for whether they are speaking - FEEDER_LOBBY_MEMBERS_STAT = 0x24, // last round stats for lobby members - FEEDER_MYTEAM_MEMBERS_STAT = 0x25, // last round stats for marine team members - FEEDER_ENEMY_MEMBERS_STAT = 0x26, // last round stats for opfor team members - FEEDER_ONLINEFRIENDS = 0x27, // list of your online friends - FEEDER_LOBBY_MEMBERS_RANK = 0x28, // rank icon - FEEDER_PARTY_MEMBERS_RANK = 0x29, // rank icon - FEEDER_ENEMY_MEMBERS_RANK = 0x2a, // rank icon - FEEDER_MYTEAM_MEMBERS_RANK = 0x2b, // rank icon - FEEDER_TESTMAPS = 0x2c, // department test maps - FEEDER_SYSTEMLINK_LOBBY_MEMBERS = 0x2d, // list of players in a system link lobby - FEEDER_LOBBY_MEMBERS_CONTROLLER = 0x2e, // icon for controller quadrant for splitscreen - FEEDER_PARTY_MEMBERS_CONTROLLER = 0x2f, // icon for controller quadrant for splitscreen - FEEDER_MYTEAM_MEMBERS_SQUAD = 0x30, // squad icon - FEEDER_ENEMY_MEMBERS_SQUAD = 0x31, // squad icon - FEEDER_INGAME_SQUAD_MEMBERS = 0x32, // Squad members displayed in MP 'Pause' menu - FEEDER_INGAME_SQUAD_MEMBERS_FULL = 0x33, // Squad members' name, rank, talk, leader displayed in PC MP 'Pause' menu - FEEDER_INGAME_SQUAD_NAMES = 0x34, // Squad names displayed in MP 'Join Squad' menu - FEEDER_INGAME_SQUAD_NAMES2 = 0x35, // Squad names displayed in MP 'Pause' menu - FEEDER_INGAME_SQUAD_NAMES_FULL = 0x36, // Squad names, lock, invite displayed in PC MP 'Pause' menu - FEEDER_CUSTOM_GAMETYPES = 0x37, // list of all the gametypes for custom matches - FEEDER_INGAME_SQUAD_MEMBER_RANK = 0x38, // Squad members' rank displayed in MP 'Pause' menu - FEEDER_INGAME_SQUAD_MEMBER_TALK = 0x39, // Squad members' talk icon displayed in MP 'Pause' menu - FEEDER_INGAME_SQUAD_LOCKED = 0x3a, // Squad lock icon displayed in MP 'Pause' menu - FEEDER_INGAME_SQUAD_MEMBER_INVITED = 0x3b, // Squad invite icon displayed in MP 'Pause' menu - FEEDER_INGAME_SQUAD_INVITE = 0x3c, // Squad invite icon displayed in MP 'Join Squad' menu - FEEDER_INGAME_SQUAD_LEADER = 0x3d, // Squad leader icon displayled in MP 'Pause' menu - FEEDER_FRIENDS = 0x3e, // list of your friends - FEEDER_PENDINGFRIENDS = 0x3f, // list of your pending friends - FEEDER_INVITES = 0x40, // list of the game invites from your friends -}; - -// display flags -enum MENU_DISPLAY_FLAG { - CG_SHOW_BLUE_TEAM_HAS_REDFLAG = 0x00000001, - CG_SHOW_RED_TEAM_HAS_BLUEFLAG = 0x00000002, - CG_SHOW_ANYTEAMGAME = 0x00000004, - CG_SHOW_CTF = 0x00000020, - CG_SHOW_OBELISK = 0x00000040, - CG_SHOW_HEALTHCRITICAL = 0x00000080, - CG_SHOW_SINGLEPLAYER = 0x00000100, - CG_SHOW_TOURNAMENT = 0x00000200, - CG_SHOW_DURINGINCOMINGVOICE = 0x00000400, - CG_SHOW_IF_PLAYER_HAS_FLAG = 0x00000800, - CG_SHOW_LANPLAYONLY = 0x00001000, - CG_SHOW_MINED = 0x00002000, - CG_SHOW_HEALTHOK = 0x00004000, - CG_SHOW_TEAMINFO = 0x00008000, - CG_SHOW_NOTEAMINFO = 0x00010000, - CG_SHOW_OTHERTEAMHASFLAG = 0x00020000, - CG_SHOW_YOURTEAMHASENEMYFLAG = 0x00040000, - CG_SHOW_ANYNONTEAMGAME = 0x00080000, - CG_SHOW_TEXTASINT = 0x00200000, - CG_SHOW_HIGHLIGHTED = 0x00100000, - CG_SHOW_NOT_V_CLEAR = 0x02000000, - CG_SHOW_2DONLY = 0x10000000 -}; - -enum MENU_UI_FLAG{ - UI_SHOW_LEADER = 0x00000001, - UI_SHOW_NOTLEADER = 0x00000002, - UI_SHOW_FAVORITESERVERS = 0x00000004, - UI_SHOW_ANYNONTEAMGAME = 0x00000008, - UI_SHOW_ANYTEAMGAME = 0x00000010, - UI_SHOW_NEWHIGHSCORE = 0x00000020, - UI_SHOW_DEMOAVAILABLE = 0x00000040, - UI_SHOW_NEWBESTTIME = 0x00000080, - UI_SHOW_FFA = 0x00000100, - UI_SHOW_NOTFFA = 0x00000200, - UI_SHOW_NETANYNONTEAMGAME = 0x00000400, - UI_SHOW_NETANYTEAMGAME = 0x00000800, - UI_SHOW_NOTFAVORITESERVERS = 0x00001000 -}; - -// font types -enum MENU_FONT_TYPE{ - UI_FONT_DEFAULT = 0, // auto-chose betwen big/reg/small - UI_FONT_NORMAL = 1, - UI_FONT_BIG = 2, - UI_FONT_SMALL = 3, - UI_FONT_BOLD = 4, - UI_FONT_CONSOLE = 5, - UI_FONT_OBJECTIVE = 6, - UI_FONT_MAX = 6, -}; - -// owner draw types -// ideally these should be done outside of this file but -// this makes it much easier for the macro expansion to -// convert them for the designers ( from the .menu files ) -enum MENU_OWNER_DRAW_TYPE { - CG_OWNERDRAW_BASE = 1, - CG_PLAYER_AMMO_VALUE = 5, - CG_PLAYER_AMMO_BACKDROP = 6, - CG_PLAYER_HEAT_VALUE = 7, - CG_PLAYER_STANCE = 20, - CG_SPECTATORS = 60, - CG_HOLD_BREATH_HINT = 71, - CG_CURSORHINT = 72, - CG_PLAYER_POWERUP = 73, - CG_PLAYER_HOLDABLE = 74, - CG_PLAYER_INVENTORY = 75, - CG_CURSORHINT_STATUS = 78, // like 'health' bar when pointing at a func_explosive - CG_PLAYER_BAR_HEALTH = 79, - CG_MANTLE_HINT = 80, - CG_PLAYER_WEAPON_NAME = 81, - CG_PLAYER_WEAPON_NAME_BACK = 82, - CG_CENTER_MESSAGE = 90, // for things like "You were killed by ..." - CG_TANK_BODY_DIR = 95, - CG_TANK_BARREL_DIR = 96, - CG_DEADQUOTE = 97, - CG_PLAYER_BAR_HEALTH_BACK = 98, - CG_MISSION_OBJECTIVE_HEADER = 99, - CG_MISSION_OBJECTIVE_LIST = 100, - CG_MISSION_OBJECTIVE_BACKDROP = 101, - CG_PAUSED_MENU_LINE = 102, - CG_OFFHAND_WEAPON_ICON_FRAG = 103, - CG_OFFHAND_WEAPON_ICON_SMOKEFLASH = 104, - CG_OFFHAND_WEAPON_AMMO_FRAG = 105, - CG_OFFHAND_WEAPON_AMMO_SMOKEFLASH = 106, - CG_OFFHAND_WEAPON_NAME_FRAG = 107, - CG_OFFHAND_WEAPON_NAME_SMOKEFLASH = 108, - CG_OFFHAND_WEAPON_SELECT_FRAG = 109, - CG_OFFHAND_WEAPON_SELECT_SMOKEFLASH = 110, - CG_SAVING = 111, - CG_PLAYER_LOW_HEALTH_OVERLAY = 112, - CG_INVALID_CMD_HINT = 113, - CG_PLAYER_SPRINT_METER = 114, - CG_PLAYER_SPRINT_BACK = 115, - CG_PLAYER_WEAPON_BACKGROUND = 116, - CG_PLAYER_WEAPON_AMMO_CLIP_GRAPHIC = 117, - CG_PLAYER_WEAPON_PRIMARY_ICON = 118, - CG_PLAYER_WEAPON_AMMO_STOCK = 119, - CG_PLAYER_WEAPON_LOW_AMMO_WARNING = 120, - CG_BATTLE_COMPASS_MARKERS = 122, - CG_BATTLE_FULLMAP_MARKERS = 123, - CG_SUCCESSFUL_CMD_HINT = 130, - CG_WAR_TEXT = 135, - CG_PLAYER_COMPASS_TICKERTAPE = 145, - CG_PLAYER_COMPASS_TICKERTAPE_NO_OBJ = 146, - CG_PLAYER_COMPASS_DOGS = 147, - CG_PLAYER_COMPASS_ARTILLERY_ICON = 148, - CG_PLAYER_COMPASS_SQUAD_OBJECTIVE = 149, - CG_PLAYER_COMPASS_PLAYER = 150, - CG_PLAYER_COMPASS_BACK = 151, - CG_PLAYER_COMPASS_POINTERS = 152, - CG_PLAYER_COMPASS_ACTORS = 153, - CG_PLAYER_COMPASS_TANKS = 154, - CG_PLAYER_COMPASS_HELICOPTERS = 155, - CG_PLAYER_COMPASS_PLANES = 156, - CG_PLAYER_COMPASS_AUTOMOBILES = 157, - CG_PLAYER_COMPASS_FRIENDS = 158, - CG_PLAYER_COMPASS_MAP = 159, - CG_PLAYER_COMPASS_NORTHCOORD = 160, - CG_PLAYER_COMPASS_EASTCOORD = 161, - CG_PLAYER_COMPASS_NCOORD_SCROLL = 162, - CG_PLAYER_COMPASS_ECOORD_SCROLL = 163, - CG_PLAYER_COMPASS_GOALDISTANCE = 164, - CG_PLAYER_ACTIONSLOT_DPAD = 165, - CG_PLAYER_ACTIONSLOT_1 = 166, - CG_PLAYER_ACTIONSLOT_2 = 167, - CG_PLAYER_ACTIONSLOT_3 = 168, - CG_PLAYER_ACTIONSLOT_4 = 169, - CG_PLAYER_COMPASS_ENEMIES = 170, - CG_PLAYER_FULLMAP_DOGS = 176, - CG_PLAYER_FULLMAP_VEHICLES = 177, - CG_PLAYER_FULLMAP_ARTILLERY_ICON = 178, - CG_PLAYER_FULLMAP_SQUAD_OBJECTIVE = 179, - CG_PLAYER_FULLMAP_BACK = 180, - CG_PLAYER_FULLMAP_MAP = 181, - CG_PLAYER_FULLMAP_POINTERS = 182, - CG_PLAYER_FULLMAP_PLAYER = 183, - CG_PLAYER_FULLMAP_ACTORS = 184, - CG_PLAYER_FULLMAP_FRIENDS = 185, - CG_PLAYER_FULLMAP_LOCATION_SELECTOR = 186, - CG_PLAYER_FULLMAP_BORDER = 187, - CG_PLAYER_FULLMAP_ENEMIES = 188, - CG_PLAYER_COMPASS = 189, - CG_VEHICLE_RETICLE = 190, - CG_HUD_TARGETS_VEHICLE = 191, - CG_HUD_TARGETS_JAVELIN = 192, - CG_TALKER1 = 193, - CG_TALKER2 = 194, - CG_TALKER3 = 195, - CG_TALKER4 = 196, - CG_FRIENDLYARROWS = 197, - CG_FRIENDLYNAMES = 198, - UI_OWNERDRAW_BASE = 200, - UI_HANDICAP = 200, - UI_EFFECTS = 201, - UI_PLAYERMODEL = 202, - UI_GAMETYPE = 205, - UI_SKILL = 207, - UI_NETSOURCE = 220, - UI_NETFILTER = 222, - UI_VOTE_KICK = 238, - UI_NETGAMETYPE = 245, - UI_SERVERREFRESHDATE = 247, - UI_SERVERMOTD = 248, - UI_GLINFO = 249, - UI_KEYBINDSTATUS = 250, - UI_JOINGAMETYPE = 253, - UI_MAPPREVIEW = 254, - UI_MENUMODEL = 257, - UI_SAVEGAME_SHOT = 258, - UI_SAVEGAMENAME = 262, - UI_SAVEGAMEINFO = 263, - UI_LOADPROFILING = 264, - UI_RECORDLEVEL = 265, - UI_AMITALKING = 266, - UI_TALKER1 = 267, - UI_TALKER2 = 268, - UI_TALKER3 = 269, - UI_TALKER4 = 270, - UI_PARTYSTATUS = 271, - UI_LOGGEDINUSER = 272, - UI_RESERVEDSLOTS = 273, - UI_PLAYLISTNAME = 274, - UI_PLAYLISTDESCRIPTION = 275, - UI_USERNAME = 276, - UI_CINEMATIC = 277, - UI_TOTALONLINE = 278, - UI_CATEGORYNAME = 279, - UI_CATEGORYDESCRIPTION = 280, - UI_PLAYLISTICON = 281, - UI_CATEGORYICON = 282, - UI_GAMETYPE_MAPNAME = 283, - CG_HUD_WAR_MOMENTUM_PROGRESS = 284, - CG_HUD_WAR_MOMENTUM_MULTIPLIER = 285, - CG_HUD_WAR_MOMENTUM_MULTIPLIER_DETAIL = 286, - CG_HUD_WAR_MOMENTUM_MULTIPLIER_BLITZKRIEG = 287, - CG_COMPETITIVE_MODE_SCORES = 288, - UI_LOAD_STATUS_SCREEN = 289, - UI_LEADERBOARD_GAMEMODE = 290, - CG_PLAYER_ACTIONSLOT_BACK_1 = 290, - CG_PLAYER_ACTIONSLOT_BACK_2 = 291, - CG_PLAYER_ACTIONSLOT_BACK_3 = 292, - CG_PLAYER_ACTIONSLOT_BACK_4 = 293, - CG_PLAYER_ACTIONSLOT_ARROW_1 = 294, - CG_PLAYER_ACTIONSLOT_ARROW_2 = 295, - CG_PLAYER_ACTIONSLOT_ARROW_3 = 296, - CG_PLAYER_ACTIONSLOT_ARROW_4 = 297, - UI_DIFFICULTY_INFO = 298, - UI_DIFFICULTY_ICON = 299, - UI_LOBBY_CHAT = 300 -}; - -// Edge relative placement values for rect->h_align and rect->v_align -enum MENU_H_ALIGNMENT { - HORIZONTAL_ALIGN_SUBLEFT = 0, // left edge of a 4:3 screen (safe area not included) - HORIZONTAL_ALIGN_LEFT = 1, // left viewable (safe area) edge - HORIZONTAL_ALIGN_CENTER = 2, // center of the screen (reticle) - HORIZONTAL_ALIGN_RIGHT = 3, // right viewable (safe area) edge - HORIZONTAL_ALIGN_FULLSCREEN = 4, // disregards safe area - HORIZONTAL_ALIGN_NOSCALE = 5, // uses exact parameters - neither adjusts for safe area nor scales for screen size - HORIZONTAL_ALIGN_TO640 = 6, // scales a real-screen resolution x down into the 0 - 640 range - HORIZONTAL_ALIGN_CENTER_SAFEAREA = 7, // center of the safearea - HORIZONTAL_ALIGN_MAX = HORIZONTAL_ALIGN_CENTER_SAFEAREA, - HORIZONTAL_ALIGN_DEFAULT = HORIZONTAL_ALIGN_SUBLEFT -}; - -enum MENU_V_ALIGNMENT { - VERTICAL_ALIGN_SUBTOP = 0, // top edge of the 4:3 screen (safe area not included) - VERTICAL_ALIGN_TOP = 1, // top viewable (safe area) edge - VERTICAL_ALIGN_CENTER = 2, // center of the screen (reticle) - VERTICAL_ALIGN_BOTTOM = 3, // bottom viewable (safe area) edge - VERTICAL_ALIGN_FULLSCREEN = 4, // disregards safe area - VERTICAL_ALIGN_NOSCALE = 5, // uses exact parameters - neither adjusts for safe area nor scales for screen size - VERTICAL_ALIGN_TO480 = 6, // scales a real-screen resolution y down into the 0 - 480 range - VERTICAL_ALIGN_CENTER_SAFEAREA = 7, // center of the save area - VERTICAL_ALIGN_MAX = VERTICAL_ALIGN_CENTER_SAFEAREA, - VERTICAL_ALIGN_DEFAULT = VERTICAL_ALIGN_SUBTOP -}; - -enum MENU_BUTTON { - BUTTON_A = 1, - BUTTON_B = 2, - BUTTON_X = 3, - BUTTON_Y = 4, - BUTTON_LSHLDR = 5, - BUTTON_RSHLDR = 6, - BUTTON_START = 14, - BUTTON_BACK = 15, - BUTTON_LSTICK = 16, - BUTTON_RSTICK = 17, - BUTTON_LTRIG = 18, - BUTTON_RTRIG = 19, - DPAD_UP = 20, - DPAD_DOWN = 21, - DPAD_LEFT = 22, - DPAD_RIGHT = 23, - APAD_UP = 28, - APAD_DOWN = 29, - APAD_LEFT = 30, - APAD_RIGHT = 31 -}; - -enum ASSET_TYPE { - ASSET_UNKNOWN = 0, - ASSET_ANIMATION = 4, // x_anim PARTIALLY VERIFIED - ASSET_MODEL = 5, // xmodel PARTIALLY VERIFIED - ASSET_MATERIAL = 6, // material VERIFIED - ASSET_BIK_FILE = 7, // .bik file PARTIALLY VERIFIED - ASSET_SOUND = 9, // loaded_sound VERIFIED - ASSET_COLLISION_MAP = 12, // collision_map PARTIALLY VERIFIED - ASSET_SHADER = 13, // shader PARTIALLY VERIFIED - ASSET_D3DBSP_DUMP = 17, // d3dbsp dump VERIFIED - ASSET_FONT = 20, // font PARTIALLY VERIFIED - ASSET_MENU = 21, // menu_file VERIFIED - ASSET_LOCAL_STRING = 23, // localized string VERIFIED - ASSET_WEAPON = 24, // weapon VERIFIED - ASSET_EFFECT = 26, // fx VERIFIED - ASSET_RAW_FILE = 32, // raw_file VERIFIED - ASSET_STRING_TABLE = 33 // string_table PARTIALLY VERIFIED -}; - -// Change this depending on the platform -// PC -#define DEVMAP_LEVEL_FIRST "devmap intro_pac" -#define DEVMAP "devmap" -// Not PC -// #define DEVMAP_LEVEL_FIRST "map intro_pac" -// #define DEVMAP "map" - -// Remove this to restore full frontend instead of limited EPD frontend -#define COOP_EPD 0 - -// LDS - This enables a German SKU with Nazi Zombies enabled *SHOULD BE SET TO 0 IF NOT APPROVED* -#define GERMAN_ZOMBIE_BUILD 0 - -#define DEVMAP_LEVEL_TRAINING "devmap training" -#define LEVEL_FIRST "intro_pac" -#define LEVEL_TRAINING "training" -#define FIRST_PLAYABLE_CAMPAIGN_LEVEL "mak" -#define FIRST_PLAYABLE_ZOMBIE_LEVEL "nazi_zombie_prototype" - -// Size define for the hud compass -// These are used for both the dynamic & non-dynamic compass drawing -// If these are changed, the cgame should be recompiled -#define COMPASS_SIZE 160 -#define MINIMAP_X 11.5 -#define MINIMAP_Y 5 -#define MINIMAP_W 89.5 -#define MINIMAP_H 89.5 - -#define COMPASS_SIZE_MP 125 -#define MINIMAP_X_MP 0 -#define MINIMAP_Y_MP 12 -#define MINIMAP_W_MP 102 -#define MINIMAP_H_MP 102 - -#define FULLSCREEN 0 0 640 480 -#define FULLSCREEN_WIDE -107 0 854 480 - -// PC -#define ORIGIN_TITLE 30 34 -// Not PC -// #define ORIGIN_TITLE 0 0 - -#define ORIGIN_TITLE_SS 104 120 - -#define FONTSCALE_SMALL 0.3095 //0.3750 // <-- COD4 // COD5 --> 0.30952//0.35897//0.24138 //14 pt //0.2900 //0.2750 // 18 -#define FONTSCALE_LOBBY 0.26 // <--Slate // 0.3010 <-- Slate Compressed // 0.3750 // <-- COD4 CONDUIT ITC small -#define FONTSCALE_NORMAL 0.3810 //0.35897//0.4583 -#define FONTSCALE_BOLD 0.5476 //0.4583 -#define FONTSCALE_BIG 0.5476 //0.5833 -#define FONTSCALE_EXTRABIG 1 //1.0000 - -// new settings -#define TEXTSIZE_SMALL FONTSCALE_SMALL -#define TEXTSIZE_SMALL_SS (FONTSCALE_SMALL*2) -#define TEXTSIZE_DEFAULT FONTSCALE_NORMAL -#define TEXTSIZE_DEFAULT_SS (FONTSCALE_NORMAL*2) -#define TEXTSIZE_TITLE FONTSCALE_BIG -#define TEXTSIZE_TITLE_SS 1 - -#define TEXTSIZE_BOLD TEXTSIZE_DEFAULT -#define TEXTSIZE_BIG TEXTSIZE_TITLE - -//#define COLOR_TITLE 1 0.8 0.4 1 -#define COLOR_TITLE 1 1 1 1 -#define COLOR_HEADER 0.69 0.69 0.69 1 -#define COLOR_FOCUSED 0.95294 0.72156 0.21176 1 //1 0.788 0.129 1 -//#define COLOR_FOCUS_YELLOW 0.95294 0.72156 0.21176 1 -#define COLOR_UNFOCUSED 0.4823 0.4823 0.4823 1 -//#define COLOR_DISABLED 0.35 0.35 0.35 1 -#define COLOR_SAFEAREA 0 0 1 1 - -#define COLOR_INFO_YELLOW COLOR_FOCUSED//1 0.84706 0 1 -#define COLOR_TEXT 0.84313 0.84313 0.84313 1 -#define COLOR_DISABLED 0.34118 0.36863 0.37647 1 -#define COLOR_TITLEBAR 0.14510 0.16078 0.16862 0.3//1 -#define COLOR_RED_TEXT 0.69020 0.00784 0.00784 1 - -#define COLOR_FADEOUT 0.09412 0.09412 0.04912 0.65 - -#define COLOR_BODY_TEXT 0.62745 0.66667 0.67451 1 - -#define COLOR_USMC 0 0.0196 0.41 -#define COLOR_JPN 0.53 0.027 0.027 -#define COLOR_USSR 0.368 0.035 0.035 -#define COLOR_GER 0.937 0.9 0.607 - -#define DEFAULT_MP_CFG "default_mp.cfg" -#define SPLITSCREEN_MP_CFG "default_splitscreen.cfg" -#define SYSTEMLINK_MP_CFG "default_systemlink.cfg" -#define XBOXLIVE_MP_CFG "default_xboxlive.cfg" - -#define MAX_RANK int(tableLookup( "mp/rankTable.csv", 0, "maxrank", 1)) -#define MAX_PRESTIGE int(tableLookup( "mp/rankIconTable.csv", 0, "maxprestige", 1)) - -#define PRESTIGE_AVAIL (stat(2326) < MAX_PRESTIGE && stat(2301) == int(tableLookup("mp/rankTable.csv",0,MAX_RANK,7))) -#define PRESTIGE_NEXT (stat(2326) < MAX_PRESTIGE && stat(252) == MAX_RANK) -#define PRESTIGE_FINISH (stat(2326) == MAX_PRESTIGE) - -#define CAN_RANK_UP (stat(252) < MAX_RANK || stat(2326) < MAX_PRESTIGE) - -// Bink constants -const quint32 BINK_SURFACE32RGBA = 6; - -#endif // ENUMS_H diff --git a/libs/compression/compression.cpp b/libs/compression/compression.cpp index 690b43f..2b5f08a 100644 --- a/libs/compression/compression.cpp +++ b/libs/compression/compression.cpp @@ -1,5 +1,5 @@ #include "compression.h" -//#include "lzokay.h" +#include "minilzo.h" #define XBOXAPI __declspec(dllimport) #include "xcompress.h" @@ -13,8 +13,8 @@ QByteArray Compression::CompressXMem(const QByteArray &data) { XMEMCODEC_PARAMETERS_LZX lzxParams = {}; lzxParams.Flags = 0; - lzxParams.WindowSize = XCOMPRESS_LZX_BLOCK_SIZE; - lzxParams.CompressionPartitionSize = XCOMPRESS_LZX_BLOCK_SIZE; + lzxParams.WindowSize = 0x20000; + lzxParams.CompressionPartitionSize = 0x80000; XMEMCOMPRESSION_CONTEXT ctx = nullptr; if (FAILED(XMemCreateCompressionContext(XMEMCODEC_LZX, &lzxParams, 0, &ctx)) || !ctx) @@ -34,25 +34,35 @@ QByteArray Compression::CompressXMem(const QByteArray &data) return output; } -QByteArray Compression::DecompressXMem(const QByteArray &data) +QByteArray Compression::DecompressXMem(const QByteArray &data, int flags, int windowSize, int partSize) { + if (data.isEmpty()) + return {}; + XMEMCODEC_PARAMETERS_LZX lzxParams = {}; - lzxParams.Flags = 0; - lzxParams.WindowSize = XCOMPRESS_LZX_BLOCK_SIZE; - lzxParams.CompressionPartitionSize = XCOMPRESS_LZX_BLOCK_SIZE; + lzxParams.Flags = flags; + lzxParams.WindowSize = windowSize; + lzxParams.CompressionPartitionSize = partSize; XMEMDECOMPRESSION_CONTEXT ctx = nullptr; if (FAILED(XMemCreateDecompressionContext(XMEMCODEC_LZX, &lzxParams, 0, &ctx)) || !ctx) - return QByteArray(); + return {}; - QByteArray output(data.size(), 0); - SIZE_T actualSize = data.size(); + // Allocate large enough buffer for decompression (16 MB is a safe upper bound) + const SIZE_T kMaxOutSize = 16 * 1024 * 1024; + QByteArray output(static_cast(kMaxOutSize), Qt::Uninitialized); + SIZE_T actualSize = kMaxOutSize; + + HRESULT hr = XMemDecompress(ctx, + output.data(), &actualSize, + data.constData(), data.size() + 16); - HRESULT hr = XMemDecompress(ctx, output.data(), &actualSize, data.constData(), data.size()); XMemDestroyDecompressionContext(ctx); - if (FAILED(hr)) - return QByteArray(); + if (FAILED(hr)) { + qWarning() << "XMemDecompress failed with HRESULT:" << hr; + return {}; + } output.resize(static_cast(actualSize)); return output; @@ -68,6 +78,46 @@ quint32 Compression::CalculateAdler32Checksum(const QByteArray &data) { return adler; } +qint64 Compression::FindZlibOffset(const QByteArray &bytes) +{ + static const QByteArray iwffs("IWffs"); + auto idx = bytes.indexOf(iwffs); + if (idx != -1) + return idx + 0x4000; + + const char header = 0x78; // z-lib: 0x78 [FLG] + int pos = -1; + while ((pos = bytes.indexOf(header, pos + 1)) != -1) + { + QByteArray window = bytes.mid(pos, 0x20); + if (!window.contains(QByteArray::fromHex("000000")) && + !window.contains(QByteArray::fromHex("FFFFFF"))) + return pos; + } + return -1; +} + +QByteArray Compression::StripHashBlocks(const QByteArray &raw, + int dataChunkSize, + int hashChunkSize) +{ + QByteArray cleaned; + cleaned.reserve(raw.size()); // upper bound + + int p = 0; + while (p < raw.size()) + { + const int chunk = qMin(dataChunkSize, raw.size() - p); + cleaned.append(raw.constData() + p, chunk); + p += chunk; + + // skip hash bytes if they are still inside the buffer + if (p < raw.size()) + p += qMin(hashChunkSize, raw.size() - p); + } + return cleaned; +} + QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) { if (aCompressedData.isEmpty()) { return {}; @@ -95,22 +145,23 @@ QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) { ret = inflate(&strm, Z_NO_FLUSH); - if (strm.avail_out < buffer.size()) { // Data has been written to the buffer + if (strm.avail_out < buffer.size()) { decompressed.append(buffer.constData(), buffer.size() - strm.avail_out); } if (ret == Z_STREAM_END) { - break; // Proper end of the data stream + break; } if (ret == Z_BUF_ERROR && strm.avail_out == 0) { - // Buffer was completely used, resize it - int newSize = buffer.size() * 2; // Double the buffer size - buffer.resize(newSize); + buffer.resize(buffer.size() * 2); } else if (ret != Z_OK) { - qWarning() << "Zlib error:" << zError(ret); + size_t errorOffset = strm.total_in; + qWarning() << "Zlib error:" << zError(ret) + << "at offset" << errorOffset + << "of" << aCompressedData.size() << "bytes"; inflateEnd(&strm); - return {}; // Return on other errors + return decompressed; } } while (ret != Z_STREAM_END); @@ -118,6 +169,7 @@ QByteArray Compression::DecompressZLIB(const QByteArray &aCompressedData) { return decompressed; } + QByteArray Compression::CompressZLIB(const QByteArray &aData) { return CompressZLIBWithSettings(aData); } @@ -242,6 +294,27 @@ QByteArray Compression::CompressDeflateWithSettings(const QByteArray &aData, int return compressed; } +QByteArray Compression::DecompressLZO(const QByteArray &aCompressedData, quint32 aDestSize) { + static bool ok = (lzo_init() == LZO_E_OK); + if (!ok) + throw std::runtime_error("lzo_init failed"); + + QByteArray dst(aDestSize, Qt::Uninitialized); + lzo_uint out = aDestSize; + + int rc = lzo1x_decompress_safe( + reinterpret_cast(aCompressedData.constData()), + static_cast(aCompressedData.size()), + reinterpret_cast(dst.data()), + &out, + nullptr); + + if (rc != LZO_E_OK || out != aDestSize) + throw std::runtime_error("LZO decompression error"); + + return dst; +} + QByteArray Compression::DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize) { return pDecompressOodle(aCompressedData, aCompressedData.length(), aDecompressedSize); } diff --git a/libs/compression/compression.h b/libs/compression/compression.h index 6bdae3b..c57bc57 100644 --- a/libs/compression/compression.h +++ b/libs/compression/compression.h @@ -47,6 +47,10 @@ class Compression { public: static quint32 CalculateAdler32Checksum(const QByteArray &data); static QByteArray DecompressZLIB(const QByteArray &aCompressedData); + static qint64 FindZlibOffset(const QByteArray &bytes); + static QByteArray StripHashBlocks(const QByteArray &raw, + int dataChunkSize = 0x200000, + int hashChunkSize = 0x2000); static QByteArray CompressZLIB(const QByteArray &aData); static QByteArray CompressZLIBWithSettings(const QByteArray &aData, int aCompressionLevel = Z_BEST_COMPRESSION, @@ -64,13 +68,14 @@ public: int aStrategy = Z_DEFAULT_STRATEGY, const QByteArray &aDictionary = {}); + static QByteArray DecompressLZO(const QByteArray &aCompressedData, quint32 aDestSize); + static QByteArray DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize); static QByteArray CompressOodle(const QByteArray &aData); static QByteArray CompressXMem(const QByteArray &data); - static QByteArray DecompressXMem(const QByteArray &data); - + static QByteArray DecompressXMem(const QByteArray &data, int flags = 0, int windowSize = 0x20000, int partSize = 0x80000); private: static quint32 pGetOodleCompressedBounds(quint32 aBufferSize); static QByteArray pCompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize, diff --git a/libs/compression/compression.pro b/libs/compression/compression.pro index a585902..3bb3af9 100644 --- a/libs/compression/compression.pro +++ b/libs/compression/compression.pro @@ -1,14 +1,17 @@ QT += core TEMPLATE = lib CONFIG += staticlib c++17 +DEFINES += MINILZO_USE_STATIC SOURCES += \ compression.cpp \ - lzokay.cpp \ + minilzo.c \ + lzoconf.h \ + lzodefs.h HEADERS += \ compression.h \ - lzokay.h + minilzo.h LIBS += \ -L$$PWD/../../third_party/xbox_sdk/lib -lxcompress64 \ diff --git a/libs/compression/lzoconf.h b/libs/compression/lzoconf.h new file mode 100644 index 0000000..f9a8bdb --- /dev/null +++ b/libs/compression/lzoconf.h @@ -0,0 +1,453 @@ +/* lzoconf.h -- configuration of the LZO data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZOCONF_H_INCLUDED +#define __LZOCONF_H_INCLUDED 1 + +#define LZO_VERSION 0x20a0 /* 2.10 */ +#define LZO_VERSION_STRING "2.10" +#define LZO_VERSION_DATE "Mar 01 2017" + +/* internal Autoconf configuration file - only used when building LZO */ +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include +#include + + +/*********************************************************************** +// LZO requires a conforming +************************************************************************/ + +#if !defined(CHAR_BIT) || (CHAR_BIT != 8) +# error "invalid CHAR_BIT" +#endif +#if !defined(UCHAR_MAX) || !defined(USHRT_MAX) || !defined(UINT_MAX) || !defined(ULONG_MAX) +# error "check your compiler installation" +#endif +#if (USHRT_MAX < 1) || (UINT_MAX < 1) || (ULONG_MAX < 1) +# error "your limits.h macros are broken" +#endif + +/* get OS and architecture defines */ +#ifndef __LZODEFS_H_INCLUDED +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// some core defines +************************************************************************/ + +/* memory checkers */ +#if !defined(__LZO_CHECKER) +# if defined(__BOUNDS_CHECKING_ON) +# define __LZO_CHECKER 1 +# elif defined(__CHECKER__) +# define __LZO_CHECKER 1 +# elif defined(__INSURE__) +# define __LZO_CHECKER 1 +# elif defined(__PURIFY__) +# define __LZO_CHECKER 1 +# endif +#endif + + +/*********************************************************************** +// integral and pointer types +************************************************************************/ + +/* lzo_uint must match size_t */ +#if !defined(LZO_UINT_MAX) +# if (LZO_ABI_LLP64) +# if (LZO_OS_WIN64) + typedef unsigned __int64 lzo_uint; + typedef __int64 lzo_int; +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF___INT64 +# else + typedef lzo_ullong_t lzo_uint; + typedef lzo_llong_t lzo_int; +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG_LONG +# endif +# define LZO_SIZEOF_LZO_INT 8 +# define LZO_UINT_MAX 0xffffffffffffffffull +# define LZO_INT_MAX 9223372036854775807LL +# define LZO_INT_MIN (-1LL - LZO_INT_MAX) +# elif (LZO_ABI_IP32L64) /* MIPS R5900 */ + typedef unsigned int lzo_uint; + typedef int lzo_int; +# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_INT +# define LZO_UINT_MAX UINT_MAX +# define LZO_INT_MAX INT_MAX +# define LZO_INT_MIN INT_MIN +# elif (ULONG_MAX >= LZO_0xffffffffL) + typedef unsigned long lzo_uint; + typedef long lzo_int; +# define LZO_SIZEOF_LZO_INT LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INT LZO_TYPEOF_LONG +# define LZO_UINT_MAX ULONG_MAX +# define LZO_INT_MAX LONG_MAX +# define LZO_INT_MIN LONG_MIN +# else +# error "lzo_uint" +# endif +#endif + +/* The larger type of lzo_uint and lzo_uint32_t. */ +#if (LZO_SIZEOF_LZO_INT >= 4) +# define lzo_xint lzo_uint +#else +# define lzo_xint lzo_uint32_t +#endif + +typedef int lzo_bool; + +/* sanity checks */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int) == LZO_SIZEOF_LZO_INT) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == LZO_SIZEOF_LZO_INT) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_xint) >= sizeof(lzo_uint32_t)) + +#ifndef __LZO_MMODEL +#define __LZO_MMODEL /*empty*/ +#endif + +/* no typedef here because of const-pointer issues */ +#define lzo_bytep unsigned char __LZO_MMODEL * +#define lzo_charp char __LZO_MMODEL * +#define lzo_voidp void __LZO_MMODEL * +#define lzo_shortp short __LZO_MMODEL * +#define lzo_ushortp unsigned short __LZO_MMODEL * +#define lzo_intp lzo_int __LZO_MMODEL * +#define lzo_uintp lzo_uint __LZO_MMODEL * +#define lzo_xintp lzo_xint __LZO_MMODEL * +#define lzo_voidpp lzo_voidp __LZO_MMODEL * +#define lzo_bytepp lzo_bytep __LZO_MMODEL * + +#define lzo_int8_tp lzo_int8_t __LZO_MMODEL * +#define lzo_uint8_tp lzo_uint8_t __LZO_MMODEL * +#define lzo_int16_tp lzo_int16_t __LZO_MMODEL * +#define lzo_uint16_tp lzo_uint16_t __LZO_MMODEL * +#define lzo_int32_tp lzo_int32_t __LZO_MMODEL * +#define lzo_uint32_tp lzo_uint32_t __LZO_MMODEL * +#if defined(lzo_int64_t) +#define lzo_int64_tp lzo_int64_t __LZO_MMODEL * +#define lzo_uint64_tp lzo_uint64_t __LZO_MMODEL * +#endif + +/* Older LZO versions used to support ancient systems and memory models + * such as 16-bit MSDOS with __huge pointers or Cray PVP, but these + * obsolete configurations are not supported any longer. + */ +#if defined(__LZO_MMODEL_HUGE) +#error "__LZO_MMODEL_HUGE memory model is unsupported" +#endif +#if (LZO_MM_PVP) +#error "LZO_MM_PVP memory model is unsupported" +#endif +#if (LZO_SIZEOF_INT < 4) +#error "LZO_SIZEOF_INT < 4 is unsupported" +#endif +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) >= 4) +/* Strange configurations where sizeof(lzo_uint) != sizeof(size_t) should + * work but have not received much testing lately, so be strict here. + */ +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(size_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(ptrdiff_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long *) == sizeof(lzo_uintptr_t)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(void *) == sizeof(lzo_voidp)) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(char *) == sizeof(lzo_bytep)) + + +/*********************************************************************** +// function types +************************************************************************/ + +/* name mangling */ +#if !defined(__LZO_EXTERN_C) +# ifdef __cplusplus +# define __LZO_EXTERN_C extern "C" +# else +# define __LZO_EXTERN_C extern +# endif +#endif + +/* calling convention */ +#if !defined(__LZO_CDECL) +# define __LZO_CDECL __lzo_cdecl +#endif + +/* DLL export information */ +#if !defined(__LZO_EXPORT1) +# define __LZO_EXPORT1 /*empty*/ +#endif +#if !defined(__LZO_EXPORT2) +# define __LZO_EXPORT2 /*empty*/ +#endif + +/* __cdecl calling convention for public C and assembly functions */ +#if !defined(LZO_PUBLIC) +# define LZO_PUBLIC(r) __LZO_EXPORT1 r __LZO_EXPORT2 __LZO_CDECL +#endif +#if !defined(LZO_EXTERN) +# define LZO_EXTERN(r) __LZO_EXTERN_C LZO_PUBLIC(r) +#endif +#if !defined(LZO_PRIVATE) +# define LZO_PRIVATE(r) static r __LZO_CDECL +#endif + +/* function types */ +typedef int +(__LZO_CDECL *lzo_compress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_decompress_t) ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_optimize_t) ( lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +typedef int +(__LZO_CDECL *lzo_compress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + +typedef int +(__LZO_CDECL *lzo_decompress_dict_t)(const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem, + const lzo_bytep dict, lzo_uint dict_len ); + + +/* Callback interface. Currently only the progress indicator ("nprogress") + * is used, but this may change in a future release. */ + +struct lzo_callback_t; +typedef struct lzo_callback_t lzo_callback_t; +#define lzo_callback_p lzo_callback_t __LZO_MMODEL * + +/* malloc & free function types */ +typedef lzo_voidp (__LZO_CDECL *lzo_alloc_func_t) + (lzo_callback_p self, lzo_uint items, lzo_uint size); +typedef void (__LZO_CDECL *lzo_free_func_t) + (lzo_callback_p self, lzo_voidp ptr); + +/* a progress indicator callback function */ +typedef void (__LZO_CDECL *lzo_progress_func_t) + (lzo_callback_p, lzo_uint, lzo_uint, int); + +struct lzo_callback_t +{ + /* custom allocators (set to 0 to disable) */ + lzo_alloc_func_t nalloc; /* [not used right now] */ + lzo_free_func_t nfree; /* [not used right now] */ + + /* a progress indicator callback function (set to 0 to disable) */ + lzo_progress_func_t nprogress; + + /* INFO: the first parameter "self" of the nalloc/nfree/nprogress + * callbacks points back to this struct, so you are free to store + * some extra info in the following variables. */ + lzo_voidp user1; + lzo_xint user2; + lzo_xint user3; +}; + + +/*********************************************************************** +// error codes and prototypes +************************************************************************/ + +/* Error codes for the compression/decompression functions. Negative + * values are errors, positive values will be used for special but + * normal events. + */ +#define LZO_E_OK 0 +#define LZO_E_ERROR (-1) +#define LZO_E_OUT_OF_MEMORY (-2) /* [lzo_alloc_func_t failure] */ +#define LZO_E_NOT_COMPRESSIBLE (-3) /* [not used right now] */ +#define LZO_E_INPUT_OVERRUN (-4) +#define LZO_E_OUTPUT_OVERRUN (-5) +#define LZO_E_LOOKBEHIND_OVERRUN (-6) +#define LZO_E_EOF_NOT_FOUND (-7) +#define LZO_E_INPUT_NOT_CONSUMED (-8) +#define LZO_E_NOT_YET_IMPLEMENTED (-9) /* [not used right now] */ +#define LZO_E_INVALID_ARGUMENT (-10) +#define LZO_E_INVALID_ALIGNMENT (-11) /* pointer argument is not properly aligned */ +#define LZO_E_OUTPUT_NOT_CONSUMED (-12) +#define LZO_E_INTERNAL_ERROR (-99) + + +#ifndef lzo_sizeof_dict_t +# define lzo_sizeof_dict_t ((unsigned)sizeof(lzo_bytep)) +#endif + +/* lzo_init() should be the first function you call. + * Check the return code ! + * + * lzo_init() is a macro to allow checking that the library and the + * compiler's view of various types are consistent. + */ +#define lzo_init() __lzo_init_v2(LZO_VERSION,(int)sizeof(short),(int)sizeof(int),\ + (int)sizeof(long),(int)sizeof(lzo_uint32_t),(int)sizeof(lzo_uint),\ + (int)lzo_sizeof_dict_t,(int)sizeof(char *),(int)sizeof(lzo_voidp),\ + (int)sizeof(lzo_callback_t)) +LZO_EXTERN(int) __lzo_init_v2(unsigned,int,int,int,int,int,int,int,int,int); + +/* version functions (useful for shared libraries) */ +LZO_EXTERN(unsigned) lzo_version(void); +LZO_EXTERN(const char *) lzo_version_string(void); +LZO_EXTERN(const char *) lzo_version_date(void); +LZO_EXTERN(const lzo_charp) _lzo_version_string(void); +LZO_EXTERN(const lzo_charp) _lzo_version_date(void); + +/* string functions */ +LZO_EXTERN(int) + lzo_memcmp(const lzo_voidp a, const lzo_voidp b, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memcpy(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memmove(lzo_voidp dst, const lzo_voidp src, lzo_uint len); +LZO_EXTERN(lzo_voidp) + lzo_memset(lzo_voidp buf, int c, lzo_uint len); + +/* checksum functions */ +LZO_EXTERN(lzo_uint32_t) + lzo_adler32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(lzo_uint32_t) + lzo_crc32(lzo_uint32_t c, const lzo_bytep buf, lzo_uint len); +LZO_EXTERN(const lzo_uint32_tp) + lzo_get_crc32_table(void); + +/* misc. */ +LZO_EXTERN(int) _lzo_config_check(void); +typedef union { + lzo_voidp a00; lzo_bytep a01; lzo_uint a02; lzo_xint a03; lzo_uintptr_t a04; + void *a05; unsigned char *a06; unsigned long a07; size_t a08; ptrdiff_t a09; +#if defined(lzo_int64_t) + lzo_uint64_t a10; +#endif +} lzo_align_t; + +/* align a char pointer on a boundary that is a multiple of 'size' */ +LZO_EXTERN(unsigned) __lzo_align_gap(const lzo_voidp p, lzo_uint size); +#define LZO_PTR_ALIGN_UP(p,size) \ + ((p) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(p),(lzo_uint)(size))) + + +/*********************************************************************** +// deprecated macros - only for backward compatibility +************************************************************************/ + +/* deprecated - use 'lzo_bytep' instead of 'lzo_byte *' */ +#define lzo_byte unsigned char +/* deprecated type names */ +#define lzo_int32 lzo_int32_t +#define lzo_uint32 lzo_uint32_t +#define lzo_int32p lzo_int32_t __LZO_MMODEL * +#define lzo_uint32p lzo_uint32_t __LZO_MMODEL * +#define LZO_INT32_MAX LZO_INT32_C(2147483647) +#define LZO_UINT32_MAX LZO_UINT32_C(4294967295) +#if defined(lzo_int64_t) +#define lzo_int64 lzo_int64_t +#define lzo_uint64 lzo_uint64_t +#define lzo_int64p lzo_int64_t __LZO_MMODEL * +#define lzo_uint64p lzo_uint64_t __LZO_MMODEL * +#define LZO_INT64_MAX LZO_INT64_C(9223372036854775807) +#define LZO_UINT64_MAX LZO_UINT64_C(18446744073709551615) +#endif +/* deprecated types */ +typedef union { lzo_bytep a; lzo_uint b; } __lzo_pu_u; +typedef union { lzo_bytep a; lzo_uint32_t b; } __lzo_pu32_u; +/* deprecated defines */ +#if !defined(LZO_SIZEOF_LZO_UINT) +# define LZO_SIZEOF_LZO_UINT LZO_SIZEOF_LZO_INT +#endif + +#if defined(LZO_CFG_COMPAT) + +#define __LZOCONF_H 1 + +#if defined(LZO_ARCH_I086) +# define __LZO_i386 1 +#elif defined(LZO_ARCH_I386) +# define __LZO_i386 1 +#endif + +#if defined(LZO_OS_DOS16) +# define __LZO_DOS 1 +# define __LZO_DOS16 1 +#elif defined(LZO_OS_DOS32) +# define __LZO_DOS 1 +#elif defined(LZO_OS_WIN16) +# define __LZO_WIN 1 +# define __LZO_WIN16 1 +#elif defined(LZO_OS_WIN32) +# define __LZO_WIN 1 +#endif + +#define __LZO_CMODEL /*empty*/ +#define __LZO_DMODEL /*empty*/ +#define __LZO_ENTRY __LZO_CDECL +#define LZO_EXTERN_CDECL LZO_EXTERN +#define LZO_ALIGN LZO_PTR_ALIGN_UP + +#define lzo_compress_asm_t lzo_compress_t +#define lzo_decompress_asm_t lzo_decompress_t + +#endif /* LZO_CFG_COMPAT */ + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 sw=4 et: */ diff --git a/libs/compression/lzodefs.h b/libs/compression/lzodefs.h new file mode 100644 index 0000000..c3e2bcf --- /dev/null +++ b/libs/compression/lzodefs.h @@ -0,0 +1,3268 @@ +/* lzodefs.h -- architecture, OS and compiler specific defines + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if 0 +#elif !defined(__LZO_LANG_OVERRIDE) +#if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__) +# if (__ASSEMBLER__+0) <= 0 +# error "__ASSEMBLER__" +# else +# define LZO_LANG_ASSEMBLER 1 +# endif +#elif defined(__cplusplus) +# if (__cplusplus+0) <= 0 +# error "__cplusplus" +# elif (__cplusplus < 199711L) +# define LZO_LANG_CXX 1 +# elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1 +# define LZO_LANG_CXX _MSVC_LANG +# else +# define LZO_LANG_CXX __cplusplus +# endif +# define LZO_LANG_CPLUSPLUS LZO_LANG_CXX +#else +# if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L) +# define LZO_LANG_C __STDC_VERSION__ +# else +# define LZO_LANG_C 1 +# endif +#endif +#endif +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) +# pragma warning(disable: 193) +#elif defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif +#if 0 +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful +#else +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul +#endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(_MSC_VER) && defined(M_I86HM) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } +#else +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif defined(__mips__) && defined(__psp__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# define LZO_CC_CLANG_C2 _MSC_VER +# define LZO_CC_CLANG_VENDOR_MICROSOFT 1 +# define LZO_INFO_CC "clang/c2" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__) +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# else +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +# if defined(__APPLE_CC__) +# define LZO_CC_CLANG_VENDOR_APPLE 1 +# define LZO_INFO_CC "clang/apple" +# else +# define LZO_CC_CLANG_VENDOR_LLVM 1 +# define LZO_INFO_CC "clang" +# endif +# if defined(__clang_version__) +# define LZO_INFO_CCVER __clang_version__ +# else +# define LZO_INFO_CCVER __VERSION__ +# endif +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if ((__ZTC__-0) == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) || defined(_M_ARM64) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__riscv) +# define LZO_ARCH_RISCV 1 +# define LZO_INFO_ARCH "riscv" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if !defined(LZO_ARCH_ARM_THUMB2) +#if (LZO_ARCH_ARM) +# if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB) +# if defined(__thumb2__) +# define LZO_ARCH_ARM_THUMB2 1 +# elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) +# define LZO_ARCH_ARM_THUMB2 1 +# elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7) +# define LZO_ARCH_ARM_THUMB2 1 +# endif +# endif +#endif +#endif +#if (LZO_ARCH_ARM_THUMB2) +# undef LZO_INFO_ARCH +# define LZO_INFO_ARCH "arm_thumb2" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON) && ((__ARM_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown LZO_ARCH_I086 memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "unexpected configuration - check your compiler defines" +# elif (LZO_CC_ZORTECHC) +# else +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(__cplusplus) +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#if defined(__cplusplus) +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(lzo_has_builtin) +#if (LZO_CC_CLANG) && defined(__has_builtin) +# define lzo_has_builtin __has_builtin +#endif +#endif +#if !defined(lzo_has_builtin) +# define lzo_has_builtin(x) 0 +#endif +#if !defined(lzo_has_attribute) +#if (LZO_CC_CLANG) && defined(__has_attribute) +# define lzo_has_attribute __has_attribute +#endif +#endif +#if !defined(lzo_has_attribute) +# define lzo_has_attribute(x) 0 +#endif +#if !defined(lzo_has_declspec_attribute) +#if (LZO_CC_CLANG) && defined(__has_declspec_attribute) +# define lzo_has_declspec_attribute __has_declspec_attribute +#endif +#endif +#if !defined(lzo_has_declspec_attribute) +# define lzo_has_declspec_attribute(x) 0 +#endif +#if !defined(lzo_has_feature) +#if (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_feature __has_feature +#endif +#endif +#if !defined(lzo_has_feature) +# define lzo_has_feature(x) 0 +#endif +#if !defined(lzo_has_extension) +#if (LZO_CC_CLANG) && defined(__has_extension) +# define lzo_has_extension __has_extension +#elif (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_extension __has_feature +#endif +#endif +#if !defined(lzo_has_extension) +# define lzo_has_extension(x) 0 +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_RESULT) +# define LZO_UNUSED_RESULT(var) LZO_UNUSED(var) +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_CLANG && LZO_CC_CLANG_C2) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_very_likely) +# ifndef __lzo_HAVE_very_likely +# define __lzo_HAVE_very_likely 1 +# endif +#else +# define __lzo_very_likely(e) __lzo_likely(e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if defined(__lzo_very_unlikely) +# ifndef __lzo_HAVE_very_unlikely +# define __lzo_HAVE_very_unlikely 1 +# endif +#else +# define __lzo_very_unlikely(e) __lzo_unlikely(e) +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#if !defined(lzo_unused_funcs_impl) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f +# elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) +# define lzo_unused_funcs_impl(r,f) static r f +# else +# define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +#if (LZO_LANG_ASSEMBLER) +# undef LZO_COMPILE_TIME_ASSERT_HEADER +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/ +#else +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#define LZO_SIZEOF_CHAR 1 +#ifndef LZO_SIZEOF_SHORT +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif +#endif +#ifndef LZO_SIZEOF_INT +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG_LONG +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF___INT16 +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#endif +#ifndef LZO_SIZEOF___INT32 +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#endif +#ifndef LZO_SIZEOF___INT64 +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#endif +#ifndef LZO_SIZEOF_VOID_P +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) +#endif +#endif +#ifndef LZO_SIZEOF_SIZE_T +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif +#endif +#ifndef LZO_SIZEOF_PTRDIFF_T +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_ARM64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 +# else +# define LZO_WORDSIZE 2 +# endif +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) + LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4) +# if defined(__NORMAL_MODE__) +# define LZO_SIZEOF_VOID_P 2 +# else +# define LZO_SIZEOF_VOID_P 4 +# endif +# else + LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2) +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#elif (LZO_ARCH_M16C) +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8) +# define LZO_ABI_IP32W64 1 +# ifndef LZO_INFO_ABI_PM +# define LZO_INFO_ABI_PM "ip32w64" +# endif +#endif +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uc" "libc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# if ((__ARM_FEATURE_UNALIGNED)+0) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +# elif 1 && (LZO_ARCH_ARM_THUMB2) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +# endif +#elif (LZO_ARCH_RISCV) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_S390) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#define LZO_TYPEOF_CHAR 1u +#define LZO_TYPEOF_SHORT 2u +#define LZO_TYPEOF_INT 3u +#define LZO_TYPEOF_LONG 4u +#define LZO_TYPEOF_LONG_LONG 5u +#define LZO_TYPEOF___INT8 17u +#define LZO_TYPEOF___INT16 18u +#define LZO_TYPEOF___INT32 19u +#define LZO_TYPEOF___INT64 20u +#define LZO_TYPEOF___INT128 21u +#define LZO_TYPEOF___INT256 22u +#define LZO_TYPEOF___MODE_QI 33u +#define LZO_TYPEOF___MODE_HI 34u +#define LZO_TYPEOF___MODE_SI 35u +#define LZO_TYPEOF___MODE_DI 36u +#define LZO_TYPEOF___MODE_TI 37u +#define LZO_TYPEOF_CHAR_P 129u +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +# if !(LZO_LANG_ASSEMBLER) + __lzo_gnuc_extension__ typedef long long lzo_llong_t__; + __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# endif +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T +#endif +#if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) +# if !(LZO_LANG_ASSEMBLER) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# endif +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T +#endif +#if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) +# if !(LZO_LANG_ASSEMBLER) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# endif +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) +# if !(LZO_LANG_ASSEMBLER) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# endif +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T) +# define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64 +# endif +#endif +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T +#endif +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +#else +#endif +#endif +#if defined(lzo_int64e_t) +# define LZO_SIZEOF_LZO_INT64E_T 8 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +# define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +# define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 +# if !(LZO_LANG_ASSEMBLER) + typedef char * lzo_intptr_t; + typedef char * lzo_uintptr_t; +# endif +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) +# if !(LZO_LANG_ASSEMBLER) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# endif +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 +# if !(LZO_LANG_ASSEMBLER) + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# endif +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +#define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +#define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +#define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +#define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +#define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +#define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +#define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +#define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif + +#endif /* already included */ + +/* vim:set ts=4 sw=4 et: */ diff --git a/libs/compression/lzokay.cpp b/libs/compression/lzokay.cpp deleted file mode 100644 index 2bccc48..0000000 --- a/libs/compression/lzokay.cpp +++ /dev/null @@ -1,647 +0,0 @@ -#include "lzokay.h" -#include -#include -#include - -/* - * Based on documentation from the Linux sources: Documentation/lzo.txt - * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/lzo.txt - */ - -namespace lzokay { - -#if _WIN32 -#define HOST_BIG_ENDIAN 0 -#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ -#define HOST_BIG_ENDIAN 1 -#else -#define HOST_BIG_ENDIAN 0 -#endif - -#if HOST_BIG_ENDIAN -static uint16_t get_le16(const uint8_t* p) { - uint16_t val = *reinterpret_cast(p); -#if __GNUC__ - return __builtin_bswap16(val); -#elif _WIN32 - return _byteswap_ushort(val); -#else - return (val = (val << 8) | ((val >> 8) & 0xFF)); -#endif -} -#else -static uint16_t get_le16(const uint8_t* p) { - return *reinterpret_cast(p); -} -#endif - -constexpr std::size_t Max255Count = std::size_t(~0) / 255 - 2; - -#define NEEDS_IN(count) \ -if (inp + (count) > inp_end) { \ - dst_size = outp - dst; \ - return EResult::InputOverrun; \ -} - -#define NEEDS_OUT(count) \ -if (outp + (count) > outp_end) { \ - dst_size = outp - dst; \ - return EResult::OutputOverrun; \ -} - -#define CONSUME_ZERO_BYTE_LENGTH \ -std::size_t offset; \ -{ \ - const uint8_t *old_inp = inp; \ - while (*inp == 0) ++inp; \ - offset = inp - old_inp; \ - if (offset > Max255Count) { \ - dst_size = outp - dst; \ - return EResult::Error; \ - } \ -} - -#define WRITE_ZERO_BYTE_LENGTH(length) \ -{ \ - std::size_t l; \ - for (l = length; l > 255; l -= 255) { *outp++ = 0; } \ - *outp++ = static_cast(l); \ -} - -constexpr uint32_t M1MaxOffset = 0x0400; -constexpr uint32_t M2MaxOffset = 0x0800; -constexpr uint32_t M3MaxOffset = 0x4000; -// constexpr uint32_t M4MaxOffset = 0xbfff; - -// constexpr uint32_t M1MinLen = 2; -// constexpr uint32_t M1MaxLen = 2; -constexpr uint32_t M2MinLen = 3; -constexpr uint32_t M2MaxLen = 8; -// constexpr uint32_t M3MinLen = 3; -constexpr uint32_t M3MaxLen = 33; -// constexpr uint32_t M4MinLen = 3; -constexpr uint32_t M4MaxLen = 9; - -constexpr uint32_t M1Marker = 0x0; -// constexpr uint32_t M2Marker = 0x40; -constexpr uint32_t M3Marker = 0x20; -constexpr uint32_t M4Marker = 0x10; - -constexpr uint32_t MaxMatchByLengthLen = 34; /* Max M3 len + 1 */ - -EResult decompress(const uint8_t* src, std::size_t src_size, - uint8_t* dst, std::size_t init_dst_size, - std::size_t& dst_size) { - dst_size = init_dst_size; - - if (src_size < 3) { - dst_size = 0; - return EResult::InputOverrun; - } - - const uint8_t* inp = src; - const uint8_t* inp_end = src + src_size; - uint8_t* outp = dst; - uint8_t* outp_end = dst + dst_size; - uint8_t* lbcur; - std::size_t lblen; - std::size_t state = 0; - std::size_t nstate = 0; - - /* First byte encoding */ - if (*inp >= 22) { - /* 22..255 : copy literal string - * length = (byte - 17) = 4..238 - * state = 4 [ don't copy extra literals ] - * skip byte - */ - std::size_t len = *inp++ - uint8_t(17); - NEEDS_IN(len) - NEEDS_OUT(len) - for (std::size_t i = 0; i < len; ++i) - *outp++ = *inp++; - state = 4; - } else if (*inp >= 18) { - /* 18..21 : copy 0..3 literals - * state = (byte - 17) = 0..3 [ copy literals ] - * skip byte - */ - nstate = *inp++ - uint8_t(17); - state = nstate; - NEEDS_IN(nstate) - NEEDS_OUT(nstate) - for (std::size_t i = 0; i < nstate; ++i) - *outp++ = *inp++; - } - /* 0..17 : follow regular instruction encoding, see below. It is worth - * noting that codes 16 and 17 will represent a block copy from - * the dictionary which is empty, and that they will always be - * invalid at this place. - */ - - while (true) { - NEEDS_IN(1) - uint8_t inst = *inp++; - if (inst & 0xC0) { - /* [M2] - * 1 L L D D D S S (128..255) - * Copy 5-8 bytes from block within 2kB distance - * state = S (copy S literals after this block) - * length = 5 + L - * Always followed by exactly one byte : H H H H H H H H - * distance = (H << 3) + D + 1 - * - * 0 1 L D D D S S (64..127) - * Copy 3-4 bytes from block within 2kB distance - * state = S (copy S literals after this block) - * length = 3 + L - * Always followed by exactly one byte : H H H H H H H H - * distance = (H << 3) + D + 1 - */ - NEEDS_IN(1) - lbcur = outp - ((*inp++ << 3) + ((inst >> 2) & 0x7) + 1); - lblen = std::size_t(inst >> 5) + 1; - nstate = inst & uint8_t(0x3); - } else if (inst & M3Marker) { - /* [M3] - * 0 0 1 L L L L L (32..63) - * Copy of small block within 16kB distance (preferably less than 34B) - * length = 2 + (L ?: 31 + (zero_bytes * 255) + non_zero_byte) - * Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S - * distance = D + 1 - * state = S (copy S literals after this block) - */ - lblen = std::size_t(inst & uint8_t(0x1f)) + 2; - if (lblen == 2) { - CONSUME_ZERO_BYTE_LENGTH - NEEDS_IN(1) - lblen += offset * 255 + 31 + *inp++; - } - NEEDS_IN(2) - nstate = get_le16(inp); - inp += 2; - lbcur = outp - ((nstate >> 2) + 1); - nstate &= 0x3; - } else if (inst & M4Marker) { - /* [M4] - * 0 0 0 1 H L L L (16..31) - * Copy of a block within 16..48kB distance (preferably less than 10B) - * length = 2 + (L ?: 7 + (zero_bytes * 255) + non_zero_byte) - * Always followed by exactly one LE16 : D D D D D D D D : D D D D D D S S - * distance = 16384 + (H << 14) + D - * state = S (copy S literals after this block) - * End of stream is reached if distance == 16384 - */ - lblen = std::size_t(inst & uint8_t(0x7)) + 2; - if (lblen == 2) { - CONSUME_ZERO_BYTE_LENGTH - NEEDS_IN(1) - lblen += offset * 255 + 7 + *inp++; - } - NEEDS_IN(2) - nstate = get_le16(inp); - inp += 2; - lbcur = outp - (((inst & 0x8) << 11) + (nstate >> 2)); - nstate &= 0x3; - if (lbcur == outp) - break; /* Stream finished */ - lbcur -= 16384; - } else { - /* [M1] Depends on the number of literals copied by the last instruction. */ - if (state == 0) { - /* If last instruction did not copy any literal (state == 0), this - * encoding will be a copy of 4 or more literal, and must be interpreted - * like this : - * - * 0 0 0 0 L L L L (0..15) : copy long literal string - * length = 3 + (L ?: 15 + (zero_bytes * 255) + non_zero_byte) - * state = 4 (no extra literals are copied) - */ - std::size_t len = inst + 3; - if (len == 3) { - CONSUME_ZERO_BYTE_LENGTH - NEEDS_IN(1) - len += offset * 255 + 15 + *inp++; - } - /* copy_literal_run */ - NEEDS_IN(len) - NEEDS_OUT(len) - for (std::size_t i = 0; i < len; ++i) - *outp++ = *inp++; - state = 4; - continue; - } else if (state != 4) { - /* If last instruction used to copy between 1 to 3 literals (encoded in - * the instruction's opcode or distance), the instruction is a copy of a - * 2-byte block from the dictionary within a 1kB distance. It is worth - * noting that this instruction provides little savings since it uses 2 - * bytes to encode a copy of 2 other bytes but it encodes the number of - * following literals for free. It must be interpreted like this : - * - * 0 0 0 0 D D S S (0..15) : copy 2 bytes from <= 1kB distance - * length = 2 - * state = S (copy S literals after this block) - * Always followed by exactly one byte : H H H H H H H H - * distance = (H << 2) + D + 1 - */ - NEEDS_IN(1) - nstate = inst & uint8_t(0x3); - lbcur = outp - ((inst >> 2) + (*inp++ << 2) + 1); - lblen = 2; - } else { - /* If last instruction used to copy 4 or more literals (as detected by - * state == 4), the instruction becomes a copy of a 3-byte block from the - * dictionary from a 2..3kB distance, and must be interpreted like this : - * - * 0 0 0 0 D D S S (0..15) : copy 3 bytes from 2..3 kB distance - * length = 3 - * state = S (copy S literals after this block) - * Always followed by exactly one byte : H H H H H H H H - * distance = (H << 2) + D + 2049 - */ - NEEDS_IN(1) - nstate = inst & uint8_t(0x3); - lbcur = outp - ((inst >> 2) + (*inp++ << 2) + 2049); - lblen = 3; - } - } - if (lbcur < dst) { - dst_size = outp - dst; - return EResult::LookbehindOverrun; - } - NEEDS_IN(nstate) - NEEDS_OUT(lblen + nstate) - /* Copy lookbehind */ - for (std::size_t i = 0; i < lblen; ++i) - *outp++ = *lbcur++; - state = nstate; - /* Copy literal */ - for (std::size_t i = 0; i < nstate; ++i) - *outp++ = *inp++; - } - - dst_size = outp - dst; - if (lblen != 3) /* Ensure terminating M4 was encountered */ - return EResult::Error; - if (inp == inp_end) - return EResult::Success; - else if (inp < inp_end) - return EResult::InputNotConsumed; - else - return EResult::InputOverrun; -} - -struct State { - const uint8_t* src; - const uint8_t* src_end; - const uint8_t* inp; - uint32_t wind_sz; - uint32_t wind_b; - uint32_t wind_e; - uint32_t cycle1_countdown; - - const uint8_t* bufp; - uint32_t buf_sz; - - /* Access next input byte and advance both ends of circular buffer */ - void get_byte(uint8_t* buf) { - if (inp >= src_end) { - if (wind_sz > 0) - --wind_sz; - buf[wind_e] = 0; - if (wind_e < DictBase::MaxMatchLen) - buf[DictBase::BufSize + wind_e] = 0; - } else { - buf[wind_e] = *inp; - if (wind_e < DictBase::MaxMatchLen) - buf[DictBase::BufSize + wind_e] = *inp; - ++inp; - } - if (++wind_e == DictBase::BufSize) - wind_e = 0; - if (++wind_b == DictBase::BufSize) - wind_b = 0; - } - - uint32_t pos2off(uint32_t pos) const { - return wind_b > pos ? wind_b - pos : DictBase::BufSize - (pos - wind_b); - } -}; - -class DictImpl : public DictBase { -public: - struct Match3Impl : DictBase::Match3 { - static uint32_t make_key(const uint8_t* data) { - return ((0x9f5f * (((uint32_t(data[0]) << 5 ^ uint32_t(data[1])) << 5) ^ data[2])) >> 5) & 0x3fff; - } - - uint16_t get_head(uint32_t key) const { - return (chain_sz[key] == 0) ? uint16_t(UINT16_MAX) : head[key]; - } - - void init() { - std::fill(std::begin(chain_sz), std::end(chain_sz), 0); - } - - void remove(uint32_t pos, const uint8_t* b) { - --chain_sz[make_key(b + pos)]; - } - - void advance(State& s, uint32_t& match_pos, uint32_t& match_count, const uint8_t* b) { - uint32_t key = make_key(b + s.wind_b); - match_pos = chain[s.wind_b] = get_head(key); - match_count = chain_sz[key]++; - if (match_count > DictBase::MaxMatchLen) - match_count = DictBase::MaxMatchLen; - head[key] = uint16_t(s.wind_b); - } - - void skip_advance(State& s, const uint8_t* b) { - uint32_t key = make_key(b + s.wind_b); - chain[s.wind_b] = get_head(key); - head[key] = uint16_t(s.wind_b); - best_len[s.wind_b] = uint16_t(DictBase::MaxMatchLen + 1); - chain_sz[key]++; - } - }; - - struct Match2Impl : DictBase::Match2 { - static uint32_t make_key(const uint8_t* data) { - return uint32_t(data[0]) ^ (uint32_t(data[1]) << 8); - } - - void init() { - std::fill(std::begin(head), std::end(head), UINT16_MAX); - } - - void add(uint16_t pos, const uint8_t* b) { - head[make_key(b + pos)] = pos; - } - - void remove(uint32_t pos, const uint8_t* b) { - uint16_t& p = head[make_key(b + pos)]; - if (p == pos) - p = UINT16_MAX; - } - - bool search(State& s, uint32_t& lb_pos, uint32_t& lb_len, - uint32_t best_pos[MaxMatchByLengthLen], const uint8_t* b) const { - uint16_t pos = head[make_key(b + s.wind_b)]; - if (pos == UINT16_MAX) - return false; - if (best_pos[2] == 0) - best_pos[2] = pos + 1; - if (lb_len < 2) { - lb_len = 2; - lb_pos = pos; - } - return true; - } - }; - - void init(State& s, const uint8_t* src, std::size_t src_size) { - auto& match3 = static_cast(_storage->match3); - auto& match2 = static_cast(_storage->match2); - - s.cycle1_countdown = DictBase::MaxDist; - match3.init(); - match2.init(); - - s.src = src; - s.src_end = src + src_size; - s.inp = src; - s.wind_sz = uint32_t(std::min(src_size, std::size_t(MaxMatchLen))); - s.wind_b = 0; - s.wind_e = s.wind_sz; - std::copy_n(s.inp, s.wind_sz, _storage->buffer); - s.inp += s.wind_sz; - - if (s.wind_e == DictBase::BufSize) - s.wind_e = 0; - - if (s.wind_sz < 3) - std::fill_n(_storage->buffer + s.wind_b + s.wind_sz, 3, 0); - } - - void reset_next_input_entry(State& s, Match3Impl& match3, Match2Impl& match2) { - /* Remove match from about-to-be-clobbered buffer entry */ - if (s.cycle1_countdown == 0) { - match3.remove(s.wind_e, _storage->buffer); - match2.remove(s.wind_e, _storage->buffer); - } else { - --s.cycle1_countdown; - } - } - - void advance(State& s, uint32_t& lb_off, uint32_t& lb_len, - uint32_t best_off[MaxMatchByLengthLen], bool skip) { - auto& match3 = static_cast(_storage->match3); - auto& match2 = static_cast(_storage->match2); - - if (skip) { - for (uint32_t i = 0; i < lb_len - 1; ++i) { - reset_next_input_entry(s, match3, match2); - match3.skip_advance(s, _storage->buffer); - match2.add(uint16_t(s.wind_b), _storage->buffer); - s.get_byte(_storage->buffer); - } - } - - lb_len = 1; - lb_off = 0; - uint32_t lb_pos; - - uint32_t best_pos[MaxMatchByLengthLen] = {}; - uint32_t match_pos, match_count; - match3.advance(s, match_pos, match_count, _storage->buffer); - - int best_char = _storage->buffer[s.wind_b]; - uint32_t best_len = lb_len; - if (lb_len >= s.wind_sz) { - if (s.wind_sz == 0) - best_char = -1; - lb_off = 0; - match3.best_len[s.wind_b] = DictBase::MaxMatchLen + 1; - } else { - if (match2.search(s, lb_pos, lb_len, best_pos, _storage->buffer) && s.wind_sz >= 3) { - for (uint32_t i = 0; i < match_count; ++i, match_pos = match3.chain[match_pos]) { - auto ref_ptr = _storage->buffer + s.wind_b; - auto match_ptr = _storage->buffer + match_pos; - auto mismatch = std::mismatch(ref_ptr, ref_ptr + s.wind_sz, match_ptr); - auto match_len = uint32_t(mismatch.first - ref_ptr); - if (match_len < 2) - continue; - if (match_len < MaxMatchByLengthLen && best_pos[match_len] == 0) - best_pos[match_len] = match_pos + 1; - if (match_len > lb_len) { - lb_len = match_len; - lb_pos = match_pos; - if (match_len == s.wind_sz || match_len > match3.best_len[match_pos]) - break; - } - } - } - if (lb_len > best_len) - lb_off = s.pos2off(lb_pos); - match3.best_len[s.wind_b] = uint16_t(lb_len); - for (auto posit = std::begin(best_pos) + 2, offit = best_off + 2; - posit != std::end(best_pos); ++posit, ++offit) { - *offit = (*posit > 0) ? s.pos2off(*posit - 1) : 0; - } - } - - reset_next_input_entry(s, match3, match2); - - match2.add(uint16_t(s.wind_b), _storage->buffer); - - s.get_byte(_storage->buffer); - - if (best_char < 0) { - s.buf_sz = 0; - lb_len = 0; - /* Signal exit */ - } else { - s.buf_sz = s.wind_sz + 1; - } - s.bufp = s.inp - s.buf_sz; - } -}; - -static void find_better_match(const uint32_t best_off[MaxMatchByLengthLen], uint32_t& lb_len, uint32_t& lb_off) { - if (lb_len <= M2MinLen || lb_off <= M2MaxOffset) - return; - if (lb_off > M2MaxOffset && lb_len >= M2MinLen + 1 && lb_len <= M2MaxLen + 1 && - best_off[lb_len - 1] != 0 && best_off[lb_len - 1] <= M2MaxOffset) { - lb_len -= 1; - lb_off = best_off[lb_len]; - } else if (lb_off > M3MaxOffset && lb_len >= M4MaxLen + 1 && lb_len <= M2MaxLen + 2 && - best_off[lb_len - 2] && best_off[lb_len] <= M2MaxOffset) { - lb_len -= 2; - lb_off = best_off[lb_len]; - } else if (lb_off > M3MaxOffset && lb_len >= M4MaxLen + 1 && lb_len <= M3MaxLen + 1 && - best_off[lb_len - 1] != 0 && best_off[lb_len - 2] <= M3MaxOffset) { - lb_len -= 1; - lb_off = best_off[lb_len]; - } -} - -static EResult encode_literal_run(uint8_t*& outp, const uint8_t* outp_end, const uint8_t* dst, std::size_t& dst_size, - const uint8_t* lit_ptr, uint32_t lit_len) { - if (outp == dst && lit_len <= 238) { - NEEDS_OUT(1); - *outp++ = uint8_t(17 + lit_len); - } else if (lit_len <= 3) { - outp[-2] = uint8_t(outp[-2] | lit_len); - } else if (lit_len <= 18) { - NEEDS_OUT(1); - *outp++ = uint8_t(lit_len - 3); - } else { - NEEDS_OUT((lit_len - 18) / 255 + 2); - *outp++ = 0; - WRITE_ZERO_BYTE_LENGTH(lit_len - 18); - } - NEEDS_OUT(lit_len); - outp = std::copy_n(lit_ptr, lit_len, outp); - return EResult::Success; -} - -static EResult encode_lookback_match(uint8_t*& outp, const uint8_t* outp_end, const uint8_t* dst, std::size_t& dst_size, - uint32_t lb_len, uint32_t lb_off, uint32_t last_lit_len) { - if (lb_len == 2) { - lb_off -= 1; - NEEDS_OUT(2); - *outp++ = uint8_t(M1Marker | ((lb_off & 0x3) << 2)); - *outp++ = uint8_t(lb_off >> 2); - } else if (lb_len <= M2MaxLen && lb_off <= M2MaxOffset) { - lb_off -= 1; - NEEDS_OUT(2); - *outp++ = uint8_t((lb_len - 1) << 5 | ((lb_off & 0x7) << 2)); - *outp++ = uint8_t(lb_off >> 3); - } else if (lb_len == M2MinLen && lb_off <= M1MaxOffset + M2MaxOffset && last_lit_len >= 4) { - lb_off -= 1 + M2MaxOffset; - NEEDS_OUT(2); - *outp++ = uint8_t(M1Marker | ((lb_off & 0x3) << 2)); - *outp++ = uint8_t(lb_off >> 2); - } else if (lb_off <= M3MaxOffset) { - lb_off -= 1; - if (lb_len <= M3MaxLen) { - NEEDS_OUT(1); - *outp++ = uint8_t(M3Marker | (lb_len - 2)); - } else { - lb_len -= M3MaxLen; - NEEDS_OUT(lb_len / 255 + 2); - *outp++ = uint8_t(M3Marker); - WRITE_ZERO_BYTE_LENGTH(lb_len); - } - NEEDS_OUT(2); - *outp++ = uint8_t(lb_off << 2); - *outp++ = uint8_t(lb_off >> 6); - } else { - lb_off -= 0x4000; - if (lb_len <= M4MaxLen) { - NEEDS_OUT(1); - *outp++ = uint8_t(M4Marker | ((lb_off & 0x4000) >> 11) | (lb_len - 2)); - } else { - lb_len -= M4MaxLen; - NEEDS_OUT(lb_len / 255 + 2); - *outp++ = uint8_t(M4Marker | ((lb_off & 0x4000) >> 11)); - WRITE_ZERO_BYTE_LENGTH(lb_len); - } - NEEDS_OUT(2); - *outp++ = uint8_t(lb_off << 2); - *outp++ = uint8_t(lb_off >> 6); - } - return EResult::Success; -} - -EResult compress(const uint8_t* src, std::size_t src_size, - uint8_t* dst, std::size_t init_dst_size, - std::size_t& dst_size, DictBase& dict) { - EResult err; - State s; - auto& d = static_cast(dict); - dst_size = init_dst_size; - uint8_t* outp = dst; - uint8_t* outp_end = dst + dst_size; - uint32_t lit_len = 0; - uint32_t lb_off, lb_len; - uint32_t best_off[MaxMatchByLengthLen]; - d.init(s, src, src_size); - const uint8_t* lit_ptr = s.inp; - d.advance(s, lb_off, lb_len, best_off, false); - while (s.buf_sz > 0) { - if (lit_len == 0) - lit_ptr = s.bufp; - if (lb_len < 2 || (lb_len == 2 && (lb_off > M1MaxOffset || lit_len == 0 || lit_len >= 4)) || - (lb_len == 2 && outp == dst) || (outp == dst && lit_len == 0)) { - lb_len = 0; - } else if (lb_len == M2MinLen && lb_off > M1MaxOffset + M2MaxOffset && lit_len >= 4) { - lb_len = 0; - } - if (lb_len == 0) { - ++lit_len; - d.advance(s, lb_off, lb_len, best_off, false); - continue; - } - find_better_match(best_off, lb_len, lb_off); - if ((err = encode_literal_run(outp, outp_end, dst, dst_size, lit_ptr, lit_len)) < EResult::Success) - return err; - if ((err = encode_lookback_match(outp, outp_end, dst, dst_size, lb_len, lb_off, lit_len)) < EResult::Success) - return err; - lit_len = 0; - d.advance(s, lb_off, lb_len, best_off, true); - } - if ((err = encode_literal_run(outp, outp_end, dst, dst_size, lit_ptr, lit_len)) < EResult::Success) - return err; - - /* Terminating M4 */ - NEEDS_OUT(3); - *outp++ = M4Marker | 1; - *outp++ = 0; - *outp++ = 0; - - dst_size = outp - dst; - return EResult::Success; -} - -} diff --git a/libs/compression/lzokay.h b/libs/compression/lzokay.h deleted file mode 100644 index 522edd8..0000000 --- a/libs/compression/lzokay.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once -#include -#include -#include - -namespace lzokay { - -enum class EResult { - LookbehindOverrun = -4, - OutputOverrun = -3, - InputOverrun = -2, - Error = -1, - Success = 0, - InputNotConsumed = 1, -}; - -class DictBase { -protected: - static constexpr uint32_t HashSize = 0x4000; - static constexpr uint32_t MaxDist = 0xbfff; - static constexpr uint32_t MaxMatchLen = 0x800; - static constexpr uint32_t BufSize = MaxDist + MaxMatchLen; - - /* List encoding of previous 3-byte data matches */ - struct Match3 { - uint16_t head[HashSize]; /* key -> chain-head-pos */ - uint16_t chain_sz[HashSize]; /* key -> chain-size */ - uint16_t chain[BufSize]; /* chain-pos -> next-chain-pos */ - uint16_t best_len[BufSize]; /* chain-pos -> best-match-length */ - }; - /* Encoding of 2-byte data matches */ - struct Match2 { - uint16_t head[1 << 16]; /* 2-byte-data -> head-pos */ - }; - - struct Data { - Match3 match3; - Match2 match2; - - /* Circular buffer caching enough data to access the maximum lookback - * distance of 48K + maximum match length of 2K. An additional 2K is - * allocated so the start of the buffer may be replicated at the end, - * therefore providing efficient circular access. - */ - uint8_t buffer[BufSize + MaxMatchLen]; - }; - using storage_type = Data; - storage_type* _storage; - DictBase() = default; - friend struct State; - friend EResult compress(const uint8_t* src, std::size_t src_size, - uint8_t* dst, std::size_t& dst_size, DictBase& dict); -}; -template class _Alloc = std::allocator> -class Dict : public DictBase { - _Alloc _allocator; -public: - Dict() { _storage = _allocator.allocate(1); } - ~Dict() { _allocator.deallocate(_storage, 1); } -}; - -EResult decompress(const uint8_t* src, std::size_t src_size, - uint8_t* dst, std::size_t dst_size, - std::size_t& out_size); -EResult compress(const uint8_t* src, std::size_t src_size, - uint8_t* dst, std::size_t dst_size, - std::size_t& out_size, DictBase& dict); -inline EResult compress(const uint8_t* src, std::size_t src_size, - uint8_t* dst, std::size_t dst_size, - std::size_t& out_size) { - Dict<> dict; - return compress(src, src_size, dst, dst_size, out_size, dict); -} - -constexpr std::size_t compress_worst_size(std::size_t s) { - return s + s / 16 + 64 + 3; -} - -} diff --git a/libs/compression/minilzo.c b/libs/compression/minilzo.c new file mode 100644 index 0000000..8fd8664 --- /dev/null +++ b/libs/compression/minilzo.c @@ -0,0 +1,6365 @@ +/* minilzo.c -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + +#define __LZO_IN_MINILZO 1 + +#if defined(LZO_CFG_FREESTANDING) +# undef MINILZO_HAVE_CONFIG_H +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include +#if defined(MINILZO_CFG_USE_INTERNAL_LZODEFS) + +#ifndef __LZODEFS_H_INCLUDED +#define __LZODEFS_H_INCLUDED 1 + +#if defined(__CYGWIN32__) && !defined(__CYGWIN__) +# define __CYGWIN__ __CYGWIN32__ +#endif +#if 1 && defined(__INTERIX) && defined(__GNUC__) && !defined(_ALL_SOURCE) +# define _ALL_SOURCE 1 +#endif +#if defined(__mips__) && defined(__R5900__) +# if !defined(__LONG_MAX__) +# define __LONG_MAX__ 9223372036854775807L +# endif +#endif +#if 0 +#elif !defined(__LZO_LANG_OVERRIDE) +#if (defined(__clang__) || defined(__GNUC__)) && defined(__ASSEMBLER__) +# if (__ASSEMBLER__+0) <= 0 +# error "__ASSEMBLER__" +# else +# define LZO_LANG_ASSEMBLER 1 +# endif +#elif defined(__cplusplus) +# if (__cplusplus+0) <= 0 +# error "__cplusplus" +# elif (__cplusplus < 199711L) +# define LZO_LANG_CXX 1 +# elif defined(_MSC_VER) && defined(_MSVC_LANG) && (_MSVC_LANG+0 >= 201402L) && 1 +# define LZO_LANG_CXX _MSVC_LANG +# else +# define LZO_LANG_CXX __cplusplus +# endif +# define LZO_LANG_CPLUSPLUS LZO_LANG_CXX +#else +# if defined(__STDC_VERSION__) && (__STDC_VERSION__+0 >= 199409L) +# define LZO_LANG_C __STDC_VERSION__ +# else +# define LZO_LANG_C 1 +# endif +#endif +#endif +#if !defined(LZO_CFG_NO_DISABLE_WUNDEF) +#if defined(__ARMCC_VERSION) +# pragma diag_suppress 193 +#elif defined(__clang__) && defined(__clang_minor__) +# pragma clang diagnostic ignored "-Wundef" +#elif defined(__INTEL_COMPILER) +# pragma warning(disable: 193) +#elif defined(__KEIL__) && defined(__C166__) +# pragma warning disable = 322 +#elif defined(__GNUC__) && defined(__GNUC_MINOR__) && !defined(__PATHSCALE__) +# if ((__GNUC__-0) >= 5 || ((__GNUC__-0) == 4 && (__GNUC_MINOR__-0) >= 2)) +# pragma GCC diagnostic ignored "-Wundef" +# endif +#elif defined(_MSC_VER) && !defined(__clang__) && !defined(__INTEL_COMPILER) && !defined(__MWERKS__) +# if ((_MSC_VER-0) >= 1300) +# pragma warning(disable: 4668) +# endif +#endif +#endif +#if 0 && defined(__POCC__) && defined(_WIN32) +# if (__POCC__ >= 400) +# pragma warn(disable: 2216) +# endif +#endif +#if 0 && defined(__WATCOMC__) +# if (__WATCOMC__ >= 1050) && (__WATCOMC__ < 1060) +# pragma warning 203 9 +# endif +#endif +#if defined(__BORLANDC__) && defined(__MSDOS__) && !defined(__FLAT__) +# pragma option -h +#endif +#if !(LZO_CFG_NO_DISABLE_WCRTNONSTDC) +#ifndef _CRT_NONSTDC_NO_DEPRECATE +#define _CRT_NONSTDC_NO_DEPRECATE 1 +#endif +#ifndef _CRT_NONSTDC_NO_WARNINGS +#define _CRT_NONSTDC_NO_WARNINGS 1 +#endif +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif +#ifndef _CRT_SECURE_NO_WARNINGS +#define _CRT_SECURE_NO_WARNINGS 1 +#endif +#endif +#if 0 +#define LZO_0xffffUL 0xfffful +#define LZO_0xffffffffUL 0xfffffffful +#else +#define LZO_0xffffUL 65535ul +#define LZO_0xffffffffUL 4294967295ul +#endif +#define LZO_0xffffL LZO_0xffffUL +#define LZO_0xffffffffL LZO_0xffffffffUL +#if (LZO_0xffffL == LZO_0xffffffffL) +# error "your preprocessor is broken 1" +#endif +#if (16ul * 16384ul != 262144ul) +# error "your preprocessor is broken 2" +#endif +#if 0 +#if (32767 >= 4294967295ul) +# error "your preprocessor is broken 3" +#endif +#if (65535u >= 4294967295ul) +# error "your preprocessor is broken 4" +#endif +#endif +#if defined(__COUNTER__) +# ifndef LZO_CFG_USE_COUNTER +# define LZO_CFG_USE_COUNTER 1 +# endif +#else +# undef LZO_CFG_USE_COUNTER +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__ZTC__) && defined(__I86__) && !defined(__OS2__) +# if !defined(MSDOS) +# define MSDOS 1 +# endif +# if !defined(_MSDOS) +# define _MSDOS 1 +# endif +#elif 0 && defined(__VERSION) && defined(MB_LEN_MAX) +# if (__VERSION == 520) && (MB_LEN_MAX == 1) +# if !defined(__AZTEC_C__) +# define __AZTEC_C__ __VERSION +# endif +# if !defined(__DOS__) +# define __DOS__ 1 +# endif +# endif +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(_MSC_VER) && defined(M_I86HM) +# define ptrdiff_t long +# define _PTRDIFF_T_DEFINED 1 +#endif +#endif +#if (UINT_MAX == LZO_0xffffL) +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +# if defined(__AZTEC_C__) && defined(__DOS__) +# define __LZO_RENAME_A 1 +# elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define __LZO_RENAME_A 1 +# elif (_MSC_VER < 700) +# define __LZO_RENAME_B 1 +# endif +# elif defined(__TSC__) && defined(__OS2__) +# define __LZO_RENAME_A 1 +# elif defined(__MSDOS__) && defined(__TURBOC__) && (__TURBOC__ < 0x0410) +# define __LZO_RENAME_A 1 +# elif defined(__PACIFIC__) && defined(DOS) +# if !defined(__far) +# define __far far +# endif +# if !defined(__near) +# define __near near +# endif +# endif +# if defined(__LZO_RENAME_A) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__far) +# define __far far +# endif +# if !defined(__huge) +# define __huge huge +# endif +# if !defined(__near) +# define __near near +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# if !defined(__huge) +# define __huge huge +# endif +# elif defined(__LZO_RENAME_B) +# if !defined(__cdecl) +# define __cdecl _cdecl +# endif +# if !defined(__far) +# define __far _far +# endif +# if !defined(__huge) +# define __huge _huge +# endif +# if !defined(__near) +# define __near _near +# endif +# if !defined(__pascal) +# define __pascal _pascal +# endif +# elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# if !defined(__cdecl) +# define __cdecl cdecl +# endif +# if !defined(__pascal) +# define __pascal pascal +# endif +# endif +# undef __LZO_RENAME_A +# undef __LZO_RENAME_B +#endif +#if (UINT_MAX == LZO_0xffffL) +#if defined(__AZTEC_C__) && defined(__DOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +#elif defined(_MSC_VER) && defined(MSDOS) +# if (_MSC_VER < 600) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# endif +# if (_MSC_VER < 700) +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# define LZO_BROKEN_SIZEOF 1 +# endif +#elif defined(__PACIFIC__) && defined(DOS) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#elif defined(__TURBOC__) && defined(__MSDOS__) +# if (__TURBOC__ < 0x0150) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +# define LZO_BROKEN_INTEGRAL_PROMOTION 1 +# endif +# if (__TURBOC__ < 0x0200) +# define LZO_BROKEN_SIZEOF 1 +# endif +# if (__TURBOC__ < 0x0400) && defined(__cplusplus) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# endif +#elif (defined(__PUREC__) || defined(__TURBOC__)) && defined(__TOS__) +# define LZO_BROKEN_CDECL_ALT_SYNTAX 1 +# define LZO_BROKEN_SIZEOF 1 +#endif +#endif +#if defined(__WATCOMC__) && (__WATCOMC__ < 900) +# define LZO_BROKEN_INTEGRAL_CONSTANTS 1 +#endif +#if defined(_CRAY) && defined(_CRAY1) +# define LZO_BROKEN_SIGNED_RIGHT_SHIFT 1 +#endif +#define LZO_PP_STRINGIZE(x) #x +#define LZO_PP_MACRO_EXPAND(x) LZO_PP_STRINGIZE(x) +#define LZO_PP_CONCAT0() /*empty*/ +#define LZO_PP_CONCAT1(a) a +#define LZO_PP_CONCAT2(a,b) a ## b +#define LZO_PP_CONCAT3(a,b,c) a ## b ## c +#define LZO_PP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_PP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_PP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_PP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_PP_ECONCAT0() LZO_PP_CONCAT0() +#define LZO_PP_ECONCAT1(a) LZO_PP_CONCAT1(a) +#define LZO_PP_ECONCAT2(a,b) LZO_PP_CONCAT2(a,b) +#define LZO_PP_ECONCAT3(a,b,c) LZO_PP_CONCAT3(a,b,c) +#define LZO_PP_ECONCAT4(a,b,c,d) LZO_PP_CONCAT4(a,b,c,d) +#define LZO_PP_ECONCAT5(a,b,c,d,e) LZO_PP_CONCAT5(a,b,c,d,e) +#define LZO_PP_ECONCAT6(a,b,c,d,e,f) LZO_PP_CONCAT6(a,b,c,d,e,f) +#define LZO_PP_ECONCAT7(a,b,c,d,e,f,g) LZO_PP_CONCAT7(a,b,c,d,e,f,g) +#define LZO_PP_EMPTY /*empty*/ +#define LZO_PP_EMPTY0() /*empty*/ +#define LZO_PP_EMPTY1(a) /*empty*/ +#define LZO_PP_EMPTY2(a,b) /*empty*/ +#define LZO_PP_EMPTY3(a,b,c) /*empty*/ +#define LZO_PP_EMPTY4(a,b,c,d) /*empty*/ +#define LZO_PP_EMPTY5(a,b,c,d,e) /*empty*/ +#define LZO_PP_EMPTY6(a,b,c,d,e,f) /*empty*/ +#define LZO_PP_EMPTY7(a,b,c,d,e,f,g) /*empty*/ +#if 1 +#define LZO_CPP_STRINGIZE(x) #x +#define LZO_CPP_MACRO_EXPAND(x) LZO_CPP_STRINGIZE(x) +#define LZO_CPP_CONCAT2(a,b) a ## b +#define LZO_CPP_CONCAT3(a,b,c) a ## b ## c +#define LZO_CPP_CONCAT4(a,b,c,d) a ## b ## c ## d +#define LZO_CPP_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e +#define LZO_CPP_CONCAT6(a,b,c,d,e,f) a ## b ## c ## d ## e ## f +#define LZO_CPP_CONCAT7(a,b,c,d,e,f,g) a ## b ## c ## d ## e ## f ## g +#define LZO_CPP_ECONCAT2(a,b) LZO_CPP_CONCAT2(a,b) +#define LZO_CPP_ECONCAT3(a,b,c) LZO_CPP_CONCAT3(a,b,c) +#define LZO_CPP_ECONCAT4(a,b,c,d) LZO_CPP_CONCAT4(a,b,c,d) +#define LZO_CPP_ECONCAT5(a,b,c,d,e) LZO_CPP_CONCAT5(a,b,c,d,e) +#define LZO_CPP_ECONCAT6(a,b,c,d,e,f) LZO_CPP_CONCAT6(a,b,c,d,e,f) +#define LZO_CPP_ECONCAT7(a,b,c,d,e,f,g) LZO_CPP_CONCAT7(a,b,c,d,e,f,g) +#endif +#define __LZO_MASK_GEN(o,b) (((((o) << ((b)-((b)!=0))) - (o)) << 1) + (o)*((b)!=0)) +#if 1 && defined(__cplusplus) +# if !defined(__STDC_CONSTANT_MACROS) +# define __STDC_CONSTANT_MACROS 1 +# endif +# if !defined(__STDC_LIMIT_MACROS) +# define __STDC_LIMIT_MACROS 1 +# endif +#endif +#if defined(__cplusplus) +# define LZO_EXTERN_C extern "C" +# define LZO_EXTERN_C_BEGIN extern "C" { +# define LZO_EXTERN_C_END } +#else +# define LZO_EXTERN_C extern +# define LZO_EXTERN_C_BEGIN /*empty*/ +# define LZO_EXTERN_C_END /*empty*/ +#endif +#if !defined(__LZO_OS_OVERRIDE) +#if (LZO_OS_FREESTANDING) +# define LZO_INFO_OS "freestanding" +#elif (LZO_OS_EMBEDDED) +# define LZO_INFO_OS "embedded" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_OS_EMBEDDED 1 +# define LZO_INFO_OS "embedded" +#elif defined(__CYGWIN__) && defined(__GNUC__) +# define LZO_OS_CYGWIN 1 +# define LZO_INFO_OS "cygwin" +#elif defined(__EMX__) && defined(__GNUC__) +# define LZO_OS_EMX 1 +# define LZO_INFO_OS "emx" +#elif defined(__BEOS__) +# define LZO_OS_BEOS 1 +# define LZO_INFO_OS "beos" +#elif defined(__Lynx__) +# define LZO_OS_LYNXOS 1 +# define LZO_INFO_OS "lynxos" +#elif defined(__OS400__) +# define LZO_OS_OS400 1 +# define LZO_INFO_OS "os400" +#elif defined(__QNX__) +# define LZO_OS_QNX 1 +# define LZO_INFO_OS "qnx" +#elif defined(__BORLANDC__) && defined(__DPMI32__) && (__BORLANDC__ >= 0x0460) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__BORLANDC__) && defined(__DPMI16__) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +#elif defined(__ZTC__) && defined(DOS386) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +#elif defined(__OS2__) || defined(__OS2V2__) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_OS216 1 +# define LZO_INFO_OS "os216" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_OS2 1 +# define LZO_INFO_OS "os2" +# else +# error "check your limits.h header" +# endif +#elif defined(__WIN64__) || defined(_WIN64) || defined(WIN64) +# define LZO_OS_WIN64 1 +# define LZO_INFO_OS "win64" +#elif defined(__WIN32__) || defined(_WIN32) || defined(WIN32) || defined(__WINDOWS_386__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__MWERKS__) && defined(__INTEL__) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +#elif defined(__WINDOWS__) || defined(_WINDOWS) || defined(_Windows) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_WIN16 1 +# define LZO_INFO_OS "win16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# else +# error "check your limits.h header" +# endif +#elif defined(__DOS__) || defined(__MSDOS__) || defined(_MSDOS) || defined(MSDOS) || (defined(__PACIFIC__) && defined(DOS)) +# if (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_OS_DOS32 1 +# define LZO_INFO_OS "dos32" +# else +# error "check your limits.h header" +# endif +#elif defined(__WATCOMC__) +# if defined(__NT__) && (UINT_MAX == LZO_0xffffL) +# define LZO_OS_DOS16 1 +# define LZO_INFO_OS "dos16" +# elif defined(__NT__) && (__WATCOMC__ < 1100) +# define LZO_OS_WIN32 1 +# define LZO_INFO_OS "win32" +# elif defined(__linux__) || defined(__LINUX__) +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +# else +# error "please specify a target using the -bt compiler option" +# endif +#elif defined(__palmos__) +# define LZO_OS_PALMOS 1 +# define LZO_INFO_OS "palmos" +#elif defined(__TOS__) || defined(__atarist__) +# define LZO_OS_TOS 1 +# define LZO_INFO_OS "tos" +#elif defined(macintosh) && !defined(__arm__) && !defined(__i386__) && !defined(__ppc__) && !defined(__x64_64__) +# define LZO_OS_MACCLASSIC 1 +# define LZO_INFO_OS "macclassic" +#elif defined(__VMS) +# define LZO_OS_VMS 1 +# define LZO_INFO_OS "vms" +#elif (defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PS2 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "ps2" +#elif defined(__mips__) && defined(__psp__) +# define LZO_OS_CONSOLE 1 +# define LZO_OS_CONSOLE_PSP 1 +# define LZO_INFO_OS "console" +# define LZO_INFO_OS_CONSOLE "psp" +#else +# define LZO_OS_POSIX 1 +# define LZO_INFO_OS "posix" +#endif +#if (LZO_OS_POSIX) +# if defined(_AIX) || defined(__AIX__) || defined(__aix__) +# define LZO_OS_POSIX_AIX 1 +# define LZO_INFO_OS_POSIX "aix" +# elif defined(__FreeBSD__) +# define LZO_OS_POSIX_FREEBSD 1 +# define LZO_INFO_OS_POSIX "freebsd" +# elif defined(__hpux__) || defined(__hpux) +# define LZO_OS_POSIX_HPUX 1 +# define LZO_INFO_OS_POSIX "hpux" +# elif defined(__INTERIX) +# define LZO_OS_POSIX_INTERIX 1 +# define LZO_INFO_OS_POSIX "interix" +# elif defined(__IRIX__) || defined(__irix__) +# define LZO_OS_POSIX_IRIX 1 +# define LZO_INFO_OS_POSIX "irix" +# elif defined(__linux__) || defined(__linux) || defined(__LINUX__) +# define LZO_OS_POSIX_LINUX 1 +# define LZO_INFO_OS_POSIX "linux" +# elif defined(__APPLE__) && defined(__MACH__) +# if ((__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__-0) >= 20000) +# define LZO_OS_POSIX_DARWIN 1040 +# define LZO_INFO_OS_POSIX "darwin_iphone" +# elif ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) >= 1040) +# define LZO_OS_POSIX_DARWIN __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ +# define LZO_INFO_OS_POSIX "darwin" +# else +# define LZO_OS_POSIX_DARWIN 1 +# define LZO_INFO_OS_POSIX "darwin" +# endif +# define LZO_OS_POSIX_MACOSX LZO_OS_POSIX_DARWIN +# elif defined(__minix__) || defined(__minix) +# define LZO_OS_POSIX_MINIX 1 +# define LZO_INFO_OS_POSIX "minix" +# elif defined(__NetBSD__) +# define LZO_OS_POSIX_NETBSD 1 +# define LZO_INFO_OS_POSIX "netbsd" +# elif defined(__OpenBSD__) +# define LZO_OS_POSIX_OPENBSD 1 +# define LZO_INFO_OS_POSIX "openbsd" +# elif defined(__osf__) +# define LZO_OS_POSIX_OSF 1 +# define LZO_INFO_OS_POSIX "osf" +# elif defined(__solaris__) || defined(__sun) +# if defined(__SVR4) || defined(__svr4__) +# define LZO_OS_POSIX_SOLARIS 1 +# define LZO_INFO_OS_POSIX "solaris" +# else +# define LZO_OS_POSIX_SUNOS 1 +# define LZO_INFO_OS_POSIX "sunos" +# endif +# elif defined(__ultrix__) || defined(__ultrix) +# define LZO_OS_POSIX_ULTRIX 1 +# define LZO_INFO_OS_POSIX "ultrix" +# elif defined(_UNICOS) +# define LZO_OS_POSIX_UNICOS 1 +# define LZO_INFO_OS_POSIX "unicos" +# else +# define LZO_OS_POSIX_UNKNOWN 1 +# define LZO_INFO_OS_POSIX "unknown" +# endif +#endif +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (UINT_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(CIL) && defined(_GNUCC) && defined(__GNUC__) +# define LZO_CC_CILLY 1 +# define LZO_INFO_CC "Cilly" +# if defined(__CILLY__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CILLY__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif 0 && defined(SDCC) && defined(__VERSION__) && !defined(__GNUC__) +# define LZO_CC_SDCC 1 +# define LZO_INFO_CC "sdcc" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(SDCC) +#elif defined(__PATHSCALE__) && defined(__PATHCC_PATCHLEVEL__) +# define LZO_CC_PATHSCALE (__PATHCC__ * 0x10000L + (__PATHCC_MINOR__-0) * 0x100 + (__PATHCC_PATCHLEVEL__-0)) +# define LZO_INFO_CC "Pathscale C" +# define LZO_INFO_CCVER __PATHSCALE__ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_PATHSCALE_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__INTEL_COMPILER) && ((__INTEL_COMPILER-0) > 0) +# define LZO_CC_INTELC __INTEL_COMPILER +# define LZO_INFO_CC "Intel C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__INTEL_COMPILER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_INTELC_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_INTELC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__POCC__) && defined(_WIN32) +# define LZO_CC_PELLESC 1 +# define LZO_INFO_CC "Pelles C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__POCC__) +#elif defined(__ARMCC_VERSION) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_ARMCC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__clang__) && defined(__c2__) && defined(__c2_version__) && defined(_MSC_VER) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# define LZO_CC_CLANG_C2 _MSC_VER +# define LZO_CC_CLANG_VENDOR_MICROSOFT 1 +# define LZO_INFO_CC "clang/c2" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__c2_version__) +#elif defined(__clang__) && defined(__llvm__) && defined(__VERSION__) +# if defined(__clang_major__) && defined(__clang_minor__) && defined(__clang_patchlevel__) +# define LZO_CC_CLANG (__clang_major__ * 0x10000L + (__clang_minor__-0) * 0x100 + (__clang_patchlevel__-0)) +# else +# define LZO_CC_CLANG 0x010000L +# endif +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_CLANG_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_CLANG_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +# if defined(__APPLE_CC__) +# define LZO_CC_CLANG_VENDOR_APPLE 1 +# define LZO_INFO_CC "clang/apple" +# else +# define LZO_CC_CLANG_VENDOR_LLVM 1 +# define LZO_INFO_CC "clang" +# endif +# if defined(__clang_version__) +# define LZO_INFO_CCVER __clang_version__ +# else +# define LZO_INFO_CCVER __VERSION__ +# endif +#elif defined(__llvm__) && defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# if defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# else +# define LZO_CC_LLVM_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# endif +# define LZO_CC_LLVM LZO_CC_LLVM_GNUC +# define LZO_INFO_CC "llvm-gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(__ACK__) && defined(_ACK) +# define LZO_CC_ACK 1 +# define LZO_INFO_CC "Amsterdam Compiler Kit C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__ARMCC_VERSION) && !defined(__GNUC__) +# define LZO_CC_ARMCC __ARMCC_VERSION +# define LZO_CC_ARMCC_ARMCC __ARMCC_VERSION +# define LZO_INFO_CC "ARM C Compiler" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ARMCC_VERSION) +#elif defined(__AZTEC_C__) +# define LZO_CC_AZTECC 1 +# define LZO_INFO_CC "Aztec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__AZTEC_C__) +#elif defined(__CODEGEARC__) +# define LZO_CC_CODEGEARC 1 +# define LZO_INFO_CC "CodeGear C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__CODEGEARC__) +#elif defined(__BORLANDC__) +# define LZO_CC_BORLANDC 1 +# define LZO_INFO_CC "Borland C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__BORLANDC__) +#elif defined(_CRAYC) && defined(_RELEASE) +# define LZO_CC_CRAYC 1 +# define LZO_INFO_CC "Cray C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_RELEASE) +#elif defined(__DMC__) && defined(__SC__) +# define LZO_CC_DMC 1 +# define LZO_INFO_CC "Digital Mars C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DMC__) +#elif defined(__DECC) +# define LZO_CC_DECC 1 +# define LZO_INFO_CC "DEC C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__DECC) +#elif (defined(__ghs) || defined(__ghs__)) && defined(__GHS_VERSION_NUMBER) && ((__GHS_VERSION_NUMBER-0) > 0) +# define LZO_CC_GHS 1 +# define LZO_INFO_CC "Green Hills C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__GHS_VERSION_NUMBER) +# if defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_GHS_MSC _MSC_VER +# elif defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__VERSION__) +# define LZO_CC_GHS_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# endif +#elif defined(__HIGHC__) +# define LZO_CC_HIGHC 1 +# define LZO_INFO_CC "MetaWare High C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__HP_aCC) && ((__HP_aCC-0) > 0) +# define LZO_CC_HPACC __HP_aCC +# define LZO_INFO_CC "HP aCC" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__HP_aCC) +#elif defined(__IAR_SYSTEMS_ICC__) +# define LZO_CC_IARC 1 +# define LZO_INFO_CC "IAR C" +# if defined(__VER__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__VER__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__IBMC__) && ((__IBMC__-0) > 0) +# define LZO_CC_IBMC __IBMC__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMC__) +#elif defined(__IBMCPP__) && ((__IBMCPP__-0) > 0) +# define LZO_CC_IBMC __IBMCPP__ +# define LZO_INFO_CC "IBM C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__IBMCPP__) +#elif defined(__KEIL__) && defined(__C166__) +# define LZO_CC_KEILC 1 +# define LZO_INFO_CC "Keil C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__C166__) +#elif defined(__LCC__) && defined(_WIN32) && defined(__LCCOPTIMLEVEL) +# define LZO_CC_LCCWIN32 1 +# define LZO_INFO_CC "lcc-win32" +# define LZO_INFO_CCVER "unknown" +#elif defined(__LCC__) +# define LZO_CC_LCC 1 +# define LZO_INFO_CC "lcc" +# if defined(__LCC_VERSION__) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__LCC_VERSION__) +# else +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__MWERKS__) && ((__MWERKS__-0) > 0) +# define LZO_CC_MWERKS __MWERKS__ +# define LZO_INFO_CC "Metrowerks C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__MWERKS__) +#elif (defined(__NDPC__) || defined(__NDPX__)) && defined(__i386) +# define LZO_CC_NDPC 1 +# define LZO_INFO_CC "Microway NDP C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PACIFIC__) +# define LZO_CC_PACIFICC 1 +# define LZO_INFO_CC "Pacific C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PACIFIC__) +#elif defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100 + (__PGIC_PATCHLEVEL__-0)) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) "." LZO_PP_MACRO_EXPAND(__PGIC_PATCHLEVEL__) +# else +# define LZO_CC_PGI (__PGIC__ * 0x10000L + (__PGIC_MINOR__-0) * 0x100) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PGIC__) "." LZO_PP_MACRO_EXPAND(__PGIC_MINOR__) ".0" +# endif +# define LZO_INFO_CC "Portland Group PGI C" +#elif defined(__PGI) && (defined(__linux__) || defined(__WIN32__)) +# define LZO_CC_PGI 1 +# define LZO_INFO_CC "Portland Group PGI C" +# define LZO_INFO_CCVER "unknown" +#elif defined(__PUREC__) && defined(__TOS__) +# define LZO_CC_PUREC 1 +# define LZO_INFO_CC "Pure C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__PUREC__) +#elif defined(__SC__) && defined(__ZTC__) +# define LZO_CC_SYMANTECC 1 +# define LZO_INFO_CC "Symantec C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SC__) +#elif defined(__SUNPRO_C) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_C-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_C +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_C) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__SUNPRO_CC) +# define LZO_INFO_CC "SunPro C" +# if ((__SUNPRO_CC-0) > 0) +# define LZO_CC_SUNPROC __SUNPRO_CC +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__SUNPRO_CC) +# else +# define LZO_CC_SUNPROC 1 +# define LZO_INFO_CCVER "unknown" +# endif +#elif defined(__TINYC__) +# define LZO_CC_TINYC 1 +# define LZO_INFO_CC "Tiny C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TINYC__) +#elif defined(__TSC__) +# define LZO_CC_TOPSPEEDC 1 +# define LZO_INFO_CC "TopSpeed C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TSC__) +#elif defined(__WATCOMC__) +# define LZO_CC_WATCOMC 1 +# define LZO_INFO_CC "Watcom C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__WATCOMC__) +#elif defined(__TURBOC__) +# define LZO_CC_TURBOC 1 +# define LZO_INFO_CC "Turbo C" +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__TURBOC__) +#elif defined(__ZTC__) +# define LZO_CC_ZORTECHC 1 +# define LZO_INFO_CC "Zortech C" +# if ((__ZTC__-0) == 0x310) +# define LZO_INFO_CCVER "0x310" +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(__ZTC__) +# endif +#elif defined(__GNUC__) && defined(__VERSION__) +# if defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100 + (__GNUC_PATCHLEVEL__-0)) +# elif defined(__GNUC_MINOR__) +# define LZO_CC_GNUC (__GNUC__ * 0x10000L + (__GNUC_MINOR__-0) * 0x100) +# else +# define LZO_CC_GNUC (__GNUC__ * 0x10000L) +# endif +# define LZO_INFO_CC "gcc" +# define LZO_INFO_CCVER __VERSION__ +#elif defined(_MSC_VER) && ((_MSC_VER-0) > 0) +# define LZO_CC_MSC _MSC_VER +# define LZO_INFO_CC "Microsoft C" +# if defined(_MSC_FULL_VER) +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) "." LZO_PP_MACRO_EXPAND(_MSC_FULL_VER) +# else +# define LZO_INFO_CCVER LZO_PP_MACRO_EXPAND(_MSC_VER) +# endif +#else +# define LZO_CC_UNKNOWN 1 +# define LZO_INFO_CC "unknown" +# define LZO_INFO_CCVER "unknown" +#endif +#if (LZO_CC_GNUC) && defined(__OPEN64__) +# if defined(__OPENCC__) && defined(__OPENCC_MINOR__) && defined(__OPENCC_PATCHLEVEL__) +# define LZO_CC_OPEN64 (__OPENCC__ * 0x10000L + (__OPENCC_MINOR__-0) * 0x100 + (__OPENCC_PATCHLEVEL__-0)) +# define LZO_CC_OPEN64_GNUC LZO_CC_GNUC +# endif +#endif +#if (LZO_CC_GNUC) && defined(__PCC__) +# if defined(__PCC__) && defined(__PCC_MINOR__) && defined(__PCC_MINORMINOR__) +# define LZO_CC_PCC (__PCC__ * 0x10000L + (__PCC_MINOR__-0) * 0x100 + (__PCC_MINORMINOR__-0)) +# define LZO_CC_PCC_GNUC LZO_CC_GNUC +# endif +#endif +#if 0 && (LZO_CC_MSC && (_MSC_VER >= 1200)) && !defined(_MSC_FULL_VER) +# error "LZO_CC_MSC: _MSC_FULL_VER is not defined" +#endif +#if !defined(__LZO_ARCH_OVERRIDE) && !(LZO_ARCH_GENERIC) && defined(_CRAY) +# if (UINT_MAX > LZO_0xffffffffL) && defined(_CRAY) +# if defined(_CRAYMPP) || defined(_CRAYT3D) || defined(_CRAYT3E) +# define LZO_ARCH_CRAY_MPP 1 +# elif defined(_CRAY1) +# define LZO_ARCH_CRAY_PVP 1 +# endif +# endif +#endif +#if !defined(__LZO_ARCH_OVERRIDE) +#if (LZO_ARCH_GENERIC) +# define LZO_INFO_ARCH "generic" +#elif (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086 1 +# define LZO_INFO_ARCH "i086" +#elif defined(__aarch64__) || defined(_M_ARM64) +# define LZO_ARCH_ARM64 1 +# define LZO_INFO_ARCH "arm64" +#elif defined(__alpha__) || defined(__alpha) || defined(_M_ALPHA) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif (LZO_ARCH_CRAY_MPP) && (defined(_CRAYT3D) || defined(_CRAYT3E)) +# define LZO_ARCH_ALPHA 1 +# define LZO_INFO_ARCH "alpha" +#elif defined(__amd64__) || defined(__x86_64__) || defined(_M_AMD64) +# define LZO_ARCH_AMD64 1 +# define LZO_INFO_ARCH "amd64" +#elif defined(__arm__) || defined(_M_ARM) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCARM__) +# define LZO_ARCH_ARM 1 +# define LZO_INFO_ARCH "arm" +#elif (UINT_MAX <= LZO_0xffffL) && defined(__AVR__) +# define LZO_ARCH_AVR 1 +# define LZO_INFO_ARCH "avr" +#elif defined(__avr32__) || defined(__AVR32__) +# define LZO_ARCH_AVR32 1 +# define LZO_INFO_ARCH "avr32" +#elif defined(__bfin__) +# define LZO_ARCH_BLACKFIN 1 +# define LZO_INFO_ARCH "blackfin" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C166__) +# define LZO_ARCH_C166 1 +# define LZO_INFO_ARCH "c166" +#elif defined(__cris__) +# define LZO_ARCH_CRIS 1 +# define LZO_INFO_ARCH "cris" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCEZ80__) +# define LZO_ARCH_EZ80 1 +# define LZO_INFO_ARCH "ez80" +#elif defined(__H8300__) || defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_ARCH_H8300 1 +# define LZO_INFO_ARCH "h8300" +#elif defined(__hppa__) || defined(__hppa) +# define LZO_ARCH_HPPA 1 +# define LZO_INFO_ARCH "hppa" +#elif defined(__386__) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_M_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_CC_ZORTECHC && defined(__I86__)) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif (LZO_OS_DOS32 && LZO_CC_HIGHC) && defined(_I386) +# define LZO_ARCH_I386 1 +# define LZO_ARCH_IA32 1 +# define LZO_INFO_ARCH "i386" +#elif defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +# define LZO_ARCH_IA64 1 +# define LZO_INFO_ARCH "ia64" +#elif (UINT_MAX == LZO_0xffffL) && defined(__m32c__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICCM16C__) +# define LZO_ARCH_M16C 1 +# define LZO_INFO_ARCH "m16c" +#elif defined(__m32r__) +# define LZO_ARCH_M32R 1 +# define LZO_INFO_ARCH "m32r" +#elif (LZO_OS_TOS) || defined(__m68k__) || defined(__m68000__) || defined(__mc68000__) || defined(__mc68020__) || defined(_M_M68K) +# define LZO_ARCH_M68K 1 +# define LZO_INFO_ARCH "m68k" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C251__) +# define LZO_ARCH_MCS251 1 +# define LZO_INFO_ARCH "mcs251" +#elif (UINT_MAX == LZO_0xffffL) && defined(__C51__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC8051__) +# define LZO_ARCH_MCS51 1 +# define LZO_INFO_ARCH "mcs51" +#elif defined(__mips__) || defined(__mips) || defined(_MIPS_ARCH) || defined(_M_MRX000) +# define LZO_ARCH_MIPS 1 +# define LZO_INFO_ARCH "mips" +#elif (UINT_MAX == LZO_0xffffL) && defined(__MSP430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__IAR_SYSTEMS_ICC__) && defined(__ICC430__) +# define LZO_ARCH_MSP430 1 +# define LZO_INFO_ARCH "msp430" +#elif defined(__powerpc__) || defined(__powerpc) || defined(__ppc__) || defined(__PPC__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PWR) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__powerpc64__) || defined(__powerpc64) || defined(__ppc64__) || defined(__PPC64__) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__powerpc64le__) || defined(__powerpc64le) || defined(__ppc64le__) || defined(__PPC64LE__) +# define LZO_ARCH_POWERPC 1 +# define LZO_INFO_ARCH "powerpc" +#elif defined(__riscv) +# define LZO_ARCH_RISCV 1 +# define LZO_INFO_ARCH "riscv" +#elif defined(__s390__) || defined(__s390) || defined(__s390x__) || defined(__s390x) +# define LZO_ARCH_S390 1 +# define LZO_INFO_ARCH "s390" +#elif defined(__sh__) || defined(_M_SH) +# define LZO_ARCH_SH 1 +# define LZO_INFO_ARCH "sh" +#elif defined(__sparc__) || defined(__sparc) || defined(__sparcv8) +# define LZO_ARCH_SPARC 1 +# define LZO_INFO_ARCH "sparc" +#elif defined(__SPU__) +# define LZO_ARCH_SPU 1 +# define LZO_INFO_ARCH "spu" +#elif (UINT_MAX == LZO_0xffffL) && defined(__z80) +# define LZO_ARCH_Z80 1 +# define LZO_INFO_ARCH "z80" +#elif (LZO_ARCH_CRAY_PVP) +# if defined(_CRAYSV1) +# define LZO_ARCH_CRAY_SV1 1 +# define LZO_INFO_ARCH "cray_sv1" +# elif (_ADDR64) +# define LZO_ARCH_CRAY_T90 1 +# define LZO_INFO_ARCH "cray_t90" +# elif (_ADDR32) +# define LZO_ARCH_CRAY_YMP 1 +# define LZO_INFO_ARCH "cray_ymp" +# else +# define LZO_ARCH_CRAY_XMP 1 +# define LZO_INFO_ARCH "cray_xmp" +# endif +#else +# define LZO_ARCH_UNKNOWN 1 +# define LZO_INFO_ARCH "unknown" +#endif +#endif +#if !defined(LZO_ARCH_ARM_THUMB2) +#if (LZO_ARCH_ARM) +# if defined(__thumb__) || defined(__thumb) || defined(_M_THUMB) +# if defined(__thumb2__) +# define LZO_ARCH_ARM_THUMB2 1 +# elif 1 && defined(__TARGET_ARCH_THUMB) && ((__TARGET_ARCH_THUMB)+0 >= 4) +# define LZO_ARCH_ARM_THUMB2 1 +# elif 1 && defined(_MSC_VER) && defined(_M_THUMB) && ((_M_THUMB)+0 >= 7) +# define LZO_ARCH_ARM_THUMB2 1 +# endif +# endif +#endif +#endif +#if (LZO_ARCH_ARM_THUMB2) +# undef LZO_INFO_ARCH +# define LZO_INFO_ARCH "arm_thumb2" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_DOS32 || LZO_OS_OS2) +# error "FIXME - missing define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN32) +# error "FIXME - missing LZO_OS_WIN32 define for CPU architecture" +#endif +#if 1 && (LZO_ARCH_UNKNOWN) && (LZO_OS_WIN64) +# error "FIXME - missing LZO_OS_WIN64 define for CPU architecture" +#endif +#if (LZO_OS_OS216 || LZO_OS_WIN16) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(BLX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && defined(DOSX286)) +# define LZO_ARCH_I086PM 1 +#elif 1 && (LZO_OS_DOS16 && LZO_CC_BORLANDC && defined(__DPMI16__)) +# define LZO_ARCH_I086PM 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) +# define LZO_ARCH_X64 1 +#elif (!LZO_ARCH_AMD64 && LZO_ARCH_X64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_AMD64 1 +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) +# define LZO_ARCH_AARCH64 1 +#elif (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_ARM64 1 +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) +# define LZO_ARCH_X86 1 +#elif (!LZO_ARCH_I386 && LZO_ARCH_X86) && defined(__LZO_ARCH_OVERRIDE) +# define LZO_ARCH_I386 1 +#endif +#if (LZO_ARCH_AMD64 && !LZO_ARCH_X64) || (!LZO_ARCH_AMD64 && LZO_ARCH_X64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM64 && !LZO_ARCH_AARCH64) || (!LZO_ARCH_ARM64 && LZO_ARCH_AARCH64) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I386 && !LZO_ARCH_X86) || (!LZO_ARCH_I386 && LZO_ARCH_X86) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB2 && !LZO_ARCH_ARM) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM_THUMB1 && LZO_ARCH_ARM_THUMB2) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086PM && !LZO_ARCH_I086) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_I086) +# if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_I386) +# if (UINT_MAX != LZO_0xffffL) && defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (UINT_MAX != LZO_0xffffffffL) && !defined(__i386_int16__) +# error "unexpected configuration - check your compiler defines" +# endif +# if (ULONG_MAX != LZO_0xffffffffL) +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# if !defined(LZO_TARGET_FEATURE_SSE2) +# if defined(__SSE2__) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif defined(_MSC_VER) && (defined(_M_IX86_FP) && ((_M_IX86_FP)+0 >= 2)) +# define LZO_TARGET_FEATURE_SSE2 1 +# elif (LZO_CC_INTELC_MSC || LZO_CC_MSC) && defined(_M_AMD64) +# define LZO_TARGET_FEATURE_SSE2 1 +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSSE3) +# if (LZO_TARGET_FEATURE_SSE2) +# if defined(__SSSE3__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# elif defined(_MSC_VER) && defined(__AVX__) +# define LZO_TARGET_FEATURE_SSSE3 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_SSE4_2) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__SSE4_2__) +# define LZO_TARGET_FEATURE_SSE4_2 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX) +# if (LZO_TARGET_FEATURE_SSSE3) +# if defined(__AVX__) +# define LZO_TARGET_FEATURE_AVX 1 +# endif +# endif +# endif +# if !defined(LZO_TARGET_FEATURE_AVX2) +# if (LZO_TARGET_FEATURE_AVX) +# if defined(__AVX2__) +# define LZO_TARGET_FEATURE_AVX2 1 +# endif +# endif +# endif +#endif +#if (LZO_TARGET_FEATURE_SSSE3 && !(LZO_TARGET_FEATURE_SSE2)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_SSE4_2 && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX && !(LZO_TARGET_FEATURE_SSSE3)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_TARGET_FEATURE_AVX2 && !(LZO_TARGET_FEATURE_AVX)) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ARCH_ARM) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if defined(__ARM_NEON) && ((__ARM_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__ARM_NEON__) && ((__ARM_NEON__)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# elif 1 && defined(__TARGET_FEATURE_NEON) && ((__TARGET_FEATURE_NEON)+0) +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# if !defined(LZO_TARGET_FEATURE_NEON) +# if 1 +# define LZO_TARGET_FEATURE_NEON 1 +# endif +# endif +#endif +#if 0 +#elif !defined(__LZO_MM_OVERRIDE) +#if (LZO_ARCH_I086) +#if (UINT_MAX != LZO_0xffffL) +# error "unexpected configuration - check your compiler defines" +#endif +#if defined(__TINY__) || defined(M_I86TM) || defined(_M_I86TM) +# define LZO_MM_TINY 1 +#elif defined(__HUGE__) || defined(_HUGE_) || defined(M_I86HM) || defined(_M_I86HM) +# define LZO_MM_HUGE 1 +#elif defined(__SMALL__) || defined(M_I86SM) || defined(_M_I86SM) || defined(SMALL_MODEL) +# define LZO_MM_SMALL 1 +#elif defined(__MEDIUM__) || defined(M_I86MM) || defined(_M_I86MM) +# define LZO_MM_MEDIUM 1 +#elif defined(__COMPACT__) || defined(M_I86CM) || defined(_M_I86CM) +# define LZO_MM_COMPACT 1 +#elif defined(__LARGE__) || defined(M_I86LM) || defined(_M_I86LM) || defined(LARGE_MODEL) +# define LZO_MM_LARGE 1 +#elif (LZO_CC_AZTECC) +# if defined(_LARGE_CODE) && defined(_LARGE_DATA) +# define LZO_MM_LARGE 1 +# elif defined(_LARGE_CODE) +# define LZO_MM_MEDIUM 1 +# elif defined(_LARGE_DATA) +# define LZO_MM_COMPACT 1 +# else +# define LZO_MM_SMALL 1 +# endif +#elif (LZO_CC_ZORTECHC && defined(__VCM__)) +# define LZO_MM_LARGE 1 +#else +# error "unknown LZO_ARCH_I086 memory model" +#endif +#if (LZO_OS_DOS16 || LZO_OS_OS216 || LZO_OS_WIN16) +#define LZO_HAVE_MM_HUGE_PTR 1 +#define LZO_HAVE_MM_HUGE_ARRAY 1 +#if (LZO_MM_TINY) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_ZORTECHC) +# undef LZO_HAVE_MM_HUGE_PTR +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# undef LZO_HAVE_MM_HUGE_ARRAY +#elif (LZO_CC_MSC && defined(_QC)) +# undef LZO_HAVE_MM_HUGE_ARRAY +# if (_MSC_VER < 600) +# undef LZO_HAVE_MM_HUGE_PTR +# endif +#elif (LZO_CC_TURBOC && (__TURBOC__ < 0x0295)) +# undef LZO_HAVE_MM_HUGE_ARRAY +#endif +#if (LZO_ARCH_I086PM) && !(LZO_HAVE_MM_HUGE_PTR) +# if (LZO_OS_DOS16) +# error "unexpected configuration - check your compiler defines" +# elif (LZO_CC_ZORTECHC) +# else +# error "unexpected configuration - check your compiler defines" +# endif +#endif +#if defined(__cplusplus) +extern "C" { +#endif +#if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0200)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_MSC || LZO_CC_TOPSPEEDC) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif (LZO_CC_TURBOC && (__TURBOC__ >= 0x0295)) + extern void __near __cdecl _AHSHIFT(void); +# define LZO_MM_AHSHIFT ((unsigned) _AHSHIFT) +#elif ((LZO_CC_AZTECC || LZO_CC_PACIFICC || LZO_CC_TURBOC) && LZO_OS_DOS16) +# define LZO_MM_AHSHIFT 12 +#elif (LZO_CC_WATCOMC) + extern unsigned char _HShift; +# define LZO_MM_AHSHIFT ((unsigned) _HShift) +#else +# error "FIXME - implement LZO_MM_AHSHIFT" +#endif +#if defined(__cplusplus) +} +#endif +#endif +#elif (LZO_ARCH_C166) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_C166 __MODEL__" +#endif +#elif (LZO_ARCH_MCS251) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#elif ((__MODEL__) == 0) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS251 __MODEL__" +#endif +#elif (LZO_ARCH_MCS51) +#if !defined(__MODEL__) +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#elif ((__MODEL__) == 1) +# define LZO_MM_SMALL 1 +#elif ((__MODEL__) == 2) +# define LZO_MM_LARGE 1 +#elif ((__MODEL__) == 3) +# define LZO_MM_TINY 1 +#elif ((__MODEL__) == 4) +# define LZO_MM_XTINY 1 +#elif ((__MODEL__) == 5) +# define LZO_MM_XSMALL 1 +#else +# error "FIXME - LZO_ARCH_MCS51 __MODEL__" +#endif +#elif (LZO_ARCH_CRAY_PVP) +# define LZO_MM_PVP 1 +#else +# define LZO_MM_FLAT 1 +#endif +#if (LZO_MM_COMPACT) +# define LZO_INFO_MM "compact" +#elif (LZO_MM_FLAT) +# define LZO_INFO_MM "flat" +#elif (LZO_MM_HUGE) +# define LZO_INFO_MM "huge" +#elif (LZO_MM_LARGE) +# define LZO_INFO_MM "large" +#elif (LZO_MM_MEDIUM) +# define LZO_INFO_MM "medium" +#elif (LZO_MM_PVP) +# define LZO_INFO_MM "pvp" +#elif (LZO_MM_SMALL) +# define LZO_INFO_MM "small" +#elif (LZO_MM_TINY) +# define LZO_INFO_MM "tiny" +#else +# error "unknown memory model" +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +#if (LZO_CC_GNUC >= 0x020800ul) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_gnuc_extension__ __extension__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_gnuc_extension__ __extension__ +#endif +#endif +#if !defined(__lzo_gnuc_extension__) +# define __lzo_gnuc_extension__ /*empty*/ +#endif +#if !defined(lzo_has_builtin) +#if (LZO_CC_CLANG) && defined(__has_builtin) +# define lzo_has_builtin __has_builtin +#endif +#endif +#if !defined(lzo_has_builtin) +# define lzo_has_builtin(x) 0 +#endif +#if !defined(lzo_has_attribute) +#if (LZO_CC_CLANG) && defined(__has_attribute) +# define lzo_has_attribute __has_attribute +#endif +#endif +#if !defined(lzo_has_attribute) +# define lzo_has_attribute(x) 0 +#endif +#if !defined(lzo_has_declspec_attribute) +#if (LZO_CC_CLANG) && defined(__has_declspec_attribute) +# define lzo_has_declspec_attribute __has_declspec_attribute +#endif +#endif +#if !defined(lzo_has_declspec_attribute) +# define lzo_has_declspec_attribute(x) 0 +#endif +#if !defined(lzo_has_feature) +#if (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_feature __has_feature +#endif +#endif +#if !defined(lzo_has_feature) +# define lzo_has_feature(x) 0 +#endif +#if !defined(lzo_has_extension) +#if (LZO_CC_CLANG) && defined(__has_extension) +# define lzo_has_extension __has_extension +#elif (LZO_CC_CLANG) && defined(__has_feature) +# define lzo_has_extension __has_feature +#endif +#endif +#if !defined(lzo_has_extension) +# define lzo_has_extension(x) 0 +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) && defined(__cplusplus) && 0 +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1200)) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +# else +# define LZO_CFG_USE_NEW_STYLE_CASTS 1 +# endif +#endif +#if !defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(__cplusplus) +# if defined(LZO_CFG_USE_NEW_STYLE_CASTS) +# undef LZO_CFG_USE_NEW_STYLE_CASTS +# endif +# define LZO_CFG_USE_NEW_STYLE_CASTS 0 +#endif +#if !defined(LZO_REINTERPRET_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_REINTERPRET_CAST(t,e) (reinterpret_cast (e)) +# endif +#endif +#if !defined(LZO_REINTERPRET_CAST) +# define LZO_REINTERPRET_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_STATIC_CAST(t,e) (static_cast (e)) +# endif +#endif +#if !defined(LZO_STATIC_CAST) +# define LZO_STATIC_CAST(t,e) ((t) (e)) +#endif +#if !defined(LZO_STATIC_CAST2) +# define LZO_STATIC_CAST2(t1,t2,e) LZO_STATIC_CAST(t1, LZO_STATIC_CAST(t2, e)) +#endif +#if !defined(LZO_UNCONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_CAST) +# define LZO_UNCONST_CAST(t,e) ((t) ((void *) ((const void *) (e)))) +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNCONST_VOLATILE_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNCONST_VOLATILE_CAST) +# define LZO_UNCONST_VOLATILE_CAST(t,e) ((t) ((volatile void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((lzo_uintptr_t) ((volatile void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CAST) +# define LZO_UNVOLATILE_CAST(t,e) ((t) ((void *) ((volatile void *) (e)))) +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# if (LZO_CFG_USE_NEW_STYLE_CASTS) +# define LZO_UNVOLATILE_CONST_CAST(t,e) (const_cast (e)) +# elif (LZO_HAVE_MM_HUGE_PTR) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) (e)) +# elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((lzo_uintptr_t) ((volatile const void *) (e))))) +# endif +#endif +#if !defined(LZO_UNVOLATILE_CONST_CAST) +# define LZO_UNVOLATILE_CONST_CAST(t,e) ((t) ((const void *) ((volatile const void *) (e)))) +#endif +#if !defined(LZO_PCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_PCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_PCAST) +# define LZO_PCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(void *, e)) +#endif +#if !defined(LZO_CCAST) +# if (LZO_HAVE_MM_HUGE_PTR) +# define LZO_CCAST(t,e) ((t) (e)) +# endif +#endif +#if !defined(LZO_CCAST) +# define LZO_CCAST(t,e) LZO_STATIC_CAST(t, LZO_STATIC_CAST(const void *, e)) +#endif +#if !defined(LZO_ICONV) +# define LZO_ICONV(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ICAST) +# define LZO_ICAST(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(LZO_ITRUNC) +# define LZO_ITRUNC(t,e) LZO_STATIC_CAST(t, e) +#endif +#if !defined(__lzo_cte) +# if (LZO_CC_MSC || LZO_CC_WATCOMC) +# define __lzo_cte(e) ((void)0,(e)) +# elif 1 +# define __lzo_cte(e) ((void)0,(e)) +# endif +#endif +#if !defined(__lzo_cte) +# define __lzo_cte(e) (e) +#endif +#if !defined(LZO_BLOCK_BEGIN) +# define LZO_BLOCK_BEGIN do { +# define LZO_BLOCK_END } while __lzo_cte(0) +#endif +#if !defined(LZO_UNUSED) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_BORLANDC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PELLESC || LZO_CC_TURBOC) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030200ul)) +# define LZO_UNUSED(var) ((void) &var) +# elif (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_UNUSED(var) ((void) var) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED(var) if (&var) ; else +# elif (LZO_CC_KEILC) +# define LZO_UNUSED(var) {extern int lzo_unused__[1-2*!(sizeof(var)>0)]; (void)lzo_unused__;} +# elif (LZO_CC_PACIFICC) +# define LZO_UNUSED(var) ((void) sizeof(var)) +# elif (LZO_CC_WATCOMC) && defined(__cplusplus) +# define LZO_UNUSED(var) ((void) var) +# else +# define LZO_UNUSED(var) ((void) &var) +# endif +#endif +#if !defined(LZO_UNUSED_RESULT) +# define LZO_UNUSED_RESULT(var) LZO_UNUSED(var) +#endif +#if !defined(LZO_UNUSED_FUNC) +# if (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0600)) +# define LZO_UNUSED_FUNC(func) ((void) func) +# elif (LZO_CC_BORLANDC || LZO_CC_NDPC || LZO_CC_TURBOC) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_CLANG || LZO_CC_LLVM) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_UNUSED_FUNC(func) if (func) ; else +# elif (LZO_CC_MSC) +# define LZO_UNUSED_FUNC(func) ((void) &func) +# elif (LZO_CC_KEILC || LZO_CC_PELLESC) +# define LZO_UNUSED_FUNC(func) {extern int lzo_unused__[1-2*!(sizeof((int)func)>0)]; (void)lzo_unused__;} +# else +# define LZO_UNUSED_FUNC(func) ((void) func) +# endif +#endif +#if !defined(LZO_UNUSED_LABEL) +# if (LZO_CC_CLANG >= 0x020800ul) +# define LZO_UNUSED_LABEL(l) (__lzo_gnuc_extension__ ((void) ((const void *) &&l))) +# elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_INTELC || LZO_CC_WATCOMC) +# define LZO_UNUSED_LABEL(l) if __lzo_cte(0) goto l +# else +# define LZO_UNUSED_LABEL(l) switch (0) case 1:goto l +# endif +#endif +#if !defined(LZO_DEFINE_UNINITIALIZED_VAR) +# if 0 +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var +# elif 0 && (LZO_CC_GNUC) +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = var +# else +# define LZO_DEFINE_UNINITIALIZED_VAR(type,var,init) type var = init +# endif +#endif +#if !defined(__lzo_inline) +#if (LZO_CC_TURBOC && (__TURBOC__ <= 0x0295)) +#elif defined(__cplusplus) +# define __lzo_inline inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_inline inline +#elif (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0550)) +# define __lzo_inline __inline +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_inline __inline__ +#elif (LZO_CC_DMC) +# define __lzo_inline __inline +#elif (LZO_CC_GHS) +# define __lzo_inline __inline__ +#elif (LZO_CC_IBMC >= 600) +# define __lzo_inline __inline__ +#elif (LZO_CC_INTELC) +# define __lzo_inline __inline +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x2405)) +# define __lzo_inline __inline +#elif (LZO_CC_MSC && (_MSC_VER >= 900)) +# define __lzo_inline __inline +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_inline __inline__ +#endif +#endif +#if defined(__lzo_inline) +# ifndef __lzo_HAVE_inline +# define __lzo_HAVE_inline 1 +# endif +#else +# define __lzo_inline /*empty*/ +#endif +#if !defined(__lzo_forceinline) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_forceinline __forceinline +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_forceinline __inline__ __attribute__((__always_inline__)) +#endif +#endif +#if defined(__lzo_forceinline) +# ifndef __lzo_HAVE_forceinline +# define __lzo_HAVE_forceinline 1 +# endif +#else +# define __lzo_forceinline __lzo_inline +#endif +#if !defined(__lzo_noinline) +#if 1 && (LZO_ARCH_I386) && (LZO_CC_GNUC >= 0x040000ul) && (LZO_CC_GNUC < 0x040003ul) +# define __lzo_noinline __attribute__((__noinline__,__used__)) +#elif (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_noinline __declspec(noinline) +#elif (LZO_CC_MWERKS && (__MWERKS__ >= 0x3200) && (LZO_OS_WIN32 || LZO_OS_WIN64)) +# if defined(__cplusplus) +# else +# define __lzo_noinline __declspec(noinline) +# endif +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noinline __attribute__((__noinline__)) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_noinline __attribute__((__noinline__)) +#endif +#endif +#if defined(__lzo_noinline) +# ifndef __lzo_HAVE_noinline +# define __lzo_HAVE_noinline 1 +# endif +#else +# define __lzo_noinline /*empty*/ +#endif +#if (__lzo_HAVE_forceinline || __lzo_HAVE_noinline) && !(__lzo_HAVE_inline) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_static_inline) +#if (LZO_CC_IBMC) +# define __lzo_static_inline __lzo_gnuc_extension__ static __lzo_inline +#endif +#endif +#if !defined(__lzo_static_inline) +# define __lzo_static_inline static __lzo_inline +#endif +#if !defined(__lzo_static_forceinline) +#if (LZO_CC_IBMC) +# define __lzo_static_forceinline __lzo_gnuc_extension__ static __lzo_forceinline +#endif +#endif +#if !defined(__lzo_static_forceinline) +# define __lzo_static_forceinline static __lzo_forceinline +#endif +#if !defined(__lzo_static_noinline) +#if (LZO_CC_IBMC) +# define __lzo_static_noinline __lzo_gnuc_extension__ static __lzo_noinline +#endif +#endif +#if !defined(__lzo_static_noinline) +# define __lzo_static_noinline static __lzo_noinline +#endif +#if !defined(__lzo_c99_extern_inline) +#if defined(__GNUC_GNU_INLINE__) +# define __lzo_c99_extern_inline __lzo_inline +#elif defined(__GNUC_STDC_INLINE__) +# define __lzo_c99_extern_inline extern __lzo_inline +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__-0 >= 199901L) +# define __lzo_c99_extern_inline extern __lzo_inline +#endif +#if !defined(__lzo_c99_extern_inline) && (__lzo_HAVE_inline) +# define __lzo_c99_extern_inline __lzo_inline +#endif +#endif +#if defined(__lzo_c99_extern_inline) +# ifndef __lzo_HAVE_c99_extern_inline +# define __lzo_HAVE_c99_extern_inline 1 +# endif +#else +# define __lzo_c99_extern_inline /*empty*/ +#endif +#if !defined(__lzo_may_alias) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_CLANG >= 0x020900ul) +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1210)) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#elif (LZO_CC_PGI >= 0x0d0a00ul) && 0 +# define __lzo_may_alias __attribute__((__may_alias__)) +#endif +#endif +#if defined(__lzo_may_alias) +# ifndef __lzo_HAVE_may_alias +# define __lzo_HAVE_may_alias 1 +# endif +#else +# define __lzo_may_alias /*empty*/ +#endif +#if !defined(__lzo_noreturn) +#if (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_IBMC >= 700) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_noreturn __attribute__((__noreturn__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) +# define __lzo_noreturn __declspec(noreturn) +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_noreturn __attribute__((__noreturn__)) +#endif +#endif +#if defined(__lzo_noreturn) +# ifndef __lzo_HAVE_noreturn +# define __lzo_HAVE_noreturn 1 +# endif +#else +# define __lzo_noreturn /*empty*/ +#endif +#if !defined(__lzo_nothrow) +#if (LZO_CC_GNUC >= 0x030300ul) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 450)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 900)) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_nothrow __attribute__((__nothrow__)) +#elif (LZO_CC_MSC && (_MSC_VER >= 1200)) && defined(__cplusplus) +# define __lzo_nothrow __declspec(nothrow) +#endif +#endif +#if defined(__lzo_nothrow) +# ifndef __lzo_HAVE_nothrow +# define __lzo_HAVE_nothrow 1 +# endif +#else +# define __lzo_nothrow /*empty*/ +#endif +#if !defined(__lzo_restrict) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 800) && !defined(__cplusplus) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_IBMC >= 1210) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 600)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 600)) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM) +# define __lzo_restrict __restrict__ +#elif (LZO_CC_MSC && (_MSC_VER >= 1400)) +# define __lzo_restrict __restrict +#elif (LZO_CC_PGI >= 0x0d0a00ul) +# define __lzo_restrict __restrict__ +#endif +#endif +#if defined(__lzo_restrict) +# ifndef __lzo_HAVE_restrict +# define __lzo_HAVE_restrict 1 +# endif +#else +# define __lzo_restrict /*empty*/ +#endif +#if !defined(__lzo_alignof) +#if (LZO_CC_ARMCC || LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_GHS) && !defined(__cplusplus) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_IBMC >= 600) +# define __lzo_alignof(e) (__lzo_gnuc_extension__ __alignof__(e)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 700)) +# define __lzo_alignof(e) __alignof__(e) +#elif (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_alignof(e) __alignof(e) +#elif (LZO_CC_SUNPROC >= 0x5100) +# define __lzo_alignof(e) __alignof__(e) +#endif +#endif +#if defined(__lzo_alignof) +# ifndef __lzo_HAVE_alignof +# define __lzo_HAVE_alignof 1 +# endif +#endif +#if !defined(__lzo_struct_packed) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_GNUC >= 0x030400ul) && !(LZO_CC_PCC_GNUC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__gcc_struct__,__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__gcc_struct__,__packed__)); +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_struct_packed(s) struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_struct_packed(s) __lzo_gnuc_extension__ struct s { +# define __lzo_struct_packed_end() } __attribute__((__packed__)); +# define __lzo_struct_packed_ma_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_packed(s) __pragma(pack(push,1)) struct s { +# define __lzo_struct_packed_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_struct_packed(s) _Packed struct s { +# define __lzo_struct_packed_end() }; +#endif +#endif +#if defined(__lzo_struct_packed) && !defined(__lzo_struct_packed_ma) +# define __lzo_struct_packed_ma(s) __lzo_struct_packed(s) +#endif +#if defined(__lzo_struct_packed_end) && !defined(__lzo_struct_packed_ma_end) +# define __lzo_struct_packed_ma_end() __lzo_struct_packed_end() +#endif +#if !defined(__lzo_byte_struct) +#if defined(__lzo_struct_packed) +# define __lzo_byte_struct(s,n) __lzo_struct_packed(s) unsigned char a[n]; __lzo_struct_packed_end() +# define __lzo_byte_struct_ma(s,n) __lzo_struct_packed_ma(s) unsigned char a[n]; __lzo_struct_packed_ma_end() +#elif (LZO_CC_CILLY || LZO_CC_CLANG || LZO_CC_PGI || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_byte_struct(s,n) struct s { unsigned char a[n]; } __attribute__((__packed__)); +# define __lzo_byte_struct_ma(s,n) struct s { unsigned char a[n]; } __lzo_may_alias __attribute__((__packed__)); +#endif +#endif +#if defined(__lzo_byte_struct) && !defined(__lzo_byte_struct_ma) +# define __lzo_byte_struct_ma(s,n) __lzo_byte_struct(s,n) +#endif +#if !defined(__lzo_struct_align16) && (__lzo_HAVE_alignof) +#if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul)) +#elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_CILLY || LZO_CC_PCC) +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_struct_align16(s) struct __declspec(align(16)) s { +# define __lzo_struct_align16_end() }; +# define __lzo_struct_align32(s) struct __declspec(align(32)) s { +# define __lzo_struct_align32_end() }; +# define __lzo_struct_align64(s) struct __declspec(align(64)) s { +# define __lzo_struct_align64_end() }; +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || (LZO_CC_IBMC >= 700) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_struct_align16(s) struct s { +# define __lzo_struct_align16_end() } __attribute__((__aligned__(16))); +# define __lzo_struct_align32(s) struct s { +# define __lzo_struct_align32_end() } __attribute__((__aligned__(32))); +# define __lzo_struct_align64(s) struct s { +# define __lzo_struct_align64_end() } __attribute__((__aligned__(64))); +#endif +#endif +#if !defined(__lzo_union_um) +#if (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020700ul)) +#elif (LZO_CC_GNUC && (LZO_CC_GNUC < 0x020800ul)) && defined(__cplusplus) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER < 810)) +#elif (LZO_CC_PCC && (LZO_CC_PCC < 0x010100ul)) +#elif (LZO_CC_SUNPROC && (LZO_CC_SUNPROC < 0x5110)) && !defined(__cplusplus) +#elif (LZO_CC_ARMCC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || (LZO_CC_PGI >= 0x0d0a00ul) || (LZO_CC_SUNPROC >= 0x5100)) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_IBMC >= 700) +# define __lzo_union_am(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_am_end() } __lzo_may_alias; +# define __lzo_union_um(s) __lzo_gnuc_extension__ union s { +# define __lzo_union_um_end() } __lzo_may_alias __attribute__((__packed__)); +#elif (LZO_CC_INTELC_MSC) || (LZO_CC_MSC && (_MSC_VER >= 1300)) +# define __lzo_union_um(s) __pragma(pack(push,1)) union s { +# define __lzo_union_um_end() } __pragma(pack(pop)); +#elif (LZO_CC_WATCOMC && (__WATCOMC__ >= 900)) +# define __lzo_union_um(s) _Packed union s { +# define __lzo_union_um_end() }; +#endif +#endif +#if !defined(__lzo_union_am) +# define __lzo_union_am(s) union s { +# define __lzo_union_am_end() }; +#endif +#if !defined(__lzo_constructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_constructor __attribute__((__constructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_constructor __attribute__((__constructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_constructor __attribute__((__constructor__)) +#endif +#endif +#if defined(__lzo_constructor) +# ifndef __lzo_HAVE_constructor +# define __lzo_HAVE_constructor 1 +# endif +#endif +#if !defined(__lzo_destructor) +#if (LZO_CC_GNUC >= 0x030400ul) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_GNUC >= 0x020700ul) +# define __lzo_destructor __attribute__((__destructor__)) +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 800)) +# define __lzo_destructor __attribute__((__destructor__,__used__)) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_destructor __attribute__((__destructor__)) +#endif +#endif +#if defined(__lzo_destructor) +# ifndef __lzo_HAVE_destructor +# define __lzo_HAVE_destructor 1 +# endif +#endif +#if (__lzo_HAVE_destructor) && !(__lzo_HAVE_constructor) +# error "unexpected configuration - check your compiler defines" +#endif +#if !defined(__lzo_likely) && !defined(__lzo_unlikely) +#if (LZO_CC_GNUC >= 0x030200ul) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_IBMC >= 1010) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_INTELC && (__INTEL_COMPILER >= 800)) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#elif (LZO_CC_CLANG && LZO_CC_CLANG_C2) +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define __lzo_likely(e) (__builtin_expect(!!(e),1)) +# define __lzo_unlikely(e) (__builtin_expect(!!(e),0)) +#endif +#endif +#if defined(__lzo_likely) +# ifndef __lzo_HAVE_likely +# define __lzo_HAVE_likely 1 +# endif +#else +# define __lzo_likely(e) (e) +#endif +#if defined(__lzo_very_likely) +# ifndef __lzo_HAVE_very_likely +# define __lzo_HAVE_very_likely 1 +# endif +#else +# define __lzo_very_likely(e) __lzo_likely(e) +#endif +#if defined(__lzo_unlikely) +# ifndef __lzo_HAVE_unlikely +# define __lzo_HAVE_unlikely 1 +# endif +#else +# define __lzo_unlikely(e) (e) +#endif +#if defined(__lzo_very_unlikely) +# ifndef __lzo_HAVE_very_unlikely +# define __lzo_HAVE_very_unlikely 1 +# endif +#else +# define __lzo_very_unlikely(e) __lzo_unlikely(e) +#endif +#if !defined(__lzo_loop_forever) +# if (LZO_CC_IBMC) +# define __lzo_loop_forever() LZO_BLOCK_BEGIN for (;;) { ; } LZO_BLOCK_END +# else +# define __lzo_loop_forever() do { ; } while __lzo_cte(1) +# endif +#endif +#if !defined(__lzo_unreachable) +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x020800ul)) && lzo_has_builtin(__builtin_unreachable) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_GNUC >= 0x040500ul) +# define __lzo_unreachable() __builtin_unreachable(); +#elif (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1300)) && 1 +# define __lzo_unreachable() __builtin_unreachable(); +#endif +#endif +#if defined(__lzo_unreachable) +# ifndef __lzo_HAVE_unreachable +# define __lzo_HAVE_unreachable 1 +# endif +#else +# if 0 +# define __lzo_unreachable() ((void)0); +# else +# define __lzo_unreachable() __lzo_loop_forever(); +# endif +#endif +#if !defined(lzo_unused_funcs_impl) +# if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +# define lzo_unused_funcs_impl(r,f) static r __attribute__((__unused__)) f +# elif 1 && (LZO_CC_BORLANDC || LZO_CC_GNUC) +# define lzo_unused_funcs_impl(r,f) static r f +# else +# define lzo_unused_funcs_impl(r,f) __lzo_static_forceinline r f +# endif +#endif +#ifndef __LZO_CTA_NAME +#if (LZO_CFG_USE_COUNTER) +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__COUNTER__) +#else +# define __LZO_CTA_NAME(a) LZO_PP_ECONCAT2(a,__LINE__) +#endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT_HEADER) +# if (LZO_CC_AZTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1u-2*!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-!(e)]; LZO_EXTERN_C_END +# elif (LZO_CC_CLANG && (LZO_CC_CLANG < 0x020900ul)) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN int __LZO_CTA_NAME(lzo_cta_f__)(int [1-2*!(e)]); LZO_EXTERN_C_END +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__)); LZO_EXTERN_C_END +# else +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) LZO_EXTERN_C_BEGIN extern int __LZO_CTA_NAME(lzo_cta__)[1-2*!(e)]; LZO_EXTERN_C_END +# endif +#endif +#if !defined(LZO_COMPILE_TIME_ASSERT) +# if (LZO_CC_AZTECC) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-!(e)];} +# elif (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030000ul)) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_DMC || LZO_CC_PACIFICC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_GNUC) && defined(__CHECKER__) && defined(__SPARSE_CHECKER__) +# define LZO_COMPILE_TIME_ASSERT(e) {(void) (0/!!(e));} +# elif (LZO_CC_GNUC >= 0x040700ul) && (LZO_CFG_USE_COUNTER) && defined(__cplusplus) +# define LZO_COMPILE_TIME_ASSERT(e) {enum {__LZO_CTA_NAME(lzo_cta_e__)=1/!!(e)} __attribute__((__unused__));} +# elif (LZO_CC_GNUC >= 0x040700ul) +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)] __attribute__((__unused__));} +# elif (LZO_CC_MSC && (_MSC_VER < 900)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# elif (LZO_CC_TURBOC && (__TURBOC__ == 0x0295)) +# define LZO_COMPILE_TIME_ASSERT(e) switch(0) case 1:case !(e):break; +# else +# define LZO_COMPILE_TIME_ASSERT(e) {typedef int __LZO_CTA_NAME(lzo_cta_t__)[1-2*!(e)];} +# endif +#endif +#if (LZO_LANG_ASSEMBLER) +# undef LZO_COMPILE_TIME_ASSERT_HEADER +# define LZO_COMPILE_TIME_ASSERT_HEADER(e) /*empty*/ +#else +LZO_COMPILE_TIME_ASSERT_HEADER(1 == 1) +#if defined(__cplusplus) +extern "C" { LZO_COMPILE_TIME_ASSERT_HEADER(2 == 2) } +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(3 == 3) +#endif +#if (LZO_ARCH_I086 || LZO_ARCH_I386) && (LZO_OS_DOS16 || LZO_OS_DOS32 || LZO_OS_OS2 || LZO_OS_OS216 || LZO_OS_WIN16 || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC) +# elif (LZO_CC_DMC || LZO_CC_SYMANTECC || LZO_CC_ZORTECHC) +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit /*empty*/ +# define __lzo_cdecl_main __cdecl +# if (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_qsort __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_qsort _stdcall +# else +# define __lzo_cdecl_qsort __cdecl +# endif +# elif (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +# else +# define __lzo_cdecl __cdecl +# define __lzo_cdecl_atexit __cdecl +# define __lzo_cdecl_main __cdecl +# define __lzo_cdecl_qsort __cdecl +# endif +# if (LZO_CC_GNUC || LZO_CC_HIGHC || LZO_CC_NDPC || LZO_CC_PACIFICC || LZO_CC_WATCOMC) +# elif (LZO_OS_OS2 && (LZO_CC_DMC || LZO_CC_SYMANTECC)) +# define __lzo_cdecl_sighandler __pascal +# elif (LZO_OS_OS2 && (LZO_CC_ZORTECHC)) +# define __lzo_cdecl_sighandler _stdcall +# elif (LZO_CC_MSC && (_MSC_VER >= 1400)) && defined(_M_CEE_PURE) +# define __lzo_cdecl_sighandler __clrcall +# elif (LZO_CC_MSC && (_MSC_VER >= 600 && _MSC_VER < 700)) +# if defined(_DLL) +# define __lzo_cdecl_sighandler _far _cdecl _loadds +# elif defined(_MT) +# define __lzo_cdecl_sighandler _far _cdecl +# else +# define __lzo_cdecl_sighandler _cdecl +# endif +# else +# define __lzo_cdecl_sighandler __cdecl +# endif +#elif (LZO_ARCH_I386) && (LZO_CC_WATCOMC) +# define __lzo_cdecl __cdecl +#elif (LZO_ARCH_M68K && LZO_OS_TOS && (LZO_CC_PUREC || LZO_CC_TURBOC)) +# define __lzo_cdecl cdecl +#endif +#if !defined(__lzo_cdecl) +# define __lzo_cdecl /*empty*/ +#endif +#if !defined(__lzo_cdecl_atexit) +# define __lzo_cdecl_atexit /*empty*/ +#endif +#if !defined(__lzo_cdecl_main) +# define __lzo_cdecl_main /*empty*/ +#endif +#if !defined(__lzo_cdecl_qsort) +# define __lzo_cdecl_qsort /*empty*/ +#endif +#if !defined(__lzo_cdecl_sighandler) +# define __lzo_cdecl_sighandler /*empty*/ +#endif +#if !defined(__lzo_cdecl_va) +# define __lzo_cdecl_va __lzo_cdecl +#endif +#if !(LZO_CFG_NO_WINDOWS_H) +#if !defined(LZO_HAVE_WINDOWS_H) +#if (LZO_OS_CYGWIN || (LZO_OS_EMX && defined(__RSXNT__)) || LZO_OS_WIN32 || LZO_OS_WIN64) +# if (LZO_CC_WATCOMC && (__WATCOMC__ < 1000)) +# elif ((LZO_OS_WIN32 && defined(__PW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x030000ul))) +# elif ((LZO_OS_CYGWIN || defined(__MINGW32__)) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x025f00ul))) +# else +# define LZO_HAVE_WINDOWS_H 1 +# endif +#endif +#endif +#endif +#define LZO_SIZEOF_CHAR 1 +#ifndef LZO_SIZEOF_SHORT +#if defined(SIZEOF_SHORT) +# define LZO_SIZEOF_SHORT (SIZEOF_SHORT) +#elif defined(__SIZEOF_SHORT__) +# define LZO_SIZEOF_SHORT (__SIZEOF_SHORT__) +#endif +#endif +#ifndef LZO_SIZEOF_INT +#if defined(SIZEOF_INT) +# define LZO_SIZEOF_INT (SIZEOF_INT) +#elif defined(__SIZEOF_INT__) +# define LZO_SIZEOF_INT (__SIZEOF_INT__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG +#if defined(SIZEOF_LONG) +# define LZO_SIZEOF_LONG (SIZEOF_LONG) +#elif defined(__SIZEOF_LONG__) +# define LZO_SIZEOF_LONG (__SIZEOF_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF_LONG_LONG +#if defined(SIZEOF_LONG_LONG) +# define LZO_SIZEOF_LONG_LONG (SIZEOF_LONG_LONG) +#elif defined(__SIZEOF_LONG_LONG__) +# define LZO_SIZEOF_LONG_LONG (__SIZEOF_LONG_LONG__) +#endif +#endif +#ifndef LZO_SIZEOF___INT16 +#if defined(SIZEOF___INT16) +# define LZO_SIZEOF___INT16 (SIZEOF___INT16) +#endif +#endif +#ifndef LZO_SIZEOF___INT32 +#if defined(SIZEOF___INT32) +# define LZO_SIZEOF___INT32 (SIZEOF___INT32) +#endif +#endif +#ifndef LZO_SIZEOF___INT64 +#if defined(SIZEOF___INT64) +# define LZO_SIZEOF___INT64 (SIZEOF___INT64) +#endif +#endif +#ifndef LZO_SIZEOF_VOID_P +#if defined(SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P (SIZEOF_VOID_P) +#elif defined(__SIZEOF_POINTER__) +# define LZO_SIZEOF_VOID_P (__SIZEOF_POINTER__) +#endif +#endif +#ifndef LZO_SIZEOF_SIZE_T +#if defined(SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T (SIZEOF_SIZE_T) +#elif defined(__SIZEOF_SIZE_T__) +# define LZO_SIZEOF_SIZE_T (__SIZEOF_SIZE_T__) +#endif +#endif +#ifndef LZO_SIZEOF_PTRDIFF_T +#if defined(SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T (SIZEOF_PTRDIFF_T) +#elif defined(__SIZEOF_PTRDIFF_T__) +# define LZO_SIZEOF_PTRDIFF_T (__SIZEOF_PTRDIFF_T__) +#endif +#endif +#define __LZO_LSR(x,b) (((x)+0ul) >> (b)) +#if !defined(LZO_SIZEOF_SHORT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_SHORT 8 +# elif (USHRT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,7) == 1) +# define LZO_SIZEOF_SHORT 1 +# elif (__LZO_LSR(USHRT_MAX,15) == 1) +# define LZO_SIZEOF_SHORT 2 +# elif (__LZO_LSR(USHRT_MAX,31) == 1) +# define LZO_SIZEOF_SHORT 4 +# elif (__LZO_LSR(USHRT_MAX,63) == 1) +# define LZO_SIZEOF_SHORT 8 +# elif (__LZO_LSR(USHRT_MAX,127) == 1) +# define LZO_SIZEOF_SHORT 16 +# else +# error "LZO_SIZEOF_SHORT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SHORT == sizeof(short)) +#if !defined(LZO_SIZEOF_INT) +# if (LZO_ARCH_CRAY_PVP) +# define LZO_SIZEOF_INT 8 +# elif (UINT_MAX == LZO_0xffffL) +# define LZO_SIZEOF_INT 2 +# elif (UINT_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,7) == 1) +# define LZO_SIZEOF_INT 1 +# elif (__LZO_LSR(UINT_MAX,15) == 1) +# define LZO_SIZEOF_INT 2 +# elif (__LZO_LSR(UINT_MAX,31) == 1) +# define LZO_SIZEOF_INT 4 +# elif (__LZO_LSR(UINT_MAX,63) == 1) +# define LZO_SIZEOF_INT 8 +# elif (__LZO_LSR(UINT_MAX,127) == 1) +# define LZO_SIZEOF_INT 16 +# else +# error "LZO_SIZEOF_INT" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_INT == sizeof(int)) +#if !defined(LZO_SIZEOF_LONG) +# if (ULONG_MAX == LZO_0xffffffffL) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,7) == 1) +# define LZO_SIZEOF_LONG 1 +# elif (__LZO_LSR(ULONG_MAX,15) == 1) +# define LZO_SIZEOF_LONG 2 +# elif (__LZO_LSR(ULONG_MAX,31) == 1) +# define LZO_SIZEOF_LONG 4 +# elif (__LZO_LSR(ULONG_MAX,39) == 1) +# define LZO_SIZEOF_LONG 5 +# elif (__LZO_LSR(ULONG_MAX,63) == 1) +# define LZO_SIZEOF_LONG 8 +# elif (__LZO_LSR(ULONG_MAX,127) == 1) +# define LZO_SIZEOF_LONG 16 +# else +# error "LZO_SIZEOF_LONG" +# endif +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_LONG == sizeof(long)) +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +# if defined(__LONG_MAX__) && defined(__LONG_LONG_MAX__) +# if (LZO_CC_GNUC >= 0x030300ul) +# if ((__LONG_MAX__-0) == (__LONG_LONG_MAX__-0)) +# define LZO_SIZEOF_LONG_LONG LZO_SIZEOF_LONG +# elif (__LZO_LSR(__LONG_LONG_MAX__,30) == 1) +# define LZO_SIZEOF_LONG_LONG 4 +# endif +# endif +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_LONG_LONG) && !defined(LZO_SIZEOF___INT64) +#if (LZO_SIZEOF_LONG > 0 && LZO_SIZEOF_LONG < 8) +#if (LZO_ARCH_I086 && LZO_CC_DMC) +#elif (LZO_CC_CILLY) && defined(__GNUC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE) +# define LZO_SIZEOF_LONG_LONG 8 +#elif ((LZO_OS_WIN32 || LZO_OS_WIN64 || defined(_WIN32)) && LZO_CC_MSC && (_MSC_VER >= 1400)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_OS_WIN64 || defined(_WIN64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_DMC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_SYMANTECC && (__SC__ >= 0x700))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC && defined(__linux__))) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_MWERKS || LZO_CC_PELLESC || LZO_CC_PGI || LZO_CC_SUNPROC)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_ARCH_I386 && (LZO_CC_INTELC || LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif ((LZO_OS_WIN32 || defined(_WIN32)) && (LZO_CC_MSC)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_BORLANDC && (__BORLANDC__ >= 0x0520))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_ARCH_I386 && (LZO_CC_WATCOMC && (__WATCOMC__ >= 1100))) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_CC_GHS && defined(__LLONG_BIT) && ((__LLONG_BIT-0) == 64)) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_WATCOMC && defined(_INTEGRAL_MAX_BITS) && ((_INTEGRAL_MAX_BITS-0) == 64)) +# define LZO_SIZEOF___INT64 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) && defined(__LLP64_IFC__) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (defined(__vms) || defined(__VMS)) && ((__INITIAL_POINTER_SIZE-0) == 64) +# define LZO_SIZEOF_LONG_LONG 8 +#elif (LZO_CC_SDCC) && (LZO_SIZEOF_INT == 2) +#elif 1 && defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) +# define LZO_SIZEOF_LONG_LONG 8 +#endif +#endif +#endif +#if defined(__cplusplus) && (LZO_CC_GNUC) +# if (LZO_CC_GNUC < 0x020800ul) +# undef LZO_SIZEOF_LONG_LONG +# endif +#endif +#if (LZO_CFG_NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(__NO_LONG_LONG) +# undef LZO_SIZEOF_LONG_LONG +#elif defined(_NO_LONGLONG) +# undef LZO_SIZEOF_LONG_LONG +#endif +#if !defined(LZO_WORDSIZE) +#if (LZO_ARCH_ALPHA) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AMD64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_ARM64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_AVR) +# define LZO_WORDSIZE 1 +#elif (LZO_ARCH_H8300) +# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) +# define LZO_WORDSIZE 4 +# else +# define LZO_WORDSIZE 2 +# endif +#elif (LZO_ARCH_I086) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_IA64) +# define LZO_WORDSIZE 8 +#elif (LZO_ARCH_M16C) +# define LZO_WORDSIZE 2 +#elif (LZO_ARCH_SPU) +# define LZO_WORDSIZE 4 +#elif (LZO_ARCH_Z80) +# define LZO_WORDSIZE 1 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_WORDSIZE 8 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# define LZO_WORDSIZE 8 +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_WORDSIZE 8 +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +#if defined(__ILP32__) || defined(__ILP32) || defined(_ILP32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 4 +#elif defined(__ILP64__) || defined(__ILP64) || defined(_ILP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LLP64__) || defined(__LLP64) || defined(_LLP64) || defined(_WIN64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) +# define LZO_SIZEOF_VOID_P 8 +#elif defined(__LP64__) || defined(__LP64) || defined(_LP64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 8) +# define LZO_SIZEOF_VOID_P 8 +#elif (LZO_ARCH_AVR) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_C166 || LZO_ARCH_MCS51 || LZO_ARCH_MCS251 || LZO_ARCH_MSP430) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_ARCH_H8300) +# if defined(__H8300H__) || defined(__H8300S__) || defined(__H8300SX__) + LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 4) +# if defined(__NORMAL_MODE__) +# define LZO_SIZEOF_VOID_P 2 +# else +# define LZO_SIZEOF_VOID_P 4 +# endif +# else + LZO_COMPILE_TIME_ASSERT_HEADER(LZO_WORDSIZE == 2) +# define LZO_SIZEOF_VOID_P 2 +# endif +# if (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_SIZEOF_INT == 4) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_INT +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_INT +# endif +#elif (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM) +# define LZO_SIZEOF_VOID_P 2 +# elif (LZO_MM_COMPACT || LZO_MM_LARGE || LZO_MM_HUGE) +# define LZO_SIZEOF_VOID_P 4 +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#elif (LZO_ARCH_M16C) +# if defined(__m32c_cpu__) || defined(__m32cm_cpu__) +# define LZO_SIZEOF_VOID_P 4 +# else +# define LZO_SIZEOF_VOID_P 2 +# endif +#elif (LZO_ARCH_SPU) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_ARCH_Z80) +# define LZO_SIZEOF_VOID_P 2 +#elif (LZO_SIZEOF_LONG == 8) && ((defined(__mips__) && defined(__R5900__)) || defined(__MIPS_PSX2__)) +# define LZO_SIZEOF_VOID_P 4 +#elif (LZO_OS_OS400 || defined(__OS400__)) +# if defined(__LLP64_IFC__) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# else +# define LZO_SIZEOF_VOID_P 16 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +# endif +#elif (defined(__vms) || defined(__VMS)) && (__INITIAL_POINTER_SIZE+0 == 64) +# define LZO_SIZEOF_VOID_P 8 +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_LONG +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_LONG +#endif +#endif +#if !defined(LZO_SIZEOF_VOID_P) +# define LZO_SIZEOF_VOID_P LZO_SIZEOF_LONG +#endif +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_VOID_P == sizeof(void *)) +#if !defined(LZO_SIZEOF_SIZE_T) +#if (LZO_ARCH_I086 || LZO_ARCH_M16C) +# define LZO_SIZEOF_SIZE_T 2 +#endif +#endif +#if !defined(LZO_SIZEOF_SIZE_T) +# define LZO_SIZEOF_SIZE_T LZO_SIZEOF_VOID_P +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_SIZE_T == sizeof(size_t)) +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +#if (LZO_ARCH_I086) +# if (LZO_MM_TINY || LZO_MM_SMALL || LZO_MM_MEDIUM || LZO_MM_HUGE) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_VOID_P +# elif (LZO_MM_COMPACT || LZO_MM_LARGE) +# if (LZO_CC_BORLANDC || LZO_CC_TURBOC) +# define LZO_SIZEOF_PTRDIFF_T 4 +# else +# define LZO_SIZEOF_PTRDIFF_T 2 +# endif +# else +# error "invalid LZO_ARCH_I086 memory model" +# endif +#endif +#endif +#if !defined(LZO_SIZEOF_PTRDIFF_T) +# define LZO_SIZEOF_PTRDIFF_T LZO_SIZEOF_SIZE_T +#endif +#if defined(offsetof) +LZO_COMPILE_TIME_ASSERT_HEADER(LZO_SIZEOF_PTRDIFF_T == sizeof(ptrdiff_t)) +#endif +#if !defined(LZO_WORDSIZE) +# define LZO_WORDSIZE LZO_SIZEOF_VOID_P +#endif +#if (LZO_ABI_NEUTRAL_ENDIAN) +# undef LZO_ABI_BIG_ENDIAN +# undef LZO_ABI_LITTLE_ENDIAN +#elif !(LZO_ABI_BIG_ENDIAN) && !(LZO_ABI_LITTLE_ENDIAN) +#if (LZO_ARCH_ALPHA) && (LZO_ARCH_CRAY_MPP) +# define LZO_ABI_BIG_ENDIAN 1 +#elif (LZO_ARCH_IA64) && (LZO_OS_POSIX_LINUX || LZO_OS_WIN64) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_ALPHA || LZO_ARCH_AMD64 || LZO_ARCH_BLACKFIN || LZO_ARCH_CRIS || LZO_ARCH_I086 || LZO_ARCH_I386 || LZO_ARCH_MSP430 || LZO_ARCH_RISCV) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif (LZO_ARCH_AVR32 || LZO_ARCH_M68K || LZO_ARCH_S390 || LZO_ARCH_SPU) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__IAR_SYSTEMS_ICC__) && defined(__LITTLE_ENDIAN__) +# if (__LITTLE_ENDIAN__ == 1) +# define LZO_ABI_LITTLE_ENDIAN 1 +# else +# define LZO_ABI_BIG_ENDIAN 1 +# endif +#elif 1 && defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEB__) && !defined(__ARMEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(__ARMEL__) && !defined(__ARMEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM) && defined(_MSC_VER) && defined(_WIN32) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM && LZO_CC_ARMCC_ARMCC) +# if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +# elif defined(__BIG_ENDIAN) +# define LZO_ABI_BIG_ENDIAN 1 +# else +# define LZO_ABI_LITTLE_ENDIAN 1 +# endif +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__ARM_BIG_ENDIAN) && ((__ARM_BIG_ENDIAN)+0) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EB__) && !defined(__AARCH64EL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(__AARCH64EL__) && !defined(__AARCH64EB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_ARM64) && defined(_MSC_VER) && defined(_WIN32) +# define LZO_ABI_LITTLE_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEB__) && !defined(__MIPSEL__) +# define LZO_ABI_BIG_ENDIAN 1 +#elif 1 && (LZO_ARCH_MIPS) && defined(__MIPSEL__) && !defined(__MIPSEB__) +# define LZO_ABI_LITTLE_ENDIAN 1 +#endif +#endif +#if (LZO_ABI_BIG_ENDIAN) && (LZO_ABI_LITTLE_ENDIAN) +# error "unexpected configuration - check your compiler defines" +#endif +#if (LZO_ABI_BIG_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "be" +#elif (LZO_ABI_LITTLE_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "le" +#elif (LZO_ABI_NEUTRAL_ENDIAN) +# define LZO_INFO_ABI_ENDIAN "neutral" +#endif +#if (LZO_SIZEOF_INT == 1 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_I8LP16 1 +# define LZO_INFO_ABI_PM "i8lp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 2 && LZO_SIZEOF_VOID_P == 2) +# define LZO_ABI_ILP16 1 +# define LZO_INFO_ABI_PM "ilp16" +#elif (LZO_SIZEOF_INT == 2 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_LP32 1 +# define LZO_INFO_ABI_PM "lp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_ILP32 1 +# define LZO_INFO_ABI_PM "ilp32" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 4 && LZO_SIZEOF_VOID_P == 8 && LZO_SIZEOF_SIZE_T == 8) +# define LZO_ABI_LLP64 1 +# define LZO_INFO_ABI_PM "llp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_LP64 1 +# define LZO_INFO_ABI_PM "lp64" +#elif (LZO_SIZEOF_INT == 8 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 8) +# define LZO_ABI_ILP64 1 +# define LZO_INFO_ABI_PM "ilp64" +#elif (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_LONG == 8 && LZO_SIZEOF_VOID_P == 4) +# define LZO_ABI_IP32L64 1 +# define LZO_INFO_ABI_PM "ip32l64" +#endif +#if (LZO_SIZEOF_INT == 4 && LZO_SIZEOF_VOID_P == 4 && LZO_WORDSIZE == 8) +# define LZO_ABI_IP32W64 1 +# ifndef LZO_INFO_ABI_PM +# define LZO_INFO_ABI_PM "ip32w64" +# endif +#endif +#if 0 +#elif !defined(__LZO_LIBC_OVERRIDE) +#if (LZO_LIBC_NAKED) +# define LZO_INFO_LIBC "naked" +#elif (LZO_LIBC_FREESTANDING) +# define LZO_INFO_LIBC "freestanding" +#elif (LZO_LIBC_MOSTLY_FREESTANDING) +# define LZO_INFO_LIBC "mfreestanding" +#elif (LZO_LIBC_ISOC90) +# define LZO_INFO_LIBC "isoc90" +#elif (LZO_LIBC_ISOC99) +# define LZO_INFO_LIBC "isoc99" +#elif (LZO_CC_ARMCC_ARMCC) && defined(__ARMCLIB_VERSION) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#elif defined(__dietlibc__) +# define LZO_LIBC_DIETLIBC 1 +# define LZO_INFO_LIBC "dietlibc" +#elif defined(_NEWLIB_VERSION) +# define LZO_LIBC_NEWLIB 1 +# define LZO_INFO_LIBC "newlib" +#elif defined(__UCLIBC__) && defined(__UCLIBC_MAJOR__) && defined(__UCLIBC_MINOR__) +# if defined(__UCLIBC_SUBLEVEL__) +# define LZO_LIBC_UCLIBC (__UCLIBC_MAJOR__ * 0x10000L + (__UCLIBC_MINOR__-0) * 0x100 + (__UCLIBC_SUBLEVEL__-0)) +# else +# define LZO_LIBC_UCLIBC 0x00090bL +# endif +# define LZO_INFO_LIBC "uc" "libc" +#elif defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# define LZO_LIBC_GLIBC (__GLIBC__ * 0x10000L + (__GLIBC_MINOR__-0) * 0x100) +# define LZO_INFO_LIBC "glibc" +#elif (LZO_CC_MWERKS) && defined(__MSL__) +# define LZO_LIBC_MSL __MSL__ +# define LZO_INFO_LIBC "msl" +#elif 1 && defined(__IAR_SYSTEMS_ICC__) +# define LZO_LIBC_ISOC90 1 +# define LZO_INFO_LIBC "isoc90" +#else +# define LZO_LIBC_DEFAULT 1 +# define LZO_INFO_LIBC "default" +#endif +#endif +#if (LZO_ARCH_I386 && (LZO_OS_DOS32 || LZO_OS_WIN32) && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +# define LZO_ASM_SYNTAX_MSC 1 +#elif (LZO_OS_WIN64 && (LZO_CC_DMC || LZO_CC_INTELC || LZO_CC_MSC || LZO_CC_PELLESC)) +#elif (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC == 0x011f00ul)) +#elif (LZO_ARCH_I386 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_ARCH_AMD64 && (LZO_CC_CLANG || LZO_CC_GNUC || LZO_CC_INTELC || LZO_CC_PATHSCALE)) +# define LZO_ASM_SYNTAX_GNUC 1 +#elif (LZO_CC_GNUC) +# define LZO_ASM_SYNTAX_GNUC 1 +#endif +#if (LZO_ASM_SYNTAX_GNUC) +#if (LZO_ARCH_I386 && LZO_CC_GNUC && (LZO_CC_GNUC < 0x020000ul)) +# define __LZO_ASM_CLOBBER "ax" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#elif (LZO_CC_INTELC && (__INTEL_COMPILER < 1000)) +# define __LZO_ASM_CLOBBER "memory" +# define __LZO_ASM_CLOBBER_LIST_CC /*empty*/ +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#else +# define __LZO_ASM_CLOBBER "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_CC : "cc" +# define __LZO_ASM_CLOBBER_LIST_CC_MEMORY : "cc", "memory" +# define __LZO_ASM_CLOBBER_LIST_EMPTY /*empty*/ +#endif +#endif +#if (LZO_ARCH_ALPHA) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_AMD64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_ARM) +# if defined(__ARM_FEATURE_UNALIGNED) +# if ((__ARM_FEATURE_UNALIGNED)+0) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +# elif 1 && (LZO_ARCH_ARM_THUMB2) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__ARM_ARCH) && ((__ARM_ARCH)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(__TARGET_ARCH_ARM) && ((__TARGET_ARCH_ARM)+0 >= 6) && (defined(__TARGET_PROFILE_A) || defined(__TARGET_PROFILE_R)) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# elif 1 && defined(_MSC_VER) && defined(_M_ARM) && ((_M_ARM)+0 >= 7) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_ARM64) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +#elif (LZO_ARCH_CRIS) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_I386) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +#elif (LZO_ARCH_IA64) +# define LZO_OPT_AVOID_INT_INDEX 1 +# define LZO_OPT_AVOID_UINT_INDEX 1 +# define LZO_OPT_PREFER_POSTINC 1 +#elif (LZO_ARCH_M68K) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if defined(__mc68020__) && !defined(__mcoldfire__) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# endif +#elif (LZO_ARCH_MIPS) +# define LZO_OPT_AVOID_UINT_INDEX 1 +#elif (LZO_ARCH_POWERPC) +# define LZO_OPT_PREFER_PREINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +# if (LZO_ABI_BIG_ENDIAN) || (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +# endif +#elif (LZO_ARCH_RISCV) +# define LZO_OPT_AVOID_UINT_INDEX 1 +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_S390) +# ifndef LZO_OPT_UNALIGNED16 +# define LZO_OPT_UNALIGNED16 1 +# endif +# ifndef LZO_OPT_UNALIGNED32 +# define LZO_OPT_UNALIGNED32 1 +# endif +# if (LZO_WORDSIZE == 8) +# ifndef LZO_OPT_UNALIGNED64 +# define LZO_OPT_UNALIGNED64 1 +# endif +# endif +#elif (LZO_ARCH_SH) +# define LZO_OPT_PREFER_POSTINC 1 +# define LZO_OPT_PREFER_PREDEC 1 +#endif +#ifndef LZO_CFG_NO_INLINE_ASM +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_INLINE_ASM 1 +#elif (LZO_CC_LLVM) +# define LZO_CFG_NO_INLINE_ASM 1 +#endif +#endif +#if (LZO_CFG_NO_INLINE_ASM) +# undef LZO_ASM_SYNTAX_MSC +# undef LZO_ASM_SYNTAX_GNUC +# undef __LZO_ASM_CLOBBER +# undef __LZO_ASM_CLOBBER_LIST_CC +# undef __LZO_ASM_CLOBBER_LIST_CC_MEMORY +# undef __LZO_ASM_CLOBBER_LIST_EMPTY +#endif +#ifndef LZO_CFG_NO_UNALIGNED +#if (LZO_ABI_NEUTRAL_ENDIAN) || (LZO_ARCH_GENERIC) +# define LZO_CFG_NO_UNALIGNED 1 +#endif +#endif +#if (LZO_CFG_NO_UNALIGNED) +# undef LZO_OPT_UNALIGNED16 +# undef LZO_OPT_UNALIGNED32 +# undef LZO_OPT_UNALIGNED64 +#endif +#if defined(__LZO_INFOSTR_MM) +#elif (LZO_MM_FLAT) && (defined(__LZO_INFOSTR_PM) || defined(LZO_INFO_ABI_PM)) +# define __LZO_INFOSTR_MM "" +#elif defined(LZO_INFO_MM) +# define __LZO_INFOSTR_MM "." LZO_INFO_MM +#else +# define __LZO_INFOSTR_MM "" +#endif +#if defined(__LZO_INFOSTR_PM) +#elif defined(LZO_INFO_ABI_PM) +# define __LZO_INFOSTR_PM "." LZO_INFO_ABI_PM +#else +# define __LZO_INFOSTR_PM "" +#endif +#if defined(__LZO_INFOSTR_ENDIAN) +#elif defined(LZO_INFO_ABI_ENDIAN) +# define __LZO_INFOSTR_ENDIAN "." LZO_INFO_ABI_ENDIAN +#else +# define __LZO_INFOSTR_ENDIAN "" +#endif +#if defined(__LZO_INFOSTR_OSNAME) +#elif defined(LZO_INFO_OS_CONSOLE) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_CONSOLE +#elif defined(LZO_INFO_OS_POSIX) +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS "." LZO_INFO_OS_POSIX +#else +# define __LZO_INFOSTR_OSNAME LZO_INFO_OS +#endif +#if defined(__LZO_INFOSTR_LIBC) +#elif defined(LZO_INFO_LIBC) +# define __LZO_INFOSTR_LIBC "." LZO_INFO_LIBC +#else +# define __LZO_INFOSTR_LIBC "" +#endif +#if defined(__LZO_INFOSTR_CCVER) +#elif defined(LZO_INFO_CCVER) +# define __LZO_INFOSTR_CCVER " " LZO_INFO_CCVER +#else +# define __LZO_INFOSTR_CCVER "" +#endif +#define LZO_INFO_STRING \ + LZO_INFO_ARCH __LZO_INFOSTR_MM __LZO_INFOSTR_PM __LZO_INFOSTR_ENDIAN \ + " " __LZO_INFOSTR_OSNAME __LZO_INFOSTR_LIBC " " LZO_INFO_CC __LZO_INFOSTR_CCVER +#if !(LZO_CFG_SKIP_LZO_TYPES) +#if (!(LZO_SIZEOF_SHORT+0 > 0 && LZO_SIZEOF_INT+0 > 0 && LZO_SIZEOF_LONG+0 > 0)) +# error "missing defines for sizes" +#endif +#if (!(LZO_SIZEOF_PTRDIFF_T+0 > 0 && LZO_SIZEOF_SIZE_T+0 > 0 && LZO_SIZEOF_VOID_P+0 > 0)) +# error "missing defines for sizes" +#endif +#define LZO_TYPEOF_CHAR 1u +#define LZO_TYPEOF_SHORT 2u +#define LZO_TYPEOF_INT 3u +#define LZO_TYPEOF_LONG 4u +#define LZO_TYPEOF_LONG_LONG 5u +#define LZO_TYPEOF___INT8 17u +#define LZO_TYPEOF___INT16 18u +#define LZO_TYPEOF___INT32 19u +#define LZO_TYPEOF___INT64 20u +#define LZO_TYPEOF___INT128 21u +#define LZO_TYPEOF___INT256 22u +#define LZO_TYPEOF___MODE_QI 33u +#define LZO_TYPEOF___MODE_HI 34u +#define LZO_TYPEOF___MODE_SI 35u +#define LZO_TYPEOF___MODE_DI 36u +#define LZO_TYPEOF___MODE_TI 37u +#define LZO_TYPEOF_CHAR_P 129u +#if !defined(lzo_llong_t) +#if (LZO_SIZEOF_LONG_LONG+0 > 0) +# if !(LZO_LANG_ASSEMBLER) + __lzo_gnuc_extension__ typedef long long lzo_llong_t__; + __lzo_gnuc_extension__ typedef unsigned long long lzo_ullong_t__; +# endif +# define lzo_llong_t lzo_llong_t__ +# define lzo_ullong_t lzo_ullong_t__ +#endif +#endif +#if !defined(lzo_int16e_t) +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) && (LZO_SIZEOF_SHORT != 2) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T +#endif +#if (LZO_SIZEOF_LONG == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) +# define lzo_int16e_t long +# define lzo_uint16e_t unsigned long +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 2) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT16E_T == LZO_TYPEOF_SHORT) +# define lzo_int16e_t int +# define lzo_uint16e_t unsigned int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 2) +# define lzo_int16e_t short int +# define lzo_uint16e_t unsigned short int +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF_SHORT +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_HI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) +# if !(LZO_LANG_ASSEMBLER) + typedef int lzo_int16e_hi_t__ __attribute__((__mode__(__HI__))); + typedef unsigned int lzo_uint16e_hi_t__ __attribute__((__mode__(__HI__))); +# endif +# define lzo_int16e_t lzo_int16e_hi_t__ +# define lzo_uint16e_t lzo_uint16e_hi_t__ +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___MODE_HI +#elif (LZO_SIZEOF___INT16 == 2) +# define lzo_int16e_t __int16 +# define lzo_uint16e_t unsigned __int16 +# define LZO_TYPEOF_LZO_INT16E_T LZO_TYPEOF___INT16 +#else +#endif +#endif +#if defined(lzo_int16e_t) +# define LZO_SIZEOF_LZO_INT16E_T 2 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == 2) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16e_t) == LZO_SIZEOF_LZO_INT16E_T) +#endif +#if !defined(lzo_int32e_t) +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) && (LZO_SIZEOF_INT != 4) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T +#endif +#if (LZO_SIZEOF_LONG == 4) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT32E_T == LZO_TYPEOF_INT) +# define lzo_int32e_t long int +# define lzo_uint32e_t unsigned long int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_INT == 4) +# define lzo_int32e_t int +# define lzo_uint32e_t unsigned int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == 4) +# define lzo_int32e_t short int +# define lzo_uint32e_t unsigned short int +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_LONG_LONG == 4) +# define lzo_int32e_t lzo_llong_t +# define lzo_uint32e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF_LONG_LONG +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x025f00ul) || LZO_CC_LLVM) && (__INT_MAX__+0 > 2147483647L) +# if !(LZO_LANG_ASSEMBLER) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# endif +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif 1 && !(LZO_CFG_TYPE_NO_MODE_SI) && (LZO_CC_GNUC >= 0x025f00ul) && defined(__AVR__) && (__LONG_MAX__+0 == 32767L) +# if !(LZO_LANG_ASSEMBLER) + typedef int lzo_int32e_si_t__ __attribute__((__mode__(__SI__))); + typedef unsigned int lzo_uint32e_si_t__ __attribute__((__mode__(__SI__))); +# endif +# define lzo_int32e_t lzo_int32e_si_t__ +# define lzo_uint32e_t lzo_uint32e_si_t__ +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___MODE_SI +#elif (LZO_SIZEOF___INT32 == 4) +# define lzo_int32e_t __int32 +# define lzo_uint32e_t unsigned __int32 +# define LZO_TYPEOF_LZO_INT32E_T LZO_TYPEOF___INT32 +#else +#endif +#endif +#if defined(lzo_int32e_t) +# define LZO_SIZEOF_LZO_INT32E_T 4 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32e_t) == LZO_SIZEOF_LZO_INT32E_T) +#endif +#if !defined(lzo_int64e_t) +#if (LZO_SIZEOF___INT64 == 8) +# if (LZO_CC_BORLANDC) && !defined(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T) +# define LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T LZO_TYPEOF___INT64 +# endif +#endif +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && (LZO_SIZEOF_LONG_LONG != 8) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T +#endif +#if (LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) && (LZO_SIZEOF___INT64 != 8) +# undef LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T +#endif +#if (LZO_SIZEOF_INT == 8) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int64e_t int +# define lzo_uint64e_t unsigned int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF_LONG_LONG) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) +# define lzo_int64e_t long int +# define lzo_uint64e_t unsigned long int +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LONG_LONG == 8) && !(LZO_CFG_PREFER_TYPEOF_ACC_INT64E_T == LZO_TYPEOF___INT64) +# define lzo_int64e_t lzo_llong_t +# define lzo_uint64e_t lzo_ullong_t +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF_LONG_LONG +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0ll) +# define LZO_UINT64_C(c) ((c) + 0ull) +# elif 0 +# define LZO_INT64_C(c) (__lzo_gnuc_extension__ (c##LL)) +# define LZO_UINT64_C(c) (__lzo_gnuc_extension__ (c##ULL)) +# else +# define LZO_INT64_C(c) (c##LL) +# define LZO_UINT64_C(c) (c##ULL) +# endif +#elif (LZO_SIZEOF___INT64 == 8) +# define lzo_int64e_t __int64 +# define lzo_uint64e_t unsigned __int64 +# define LZO_TYPEOF_LZO_INT64E_T LZO_TYPEOF___INT64 +# if (LZO_CC_BORLANDC) +# define LZO_INT64_C(c) ((c) + 0i64) +# define LZO_UINT64_C(c) ((c) + 0ui64) +# else +# define LZO_INT64_C(c) (c##i64) +# define LZO_UINT64_C(c) (c##ui64) +# endif +#else +#endif +#endif +#if defined(lzo_int64e_t) +# define LZO_SIZEOF_LZO_INT64E_T 8 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64e_t) == LZO_SIZEOF_LZO_INT64E_T) +#endif +#if !defined(lzo_int32l_t) +#if defined(lzo_int32e_t) +# define lzo_int32l_t lzo_int32e_t +# define lzo_uint32l_t lzo_uint32e_t +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LZO_INT32E_T +# define LZO_TYPEOF_LZO_INT32L_T LZO_TYPEOF_LZO_INT32E_T +#elif (LZO_SIZEOF_INT >= 4) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_int32l_t int +# define lzo_uint32l_t unsigned int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_INT +#elif (LZO_SIZEOF_LONG >= 4) +# define lzo_int32l_t long int +# define lzo_uint32l_t unsigned long int +# define LZO_SIZEOF_LZO_INT32L_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INT32L_T LZO_SIZEOF_LONG +#else +# error "lzo_int32l_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32l_t) == LZO_SIZEOF_LZO_INT32L_T) +#endif +#if !defined(lzo_int64l_t) +#if defined(lzo_int64e_t) +# define lzo_int64l_t lzo_int64e_t +# define lzo_uint64l_t lzo_uint64e_t +# define LZO_SIZEOF_LZO_INT64L_T LZO_SIZEOF_LZO_INT64E_T +# define LZO_TYPEOF_LZO_INT64L_T LZO_TYPEOF_LZO_INT64E_T +#else +#endif +#endif +#if defined(lzo_int64l_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64l_t) == LZO_SIZEOF_LZO_INT64L_T) +#endif +#if !defined(lzo_int32f_t) +#if (LZO_SIZEOF_SIZE_T >= 8) +# define lzo_int32f_t lzo_int64l_t +# define lzo_uint32f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT64L_T +#else +# define lzo_int32f_t lzo_int32l_t +# define lzo_uint32f_t lzo_uint32l_t +# define LZO_SIZEOF_LZO_INT32F_T LZO_SIZEOF_LZO_INT32L_T +# define LZO_TYPEOF_LZO_INT32F_T LZO_TYPEOF_LZO_INT32L_T +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) >= 4) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32f_t) == LZO_SIZEOF_LZO_INT32F_T) +#endif +#if !defined(lzo_int64f_t) +#if defined(lzo_int64l_t) +# define lzo_int64f_t lzo_int64l_t +# define lzo_uint64f_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INT64F_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INT64F_T LZO_TYPEOF_LZO_INT64L_T +#else +#endif +#endif +#if defined(lzo_int64f_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) >= 8) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64f_t) == LZO_SIZEOF_LZO_INT64F_T) +#endif +#if !defined(lzo_intptr_t) +#if 1 && (LZO_OS_OS400 && (LZO_SIZEOF_VOID_P == 16)) +# define __LZO_INTPTR_T_IS_POINTER 1 +# if !(LZO_LANG_ASSEMBLER) + typedef char * lzo_intptr_t; + typedef char * lzo_uintptr_t; +# endif +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_VOID_P +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_CHAR_P +#elif (LZO_CC_MSC && (_MSC_VER >= 1300) && (LZO_SIZEOF_VOID_P == 4) && (LZO_SIZEOF_INT == 4)) +# if !(LZO_LANG_ASSEMBLER) + typedef __w64 int lzo_intptr_t; + typedef __w64 unsigned int lzo_uintptr_t; +# endif +# define lzo_intptr_t lzo_intptr_t +# define lzo_uintptr_t lzo_uintptr_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_SHORT == LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT > LZO_SIZEOF_VOID_P) +# define lzo_intptr_t short +# define lzo_uintptr_t unsigned short +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_SHORT +#elif (LZO_SIZEOF_INT >= LZO_SIZEOF_VOID_P) && (LZO_SIZEOF_INT < LZO_SIZEOF_LONG) +# define lzo_intptr_t int +# define lzo_uintptr_t unsigned int +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_INT +#elif (LZO_SIZEOF_LONG >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t long +# define lzo_uintptr_t unsigned long +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LONG +#elif (LZO_SIZEOF_LZO_INT64L_T >= LZO_SIZEOF_VOID_P) +# define lzo_intptr_t lzo_int64l_t +# define lzo_uintptr_t lzo_uint64l_t +# define LZO_SIZEOF_LZO_INTPTR_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_INTPTR_T LZO_TYPEOF_LZO_INT64L_T +#else +# error "lzo_intptr_t" +#endif +#endif +#if 1 + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) >= sizeof(void *)) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_intptr_t) == sizeof(lzo_uintptr_t)) +#endif +#if !defined(lzo_word_t) +#if defined(LZO_WORDSIZE) && (LZO_WORDSIZE+0 > 0) +#if (LZO_WORDSIZE == LZO_SIZEOF_LZO_INTPTR_T) && !(__LZO_INTPTR_T_IS_POINTER) +# define lzo_word_t lzo_uintptr_t +# define lzo_sword_t lzo_intptr_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INTPTR_T +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LZO_INTPTR_T +#elif (LZO_WORDSIZE == LZO_SIZEOF_LONG) +# define lzo_word_t unsigned long +# define lzo_sword_t long +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LONG +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_LONG +#elif (LZO_WORDSIZE == LZO_SIZEOF_INT) +# define lzo_word_t unsigned int +# define lzo_sword_t int +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_INT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_INT +#elif (LZO_WORDSIZE == LZO_SIZEOF_SHORT) +# define lzo_word_t unsigned short +# define lzo_sword_t short +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_SHORT +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_SHORT +#elif (LZO_WORDSIZE == 1) +# define lzo_word_t unsigned char +# define lzo_sword_t signed char +# define LZO_SIZEOF_LZO_WORD_T 1 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF_CHAR +#elif (LZO_WORDSIZE == LZO_SIZEOF_LZO_INT64L_T) +# define lzo_word_t lzo_uint64l_t +# define lzo_sword_t lzo_int64l_t +# define LZO_SIZEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +# define LZO_TYPEOF_LZO_WORD_T LZO_SIZEOF_LZO_INT64L_T +#elif (LZO_ARCH_SPU) && (LZO_CC_GNUC) +#if 0 +# if !(LZO_LANG_ASSEMBLER) + typedef unsigned lzo_word_t __attribute__((__mode__(__V16QI__))); + typedef int lzo_sword_t __attribute__((__mode__(__V16QI__))); +# endif +# define lzo_word_t lzo_word_t +# define lzo_sword_t lzo_sword_t +# define LZO_SIZEOF_LZO_WORD_T 16 +# define LZO_TYPEOF_LZO_WORD_T LZO_TYPEOF___MODE_V16QI +#endif +#else +# error "lzo_word_t" +#endif +#endif +#endif +#if 1 && defined(lzo_word_t) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_word_t) == LZO_WORDSIZE) + LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_sword_t) == LZO_WORDSIZE) +#endif +#if 1 +#define lzo_int8_t signed char +#define lzo_uint8_t unsigned char +#define LZO_SIZEOF_LZO_INT8_T 1 +#define LZO_TYPEOF_LZO_INT8_T LZO_TYPEOF_CHAR +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == sizeof(lzo_uint8_t)) +#endif +#if defined(lzo_int16e_t) +#define lzo_int16_t lzo_int16e_t +#define lzo_uint16_t lzo_uint16e_t +#define LZO_SIZEOF_LZO_INT16_T LZO_SIZEOF_LZO_INT16E_T +#define LZO_TYPEOF_LZO_INT16_T LZO_TYPEOF_LZO_INT16E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == sizeof(lzo_uint16_t)) +#endif +#if defined(lzo_int32e_t) +#define lzo_int32_t lzo_int32e_t +#define lzo_uint32_t lzo_uint32e_t +#define LZO_SIZEOF_LZO_INT32_T LZO_SIZEOF_LZO_INT32E_T +#define LZO_TYPEOF_LZO_INT32_T LZO_TYPEOF_LZO_INT32E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == sizeof(lzo_uint32_t)) +#endif +#if defined(lzo_int64e_t) +#define lzo_int64_t lzo_int64e_t +#define lzo_uint64_t lzo_uint64e_t +#define LZO_SIZEOF_LZO_INT64_T LZO_SIZEOF_LZO_INT64E_T +#define LZO_TYPEOF_LZO_INT64_T LZO_TYPEOF_LZO_INT64E_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == sizeof(lzo_uint64_t)) +#endif +#if 1 +#define lzo_int_least32_t lzo_int32l_t +#define lzo_uint_least32_t lzo_uint32l_t +#define LZO_SIZEOF_LZO_INT_LEAST32_T LZO_SIZEOF_LZO_INT32L_T +#define LZO_TYPEOF_LZO_INT_LEAST32_T LZO_TYPEOF_LZO_INT32L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least32_t) == sizeof(lzo_uint_least32_t)) +#endif +#if defined(lzo_int64l_t) +#define lzo_int_least64_t lzo_int64l_t +#define lzo_uint_least64_t lzo_uint64l_t +#define LZO_SIZEOF_LZO_INT_LEAST64_T LZO_SIZEOF_LZO_INT64L_T +#define LZO_TYPEOF_LZO_INT_LEAST64_T LZO_TYPEOF_LZO_INT64L_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_least64_t) == sizeof(lzo_uint_least64_t)) +#endif +#if 1 +#define lzo_int_fast32_t lzo_int32f_t +#define lzo_uint_fast32_t lzo_uint32f_t +#define LZO_SIZEOF_LZO_INT_FAST32_T LZO_SIZEOF_LZO_INT32F_T +#define LZO_TYPEOF_LZO_INT_FAST32_T LZO_TYPEOF_LZO_INT32F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) >= 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast32_t) == sizeof(lzo_uint_fast32_t)) +#endif +#if defined(lzo_int64f_t) +#define lzo_int_fast64_t lzo_int64f_t +#define lzo_uint_fast64_t lzo_uint64f_t +#define LZO_SIZEOF_LZO_INT_FAST64_T LZO_SIZEOF_LZO_INT64F_T +#define LZO_TYPEOF_LZO_INT_FAST64_T LZO_TYPEOF_LZO_INT64F_T +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) >= 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int_fast64_t) == sizeof(lzo_uint_fast64_t)) +#endif +#if !defined(LZO_INT16_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) ((c) + 0) +# define LZO_UINT16_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) ((c) + 0L) +# define LZO_UINT16_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 2) +# define LZO_INT16_C(c) (c) +# define LZO_UINT16_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 2) +# define LZO_INT16_C(c) (c##L) +# define LZO_UINT16_C(c) (c##UL) +# else +# error "LZO_INT16_C" +# endif +#endif +#if !defined(LZO_INT32_C) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) ((c) + 0) +# define LZO_UINT32_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) ((c) + 0L) +# define LZO_UINT32_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 4) +# define LZO_INT32_C(c) (c) +# define LZO_UINT32_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 4) +# define LZO_INT32_C(c) (c##L) +# define LZO_UINT32_C(c) (c##UL) +# elif (LZO_SIZEOF_LONG_LONG >= 4) +# define LZO_INT32_C(c) (c##LL) +# define LZO_UINT32_C(c) (c##ULL) +# else +# error "LZO_INT32_C" +# endif +#endif +#if !defined(LZO_INT64_C) && defined(lzo_int64l_t) +# if (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) ((c) + 0) +# define LZO_UINT64_C(c) ((c) + 0U) +# elif (LZO_BROKEN_INTEGRAL_CONSTANTS) && (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) ((c) + 0L) +# define LZO_UINT64_C(c) ((c) + 0UL) +# elif (LZO_SIZEOF_INT >= 8) +# define LZO_INT64_C(c) (c) +# define LZO_UINT64_C(c) (c##U) +# elif (LZO_SIZEOF_LONG >= 8) +# define LZO_INT64_C(c) (c##L) +# define LZO_UINT64_C(c) (c##UL) +# else +# error "LZO_INT64_C" +# endif +#endif +#endif + +#endif + +#endif + +#undef LZO_HAVE_CONFIG_H +#include "minilzo.h" + +#if !defined(MINILZO_VERSION) || (MINILZO_VERSION != 0x20a0) +# error "version mismatch in miniLZO source files" +#endif + +#ifdef MINILZO_HAVE_CONFIG_H +# define LZO_HAVE_CONFIG_H 1 +#endif + +#ifndef __LZO_CONF_H +#define __LZO_CONF_H 1 + +#if !defined(__LZO_IN_MINILZO) +#if defined(LZO_CFG_FREESTANDING) && (LZO_CFG_FREESTANDING) +# define LZO_LIBC_FREESTANDING 1 +# define LZO_OS_FREESTANDING 1 +#endif +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER) +# include LZO_CFG_EXTRA_CONFIG_HEADER +#endif +#if defined(__LZOCONF_H) || defined(__LZOCONF_H_INCLUDED) +# error "include this file first" +#endif +#if defined(LZO_CFG_BUILD_DLL) && (LZO_CFG_BUILD_DLL+0) && !defined(__LZO_EXPORT1) && !defined(__LZO_EXPORT2) && 0 +#ifndef __LZODEFS_H_INCLUDED +#if defined(LZO_HAVE_CONFIG_H) +# include +#endif +#include +#include +#include +#endif +#endif +#include +#if defined(LZO_CFG_EXTRA_CONFIG_HEADER2) +# include LZO_CFG_EXTRA_CONFIG_HEADER2 +#endif +#endif + +#if !defined(__LZOCONF_H_INCLUDED) || (LZO_VERSION+0 != 0x20a0) +# error "version mismatch" +#endif + +#if (LZO_CC_MSC && (_MSC_VER >= 1000 && _MSC_VER < 1100)) +# pragma warning(disable: 4702) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1000)) +# pragma warning(disable: 4127 4701) +# pragma warning(disable: 4514 4710 4711) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1300)) +# pragma warning(disable: 4820) +#endif +#if (LZO_CC_MSC && (_MSC_VER >= 1800)) +# pragma warning(disable: 4746) +#endif +#if (LZO_CC_INTELC && (__INTEL_COMPILER >= 900)) +# pragma warning(disable: 1684) +#endif + +#if (LZO_CC_SUNPROC) +#if !defined(__cplusplus) +# pragma error_messages(off,E_END_OF_LOOP_CODE_NOT_REACHED) +# pragma error_messages(off,E_LOOP_NOT_ENTERED_AT_TOP) +# pragma error_messages(off,E_STATEMENT_NOT_REACHED) +#endif +#endif + +#if !defined(__LZO_NOEXPORT1) +# define __LZO_NOEXPORT1 /*empty*/ +#endif +#if !defined(__LZO_NOEXPORT2) +# define __LZO_NOEXPORT2 /*empty*/ +#endif + +#if 1 +# define LZO_PUBLIC_DECL(r) LZO_EXTERN(r) +#endif +#if 1 +# define LZO_PUBLIC_IMPL(r) LZO_PUBLIC(r) +#endif +#if !defined(LZO_LOCAL_DECL) +# define LZO_LOCAL_DECL(r) __LZO_EXTERN_C LZO_LOCAL_IMPL(r) +#endif +#if !defined(LZO_LOCAL_IMPL) +# define LZO_LOCAL_IMPL(r) __LZO_NOEXPORT1 r __LZO_NOEXPORT2 __LZO_CDECL +#endif +#if 1 +# define LZO_STATIC_DECL(r) LZO_PRIVATE(r) +#endif +#if 1 +# define LZO_STATIC_IMPL(r) LZO_PRIVATE(r) +#endif + +#if defined(__LZO_IN_MINILZO) || (LZO_CFG_FREESTANDING) +#elif 1 +# include +#else +# define LZO_WANT_ACC_INCD_H 1 +#endif +#if defined(LZO_HAVE_CONFIG_H) +# define LZO_CFG_NO_CONFIG_HEADER 1 +#endif + +#if 1 && !defined(LZO_CFG_FREESTANDING) +#if 1 && !defined(HAVE_STRING_H) +#define HAVE_STRING_H 1 +#endif +#if 1 && !defined(HAVE_MEMCMP) +#define HAVE_MEMCMP 1 +#endif +#if 1 && !defined(HAVE_MEMCPY) +#define HAVE_MEMCPY 1 +#endif +#if 1 && !defined(HAVE_MEMMOVE) +#define HAVE_MEMMOVE 1 +#endif +#if 1 && !defined(HAVE_MEMSET) +#define HAVE_MEMSET 1 +#endif +#endif + +#if 1 && defined(HAVE_STRING_H) +#include +#endif + +#if 1 || defined(lzo_int8_t) || defined(lzo_uint8_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int8_t) == 1) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint8_t) == 1) +#endif +#if 1 || defined(lzo_int16_t) || defined(lzo_uint16_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int16_t) == 2) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint16_t) == 2) +#endif +#if 1 || defined(lzo_int32_t) || defined(lzo_uint32_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int32_t) == 4) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint32_t) == 4) +#endif +#if defined(lzo_int64_t) || defined(lzo_uint64_t) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_int64_t) == 8) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(lzo_uint64_t) == 8) +#endif + +#if (LZO_CFG_FREESTANDING) +# undef HAVE_MEMCMP +# undef HAVE_MEMCPY +# undef HAVE_MEMMOVE +# undef HAVE_MEMSET +#endif + +#if !(HAVE_MEMCMP) +# undef memcmp +# define memcmp(a,b,c) lzo_memcmp(a,b,c) +#else +# undef lzo_memcmp +# define lzo_memcmp(a,b,c) memcmp(a,b,c) +#endif +#if !(HAVE_MEMCPY) +# undef memcpy +# define memcpy(a,b,c) lzo_memcpy(a,b,c) +#else +# undef lzo_memcpy +# define lzo_memcpy(a,b,c) memcpy(a,b,c) +#endif +#if !(HAVE_MEMMOVE) +# undef memmove +# define memmove(a,b,c) lzo_memmove(a,b,c) +#else +# undef lzo_memmove +# define lzo_memmove(a,b,c) memmove(a,b,c) +#endif +#if !(HAVE_MEMSET) +# undef memset +# define memset(a,b,c) lzo_memset(a,b,c) +#else +# undef lzo_memset +# define lzo_memset(a,b,c) memset(a,b,c) +#endif + +#undef NDEBUG +#if (LZO_CFG_FREESTANDING) +# undef LZO_DEBUG +# define NDEBUG 1 +# undef assert +# define assert(e) ((void)0) +#else +# if !defined(LZO_DEBUG) +# define NDEBUG 1 +# endif +# include +#endif + +#if 0 && defined(__BOUNDS_CHECKING_ON) +# include +#else +# define BOUNDS_CHECKING_OFF_DURING(stmt) stmt +# define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr) +#endif + +#if (LZO_CFG_PGO) +# undef __lzo_likely +# undef __lzo_unlikely +# define __lzo_likely(e) (e) +# define __lzo_unlikely(e) (e) +#endif + +#undef _ +#undef __ +#undef ___ +#undef ____ +#undef _p0 +#undef _p1 +#undef _p2 +#undef _p3 +#undef _p4 +#undef _s0 +#undef _s1 +#undef _s2 +#undef _s3 +#undef _s4 +#undef _ww + +#if 1 +# define LZO_BYTE(x) ((unsigned char) (x)) +#else +# define LZO_BYTE(x) ((unsigned char) ((x) & 0xff)) +#endif + +#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b)) +#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b)) +#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c)) +#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c)) + +#define lzo_sizeof(type) ((lzo_uint) (sizeof(type))) + +#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array)))) + +#define LZO_SIZE(bits) (1u << (bits)) +#define LZO_MASK(bits) (LZO_SIZE(bits) - 1) + +#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits)) +#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1) + +#if !defined(DMUL) +#if 0 + +# define DMUL(a,b) ((lzo_xint) ((lzo_uint32_t)(a) * (lzo_uint32_t)(b))) +#else +# define DMUL(a,b) ((lzo_xint) ((a) * (b))) +#endif +#endif + +#ifndef __LZO_FUNC_H +#define __LZO_FUNC_H 1 + +#if !defined(LZO_BITOPS_USE_ASM_BITSCAN) && !defined(LZO_BITOPS_USE_GNUC_BITSCAN) && !defined(LZO_BITOPS_USE_MSC_BITSCAN) +#if 1 && (LZO_ARCH_AMD64) && (LZO_CC_GNUC && (LZO_CC_GNUC < 0x040000ul)) && (LZO_ASM_SYNTAX_GNUC) +#define LZO_BITOPS_USE_ASM_BITSCAN 1 +#elif (LZO_CC_CLANG || (LZO_CC_GNUC >= 0x030400ul) || (LZO_CC_INTELC_GNUC && (__INTEL_COMPILER >= 1000)) || (LZO_CC_LLVM && (!defined(__llvm_tools_version__) || (__llvm_tools_version__+0 >= 0x010500ul)))) +#define LZO_BITOPS_USE_GNUC_BITSCAN 1 +#elif (LZO_OS_WIN32 || LZO_OS_WIN64) && ((LZO_CC_INTELC_MSC && (__INTEL_COMPILER >= 1010)) || (LZO_CC_MSC && (_MSC_VER >= 1400))) +#define LZO_BITOPS_USE_MSC_BITSCAN 1 +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#include +#endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) +#pragma intrinsic(_BitScanReverse) +#pragma intrinsic(_BitScanForward) +#endif +#if (LZO_CC_MSC) && (LZO_ARCH_AMD64) +#pragma intrinsic(_BitScanReverse64) +#pragma intrinsic(_BitScanForward64) +#endif +#endif +#endif + +__lzo_static_forceinline unsigned lzo_bitops_ctlz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanReverse(&r, v); return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 31; +#define lzo_bitops_ctlz32(v) lzo_bitops_ctlz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT == 4) + unsigned r; r = (unsigned) __builtin_clz(v); return r; +#define lzo_bitops_ctlz32(v) ((unsigned) __builtin_clz(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzl(v); return r ^ 32; +#define lzo_bitops_ctlz32(v) (((unsigned) __builtin_clzl(v)) ^ 32) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_ctlz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanReverse64(&r, v); return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsr %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r ^ 63; +#define lzo_bitops_ctlz64(v) lzo_bitops_ctlz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzl(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG == 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_clzll(v); return r; +#define lzo_bitops_ctlz64(v) ((unsigned) __builtin_clzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +__lzo_static_forceinline unsigned lzo_bitops_cttz32_func(lzo_uint32_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) + unsigned long r; (void) _BitScanForward(&r, v); return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64 || LZO_ARCH_I386) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint32_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz32(v) lzo_bitops_cttz32_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_INT >= 4) + unsigned r; r = (unsigned) __builtin_ctz(v); return r; +#define lzo_bitops_cttz32(v) ((unsigned) __builtin_ctz(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} + +#if defined(lzo_uint64_t) +__lzo_static_forceinline unsigned lzo_bitops_cttz64_func(lzo_uint64_t v) +{ +#if (LZO_BITOPS_USE_MSC_BITSCAN) && (LZO_ARCH_AMD64) + unsigned long r; (void) _BitScanForward64(&r, v); return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_ASM_BITSCAN) && (LZO_ARCH_AMD64) && (LZO_ASM_SYNTAX_GNUC) + lzo_uint64_t r; + __asm__("bsf %1,%0" : "=r" (r) : "rm" (v) __LZO_ASM_CLOBBER_LIST_CC); + return (unsigned) r; +#define lzo_bitops_cttz64(v) lzo_bitops_cttz64_func(v) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzl(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzl(v)) +#elif (LZO_BITOPS_USE_GNUC_BITSCAN) && (LZO_SIZEOF_LONG_LONG >= 8) && (LZO_WORDSIZE >= 8) + unsigned r; r = (unsigned) __builtin_ctzll(v); return r; +#define lzo_bitops_cttz64(v) ((unsigned) __builtin_ctzll(v)) +#else + LZO_UNUSED(v); return 0; +#endif +} +#endif + +lzo_unused_funcs_impl(void, lzo_bitops_unused_funcs)(void) +{ + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); + LZO_UNUSED_FUNC(lzo_bitops_ctlz32_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz32_func); +#if defined(lzo_uint64_t) + LZO_UNUSED_FUNC(lzo_bitops_ctlz64_func); + LZO_UNUSED_FUNC(lzo_bitops_cttz64_func); +#endif +} + +#if defined(__lzo_alignof) && !(LZO_CFG_NO_UNALIGNED) +#if !defined(lzo_memops_tcheck__) && 0 +#define lzo_memops_tcheck__(t,a,b) ((void)0, sizeof(t) == (a) && __lzo_alignof(t) == (b)) +#endif +#endif +#ifndef lzo_memops_TU0p +#define lzo_memops_TU0p void __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU1p +#define lzo_memops_TU1p unsigned char __LZO_MMODEL * +#endif +#ifndef lzo_memops_TU2p +#if (LZO_OPT_UNALIGNED16) +typedef lzo_uint16_t __lzo_may_alias lzo_memops_TU2; +#define lzo_memops_TU2p volatile lzo_memops_TU2 * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU2_struct,2) +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#else +struct lzo_memops_TU2_struct { unsigned char a[2]; } __lzo_may_alias; +typedef struct lzo_memops_TU2_struct lzo_memops_TU2; +#endif +#ifndef lzo_memops_TU2p +#define lzo_memops_TU2p lzo_memops_TU2 * +#endif +#endif +#ifndef lzo_memops_TU4p +#if (LZO_OPT_UNALIGNED32) +typedef lzo_uint32_t __lzo_may_alias lzo_memops_TU4; +#define lzo_memops_TU4p volatile lzo_memops_TU4 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU4_struct,4) +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#else +struct lzo_memops_TU4_struct { unsigned char a[4]; } __lzo_may_alias; +typedef struct lzo_memops_TU4_struct lzo_memops_TU4; +#endif +#ifndef lzo_memops_TU4p +#define lzo_memops_TU4p lzo_memops_TU4 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_TU8p +#if (LZO_OPT_UNALIGNED64) +typedef lzo_uint64_t __lzo_may_alias lzo_memops_TU8; +#define lzo_memops_TU8p volatile lzo_memops_TU8 __LZO_MMODEL * +#elif defined(__lzo_byte_struct) +__lzo_byte_struct(lzo_memops_TU8_struct,8) +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#else +struct lzo_memops_TU8_struct { unsigned char a[8]; } __lzo_may_alias; +typedef struct lzo_memops_TU8_struct lzo_memops_TU8; +#endif +#ifndef lzo_memops_TU8p +#define lzo_memops_TU8p lzo_memops_TU8 __LZO_MMODEL * +#endif +#endif +#ifndef lzo_memops_set_TU1p +#define lzo_memops_set_TU1p volatile lzo_memops_TU1p +#endif +#ifndef lzo_memops_move_TU1p +#define lzo_memops_move_TU1p lzo_memops_TU1p +#endif +#define LZO_MEMOPS_SET1(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__1 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__1[0] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET2(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__2 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__2[0] = LZO_BYTE(cc); d__2[1] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET3(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__3 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__3[0] = LZO_BYTE(cc); d__3[1] = LZO_BYTE(cc); d__3[2] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_SET4(dd,cc) \ + LZO_BLOCK_BEGIN \ + lzo_memops_set_TU1p d__4 = (lzo_memops_set_TU1p) (lzo_memops_TU0p) (dd); \ + d__4[0] = LZO_BYTE(cc); d__4[1] = LZO_BYTE(cc); d__4[2] = LZO_BYTE(cc); d__4[3] = LZO_BYTE(cc); \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE1(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__1 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__1 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__1[0] = s__1[0]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE2(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__2 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__2 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__2[0] = s__2[0]; d__2[1] = s__2[1]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE3(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__3 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__3 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__3[0] = s__3[0]; d__3[1] = s__3[1]; d__3[2] = s__3[2]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE4(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__4 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__4 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__4[0] = s__4[0]; d__4[1] = s__4[1]; d__4[2] = s__4[2]; d__4[3] = s__4[3]; \ + LZO_BLOCK_END +#define LZO_MEMOPS_MOVE8(dd,ss) \ + LZO_BLOCK_BEGIN \ + lzo_memops_move_TU1p d__8 = (lzo_memops_move_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_move_TU1p s__8 = (const lzo_memops_move_TU1p) (const lzo_memops_TU0p) (ss); \ + d__8[0] = s__8[0]; d__8[1] = s__8[1]; d__8[2] = s__8[2]; d__8[3] = s__8[3]; \ + d__8[4] = s__8[4]; d__8[5] = s__8[5]; d__8[6] = s__8[6]; d__8[7] = s__8[7]; \ + LZO_BLOCK_END +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU1p)0)==1) +#define LZO_MEMOPS_COPY1(dd,ss) LZO_MEMOPS_MOVE1(dd,ss) +#if (LZO_OPT_UNALIGNED16) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) +#define LZO_MEMOPS_COPY2(dd,ss) \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss) +#elif defined(lzo_memops_tcheck__) +#define LZO_MEMOPS_COPY2(dd,ss) \ + LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU2,2,1)) { \ + * (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE2(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY2(dd,ss) LZO_MEMOPS_MOVE2(dd,ss) +#endif +#if (LZO_OPT_UNALIGNED32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) +#define LZO_MEMOPS_COPY4(dd,ss) \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss) +#elif defined(lzo_memops_tcheck__) +#define LZO_MEMOPS_COPY4(dd,ss) \ + LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU4,4,1)) { \ + * (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE4(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY4(dd,ss) LZO_MEMOPS_MOVE4(dd,ss) +#endif +#if (LZO_WORDSIZE != 8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#else +#if (LZO_OPT_UNALIGNED64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) +#define LZO_MEMOPS_COPY8(dd,ss) \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss) +#elif (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN LZO_MEMOPS_COPY4(dd,ss); LZO_MEMOPS_COPY4((lzo_memops_TU1p)(lzo_memops_TU0p)(dd)+4,(const lzo_memops_TU1p)(const lzo_memops_TU0p)(ss)+4); LZO_BLOCK_END +#elif defined(lzo_memops_tcheck__) +#define LZO_MEMOPS_COPY8(dd,ss) \ + LZO_BLOCK_BEGIN if (lzo_memops_tcheck__(lzo_memops_TU8,8,1)) { \ + * (lzo_memops_TU8p) (lzo_memops_TU0p) (dd) = * (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss); \ + } else { LZO_MEMOPS_MOVE8(dd,ss); } LZO_BLOCK_END +#else +#define LZO_MEMOPS_COPY8(dd,ss) LZO_MEMOPS_MOVE8(dd,ss) +#endif +#endif +#define LZO_MEMOPS_COPYN(dd,ss,nn) \ + LZO_BLOCK_BEGIN \ + lzo_memops_TU1p d__n = (lzo_memops_TU1p) (lzo_memops_TU0p) (dd); \ + const lzo_memops_TU1p s__n = (const lzo_memops_TU1p) (const lzo_memops_TU0p) (ss); \ + lzo_uint n__n = (nn); \ + while ((void)0, n__n >= 8) { LZO_MEMOPS_COPY8(d__n, s__n); d__n += 8; s__n += 8; n__n -= 8; } \ + if ((void)0, n__n >= 4) { LZO_MEMOPS_COPY4(d__n, s__n); d__n += 4; s__n += 4; n__n -= 4; } \ + if ((void)0, n__n > 0) do { *d__n++ = *s__n++; } while (--n__n > 0); \ + LZO_BLOCK_END + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_le16(const lzo_voidp ss) +{ + lzo_uint16_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(&v, ss); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU2p s = (const lzo_memops_TU2p) ss; + unsigned long vv; + __asm__("lhbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint16_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint16_t) (((lzo_uint16_t)s[0]) | ((lzo_uint16_t)s[1] << 8)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_LE16(ss) lzo_memops_get_le16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_le32(const lzo_voidp ss) +{ + lzo_uint32_t v; +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(&v, ss); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + const lzo_memops_TU4p s = (const lzo_memops_TU4p) ss; + unsigned long vv; + __asm__("lwbrx %0,0,%1" : "=r" (vv) : "r" (s), "m" (*s)); + v = (lzo_uint32_t) vv; +#else + const lzo_memops_TU1p s = (const lzo_memops_TU1p) ss; + v = (lzo_uint32_t) (((lzo_uint32_t)s[0]) | ((lzo_uint32_t)s[1] << 8) | ((lzo_uint32_t)s[2] << 16) | ((lzo_uint32_t)s[3] << 24)); +#endif + return v; +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_LE32(ss) lzo_memops_get_le32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_GET_LE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) +#endif + +__lzo_static_forceinline lzo_uint16_t lzo_memops_get_ne16(const lzo_voidp ss) +{ + lzo_uint16_t v; + LZO_MEMOPS_COPY2(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED16) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU2p)0)==2) +#define LZO_MEMOPS_GET_NE16(ss) (* (const lzo_memops_TU2p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_NE16(ss) lzo_memops_get_ne16(ss) +#endif + +__lzo_static_forceinline lzo_uint32_t lzo_memops_get_ne32(const lzo_voidp ss) +{ + lzo_uint32_t v; + LZO_MEMOPS_COPY4(&v, ss); + return v; +} +#if (LZO_OPT_UNALIGNED32) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU4p)0)==4) +#define LZO_MEMOPS_GET_NE32(ss) (* (const lzo_memops_TU4p) (const lzo_memops_TU0p) (ss)) +#else +#define LZO_MEMOPS_GET_NE32(ss) lzo_memops_get_ne32(ss) +#endif + +#if (LZO_OPT_UNALIGNED64) +LZO_COMPILE_TIME_ASSERT_HEADER(sizeof(*(lzo_memops_TU8p)0)==8) +#define LZO_MEMOPS_GET_NE64(ss) (* (const lzo_memops_TU8p) (const lzo_memops_TU0p) (ss)) +#endif + +__lzo_static_forceinline void lzo_memops_put_le16(lzo_voidp dd, lzo_uint16_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY2(dd, &vv); +#elif (LZO_OPT_UNALIGNED16 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU2p d = (lzo_memops_TU2p) dd; + unsigned long v = vv; + __asm__("sthbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE16(dd,vv) lzo_memops_put_le16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_le32(lzo_voidp dd, lzo_uint32_t vv) +{ +#if (LZO_ABI_LITTLE_ENDIAN) + LZO_MEMOPS_COPY4(dd, &vv); +#elif (LZO_OPT_UNALIGNED32 && LZO_ARCH_POWERPC && LZO_ABI_BIG_ENDIAN) && (LZO_ASM_SYNTAX_GNUC) + lzo_memops_TU4p d = (lzo_memops_TU4p) dd; + unsigned long v = vv; + __asm__("stwbrx %2,0,%1" : "=m" (*d) : "r" (d), "r" (v)); +#else + lzo_memops_TU1p d = (lzo_memops_TU1p) dd; + d[0] = LZO_BYTE((vv ) & 0xff); + d[1] = LZO_BYTE((vv >> 8) & 0xff); + d[2] = LZO_BYTE((vv >> 16) & 0xff); + d[3] = LZO_BYTE((vv >> 24) & 0xff); +#endif +} +#if (LZO_OPT_UNALIGNED32) && (LZO_ABI_LITTLE_ENDIAN) +#define LZO_MEMOPS_PUT_LE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_LE32(dd,vv) lzo_memops_put_le32(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne16(lzo_voidp dd, lzo_uint16_t vv) +{ + LZO_MEMOPS_COPY2(dd, &vv); +} +#if (LZO_OPT_UNALIGNED16) +#define LZO_MEMOPS_PUT_NE16(dd,vv) (* (lzo_memops_TU2p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE16(dd,vv) lzo_memops_put_ne16(dd,vv) +#endif + +__lzo_static_forceinline void lzo_memops_put_ne32(lzo_voidp dd, lzo_uint32_t vv) +{ + LZO_MEMOPS_COPY4(dd, &vv); +} +#if (LZO_OPT_UNALIGNED32) +#define LZO_MEMOPS_PUT_NE32(dd,vv) (* (lzo_memops_TU4p) (lzo_memops_TU0p) (dd) = (vv)) +#else +#define LZO_MEMOPS_PUT_NE32(dd,vv) lzo_memops_put_ne32(dd,vv) +#endif + +lzo_unused_funcs_impl(void, lzo_memops_unused_funcs)(void) +{ + LZO_UNUSED_FUNC(lzo_memops_unused_funcs); + LZO_UNUSED_FUNC(lzo_memops_get_le16); + LZO_UNUSED_FUNC(lzo_memops_get_le32); + LZO_UNUSED_FUNC(lzo_memops_get_ne16); + LZO_UNUSED_FUNC(lzo_memops_get_ne32); + LZO_UNUSED_FUNC(lzo_memops_put_le16); + LZO_UNUSED_FUNC(lzo_memops_put_le32); + LZO_UNUSED_FUNC(lzo_memops_put_ne16); + LZO_UNUSED_FUNC(lzo_memops_put_ne32); +} + +#endif + +#ifndef UA_SET1 +#define UA_SET1 LZO_MEMOPS_SET1 +#endif +#ifndef UA_SET2 +#define UA_SET2 LZO_MEMOPS_SET2 +#endif +#ifndef UA_SET3 +#define UA_SET3 LZO_MEMOPS_SET3 +#endif +#ifndef UA_SET4 +#define UA_SET4 LZO_MEMOPS_SET4 +#endif +#ifndef UA_MOVE1 +#define UA_MOVE1 LZO_MEMOPS_MOVE1 +#endif +#ifndef UA_MOVE2 +#define UA_MOVE2 LZO_MEMOPS_MOVE2 +#endif +#ifndef UA_MOVE3 +#define UA_MOVE3 LZO_MEMOPS_MOVE3 +#endif +#ifndef UA_MOVE4 +#define UA_MOVE4 LZO_MEMOPS_MOVE4 +#endif +#ifndef UA_MOVE8 +#define UA_MOVE8 LZO_MEMOPS_MOVE8 +#endif +#ifndef UA_COPY1 +#define UA_COPY1 LZO_MEMOPS_COPY1 +#endif +#ifndef UA_COPY2 +#define UA_COPY2 LZO_MEMOPS_COPY2 +#endif +#ifndef UA_COPY3 +#define UA_COPY3 LZO_MEMOPS_COPY3 +#endif +#ifndef UA_COPY4 +#define UA_COPY4 LZO_MEMOPS_COPY4 +#endif +#ifndef UA_COPY8 +#define UA_COPY8 LZO_MEMOPS_COPY8 +#endif +#ifndef UA_COPYN +#define UA_COPYN LZO_MEMOPS_COPYN +#endif +#ifndef UA_COPYN_X +#define UA_COPYN_X LZO_MEMOPS_COPYN +#endif +#ifndef UA_GET_LE16 +#define UA_GET_LE16 LZO_MEMOPS_GET_LE16 +#endif +#ifndef UA_GET_LE32 +#define UA_GET_LE32 LZO_MEMOPS_GET_LE32 +#endif +#ifdef LZO_MEMOPS_GET_LE64 +#ifndef UA_GET_LE64 +#define UA_GET_LE64 LZO_MEMOPS_GET_LE64 +#endif +#endif +#ifndef UA_GET_NE16 +#define UA_GET_NE16 LZO_MEMOPS_GET_NE16 +#endif +#ifndef UA_GET_NE32 +#define UA_GET_NE32 LZO_MEMOPS_GET_NE32 +#endif +#ifdef LZO_MEMOPS_GET_NE64 +#ifndef UA_GET_NE64 +#define UA_GET_NE64 LZO_MEMOPS_GET_NE64 +#endif +#endif +#ifndef UA_PUT_LE16 +#define UA_PUT_LE16 LZO_MEMOPS_PUT_LE16 +#endif +#ifndef UA_PUT_LE32 +#define UA_PUT_LE32 LZO_MEMOPS_PUT_LE32 +#endif +#ifndef UA_PUT_NE16 +#define UA_PUT_NE16 LZO_MEMOPS_PUT_NE16 +#endif +#ifndef UA_PUT_NE32 +#define UA_PUT_NE32 LZO_MEMOPS_PUT_NE32 +#endif + +#define MEMCPY8_DS(dest,src,len) \ + lzo_memcpy(dest,src,len); dest += len; src += len + +#define BZERO8_PTR(s,l,n) \ + lzo_memset((lzo_voidp)(s),0,(lzo_uint)(l)*(n)) + +#define MEMCPY_DS(dest,src,len) \ + do *dest++ = *src++; while (--len > 0) + +LZO_EXTERN(const lzo_bytep) lzo_copyright(void); + +#ifndef __LZO_PTR_H +#define __LZO_PTR_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if (LZO_ARCH_I086) +#error "LZO_ARCH_I086 is unsupported" +#elif (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#else +#define PTR(a) ((lzo_uintptr_t) (a)) +#define PTR_LINEAR(a) PTR(a) +#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0) +#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0) +#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0) +#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0) +#endif + +#define PTR_LT(a,b) (PTR(a) < PTR(b)) +#define PTR_GE(a,b) (PTR(a) >= PTR(b)) +#define PTR_DIFF(a,b) (PTR(a) - PTR(b)) +#define pd(a,b) ((lzo_uint) ((a)-(b))) + +LZO_EXTERN(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr); + +typedef union +{ + char a_char; + unsigned char a_uchar; + short a_short; + unsigned short a_ushort; + int a_int; + unsigned int a_uint; + long a_long; + unsigned long a_ulong; + lzo_int a_lzo_int; + lzo_uint a_lzo_uint; + lzo_xint a_lzo_xint; + lzo_int16_t a_lzo_int16_t; + lzo_uint16_t a_lzo_uint16_t; + lzo_int32_t a_lzo_int32_t; + lzo_uint32_t a_lzo_uint32_t; +#if defined(lzo_uint64_t) + lzo_int64_t a_lzo_int64_t; + lzo_uint64_t a_lzo_uint64_t; +#endif + size_t a_size_t; + ptrdiff_t a_ptrdiff_t; + lzo_uintptr_t a_lzo_uintptr_t; + void * a_void_p; + char * a_char_p; + unsigned char * a_uchar_p; + const void * a_c_void_p; + const char * a_c_char_p; + const unsigned char * a_c_uchar_p; + lzo_voidp a_lzo_voidp; + lzo_bytep a_lzo_bytep; + const lzo_voidp a_c_lzo_voidp; + const lzo_bytep a_c_lzo_bytep; +} +lzo_full_align_t; + +#ifdef __cplusplus +} +#endif + +#endif + +#ifndef LZO_DETERMINISTIC +#define LZO_DETERMINISTIC 1 +#endif + +#ifndef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 1 +#endif + +#if (LZO_DICT_USE_PTR) +# define lzo_dict_t const lzo_bytep +# define lzo_dict_p lzo_dict_t * +#else +# define lzo_dict_t lzo_uint +# define lzo_dict_p lzo_dict_t * +#endif + +#endif + +#if !defined(MINILZO_CFG_SKIP_LZO_PTR) + +LZO_PUBLIC(lzo_uintptr_t) +__lzo_ptr_linear(const lzo_voidp ptr) +{ + lzo_uintptr_t p; + +#if (LZO_ARCH_I086) +#error "LZO_ARCH_I086 is unsupported" +#elif (LZO_MM_PVP) +#error "LZO_MM_PVP is unsupported" +#else + p = (lzo_uintptr_t) PTR_LINEAR(ptr); +#endif + + return p; +} + +LZO_PUBLIC(unsigned) +__lzo_align_gap(const lzo_voidp ptr, lzo_uint size) +{ +#if (__LZO_UINTPTR_T_IS_POINTER) +#error "__LZO_UINTPTR_T_IS_POINTER is unsupported" +#else + lzo_uintptr_t p, n; + if (size < 2) return 0; + p = __lzo_ptr_linear(ptr); +#if 0 + n = (((p + size - 1) / size) * size) - p; +#else + if ((size & (size - 1)) != 0) + return 0; + n = size; n = ((p + n - 1) & ~(n - 1)) - p; +#endif +#endif + assert((long)n >= 0); + assert(n <= size); + return (unsigned)n; +} + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_UTIL) + +/* If you use the LZO library in a product, I would appreciate that you + * keep this copyright string in the executable of your product. + */ + +static const char lzo_copyright_[] = +#if !defined(__LZO_IN_MINLZO) + LZO_VERSION_STRING; +#else + "\r\n\n" + "LZO data compression library.\n" + "$Copyright: LZO Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer\n" + "\n" + "http://www.oberhumer.com $\n\n" + "$Id: LZO version: v" LZO_VERSION_STRING ", " LZO_VERSION_DATE " $\n" + "$Info: " LZO_INFO_STRING " $\n"; +#endif +static const char lzo_version_string_[] = LZO_VERSION_STRING; +static const char lzo_version_date_[] = LZO_VERSION_DATE; + +LZO_PUBLIC(const lzo_bytep) +lzo_copyright(void) +{ + return (const lzo_bytep) lzo_copyright_; +} + +LZO_PUBLIC(unsigned) +lzo_version(void) +{ + return LZO_VERSION; +} + +LZO_PUBLIC(const char *) +lzo_version_string(void) +{ + return lzo_version_string_; +} + +LZO_PUBLIC(const char *) +lzo_version_date(void) +{ + return lzo_version_date_; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_string(void) +{ + return lzo_version_string_; +} + +LZO_PUBLIC(const lzo_charp) +_lzo_version_date(void) +{ + return lzo_version_date_; +} + +#define LZO_BASE 65521u +#define LZO_NMAX 5552 + +#define LZO_DO1(buf,i) s1 += buf[i]; s2 += s1 +#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1) +#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2) +#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4) +#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8) + +LZO_PUBLIC(lzo_uint32_t) +lzo_adler32(lzo_uint32_t adler, const lzo_bytep buf, lzo_uint len) +{ + lzo_uint32_t s1 = adler & 0xffff; + lzo_uint32_t s2 = (adler >> 16) & 0xffff; + unsigned k; + + if (buf == NULL) + return 1; + + while (len > 0) + { + k = len < LZO_NMAX ? (unsigned) len : LZO_NMAX; + len -= k; + if (k >= 16) do + { + LZO_DO16(buf,0); + buf += 16; + k -= 16; + } while (k >= 16); + if (k != 0) do + { + s1 += *buf++; + s2 += s1; + } while (--k > 0); + s1 %= LZO_BASE; + s2 %= LZO_BASE; + } + return (s2 << 16) | s1; +} + +#undef LZO_DO1 +#undef LZO_DO2 +#undef LZO_DO4 +#undef LZO_DO8 +#undef LZO_DO16 + +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_STRING) +#undef lzo_memcmp +#undef lzo_memcpy +#undef lzo_memmove +#undef lzo_memset +#if !defined(__LZO_MMODEL_HUGE) +# undef LZO_HAVE_MM_HUGE_PTR +#endif +#define lzo_hsize_t lzo_uint +#define lzo_hvoid_p lzo_voidp +#define lzo_hbyte_p lzo_bytep +#define LZOLIB_PUBLIC(r,f) LZO_PUBLIC(r) f +#define lzo_hmemcmp lzo_memcmp +#define lzo_hmemcpy lzo_memcpy +#define lzo_hmemmove lzo_memmove +#define lzo_hmemset lzo_memset +#define __LZOLIB_HMEMCPY_CH_INCLUDED 1 +#if !defined(LZOLIB_PUBLIC) +# define LZOLIB_PUBLIC(r,f) r __LZOLIB_FUNCNAME(f) +#endif +LZOLIB_PUBLIC(int, lzo_hmemcmp) (const lzo_hvoid_p s1, const lzo_hvoid_p s2, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCMP) + const lzo_hbyte_p p1 = LZO_STATIC_CAST(const lzo_hbyte_p, s1); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, s2); + if __lzo_likely(len > 0) do + { + int d = *p1 - *p2; + if (d != 0) + return d; + p1++; p2++; + } while __lzo_likely(--len > 0); + return 0; +#else + return memcmp(s1, s2, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemcpy) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMCPY) + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); + if (!(len > 0) || p1 == p2) + return dest; + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + return dest; +#else + return memcpy(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemmove) (lzo_hvoid_p dest, const lzo_hvoid_p src, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMMOVE) + lzo_hbyte_p p1 = LZO_STATIC_CAST(lzo_hbyte_p, dest); + const lzo_hbyte_p p2 = LZO_STATIC_CAST(const lzo_hbyte_p, src); + if (!(len > 0) || p1 == p2) + return dest; + if (p1 < p2) + { + do + *p1++ = *p2++; + while __lzo_likely(--len > 0); + } + else + { + p1 += len; + p2 += len; + do + *--p1 = *--p2; + while __lzo_likely(--len > 0); + } + return dest; +#else + return memmove(dest, src, len); +#endif +} +LZOLIB_PUBLIC(lzo_hvoid_p, lzo_hmemset) (lzo_hvoid_p s, int cc, lzo_hsize_t len) +{ +#if (LZO_HAVE_MM_HUGE_PTR) || !(HAVE_MEMSET) + lzo_hbyte_p p = LZO_STATIC_CAST(lzo_hbyte_p, s); + unsigned char c = LZO_ITRUNC(unsigned char, cc); + if __lzo_likely(len > 0) do + *p++ = c; + while __lzo_likely(--len > 0); + return s; +#else + return memset(s, cc, len); +#endif +} +#undef LZOLIB_PUBLIC +#endif +#if !defined(MINILZO_CFG_SKIP_LZO_INIT) + +#if !defined(__LZO_IN_MINILZO) + +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT + + LZOCHK_ASSERT((LZO_UINT32_C(1) << (int)(8*sizeof(LZO_UINT32_C(1))-1)) > 0) + LZOCHK_ASSERT_IS_SIGNED_T(lzo_int) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uint) +#if !(__LZO_UINTPTR_T_IS_POINTER) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_uintptr_t) +#endif + LZOCHK_ASSERT(sizeof(lzo_uintptr_t) >= sizeof(lzo_voidp)) + LZOCHK_ASSERT_IS_UNSIGNED_T(lzo_xint) + +#endif +#undef LZOCHK_ASSERT + +union lzo_config_check_union { + lzo_uint a[2]; + unsigned char b[2*LZO_MAX(8,sizeof(lzo_uint))]; +#if defined(lzo_uint64_t) + lzo_uint64_t c[2]; +#endif +}; + +#if 0 +#define u2p(ptr,off) ((lzo_voidp) (((lzo_bytep)(lzo_voidp)(ptr)) + (off))) +#else +static __lzo_noinline lzo_voidp u2p(lzo_voidp ptr, lzo_uint off) +{ + return (lzo_voidp) ((lzo_bytep) ptr + off); +} +#endif + +LZO_PUBLIC(int) +_lzo_config_check(void) +{ +#if (LZO_CC_CLANG && (LZO_CC_CLANG >= 0x030100ul && LZO_CC_CLANG < 0x030300ul)) +# if 0 + volatile +# endif +#endif + union lzo_config_check_union u; + lzo_voidp p; + unsigned r = 1; + + u.a[0] = u.a[1] = 0; + p = u2p(&u, 0); + r &= ((* (lzo_bytep) p) == 0); +#if !(LZO_CFG_NO_CONFIG_CHECK) +#if (LZO_ABI_BIG_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[sizeof(lzo_uint) - 1] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + u.a[0] = u.a[1] = 0; u.b[0] = 128; + p = u2p(&u, 0); + r &= ((* (lzo_uintp) p) == 128); +#endif + u.a[0] = u.a[1] = 0; + u.b[0] = 1; u.b[3] = 2; + p = u2p(&u, 1); + r &= UA_GET_NE16(p) == 0; + r &= UA_GET_LE16(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE16(p) == 128; + u.b[2] = 129; + r &= UA_GET_LE16(p) == LZO_UINT16_C(0x8180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8081); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE16(p) == LZO_UINT16_C(0x8180); +#endif + u.a[0] = u.a[1] = 0; + u.b[0] = 3; u.b[5] = 4; + p = u2p(&u, 1); + r &= UA_GET_NE32(p) == 0; + r &= UA_GET_LE32(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE32(p) == 128; + u.b[2] = 129; u.b[3] = 130; u.b[4] = 131; + r &= UA_GET_LE32(p) == LZO_UINT32_C(0x83828180); +#if (LZO_ABI_BIG_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x80818283); +#endif +#if (LZO_ABI_LITTLE_ENDIAN) + r &= UA_GET_NE32(p) == LZO_UINT32_C(0x83828180); +#endif +#if defined(UA_GET_NE64) + u.c[0] = u.c[1] = 0; + u.b[0] = 5; u.b[9] = 6; + p = u2p(&u, 1); + u.c[0] = u.c[1] = 0; + r &= UA_GET_NE64(p) == 0; +#if defined(UA_GET_LE64) + r &= UA_GET_LE64(p) == 0; + u.b[1] = 128; + r &= UA_GET_LE64(p) == 128; +#endif +#endif +#if defined(lzo_bitops_ctlz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz32(v) == 31 - i; + r &= lzo_bitops_ctlz32_func(v) == 31 - i; + }} +#endif +#if defined(lzo_bitops_ctlz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_ctlz64(v) == 63 - i; + r &= lzo_bitops_ctlz64_func(v) == 63 - i; + }} +#endif +#if defined(lzo_bitops_cttz32) + { unsigned i = 0; lzo_uint32_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz32(v) == i; + r &= lzo_bitops_cttz32_func(v) == i; + }} +#endif +#if defined(lzo_bitops_cttz64) + { unsigned i = 0; lzo_uint64_t v; + for (v = 1; v != 0 && r == 1; v <<= 1, i++) { + r &= lzo_bitops_cttz64(v) == i; + r &= lzo_bitops_cttz64_func(v) == i; + }} +#endif +#endif + LZO_UNUSED_FUNC(lzo_bitops_unused_funcs); + + return r == 1 ? LZO_E_OK : LZO_E_ERROR; +} + +LZO_PUBLIC(int) +__lzo_init_v2(unsigned v, int s1, int s2, int s3, int s4, int s5, + int s6, int s7, int s8, int s9) +{ + int r; + +#if defined(__LZO_IN_MINILZO) +#elif (LZO_CC_MSC && ((_MSC_VER) < 700)) +#else +#define LZO_WANT_ACC_CHK_CH 1 +#undef LZOCHK_ASSERT +#define LZOCHK_ASSERT(expr) LZO_COMPILE_TIME_ASSERT(expr) +#endif +#undef LZOCHK_ASSERT + + if (v == 0) + return LZO_E_ERROR; + + r = (s1 == -1 || s1 == (int) sizeof(short)) && + (s2 == -1 || s2 == (int) sizeof(int)) && + (s3 == -1 || s3 == (int) sizeof(long)) && + (s4 == -1 || s4 == (int) sizeof(lzo_uint32_t)) && + (s5 == -1 || s5 == (int) sizeof(lzo_uint)) && + (s6 == -1 || s6 == (int) lzo_sizeof_dict_t) && + (s7 == -1 || s7 == (int) sizeof(char *)) && + (s8 == -1 || s8 == (int) sizeof(lzo_voidp)) && + (s9 == -1 || s9 == (int) sizeof(lzo_callback_t)); + if (!r) + return LZO_E_ERROR; + + r = _lzo_config_check(); + if (r != LZO_E_OK) + return r; + + return r; +} + +#if !defined(__LZO_IN_MINILZO) + +#if (LZO_OS_WIN16 && LZO_CC_WATCOMC) && defined(__SW_BD) + +#if 0 +BOOL FAR PASCAL LibMain ( HANDLE hInstance, WORD wDataSegment, + WORD wHeapSize, LPSTR lpszCmdLine ) +#else +int __far __pascal LibMain ( int a, short b, short c, long d ) +#endif +{ + LZO_UNUSED(a); LZO_UNUSED(b); LZO_UNUSED(c); LZO_UNUSED(d); + return 1; +} + +#endif + +#endif + +#endif + +#define LZO1X 1 +#define LZO_EOF_CODE 1 +#define M2_MAX_OFFSET 0x0800 + +#if !defined(MINILZO_CFG_SKIP_LZO1X_1_COMPRESS) + +#if 1 && defined(UA_GET_LE32) +#undef LZO_DICT_USE_PTR +#define LZO_DICT_USE_PTR 0 +#undef lzo_dict_t +#define lzo_dict_t lzo_uint16_t +#endif + +#define LZO_NEED_DICT_H 1 +#ifndef D_BITS +#define D_BITS 14 +#endif +#define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5) +#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f) +#if 1 +#define DINDEX(dv,p) DM(((DMUL(0x1824429d,dv)) >> (32-D_BITS))) +#else +#define DINDEX(dv,p) DM((dv) + ((dv) >> (32-D_BITS))) +#endif + +#ifndef __LZO_CONFIG1X_H +#define __LZO_CONFIG1X_H 1 + +#if !defined(LZO1X) && !defined(LZO1Y) && !defined(LZO1Z) +# define LZO1X 1 +#endif + +#if !defined(__LZO_IN_MINILZO) +#include +#endif + +#ifndef LZO_EOF_CODE +#define LZO_EOF_CODE 1 +#endif +#undef LZO_DETERMINISTIC + +#define M1_MAX_OFFSET 0x0400 +#ifndef M2_MAX_OFFSET +#define M2_MAX_OFFSET 0x0800 +#endif +#define M3_MAX_OFFSET 0x4000 +#define M4_MAX_OFFSET 0xbfff + +#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET) + +#define M1_MIN_LEN 2 +#define M1_MAX_LEN 2 +#define M2_MIN_LEN 3 +#ifndef M2_MAX_LEN +#define M2_MAX_LEN 8 +#endif +#define M3_MIN_LEN 3 +#define M3_MAX_LEN 33 +#define M4_MIN_LEN 3 +#define M4_MAX_LEN 9 + +#define M1_MARKER 0 +#define M2_MARKER 64 +#define M3_MARKER 32 +#define M4_MARKER 16 + +#ifndef MIN_LOOKAHEAD +#define MIN_LOOKAHEAD (M2_MAX_LEN + 1) +#endif + +#if defined(LZO_NEED_DICT_H) + +#ifndef LZO_HASH +#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B +#endif +#define DL_MIN_LEN M2_MIN_LEN + +#ifndef __LZO_DICT_H +#define __LZO_DICT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(D_BITS) && defined(DBITS) +# define D_BITS DBITS +#endif +#if !defined(D_BITS) +# error "D_BITS is not defined" +#endif +#if (D_BITS < 16) +# define D_SIZE LZO_SIZE(D_BITS) +# define D_MASK LZO_MASK(D_BITS) +#else +# define D_SIZE LZO_USIZE(D_BITS) +# define D_MASK LZO_UMASK(D_BITS) +#endif +#define D_HIGH ((D_MASK >> 1) + 1) + +#if !defined(DD_BITS) +# define DD_BITS 0 +#endif +#define DD_SIZE LZO_SIZE(DD_BITS) +#define DD_MASK LZO_MASK(DD_BITS) + +#if !defined(DL_BITS) +# define DL_BITS (D_BITS - DD_BITS) +#endif +#if (DL_BITS < 16) +# define DL_SIZE LZO_SIZE(DL_BITS) +# define DL_MASK LZO_MASK(DL_BITS) +#else +# define DL_SIZE LZO_USIZE(DL_BITS) +# define DL_MASK LZO_UMASK(DL_BITS) +#endif + +#if (D_BITS != DL_BITS + DD_BITS) +# error "D_BITS does not match" +#endif +#if (D_BITS < 6 || D_BITS > 18) +# error "invalid D_BITS" +#endif +#if (DL_BITS < 6 || DL_BITS > 20) +# error "invalid DL_BITS" +#endif +#if (DD_BITS < 0 || DD_BITS > 6) +# error "invalid DD_BITS" +#endif + +#if !defined(DL_MIN_LEN) +# define DL_MIN_LEN 3 +#endif +#if !defined(DL_SHIFT) +# define DL_SHIFT ((DL_BITS + (DL_MIN_LEN - 1)) / DL_MIN_LEN) +#endif + +#define LZO_HASH_GZIP 1 +#define LZO_HASH_GZIP_INCREMENTAL 2 +#define LZO_HASH_LZO_INCREMENTAL_A 3 +#define LZO_HASH_LZO_INCREMENTAL_B 4 + +#if !defined(LZO_HASH) +# error "choose a hashing strategy" +#endif + +#undef DM +#undef DX + +#if (DL_MIN_LEN == 3) +# define _DV2_A(p,shift1,shift2) \ + (((( (lzo_xint)((p)[0]) << shift1) ^ (p)[1]) << shift2) ^ (p)[2]) +# define _DV2_B(p,shift1,shift2) \ + (((( (lzo_xint)((p)[2]) << shift1) ^ (p)[1]) << shift2) ^ (p)[0]) +# define _DV3_B(p,shift1,shift2,shift3) \ + ((_DV2_B((p)+1,shift1,shift2) << (shift3)) ^ (p)[0]) +#elif (DL_MIN_LEN == 2) +# define _DV2_A(p,shift1,shift2) \ + (( (lzo_xint)(p[0]) << shift1) ^ p[1]) +# define _DV2_B(p,shift1,shift2) \ + (( (lzo_xint)(p[1]) << shift1) ^ p[2]) +#else +# error "invalid DL_MIN_LEN" +#endif +#define _DV_A(p,shift) _DV2_A(p,shift,shift) +#define _DV_B(p,shift) _DV2_B(p,shift,shift) +#define DA2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) + (p)[1]) << (s1)) + (p)[0]) +#define DS2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) - (p)[1]) << (s1)) - (p)[0]) +#define DX2(p,s1,s2) \ + (((((lzo_xint)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0]) +#define DA3(p,s1,s2,s3) ((DA2((p)+1,s2,s3) << (s1)) + (p)[0]) +#define DS3(p,s1,s2,s3) ((DS2((p)+1,s2,s3) << (s1)) - (p)[0]) +#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0]) +#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s))) +#define DM(v) DMS(v,0) + +#if (LZO_HASH == LZO_HASH_GZIP) +# define _DINDEX(dv,p) (_DV_A((p),DL_SHIFT)) + +#elif (LZO_HASH == LZO_HASH_GZIP_INCREMENTAL) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),DL_SHIFT) +# define DVAL_NEXT(dv,p) dv = (((dv) << DL_SHIFT) ^ p[2]) +# define _DINDEX(dv,p) (dv) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_A) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_A((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= (lzo_xint)(p[-1]) << (2*5); dv = (((dv) << 5) ^ p[2]) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#elif (LZO_HASH == LZO_HASH_LZO_INCREMENTAL_B) +# define __LZO_HASH_INCREMENTAL 1 +# define DVAL_FIRST(dv,p) dv = _DV_B((p),5) +# define DVAL_NEXT(dv,p) \ + dv ^= p[-1]; dv = (((dv) >> 5) ^ ((lzo_xint)(p[2]) << (2*5))) +# define _DINDEX(dv,p) ((DMUL(0x9f5f,dv)) >> 5) +# define DVAL_LOOKAHEAD DL_MIN_LEN + +#else +# error "choose a hashing strategy" +#endif + +#ifndef DINDEX +#define DINDEX(dv,p) ((lzo_uint)((_DINDEX(dv,p)) & DL_MASK) << DD_BITS) +#endif +#if !defined(DINDEX1) && defined(D_INDEX1) +#define DINDEX1 D_INDEX1 +#endif +#if !defined(DINDEX2) && defined(D_INDEX2) +#define DINDEX2 D_INDEX2 +#endif + +#if !defined(__LZO_HASH_INCREMENTAL) +# define DVAL_FIRST(dv,p) ((void) 0) +# define DVAL_NEXT(dv,p) ((void) 0) +# define DVAL_LOOKAHEAD 0 +#endif + +#if !defined(DVAL_ASSERT) +#if defined(__LZO_HASH_INCREMENTAL) && !defined(NDEBUG) +#if 1 && (LZO_CC_ARMCC_GNUC || LZO_CC_CLANG || (LZO_CC_GNUC >= 0x020700ul) || LZO_CC_INTELC_GNUC || LZO_CC_LLVM || LZO_CC_PATHSCALE || LZO_CC_PGI) +static void __attribute__((__unused__)) +#else +static void +#endif +DVAL_ASSERT(lzo_xint dv, const lzo_bytep p) +{ + lzo_xint df; + DVAL_FIRST(df,(p)); + assert(DINDEX(dv,p) == DINDEX(df,p)); +} +#else +# define DVAL_ASSERT(dv,p) ((void) 0) +#endif +#endif + +#if (LZO_DICT_USE_PTR) +# define DENTRY(p,in) (p) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex] +#else +# define DENTRY(p,in) ((lzo_dict_t) pd(p, in)) +# define GINDEX(m_pos,m_off,dict,dindex,in) m_off = dict[dindex] +#endif + +#if (DD_BITS == 0) + +# define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in) +# define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in) +# define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in) + +#else + +# define UPDATE_D(dict,drun,dv,p,in) \ + dict[ DINDEX(dv,p) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_I(dict,drun,index,p,in) \ + dict[ (index) + drun++ ] = DENTRY(p,in); drun &= DD_MASK +# define UPDATE_P(ptr,drun,p,in) \ + (ptr) [ drun++ ] = DENTRY(p,in); drun &= DD_MASK + +#endif + +#if (LZO_DICT_USE_PTR) + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_pos == NULL || (m_off = pd(ip, m_pos)) > max_offset) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (BOUNDS_CHECKING_OFF_IN_EXPR(( \ + m_pos = ip - (lzo_uint) PTR_DIFF(ip,m_pos), \ + PTR_LT(m_pos,in) || \ + (m_off = (lzo_uint) PTR_DIFF(ip,m_pos)) == 0 || \ + m_off > max_offset ))) + +#else + +#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \ + (m_off == 0 || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \ + (pd(ip, in) <= m_off || \ + ((m_off = pd(ip, in) - m_off) > max_offset) || \ + (m_pos = (ip) - (m_off), 0) ) + +#endif + +#if (LZO_DETERMINISTIC) +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_DET +#else +# define LZO_CHECK_MPOS LZO_CHECK_MPOS_NON_DET +#endif + +#ifdef __cplusplus +} +#endif + +#endif + +#endif + +#endif + +#define LZO_DETERMINISTIC !(LZO_DICT_USE_PTR) + +#ifndef DO_COMPRESS +#define DO_COMPRESS lzo1x_1_compress +#endif + +#if 1 && defined(DO_COMPRESS) && !defined(do_compress) +# define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) +#endif + +static __lzo_noinline lzo_uint +do_compress ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_uint ti, lzo_voidp wrkmem) +{ + const lzo_bytep ip; + lzo_bytep op; + const lzo_bytep const in_end = in + in_len; + const lzo_bytep const ip_end = in + in_len - 20; + const lzo_bytep ii; + lzo_dict_p const dict = (lzo_dict_p) wrkmem; + + op = out; + ip = in; + ii = ip; + + ip += ti < 4 ? 4 - ti : 0; + for (;;) + { + const lzo_bytep m_pos; +#if !(LZO_DETERMINISTIC) + LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); + lzo_uint m_len; + lzo_uint dindex; +next: + if __lzo_unlikely(ip >= ip_end) + break; + DINDEX1(dindex,ip); + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; +#if 1 + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + DINDEX2(dindex,ip); +#endif + GINDEX(m_pos,m_off,dict,dindex,in); + if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) + goto literal; + if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) + goto try_match; + goto literal; + +try_match: +#if (LZO_OPT_UNALIGNED32) + if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) +#else + if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) +#endif + { +literal: + UPDATE_I(dict,0,dindex,ip,in); + ip += 1 + ((ip - ii) >> 5); + continue; + } + UPDATE_I(dict,0,dindex,ip,in); +#else + lzo_uint m_off; + lzo_uint m_len; + { + lzo_uint32_t dv; + lzo_uint dindex; +literal: + ip += 1 + ((ip - ii) >> 5); +next: + if __lzo_unlikely(ip >= ip_end) + break; + dv = UA_GET_LE32(ip); + dindex = DINDEX(dv,ip); + GINDEX(m_off,m_pos,in+dict,dindex,in); + UPDATE_I(dict,0,dindex,ip,in); + if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) + goto literal; + } +#endif + + ii -= ti; ti = 0; + { + lzo_uint t = pd(ip,ii); + if (t != 0) + { + if (t <= 3) + { + op[-2] = LZO_BYTE(op[-2] | t); +#if (LZO_OPT_UNALIGNED32) + UA_COPY4(op, ii); + op += t; +#else + { do *op++ = *ii++; while (--t > 0); } +#endif + } +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) + else if (t <= 16) + { + *op++ = LZO_BYTE(t - 3); + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); + op += t; + } +#endif + else + { + if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + *op++ = 0; + while __lzo_unlikely(tt > 255) + { + tt -= 255; + UA_SET1(op, 0); + op++; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } +#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) + do { + UA_COPY8(op, ii); + UA_COPY8(op+8, ii+8); + op += 16; ii += 16; t -= 16; + } while (t >= 16); if (t > 0) +#endif + { do *op++ = *ii++; while (--t > 0); } + } + } + } + m_len = 4; + { +#if (LZO_OPT_UNALIGNED64) + lzo_uint64_t v; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 8; + v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) + m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (64 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (64 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) + m_len += lzo_bitops_cttz64(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#elif (LZO_OPT_UNALIGNED32) + lzo_uint32_t v; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if __lzo_unlikely(v == 0) { + do { + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if (v != 0) + break; + m_len += 4; + v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (v == 0); + } +#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) + m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; +#elif (LZO_ABI_BIG_ENDIAN) + if ((v >> (32 - CHAR_BIT)) == 0) do { + v <<= CHAR_BIT; + m_len += 1; + } while ((v >> (32 - CHAR_BIT)) == 0); +#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) + m_len += lzo_bitops_cttz32(v) / CHAR_BIT; +#elif (LZO_ABI_LITTLE_ENDIAN) + if ((v & UCHAR_MAX) == 0) do { + v >>= CHAR_BIT; + m_len += 1; + } while ((v & UCHAR_MAX) == 0); +#else + if (ip[m_len] == m_pos[m_len]) do { + m_len += 1; + } while (ip[m_len] == m_pos[m_len]); +#endif +#else + if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { + do { + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if (ip[m_len] != m_pos[m_len]) + break; + m_len += 1; + if __lzo_unlikely(ip + m_len >= ip_end) + goto m_len_done; + } while (ip[m_len] == m_pos[m_len]); + } +#endif + } +m_len_done: + m_off = pd(ip,m_pos); + ip += m_len; + ii = ip; + if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) + { + m_off -= 1; +#if defined(LZO1X) + *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); + *op++ = LZO_BYTE(m_off >> 3); +#elif defined(LZO1Y) + *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); + *op++ = LZO_BYTE(m_off >> 2); +#endif + } + else if (m_off <= M3_MAX_OFFSET) + { + m_off -= 1; + if (m_len <= M3_MAX_LEN) + *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); + else + { + m_len -= M3_MAX_LEN; + *op++ = M3_MARKER | 0; + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; + UA_SET1(op, 0); + op++; + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + else + { + m_off -= 0x4000; + if (m_len <= M4_MAX_LEN) + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); + else + { + m_len -= M4_MAX_LEN; + *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); + while __lzo_unlikely(m_len > 255) + { + m_len -= 255; + UA_SET1(op, 0); + op++; + } + *op++ = LZO_BYTE(m_len); + } + *op++ = LZO_BYTE(m_off << 2); + *op++ = LZO_BYTE(m_off >> 6); + } + goto next; + } + + *out_len = pd(op, out); + return pd(in_end,ii-ti); +} + +LZO_PUBLIC(int) +DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +{ + const lzo_bytep ip = in; + lzo_bytep op = out; + lzo_uint l = in_len; + lzo_uint t = 0; + + while (l > 20) + { + lzo_uint ll = l; + lzo_uintptr_t ll_end; +#if 0 || (LZO_DETERMINISTIC) + ll = LZO_MIN(ll, 49152); +#endif + ll_end = (lzo_uintptr_t)ip + ll; + if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) + break; +#if (LZO_DETERMINISTIC) + lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); +#endif + t = do_compress(ip,ll,op,out_len,t,wrkmem); + ip += ll; + op += *out_len; + l -= ll; + } + t += l; + + if (t > 0) + { + const lzo_bytep ii = in + in_len - t; + + if (op == out && t <= 238) + *op++ = LZO_BYTE(17 + t); + else if (t <= 3) + op[-2] = LZO_BYTE(op[-2] | t); + else if (t <= 18) + *op++ = LZO_BYTE(t - 3); + else + { + lzo_uint tt = t - 18; + + *op++ = 0; + while (tt > 255) + { + tt -= 255; + UA_SET1(op, 0); + op++; + } + assert(tt > 0); + *op++ = LZO_BYTE(tt); + } + UA_COPYN(op, ii, t); + op += t; + } + + *op++ = M4_MARKER | 1; + *op++ = 0; + *op++ = 0; + + *out_len = pd(op, out); + return LZO_E_OK; +} + +#endif + +#undef do_compress +#undef DO_COMPRESS +#undef LZO_HASH + +#undef LZO_TEST_OVERRUN +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_IP_AND_TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef TEST_IV +#undef TEST_OV +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + NEED_IP(1); + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+3); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + for (;;) + { + NEED_IP(3); + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_IV(t); + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + t += 3; + if (t >= 8) do + { + UA_COPY8(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !(LZO_OPT_UNALIGNED32) + } + else +#endif +#endif +#if !(LZO_OPT_UNALIGNED32) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + for (;;) { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 31 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 7 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY8(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } + } + +eof_found: + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +#define LZO_TEST_OVERRUN 1 +#undef DO_DECOMPRESS +#define DO_DECOMPRESS lzo1x_decompress_safe + +#if !defined(MINILZO_CFG_SKIP_LZO1X_DECOMPRESS_SAFE) + +#if defined(LZO_TEST_OVERRUN) +# if !defined(LZO_TEST_OVERRUN_INPUT) +# define LZO_TEST_OVERRUN_INPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_OUTPUT) +# define LZO_TEST_OVERRUN_OUTPUT 2 +# endif +# if !defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define LZO_TEST_OVERRUN_LOOKBEHIND 1 +# endif +#endif + +#undef TEST_IP +#undef TEST_OP +#undef TEST_IP_AND_TEST_OP +#undef TEST_LB +#undef TEST_LBO +#undef NEED_IP +#undef NEED_OP +#undef TEST_IV +#undef TEST_OV +#undef HAVE_TEST_IP +#undef HAVE_TEST_OP +#undef HAVE_NEED_IP +#undef HAVE_NEED_OP +#undef HAVE_ANY_IP +#undef HAVE_ANY_OP + +#if defined(LZO_TEST_OVERRUN_INPUT) +# if (LZO_TEST_OVERRUN_INPUT >= 1) +# define TEST_IP (ip < ip_end) +# endif +# if (LZO_TEST_OVERRUN_INPUT >= 2) +# define NEED_IP(x) \ + if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun +# define TEST_IV(x) if ((x) > (lzo_uint)0 - (511)) goto input_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_OUTPUT) +# if (LZO_TEST_OVERRUN_OUTPUT >= 1) +# define TEST_OP (op <= op_end) +# endif +# if (LZO_TEST_OVERRUN_OUTPUT >= 2) +# undef TEST_OP +# define NEED_OP(x) \ + if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun +# define TEST_OV(x) if ((x) > (lzo_uint)0 - (511)) goto output_overrun +# endif +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +# define TEST_LB(m_pos) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op)) goto lookbehind_overrun +# define TEST_LBO(m_pos,o) if (PTR_LT(m_pos,out) || PTR_GE(m_pos,op-(o))) goto lookbehind_overrun +#else +# define TEST_LB(m_pos) ((void) 0) +# define TEST_LBO(m_pos,o) ((void) 0) +#endif + +#if !defined(LZO_EOF_CODE) && !defined(TEST_IP) +# define TEST_IP (ip < ip_end) +#endif + +#if defined(TEST_IP) +# define HAVE_TEST_IP 1 +#else +# define TEST_IP 1 +#endif +#if defined(TEST_OP) +# define HAVE_TEST_OP 1 +#else +# define TEST_OP 1 +#endif + +#if defined(HAVE_TEST_IP) && defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP (TEST_IP && TEST_OP) +#elif defined(HAVE_TEST_IP) +# define TEST_IP_AND_TEST_OP TEST_IP +#elif defined(HAVE_TEST_OP) +# define TEST_IP_AND_TEST_OP TEST_OP +#else +# define TEST_IP_AND_TEST_OP 1 +#endif + +#if defined(NEED_IP) +# define HAVE_NEED_IP 1 +#else +# define NEED_IP(x) ((void) 0) +# define TEST_IV(x) ((void) 0) +#endif +#if defined(NEED_OP) +# define HAVE_NEED_OP 1 +#else +# define NEED_OP(x) ((void) 0) +# define TEST_OV(x) ((void) 0) +#endif + +#if defined(HAVE_TEST_IP) || defined(HAVE_NEED_IP) +# define HAVE_ANY_IP 1 +#endif +#if defined(HAVE_TEST_OP) || defined(HAVE_NEED_OP) +# define HAVE_ANY_OP 1 +#endif + +#if defined(DO_DECOMPRESS) +LZO_PUBLIC(int) +DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, + lzo_bytep out, lzo_uintp out_len, + lzo_voidp wrkmem ) +#endif +{ + lzo_bytep op; + const lzo_bytep ip; + lzo_uint t; +#if defined(COPY_DICT) + lzo_uint m_off; + const lzo_bytep dict_end; +#else + const lzo_bytep m_pos; +#endif + + const lzo_bytep const ip_end = in + in_len; +#if defined(HAVE_ANY_OP) + lzo_bytep const op_end = out + *out_len; +#endif +#if defined(LZO1Z) + lzo_uint last_m_off = 0; +#endif + + LZO_UNUSED(wrkmem); + +#if defined(COPY_DICT) + if (dict) + { + if (dict_len > M4_MAX_OFFSET) + { + dict += dict_len - M4_MAX_OFFSET; + dict_len = M4_MAX_OFFSET; + } + dict_end = dict + dict_len; + } + else + { + dict_len = 0; + dict_end = NULL; + } +#endif + + *out_len = 0; + + op = out; + ip = in; + + NEED_IP(1); + if (*ip > 17) + { + t = *ip++ - 17; + if (t < 4) + goto match_next; + assert(t > 0); NEED_OP(t); NEED_IP(t+3); + do *op++ = *ip++; while (--t > 0); + goto first_literal_run; + } + + for (;;) + { + NEED_IP(3); + t = *ip++; + if (t >= 16) + goto match; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_IV(t); + NEED_IP(1); + } + t += 15 + *ip++; + } + assert(t > 0); NEED_OP(t+3); NEED_IP(t+6); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + t += 3; + if (t >= 8) do + { + UA_COPY8(op,ip); + op += 8; ip += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } + if (t > 0) + { + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } + } +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (PTR_ALIGNED2_4(op,ip)) + { +#endif + UA_COPY4(op,ip); + op += 4; ip += 4; + if (--t > 0) + { + if (t >= 4) + { + do { + UA_COPY4(op,ip); + op += 4; ip += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *ip++; while (--t > 0); + } + else + do *op++ = *ip++; while (--t > 0); + } +#if !(LZO_OPT_UNALIGNED32) + } + else +#endif +#endif +#if !(LZO_OPT_UNALIGNED32) + { + *op++ = *ip++; *op++ = *ip++; *op++ = *ip++; + do *op++ = *ip++; while (--t > 0); + } +#endif + +first_literal_run: + + t = *ip++; + if (t >= 16) + goto match; +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(3); + t = 3; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - (1 + M2_MAX_OFFSET); + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(3); + *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + + for (;;) { +match: + if (t >= 64) + { +#if defined(COPY_DICT) +#if defined(LZO1X) + m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3); + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2); + t = (t >> 4) - 3; +#elif defined(LZO1Z) + m_off = t & 0x1f; + if (m_off >= 0x1c) + m_off = last_m_off; + else + { + m_off = 1 + (m_off << 6) + (*ip++ >> 2); + last_m_off = m_off; + } + t = (t >> 5) - 1; +#endif +#else +#if defined(LZO1X) + m_pos = op - 1; + m_pos -= (t >> 2) & 7; + m_pos -= *ip++ << 3; + t = (t >> 5) - 1; +#elif defined(LZO1Y) + m_pos = op - 1; + m_pos -= (t >> 2) & 3; + m_pos -= *ip++ << 2; + t = (t >> 4) - 3; +#elif defined(LZO1Z) + { + lzo_uint off = t & 0x1f; + m_pos = op; + if (off >= 0x1c) + { + assert(last_m_off > 0); + m_pos -= last_m_off; + } + else + { + off = 1 + (off << 6) + (*ip++ >> 2); + m_pos -= off; + last_m_off = off; + } + } + t = (t >> 5) - 1; +#endif + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); + goto copy_match; +#endif + } + else if (t >= 32) + { + t &= 31; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 31 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (ip[0] << 6) + (ip[1] >> 2); + last_m_off = m_off; +#else + m_off = 1 + (ip[0] >> 2) + (ip[1] << 6); +#endif +#else +#if defined(LZO1Z) + { + lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2); + m_pos = op - off; + last_m_off = off; + } +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos = op - 1; + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos = op - 1; + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif +#endif + ip += 2; + } + else if (t >= 16) + { +#if defined(COPY_DICT) + m_off = (t & 8) << 11; +#else + m_pos = op; + m_pos -= (t & 8) << 11; +#endif + t &= 7; + if (t == 0) + { + while (*ip == 0) + { + t += 255; + ip++; + TEST_OV(t); + NEED_IP(1); + } + t += 7 + *ip++; + NEED_IP(2); + } +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off += (ip[0] << 6) + (ip[1] >> 2); +#else + m_off += (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_off == 0) + goto eof_found; + m_off += 0x4000; +#if defined(LZO1Z) + last_m_off = m_off; +#endif +#else +#if defined(LZO1Z) + m_pos -= (ip[0] << 6) + (ip[1] >> 2); +#elif (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN) + m_pos -= UA_GET_LE16(ip) >> 2; +#else + m_pos -= (ip[0] >> 2) + (ip[1] << 6); +#endif + ip += 2; + if (m_pos == op) + goto eof_found; + m_pos -= 0x4000; +#if defined(LZO1Z) + last_m_off = pd((const lzo_bytep)op, m_pos); +#endif +#endif + } + else + { +#if defined(COPY_DICT) +#if defined(LZO1Z) + m_off = 1 + (t << 6) + (*ip++ >> 2); + last_m_off = m_off; +#else + m_off = 1 + (t >> 2) + (*ip++ << 2); +#endif + NEED_OP(2); + t = 2; COPY_DICT(t,m_off) +#else +#if defined(LZO1Z) + t = 1 + (t << 6) + (*ip++ >> 2); + m_pos = op - t; + last_m_off = t; +#else + m_pos = op - 1; + m_pos -= t >> 2; + m_pos -= *ip++ << 2; +#endif + TEST_LB(m_pos); NEED_OP(2); + *op++ = *m_pos++; *op++ = *m_pos; +#endif + goto match_done; + } + +#if defined(COPY_DICT) + + NEED_OP(t+3-1); + t += 3-1; COPY_DICT(t,m_off) + +#else + + TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1); +#if (LZO_OPT_UNALIGNED64) && (LZO_OPT_UNALIGNED32) + if (op - m_pos >= 8) + { + t += (3 - 1); + if (t >= 8) do + { + UA_COPY8(op,m_pos); + op += 8; m_pos += 8; t -= 8; + } while (t >= 8); + if (t >= 4) + { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } + if (t > 0) + { + *op++ = m_pos[0]; + if (t > 1) { *op++ = m_pos[1]; if (t > 2) { *op++ = m_pos[2]; } } + } + } + else +#elif (LZO_OPT_UNALIGNED32) || (LZO_ALIGNED_OK_4) +#if !(LZO_OPT_UNALIGNED32) + if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos)) + { + assert((op - m_pos) >= 4); +#else + if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4) + { +#endif + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4 - (3 - 1); + do { + UA_COPY4(op,m_pos); + op += 4; m_pos += 4; t -= 4; + } while (t >= 4); + if (t > 0) do *op++ = *m_pos++; while (--t > 0); + } + else +#endif + { +copy_match: + *op++ = *m_pos++; *op++ = *m_pos++; + do *op++ = *m_pos++; while (--t > 0); + } + +#endif + +match_done: +#if defined(LZO1Z) + t = ip[-1] & 3; +#else + t = ip[-2] & 3; +#endif + if (t == 0) + break; + +match_next: + assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+3); +#if 0 + do *op++ = *ip++; while (--t > 0); +#else + *op++ = *ip++; + if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } } +#endif + t = *ip++; + } + } + +eof_found: + *out_len = pd(op, out); + return (ip == ip_end ? LZO_E_OK : + (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); + +#if defined(HAVE_NEED_IP) +input_overrun: + *out_len = pd(op, out); + return LZO_E_INPUT_OVERRUN; +#endif + +#if defined(HAVE_NEED_OP) +output_overrun: + *out_len = pd(op, out); + return LZO_E_OUTPUT_OVERRUN; +#endif + +#if defined(LZO_TEST_OVERRUN_LOOKBEHIND) +lookbehind_overrun: + *out_len = pd(op, out); + return LZO_E_LOOKBEHIND_OVERRUN; +#endif +} + +#endif + +/***** End of minilzo.c *****/ diff --git a/libs/compression/minilzo.h b/libs/compression/minilzo.h new file mode 100644 index 0000000..c1c2297 --- /dev/null +++ b/libs/compression/minilzo.h @@ -0,0 +1,106 @@ +/* minilzo.h -- mini subset of the LZO real-time data compression library + + This file is part of the LZO real-time data compression library. + + Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer + All Rights Reserved. + + The LZO library is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + The LZO library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the LZO library; see the file COPYING. + If not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + Markus F.X.J. Oberhumer + + http://www.oberhumer.com/opensource/lzo/ + */ + +/* + * NOTE: + * the full LZO package can be found at + * http://www.oberhumer.com/opensource/lzo/ + */ + + +#ifndef __MINILZO_H_INCLUDED +#define __MINILZO_H_INCLUDED 1 + +#define MINILZO_VERSION 0x20a0 /* 2.10 */ + +#if defined(__LZOCONF_H_INCLUDED) +# error "you cannot use both LZO and miniLZO" +#endif + +/* internal Autoconf configuration file - only used when building miniLZO */ +#ifdef MINILZO_HAVE_CONFIG_H +# include +#endif +#include +#include + +#ifndef __LZODEFS_H_INCLUDED +#include "lzodefs.h" +#endif +#undef LZO_HAVE_CONFIG_H +#include "lzoconf.h" + +#if !defined(LZO_VERSION) || (LZO_VERSION != MINILZO_VERSION) +# error "version mismatch in header files" +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +/*********************************************************************** +// +************************************************************************/ + +/* Memory required for the wrkmem parameter. + * When the required size is 0, you can also pass a NULL pointer. + */ + +#define LZO1X_MEM_COMPRESS LZO1X_1_MEM_COMPRESS +#define LZO1X_1_MEM_COMPRESS ((lzo_uint32_t) (16384L * lzo_sizeof_dict_t)) +#define LZO1X_MEM_DECOMPRESS (0) + + +/* compression */ +LZO_EXTERN(int) +lzo1x_1_compress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem ); + +/* decompression */ +LZO_EXTERN(int) +lzo1x_decompress ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + +/* safe decompression with overrun testing */ +LZO_EXTERN(int) +lzo1x_decompress_safe ( const lzo_bytep src, lzo_uint src_len, + lzo_bytep dst, lzo_uintp dst_len, + lzo_voidp wrkmem /* NOT USED */ ); + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* already included */ + + +/* vim:set ts=4 sw=4 et: */ diff --git a/libs/core/core.pro b/libs/core/core.pro index 8cb5e5d..16bc396 100644 --- a/libs/core/core.pro +++ b/libs/core/core.pro @@ -3,11 +3,19 @@ TEMPLATE = lib CONFIG += staticlib c++17 SOURCES += \ + highlighter_cfg.cpp \ + highlighter_shock.cpp \ + highlighter_rumble.cpp \ + highlighter_gsc.cpp \ logmanager.cpp \ statusbarmanager.cpp HEADERS += \ enums.h \ + highlighter_cfg.h \ + highlighter_shock.h \ + highlighter_rumble.h \ + highlighter_gsc.h \ logmanager.h \ stringutils.h \ utils.h \ diff --git a/libs/core/enums.h b/libs/core/enums.h index 92a9739..77713ab 100644 --- a/libs/core/enums.h +++ b/libs/core/enums.h @@ -650,25 +650,6 @@ enum MENU_BUTTON { APAD_RIGHT = 31 }; -enum ASSET_TYPE { - ASSET_UNKNOWN = 0, - ASSET_ANIMATION = 4, // x_anim PARTIALLY VERIFIED - ASSET_MODEL = 5, // xmodel PARTIALLY VERIFIED - ASSET_MATERIAL = 6, // material VERIFIED - ASSET_BIK_FILE = 7, // .bik file PARTIALLY VERIFIED - ASSET_SOUND = 9, // loaded_sound VERIFIED - ASSET_COLLISION_MAP = 12, // collision_map PARTIALLY VERIFIED - ASSET_SHADER = 13, // shader PARTIALLY VERIFIED - ASSET_D3DBSP_DUMP = 17, // d3dbsp dump VERIFIED - ASSET_FONT = 20, // font PARTIALLY VERIFIED - ASSET_MENU = 21, // menu_file VERIFIED - ASSET_LOCAL_STRING = 23, // localized string VERIFIED - ASSET_WEAPON = 24, // weapon VERIFIED - ASSET_EFFECT = 26, // fx VERIFIED - ASSET_RAW_FILE = 32, // raw_file VERIFIED - ASSET_STRING_TABLE = 33 // string_table PARTIALLY VERIFIED -}; - enum SHADER_TYPE { SHADER_NONE = 0x00, SHADER_PIXEL = 0x01, diff --git a/libs/core/highlighter_cfg.cpp b/libs/core/highlighter_cfg.cpp new file mode 100644 index 0000000..1609fa8 --- /dev/null +++ b/libs/core/highlighter_cfg.cpp @@ -0,0 +1,111 @@ +#include "highlighter_cfg.h" + +Highlighter_CFG::Highlighter_CFG(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // Command keywords: set, seta, bind, etc. + keywordFormat.setForeground(QColor("#569CD6")); + keywordFormat.setFontWeight(QFont::Bold); + const QString keywordPatterns[] = { + QStringLiteral("\\bset\\b"), + QStringLiteral("\\bseta\\b"), + QStringLiteral("\\bbind\\b"), + QStringLiteral("\\bvstr\\b"), + QStringLiteral("\\bsay\\b"), + QStringLiteral("\\bwait\\b"), + QStringLiteral("\\bexec\\b"), + QStringLiteral("\\bunbind\\b"), + QStringLiteral("\\bcreatefx\\b"), + QStringLiteral("\\bcreatefx_drawdist\\b"), + QStringLiteral("\\bcreatefx_scaleid\\b"), + QStringLiteral("\\bbindaxis\\b") + }; + for (const QString &pattern : keywordPatterns) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + // Button constants: BUTTON_*, DPAD_* + buttonFormat.setForeground(QColor("#4EC9B0")); + rule.pattern = QRegularExpression(QStringLiteral("\\b(BUTTON|DPAD)_[A-Z]+\\b")); + rule.format = buttonFormat; + highlightingRules.append(rule); + + // Highlight *entire* 'bind var' or 'seta var' as one match, so we can highlight the variable part manually in highlightBlock() + // Regex captures the command and the following variable as two groups + bindSetVariablePattern = QRegularExpression(QStringLiteral("\\b(bind|bindaxis|set|seta)\\s+(\\w+)")); + + // Quoted strings (highlight first so numbers inside are overridden) + quotationFormat.setForeground(QColor("#CE9178")); + rule.pattern = QRegularExpression(QStringLiteral("\".*?\"")); + rule.format = quotationFormat; + highlightingRules.append(rule); + + // Numbers (normal numbers, no filtering for inside strings, since strings override them) + numberFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("\\b-?\\d+(\\.\\d+)?f?\\b")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Comments: single-line comments with // + singleLineCommentFormat.setForeground(QColor("#6A9955")); + rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*")); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + // Command chaining symbol: ; + operatorFormat.setForeground(QColor("#D4D4D4")); + rule.pattern = QRegularExpression(QStringLiteral(";")); + rule.format = operatorFormat; + highlightingRules.append(rule); +} + +void Highlighter_CFG::highlightBlock(const QString &text) { + // Apply all standard highlighting rules + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + // Highlight the immediate variable after 'bind', 'bindaxis', 'set', or 'seta' + QRegularExpressionMatchIterator iter = bindSetVariablePattern.globalMatch(text); + while (iter.hasNext()) { + QRegularExpressionMatch match = iter.next(); + int varStart = match.capturedStart(2); // Group 2 is the variable + int varLength = match.capturedLength(2); + setFormat(varStart, varLength, variableFormat); + } + + setCurrentBlockState(0); + + // Handle multiline comments safely + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = text.indexOf(commentStartExpression); + + while (startIndex >= 0) { + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.hasMatch() ? match.capturedStart() : -1; + + int commentLength; + if (endIndex == -1) { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } else { + commentLength = endIndex - startIndex + match.capturedLength(); + } + + // Safety check to avoid infinite loops + if (commentLength <= 0) { + break; + } + + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); + } +} diff --git a/libs/core/highlighter_cfg.h b/libs/core/highlighter_cfg.h new file mode 100644 index 0000000..a2a764a --- /dev/null +++ b/libs/core/highlighter_cfg.h @@ -0,0 +1,45 @@ +#ifndef HIGHLIGHTER_CFG_H +#define HIGHLIGHTER_CFG_H + +#include +#include + +class Highlighter_CFG : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_CFG(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + QList highlightingRules; + + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; + QRegularExpression bindSetVariablePattern; + QTextCharFormat buttonFormat; + QTextCharFormat operatorFormat; + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat preprocessorFormat; + QTextCharFormat variableFormat; + QTextCharFormat numberFormat; + QTextCharFormat devBlockCommentFormat; + + QRegularExpression devCommentStart; + QRegularExpression devCommentEnd; +}; + +#endif // HIGHLIGHTER_CFG_H diff --git a/libs/core/highlighter_gsc.cpp b/libs/core/highlighter_gsc.cpp new file mode 100644 index 0000000..94ea303 --- /dev/null +++ b/libs/core/highlighter_gsc.cpp @@ -0,0 +1,138 @@ +#include "highlighter_gsc.h" + +Highlighter_GSC::Highlighter_GSC(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // C++ Keywords + keywordFormat.setForeground(QColor("#569CD6")); + keywordFormat.setFontWeight(QFont::Bold); + const QString keywordPatterns[] = { + QStringLiteral("\\bchar\\b"), QStringLiteral("\\bclass\\b"), QStringLiteral("\\bconst\\b"), + QStringLiteral("\\bdouble\\b"), QStringLiteral("\\benum\\b"), QStringLiteral("\\bexplicit\\b"), + QStringLiteral("\\bfriend\\b"), QStringLiteral("\\binline\\b"), QStringLiteral("\\bint\\b"), + QStringLiteral("\\blong\\b"), QStringLiteral("\\bnamespace\\b"), QStringLiteral("\\boperator\\b"), + QStringLiteral("\\bprivate\\b"), QStringLiteral("\\bprotected\\b"), QStringLiteral("\\bpublic\\b"), + QStringLiteral("\\bshort\\b"), QStringLiteral("\\bsignals\\b"), QStringLiteral("\\bsigned\\b"), + QStringLiteral("\\bslots\\b"), QStringLiteral("\\bstatic\\b"), QStringLiteral("\\bstruct\\b"), + QStringLiteral("\\btemplate\\b"), QStringLiteral("\\btypedef\\b"), QStringLiteral("\\btypename\\b"), + QStringLiteral("\\bunion\\b"), QStringLiteral("\\bunsigned\\b"), QStringLiteral("\\bvirtual\\b"), + QStringLiteral("\\bvoid\\b"), QStringLiteral("\\bvolatile\\b"), QStringLiteral("\\bbool\\b") + }; + for (const QString &pattern : keywordPatterns) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + // GSC Control Keywords + const QString gscKeywords[] = { + QStringLiteral("\\bif\\b"), QStringLiteral("\\belse\\b"), QStringLiteral("\\bswitch\\b"), + QStringLiteral("\\bcase\\b"), QStringLiteral("\\bbreak\\b"), QStringLiteral("\\bbreakpoint\\b"), + QStringLiteral("\\bcontinue\\b"), QStringLiteral("\\bfor\\b"), QStringLiteral("\\bwhile\\b"), + QStringLiteral("\\breturn\\b"), QStringLiteral("\\bdefault\\b"), QStringLiteral("\\bwait\\b"), + QStringLiteral("\\bwaittill\\b"), QStringLiteral("\\bwaittillframeend\\b"), + QStringLiteral("\\bendon\\b"), QStringLiteral("\\bnotify\\b"), QStringLiteral("\\bthread\\b") + }; + for (const QString &pattern : gscKeywords) { + rule.pattern = QRegularExpression(pattern); + rule.format = keywordFormat; + highlightingRules.append(rule); + } + + // Class format + classFormat.setForeground(QColor("#C586C0")); + classFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("\\bQ[A-Za-z]+\\b")); + rule.format = classFormat; + highlightingRules.append(rule); + + // Preprocessor: #include and #using_animtree + preprocessorFormat.setForeground(QColor("#D7BA7D")); + preprocessorFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("^\\s*#(?:include|using_animtree)\\b.*")); + rule.format = preprocessorFormat; + highlightingRules.append(rule); + + // Hardcoded Variables: self, level, game + variableFormat.setForeground(QColor("#4EC9B0")); + rule.pattern = QRegularExpression(QStringLiteral("\\b(self|level|game)\\b")); + rule.format = variableFormat; + highlightingRules.append(rule); + + // Quoted Strings + quotationFormat.setForeground(QColor("#CE9178")); + rule.pattern = QRegularExpression(QStringLiteral("\".*?\"")); + rule.format = quotationFormat; + highlightingRules.append(rule); + + // Numeric literals (including optional .f) + numberFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("\\b-?\\d+(\\.\\d+)?f?\\b")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Boolean literals + rule.pattern = QRegularExpression(QStringLiteral("\\b(true|false|undefined)\\b")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Function calls + functionFormat.setForeground(QColor("#9CDCFE")); + functionFormat.setFontItalic(true); + rule.pattern = QRegularExpression(QStringLiteral("\\b[A-Za-z_][A-Za-z0-9_]*(?=\\s*\\()")); + rule.format = functionFormat; + highlightingRules.append(rule); + + // Function pointers ::func + rule.pattern = QRegularExpression(QStringLiteral("::\\b(\\w+)\\b")); + rule.format = functionFormat; + highlightingRules.append(rule); + + // Single-line comments + singleLineCommentFormat.setForeground(QColor("#6A9955")); + rule.pattern = QRegularExpression(QStringLiteral("//[^\n]*")); + rule.format = singleLineCommentFormat; + highlightingRules.append(rule); + + // Developer block comments /# ... #/ + devBlockCommentFormat.setForeground(QColor("#6A9955")); + devCommentStart = QRegularExpression(QStringLiteral("/#")); + devCommentEnd = QRegularExpression(QStringLiteral("#/")); + + // Multi-line comment /* ... */ + multiLineCommentFormat.setForeground(QColor("#6A9955")); + commentStartExpression = QRegularExpression(QStringLiteral("/\\*")); + commentEndExpression = QRegularExpression(QStringLiteral("\\*/")); +} + + +void Highlighter_GSC::highlightBlock(const QString &text) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + setCurrentBlockState(0); + + int startIndex = 0; + if (previousBlockState() != 1) + startIndex = text.indexOf(commentStartExpression); + + while (startIndex >= 0) { + QRegularExpressionMatch match = commentEndExpression.match(text, startIndex); + int endIndex = match.capturedStart(); + int commentLength = 0; + if (endIndex == -1) { + setCurrentBlockState(1); + commentLength = text.length() - startIndex; + } else { + commentLength = endIndex - startIndex + + match.capturedLength(); + } + setFormat(startIndex, commentLength, multiLineCommentFormat); + startIndex = text.indexOf(commentStartExpression, startIndex + commentLength); + } +} diff --git a/libs/core/highlighter_gsc.h b/libs/core/highlighter_gsc.h new file mode 100644 index 0000000..0fbeb62 --- /dev/null +++ b/libs/core/highlighter_gsc.h @@ -0,0 +1,42 @@ +#ifndef HIGHLIGHTER_GSC_H +#define HIGHLIGHTER_GSC_H + +#include +#include + +class Highlighter_GSC : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_GSC(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule + { + QRegularExpression pattern; + QTextCharFormat format; + }; + QList highlightingRules; + + QRegularExpression commentStartExpression; + QRegularExpression commentEndExpression; + QTextCharFormat keywordFormat; + QTextCharFormat classFormat; + QTextCharFormat quotationFormat; + QTextCharFormat functionFormat; + QTextCharFormat singleLineCommentFormat; + QTextCharFormat multiLineCommentFormat; + QTextCharFormat preprocessorFormat; + QTextCharFormat variableFormat; + QTextCharFormat numberFormat; + QTextCharFormat devBlockCommentFormat; + + QRegularExpression devCommentStart; + QRegularExpression devCommentEnd; +}; + +#endif // HIGHLIGHTER_GSC_H diff --git a/libs/core/highlighter_rumble.cpp b/libs/core/highlighter_rumble.cpp new file mode 100644 index 0000000..4bbb45c --- /dev/null +++ b/libs/core/highlighter_rumble.cpp @@ -0,0 +1,37 @@ +#include "highlighter_rumble.h" + +Highlighter_Rumble::Highlighter_Rumble(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // Format for the "RUMBLEGRAPHFILE" header + headerFormat.setForeground(QColor("#569CD6")); + headerFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("^RUMBLEGRAPHFILE\\b")); + rule.format = headerFormat; + highlightingRules.append(rule); + + // Format for line count (second line, typically a single integer) + countFormat.setForeground(QColor("#C586C0")); + rule.pattern = QRegularExpression(QStringLiteral("^\\d+$")); + rule.format = countFormat; + highlightingRules.append(rule); + + // Format for floating-point number pairs (e.g. 0.0000 0.4701) + floatPairFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("^\\s*-?\\d+\\.\\d+\\s+-?\\d+\\.\\d+\\s*$")); + rule.format = floatPairFormat; + highlightingRules.append(rule); +} + +void Highlighter_Rumble::highlightBlock(const QString &text) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + setCurrentBlockState(0); +} diff --git a/libs/core/highlighter_rumble.h b/libs/core/highlighter_rumble.h new file mode 100644 index 0000000..2f45664 --- /dev/null +++ b/libs/core/highlighter_rumble.h @@ -0,0 +1,29 @@ +#ifndef HIGHLIGHTER_RUMBLE_H +#define HIGHLIGHTER_RUMBLE_H + +#include +#include + +class Highlighter_Rumble : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_Rumble(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QTextCharFormat headerFormat; + QTextCharFormat countFormat; + QTextCharFormat floatPairFormat; +}; + +#endif // HIGHLIGHTER_RUMBLE_H diff --git a/libs/core/highlighter_shock.cpp b/libs/core/highlighter_shock.cpp new file mode 100644 index 0000000..17f4675 --- /dev/null +++ b/libs/core/highlighter_shock.cpp @@ -0,0 +1,43 @@ +#include "highlighter_shock.h" + +Highlighter_Shock::Highlighter_Shock(QTextDocument *parent) + : QSyntaxHighlighter(parent) { + HighlightingRule rule; + + // Format for bg_shock_* keys + keyFormat.setForeground(QColor("#569CD6")); + keyFormat.setFontWeight(QFont::Bold); + rule.pattern = QRegularExpression(QStringLiteral("\\bbg_shock_[\\w]+\\b")); + rule.format = keyFormat; + highlightingRules.append(rule); + + // Format for quoted string values + stringFormat.setForeground(QColor("#CE9178")); + rule.pattern = QRegularExpression(QStringLiteral("\"[^\"]*\"")); + rule.format = stringFormat; + highlightingRules.append(rule); + + // Format for numeric values inside quotes (overridden by stringFormat but still useful for raw values) + numberFormat.setForeground(QColor("#B5CEA8")); + rule.pattern = QRegularExpression(QStringLiteral("-?\\d+(\\.\\d+)?")); + rule.format = numberFormat; + highlightingRules.append(rule); + + // Optional: Format for control groups (e.g., bg_shock_volume_*) + subgroupFormat.setForeground(QColor("#4EC9B0")); + rule.pattern = QRegularExpression(QStringLiteral("\\bbg_shock_volume_\\w+\\b")); + rule.format = subgroupFormat; + highlightingRules.append(rule); +} + +void Highlighter_Shock::highlightBlock(const QString &text) { + for (const HighlightingRule &rule : std::as_const(highlightingRules)) { + QRegularExpressionMatchIterator matchIterator = rule.pattern.globalMatch(text); + while (matchIterator.hasNext()) { + QRegularExpressionMatch match = matchIterator.next(); + setFormat(match.capturedStart(), match.capturedLength(), rule.format); + } + } + + setCurrentBlockState(0); +} diff --git a/libs/core/highlighter_shock.h b/libs/core/highlighter_shock.h new file mode 100644 index 0000000..7215c70 --- /dev/null +++ b/libs/core/highlighter_shock.h @@ -0,0 +1,30 @@ +#ifndef HIGHLIGHTER_SHOCK_H +#define HIGHLIGHTER_SHOCK_H + +#include +#include + +class Highlighter_Shock : public QSyntaxHighlighter +{ + Q_OBJECT + +public: + Highlighter_Shock(QTextDocument *parent = nullptr); + +protected: + void highlightBlock(const QString &text) override; + +private: + struct HighlightingRule { + QRegularExpression pattern; + QTextCharFormat format; + }; + QVector highlightingRules; + + QTextCharFormat keyFormat; + QTextCharFormat stringFormat; + QTextCharFormat numberFormat; + QTextCharFormat subgroupFormat; +}; + +#endif // HIGHLIGHTER_SHOCK_H diff --git a/libs/core/utils.h b/libs/core/utils.h index 9ebf74c..ed50b2f 100644 --- a/libs/core/utils.h +++ b/libs/core/utils.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include class Utils { public: @@ -22,6 +24,178 @@ public: testFile.close(); return true; } + static quint8 ReverseBits(quint8 b) { + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + return b; + } + static QIcon CreateAssetIcon(const QString& name, QColor color = QColor()) { + constexpr int iconSize = 32; + constexpr int padding = 4; + + QImage result(iconSize, iconSize, QImage::Format_ARGB32); + result.fill(Qt::transparent); + + if (!color.isValid()) { + color = Utils::StringToColor(name); + } + + QPainter painter(&result); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::TextAntialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + + // Draw background + QBrush brush(color); + brush.setStyle(Qt::SolidPattern); + painter.setBrush(color); + painter.setPen(Qt::NoPen); + painter.drawRoundedRect(0, 0, iconSize, iconSize, 4, 4); + + // Set base font + QFont font("Heavitas"); + font.setPixelSize(iconSize); // Start large + painter.setFont(font); + + // Adjust font size to fit text width (only reduce, not increase) + QFontMetrics fm(font); + int textWidth = fm.horizontalAdvance(name); + while (textWidth > iconSize - 2 * padding && font.pixelSize() > 1) { + font.setPixelSize(font.pixelSize() - 1); + painter.setFont(font); + fm = QFontMetrics(font); + textWidth = fm.horizontalAdvance(name); + } + + // Calculate vertical scaling factor + qreal scaleY = 1.2 * iconSize / fm.height(); + + // Apply transform: scale vertically, center align + painter.save(); + painter.translate(iconSize / 2.0, iconSize / 2.0); + painter.scale(1.0, scaleY); + painter.translate(-iconSize / 2.0, -iconSize / 2.0); + + QRect textRect(0, 0, iconSize, iconSize); + + // Draw stroke + painter.setPen(Qt::black); + for (int dx = 0; dx <= 1; ++dx) { + for (int dy = 0; dy <= 1; ++dy) { + if (dx || dy) + painter.drawText(textRect.translated(dx, dy), Qt::AlignCenter, name); + } + } + + // Draw main text + painter.setPen(Qt::white); + painter.drawText(textRect, Qt::AlignCenter, name); + painter.restore(); + + // Debug output + QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/"); + result.save(QDir().absoluteFilePath(".") + "/icons/" + name + ".png"); + + return QIcon(QPixmap::fromImage(result)); + } + + static QIcon CreateGameIcon(const int gameNum, QColor color = QColor()) { + constexpr int size = 32; + constexpr int padding = 4; // pixels of padding on all sides + const int contentSize = size - 2 * padding; + + QImage result(size, size, QImage::Format_ARGB32); + result.fill(Qt::transparent); + + if (!color.isValid()) { + color = Utils::StringToColor(QString("COD%1").arg(gameNum)); + } + + QPainter painter(&result); + painter.setRenderHint(QPainter::Antialiasing, false); + painter.setRenderHint(QPainter::TextAntialiasing, false); + painter.setRenderHint(QPainter::SmoothPixmapTransform, false); + + // Draw background + painter.setBrush(color); + painter.setPen(Qt::NoPen); + painter.drawRoundedRect(0, 0, size, size, 4, 4); + + // === Font Setup === + QFont codFont("Heavitas"); + codFont.setPixelSize(contentSize * 0.40); + + QFont numFont("Heavitas"); + numFont.setPixelSize(contentSize); + + // === Layout Areas (inside padding) === + const QRect contentRect(padding, padding, contentSize, contentSize); + const int col1 = contentRect.left(); + const int col2 = contentRect.left() + contentRect.width() / 3; + + const int thirdH = contentRect.height() / 3; + const QRect codRects[] = { + QRect(col1, 2 + contentRect.top(), contentRect.width() / 3, thirdH), + QRect(col1, contentRect.top() + thirdH, contentRect.width() / 3, thirdH), + QRect(col1, -2 + contentRect.top() + 2 * thirdH, contentRect.width() / 3, thirdH), + }; + + const QRect numRect(col2, contentRect.top(), contentRect.width() * 2 / 3, contentRect.height()); + + const QString codLetters[] = { "C", "O", "D" }; + const QString numText = QString::number(gameNum); + + // === Stroke pass === + for (int dx = -1; dx <= 2; ++dx) { + for (int dy = -1; dy <= 2; ++dy) { + if (dx == 0 && dy == 0) continue; + + painter.setPen(Qt::black); + painter.setFont(codFont); + for (int i = 0; i < 3; ++i) + painter.drawText(codRects[i].translated(dx, dy), Qt::AlignCenter, codLetters[i]); + + painter.setFont(numFont); + painter.drawText(numRect.translated(dx, dy), Qt::AlignCenter, numText); + } + } + + // === Fill pass === + painter.setPen(Qt::white); + painter.setFont(codFont); + for (int i = 0; i < 3; ++i) + painter.drawText(codRects[i], Qt::AlignCenter, codLetters[i]); + + painter.setFont(numFont); + painter.drawText(numRect, Qt::AlignCenter, numText); + + // Save & return icon + QDir().mkdir(QDir().absoluteFilePath(".") + "/icons/"); + result.save(QDir().absoluteFilePath(".") + QString("/icons/COD%1.png").arg(gameNum)); + + return QIcon(QPixmap::fromImage(result)); + } + + + static QColor StringToColor(const QString& str) { + // 1. Hash the string using Qt's built-in hash (MD5, SHA1, or any) + QByteArray hash = QCryptographicHash::hash(str.toUtf8(), QCryptographicHash::Md5); + + // 2. Use first 3 bytes of hash for RGB + // This guarantees same string = same color every time + int r = static_cast(hash[0]); + int g = static_cast(hash[1]); + int b = static_cast(hash[2]); + + // 3. Optionally adjust brightness or saturation to avoid too dark/light colors + QColor color(r, g, b); + if (color.value() < 128) { // brighten if too dark + color = color.lighter(150); + } + + return color; + } static bool ReadUntilString(QDataStream* stream, const QString& targetString) { if (!stream || targetString.isEmpty()) { return false; // Invalid input @@ -90,53 +264,6 @@ public: return false; } - /* - AssetTypeToString() - - Convert asset type string to asset desc string -*/ - static QString AssetTypeToString(const QString aAssetType) { - const QString cleanedType = aAssetType.toUpper(); - if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED - return "LOCAL STRING"; - } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED - return "RAW FILE"; - } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED - return "EFFECT"; - } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED - return "SOUND"; - } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED - return "ANIMATION"; - } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED - return "COLLISION MAP"; - } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED - return "STRING TABLE"; - } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED - return "MENU"; - } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED - return "TECH SET"; - } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED - return "WEAPON"; - } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED - return "GFX MAP"; - } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED - return "LIGHT DEF"; - } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED - return "FONT"; - } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED - return "MODEL"; - } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED - return "D3DBSP"; - } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED - return "IMAGE"; - } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED - return "GAME MAP SP"; - } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED - return "COL MAP SP"; - } - return aAssetType; - } - /* LumpTypeToString() diff --git a/libs/ddsfile/enums.h b/libs/ddsfile/enums.h index b5f8204..7d5f5c0 100644 --- a/libs/ddsfile/enums.h +++ b/libs/ddsfile/enums.h @@ -648,25 +648,6 @@ enum MENU_BUTTON { APAD_RIGHT = 31 }; -enum ASSET_TYPE { - ASSET_UNKNOWN = 0, - ASSET_ANIMATION = 4, // x_anim PARTIALLY VERIFIED - ASSET_MODEL = 5, // xmodel PARTIALLY VERIFIED - ASSET_MATERIAL = 6, // material VERIFIED - ASSET_BIK_FILE = 7, // .bik file PARTIALLY VERIFIED - ASSET_SOUND = 9, // loaded_sound VERIFIED - ASSET_COLLISION_MAP = 12, // collision_map PARTIALLY VERIFIED - ASSET_SHADER = 13, // shader PARTIALLY VERIFIED - ASSET_D3DBSP_DUMP = 17, // d3dbsp dump VERIFIED - ASSET_FONT = 20, // font PARTIALLY VERIFIED - ASSET_MENU = 21, // menu_file VERIFIED - ASSET_LOCAL_STRING = 23, // localized string VERIFIED - ASSET_WEAPON = 24, // weapon VERIFIED - ASSET_EFFECT = 26, // fx VERIFIED - ASSET_RAW_FILE = 32, // raw_file VERIFIED - ASSET_STRING_TABLE = 33 // string_table PARTIALLY VERIFIED -}; - enum SHADER_TYPE { SHADER_NONE = 0x00, SHADER_PIXEL = 0x01, diff --git a/libs/encryption/encryption.cpp b/libs/encryption/encryption.cpp index 613ea2e..81e2abe 100644 --- a/libs/encryption/encryption.cpp +++ b/libs/encryption/encryption.cpp @@ -1,6 +1,7 @@ #include "encryption.h" #include "QtZlib/zlib.h" #include "ecrypt-sync.h" +#include "compression.h" void Encryption::Convert32BitTo8Bit(quint32 value, quint8 *array) { array[0] = static_cast(value >> 0); @@ -350,7 +351,7 @@ void Encryption::generateNewIV(int index, const QByteArray &hash, QByteArray &iv ivCounter[index]++; } -QByteArray Encryption::decryptFastFile(const QByteArray &fastFileData) +QByteArray Encryption::decryptFastFile_BO2(const QByteArray &fastFileData) { const QByteArray bo2_salsa20_key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); @@ -438,3 +439,68 @@ QByteArray Encryption::decryptFastFile(const QByteArray &fastFileData) return finalFastFile; } + +QByteArray Encryption::decryptFastFile_BO3(const QByteArray &fastFileData) { + const QByteArray salsaKey = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + + QByteArray ivTable(0xFB0, 0); + fillIVTable(fastFileData, ivTable, 0xFB0 - 1); + + QVector ivCounter(4, 1); + QDataStream stream(fastFileData); + stream.setByteOrder(QDataStream::LittleEndian); + + QByteArray finalFastFile; + QByteArray sha1Hash(20, 0); + QByteArray ivPtr(8, 0); + int chunkIndex = 0; + + while (!stream.atEnd()) { + if (stream.device()->bytesAvailable() < 4) { + qWarning() << "No sufficient data for chunk size at offset:" << stream.device()->pos(); + break; + } + + quint32 dataLength; + stream >> dataLength; + + if (dataLength == 0 || dataLength > fastFileData.size() - stream.device()->pos()) { + qWarning() << "Invalid data length at offset:" << stream.device()->pos(); + break; + } + + fillIV(chunkIndex % 4, ivPtr, ivTable, ivCounter); + + ECRYPT_ctx x; + ECRYPT_keysetup(&x, reinterpret_cast(salsaKey.constData()), 256, 0); + ECRYPT_ivsetup(&x, reinterpret_cast(ivPtr.constData())); + + QByteArray encryptedBlock = fastFileData.mid(stream.device()->pos(), dataLength); + QByteArray decryptedBlock(dataLength, Qt::Uninitialized); + + ECRYPT_decrypt_bytes(&x, + reinterpret_cast(encryptedBlock.constData()), + reinterpret_cast(decryptedBlock.data()), + dataLength); + + // SHA1 hash update + sha1Hash = QCryptographicHash::hash(decryptedBlock, QCryptographicHash::Sha1); + + // Decompress (ZLIB raw DEFLATE) + QByteArray decompressedData = Compression::DecompressDeflate(decryptedBlock); + if (decompressedData.isEmpty()) { + qWarning() << "Failed decompression at chunk index:" << chunkIndex; + return QByteArray(); + } + + finalFastFile.append(decompressedData); + + // Update IV table using SHA1 + generateNewIV(chunkIndex % 4, sha1Hash, ivTable, ivCounter); + + stream.skipRawData(dataLength); + chunkIndex++; + } + + return finalFastFile; +} diff --git a/libs/encryption/encryption.h b/libs/encryption/encryption.h index 6b36041..f03d85e 100644 --- a/libs/encryption/encryption.h +++ b/libs/encryption/encryption.h @@ -46,7 +46,8 @@ public: static void generateNewIV(int index, const QByteArray& hash, QByteArray& ivTable, QVector& ivCounter); - static QByteArray decryptFastFile(const QByteArray& fastFileData); + static QByteArray decryptFastFile_BO2(const QByteArray& fastFileData); + static QByteArray decryptFastFile_BO3(const QByteArray& fastFileData); }; #endif // ENCRYPTION_H diff --git a/libs/encryption/encryption.pro b/libs/encryption/encryption.pro index 28d2cfb..d923b34 100644 --- a/libs/encryption/encryption.pro +++ b/libs/encryption/encryption.pro @@ -17,4 +17,16 @@ HEADERS += \ config_win32.h \ sha1.h +app.depends += \ + compression + +LIBS += \ + -L$$OUT_PWD/../ -lcompression + +INCLUDEPATH += \ + $$PWD/../compression + +DEPENDPATH += \ + $$PWD/../compression + DESTDIR = $$OUT_PWD/../ diff --git a/libs/fastfile/360/fastfile_cod10_360.cpp b/libs/fastfile/360/fastfile_cod10_360.cpp new file mode 100644 index 0000000..005d649 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod10_360.cpp @@ -0,0 +1,115 @@ +#include "fastfile_cod10_360.h" +#include "zonefile_cod10_360.h" +#include "encryption.h" + +#include +#include + +FastFile_COD10_360::FastFile_COD10_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD10"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + + // Select key based on game. + QByteArray key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + + // 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(); + } + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD10_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod10_360.h b/libs/fastfile/360/fastfile_cod10_360.h new file mode 100644 index 0000000..b0574a1 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod10_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD10_360_H diff --git a/libs/fastfile/360/fastfile_cod11_360.cpp b/libs/fastfile/360/fastfile_cod11_360.cpp new file mode 100644 index 0000000..33477b2 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod11_360.cpp @@ -0,0 +1,107 @@ +#include "fastfile_cod11_360.h" +#include "zonefile_cod11_360.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD11_360::FastFile_COD11_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD11"); + SetPlatform("PC"); +} + +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() { + 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; +} + +bool FastFile_COD11_360::Load(const QByteArray aData) { + QByteArray decompressedData; + + // Prepare data stream for parsing + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Verify magic header + QByteArray fileMagic(8, Qt::Uninitialized); + fastFileStream.readRawData(fileMagic.data(), 8); + if (fileMagic != "TAff0000") { + qWarning() << "Invalid fast file magic for COD12!"; + return false; + } + + // Skip: File size (4 bytes), flags/version (4 bytes), unknown (8 bytes), build tag (32 bytes), RSA signature (256 bytes) + fastFileStream.skipRawData(4 + 4 + 8 + 32 + 256); // total 304 bytes skipped so far + 8 bytes magic = 312 bytes at correct position. + + // Correctly positioned at 0x138 + QByteArray encryptedData = aData.mid(0x138); + decompressedData = Encryption::decryptFastFile_BO3(encryptedData); + + // Output for verification/testing + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + // Load the zone file with decompressed data + ZoneFile_COD11_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + if (!zoneFile.Load(decompressedData)) { + qWarning() << "Failed to load ZoneFile!"; + return false; + } + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod11_360.h b/libs/fastfile/360/fastfile_cod11_360.h new file mode 100644 index 0000000..a14c43c --- /dev/null +++ b/libs/fastfile/360/fastfile_cod11_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD11_360_H diff --git a/libs/fastfile/360/fastfile_cod12_360.cpp b/libs/fastfile/360/fastfile_cod12_360.cpp new file mode 100644 index 0000000..8e051b9 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod12_360.cpp @@ -0,0 +1,107 @@ +#include "fastfile_cod12_360.h" +#include "zonefile_cod12_360.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD12_360::FastFile_COD12_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD12"); + SetPlatform("PC"); +} + +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() { + 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 + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Verify magic header + QByteArray fileMagic(8, Qt::Uninitialized); + fastFileStream.readRawData(fileMagic.data(), 8); + if (fileMagic != "TAff0000") { + qWarning() << "Invalid fast file magic for COD12!"; + return false; + } + + // Skip: File size (4 bytes), flags/version (4 bytes), unknown (8 bytes), build tag (32 bytes), RSA signature (256 bytes) + fastFileStream.skipRawData(4 + 4 + 8 + 32 + 256); // total 304 bytes skipped so far + 8 bytes magic = 312 bytes at correct position. + + // Correctly positioned at 0x138 + QByteArray encryptedData = aData.mid(0x138); + decompressedData = Encryption::decryptFastFile_BO3(encryptedData); + + // Output for verification/testing + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + // Load the zone file with decompressed data + ZoneFile_COD12_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + if (!zoneFile.Load(decompressedData)) { + qWarning() << "Failed to load ZoneFile!"; + return false; + } + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod12_360.h b/libs/fastfile/360/fastfile_cod12_360.h new file mode 100644 index 0000000..082d89a --- /dev/null +++ b/libs/fastfile/360/fastfile_cod12_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD12_360_H diff --git a/libs/fastfile/fastfile_cod2.cpp b/libs/fastfile/360/fastfile_cod2_360.cpp similarity index 56% rename from libs/fastfile/fastfile_cod2.cpp rename to libs/fastfile/360/fastfile_cod2_360.cpp index 8c58687..bf234d8 100644 --- a/libs/fastfile/fastfile_cod2.cpp +++ b/libs/fastfile/360/fastfile_cod2_360.cpp @@ -1,25 +1,48 @@ -#include "fastfile_cod2.h" +#include "fastfile_cod2_360.h" #include "utils.h" #include "compression.h" -#include "zonefile_cod2.h" +#include "zonefile_cod2_360.h" #include #include -FastFile_COD2::FastFile_COD2() { +FastFile_COD2_360::FastFile_COD2_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD2"); +} + +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() { } -FastFile_COD2::~FastFile_COD2() { - -} - -QByteArray FastFile_COD2::GetBinaryData() { +QByteArray FastFile_COD2_360::GetBinaryData() { return QByteArray(); } -bool FastFile_COD2::Load(const QString aFilePath) { +bool FastFile_COD2_360::Load(const QString aFilePath) { if (aFilePath.isEmpty()) { return false; } @@ -32,11 +55,9 @@ bool FastFile_COD2::Load(const QString aFilePath) { } // Decompress fastfile and close - const QString fastFileStem = aFilePath.section("/", -1, -1).section(".", 0, 0); - qDebug() << "fastFileStem: " << fastFileStem; - SetStem(fastFileStem); + SetStem(aFilePath.section("/", -1, -1)); if (!Load(file->readAll())) { - qDebug() << "Error: Failed to load fastfile: " << fastFileStem; + qDebug() << "Error: Failed to load fastfile: " << GetStem(); return false; } @@ -46,38 +67,22 @@ bool FastFile_COD2::Load(const QString aFilePath) { return true; } -bool FastFile_COD2::Load(const QByteArray aData) { +bool FastFile_COD2_360::Load(const QByteArray aData) { // Create a QDataStream on the input data. QDataStream fastFileStream(aData); fastFileStream.setByteOrder(QDataStream::LittleEndian); - // Parse header values. - SetCompany(COMPANY_INFINITY_WARD); - SetType(FILETYPE_FAST_FILE); - SetSignage(SIGNAGE_UNSIGNED); - SetMagic(0); - SetVersion(0); - SetPlatform("360"); - SetGame("COD2"); - Utils::ReadUntilHex(&fastFileStream, "78"); QByteArray compressedData = aData.mid(fastFileStream.device()->pos()); QByteArray decompressedData = Compression::DecompressZLIB(compressedData); - QDir exportsDir(QDir::currentPath()); - exportsDir.mkdir("exports"); - - QFile testFile("exports/" + GetStem() + ".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_COD2 zoneFile; - zoneFile.SetStem(GetStem()); - zoneFile.Load(decompressedData, FF_PLATFORM_XBOX); - SetZoneFile(std::make_shared(zoneFile)); + ZoneFile_COD2_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); return true; } diff --git a/libs/fastfile/360/fastfile_cod2_360.h b/libs/fastfile/360/fastfile_cod2_360.h new file mode 100644 index 0000000..d1fe760 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod2_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD2_360_H diff --git a/libs/fastfile/360/fastfile_cod4_360.cpp b/libs/fastfile/360/fastfile_cod4_360.cpp new file mode 100644 index 0000000..a6e9899 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod4_360.cpp @@ -0,0 +1,139 @@ +#include "fastfile_cod4_360.h" +#include "zonefile_cod4_360.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD4_360::FastFile_COD4_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD4"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData.mid(12)); + fastFileStream.setByteOrder(QDataStream::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 sigBlocks = QVector(); + 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; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod4_360.h b/libs/fastfile/360/fastfile_cod4_360.h new file mode 100644 index 0000000..5f8cdb2 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod4_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD4_360_H diff --git a/libs/fastfile/360/fastfile_cod5_360.cpp b/libs/fastfile/360/fastfile_cod5_360.cpp new file mode 100644 index 0000000..1488c3c --- /dev/null +++ b/libs/fastfile/360/fastfile_cod5_360.cpp @@ -0,0 +1,89 @@ +#include "fastfile_cod5_360.h" +#include "zonefile_cod5_360.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD5_360::FastFile_COD5_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD5"); +} + +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() { + 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; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod5_360.h b/libs/fastfile/360/fastfile_cod5_360.h new file mode 100644 index 0000000..80ba475 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod5_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD5_360_H diff --git a/libs/fastfile/360/fastfile_cod6_360.cpp b/libs/fastfile/360/fastfile_cod6_360.cpp new file mode 100644 index 0000000..51d2132 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod6_360.cpp @@ -0,0 +1,109 @@ +#include "fastfile_cod6_360.h" +#include "zonefile_cod6_360.h" + +#include "compression.h" +#include "encryption.h" +#include "utils.h" + +#include +#include + +FastFile_COD6_360::FastFile_COD6_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD6"); +} + +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() { + 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) { + const qint64 zlibOffset = Compression::FindZlibOffset(aData); + if (zlibOffset == -1) + { + qWarning() << "Z-Lib stream not found"; + return false; + } + QByteArray compressed = aData.mid(zlibOffset); + + // 2. Try plain decompression first ------------------------------ + QByteArray decompressed = Compression::DecompressZLIB(compressed); + + // 3. If that failed or looks too small, try stripping hash blocks + if (decompressed.isEmpty() || decompressed.size() < 1024) + { + QByteArray stripped = Compression::StripHashBlocks(compressed); + QByteArray retry = Compression::DecompressZLIB(stripped); + if (!retry.isEmpty()) + decompressed.swap(retry); + } + + if (decompressed.isEmpty()) + { + qWarning() << "Unable to decompress fast-file"; + return false; + } + + // Optional – keep a copy on disk for quick inspection + Utils::ExportData(GetBaseStem() + ".zone", decompressed); + + // 4. Forward to zone-file loader -------------------------------- + auto zoneFile = std::make_shared(); + zoneFile->SetStem(GetStem()); + zoneFile->Load(decompressed); + SetZoneFile(zoneFile); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod6_360.h b/libs/fastfile/360/fastfile_cod6_360.h new file mode 100644 index 0000000..8a7f430 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod6_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD6_360_H diff --git a/libs/fastfile/360/fastfile_cod7_360.cpp b/libs/fastfile/360/fastfile_cod7_360.cpp new file mode 100644 index 0000000..90d645e --- /dev/null +++ b/libs/fastfile/360/fastfile_cod7_360.cpp @@ -0,0 +1,151 @@ +#include "fastfile_cod7_360.h" +#include "zonefile_cod7_360.h" + +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD7_360::FastFile_COD7_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD7"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD7_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + + // Select key based on game. + QByteArray key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d"); + 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++; + } + + zoneFile.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod7_360.h b/libs/fastfile/360/fastfile_cod7_360.h new file mode 100644 index 0000000..a30972c --- /dev/null +++ b/libs/fastfile/360/fastfile_cod7_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD7_360_H diff --git a/libs/fastfile/360/fastfile_cod8_360.cpp b/libs/fastfile/360/fastfile_cod8_360.cpp new file mode 100644 index 0000000..746fc9e --- /dev/null +++ b/libs/fastfile/360/fastfile_cod8_360.cpp @@ -0,0 +1,115 @@ +#include "fastfile_cod8_360.h" +#include "zonefile_cod8_360.h" +#include "encryption.h" + +#include +#include + +FastFile_COD8_360::FastFile_COD8_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD8"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + + // Select key based on game. + QByteArray key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + + // 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(); + } + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD8_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod8_360.h b/libs/fastfile/360/fastfile_cod8_360.h new file mode 100644 index 0000000..793cc5a --- /dev/null +++ b/libs/fastfile/360/fastfile_cod8_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD8_360_H diff --git a/libs/fastfile/360/fastfile_cod9_360.cpp b/libs/fastfile/360/fastfile_cod9_360.cpp new file mode 100644 index 0000000..1362e59 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod9_360.cpp @@ -0,0 +1,115 @@ +#include "fastfile_cod9_360.h" +#include "zonefile_cod9_360.h" +#include "encryption.h" + +#include +#include + +FastFile_COD9_360::FastFile_COD9_360() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("360"); + SetGame("COD9"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + + // Select key based on game. + QByteArray key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + + // 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(); + } + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD9_360 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/360/fastfile_cod9_360.h b/libs/fastfile/360/fastfile_cod9_360.h new file mode 100644 index 0000000..84fa4a8 --- /dev/null +++ b/libs/fastfile/360/fastfile_cod9_360.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD9_360_H diff --git a/libs/fastfile/PC/fastfile_cod10_pc.cpp b/libs/fastfile/PC/fastfile_cod10_pc.cpp new file mode 100644 index 0000000..fcde932 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod10_pc.cpp @@ -0,0 +1,137 @@ +#include "fastfile_cod10_pc.h" +#include "zonefile_cod10_pc.h" +#include "encryption.h" + +#include +#include + +FastFile_COD10_PC::FastFile_COD10_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD10"); + SetPlatform("PC"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod10_pc.h b/libs/fastfile/PC/fastfile_cod10_pc.h new file mode 100644 index 0000000..c4041d4 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod10_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD10_PC_H diff --git a/libs/fastfile/PC/fastfile_cod11_pc.cpp b/libs/fastfile/PC/fastfile_cod11_pc.cpp new file mode 100644 index 0000000..300e1eb --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod11_pc.cpp @@ -0,0 +1,137 @@ +#include "fastfile_cod11_pc.h" +#include "zonefile_cod11_pc.h" +#include "encryption.h" + +#include +#include + +FastFile_COD11_PC::FastFile_COD11_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD11"); + SetPlatform("PC"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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_COD11_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod11_pc.h b/libs/fastfile/PC/fastfile_cod11_pc.h new file mode 100644 index 0000000..cf493d5 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod11_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD11_PC_H diff --git a/libs/fastfile/PC/fastfile_cod12_pc.cpp b/libs/fastfile/PC/fastfile_cod12_pc.cpp new file mode 100644 index 0000000..b405990 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod12_pc.cpp @@ -0,0 +1,151 @@ +#include "fastfile_cod12_pc.h" +#include "zonefile_cod12_pc.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD12_PC::FastFile_COD12_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD12"); + SetPlatform("PC"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD12_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // 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); + + zoneFile.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod12_pc.h b/libs/fastfile/PC/fastfile_cod12_pc.h new file mode 100644 index 0000000..5613275 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod12_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD12_PC_H diff --git a/libs/fastfile/PC/fastfile_cod4_pc.cpp b/libs/fastfile/PC/fastfile_cod4_pc.cpp new file mode 100644 index 0000000..a2fe992 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod4_pc.cpp @@ -0,0 +1,93 @@ +#include "fastfile_cod4_pc.h" +#include "zonefile_cod4_pc.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD4_PC::FastFile_COD4_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("PC"); + SetGame("COD4"); +} + +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() { + return QByteArray(); +} + +bool FastFile_COD4_PC::Load(const QString aFilePath) { + StatusBarManager::instance().updateStatus("Loading " + GetGame() + " 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // For COD5, simply decompress from offset 12. + decompressedData = Compression::DecompressZLIB(aData.mid(12)); + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + ZoneFile_COD4_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod4_pc.h b/libs/fastfile/PC/fastfile_cod4_pc.h new file mode 100644 index 0000000..3b5e3d0 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod4_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD4_PC_H diff --git a/libs/fastfile/PC/fastfile_cod5_pc.cpp b/libs/fastfile/PC/fastfile_cod5_pc.cpp new file mode 100644 index 0000000..6cb91f0 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod5_pc.cpp @@ -0,0 +1,93 @@ +#include "fastfile_cod5_pc.h" +#include "zonefile_cod5_pc.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD5_PC::FastFile_COD5_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("PC"); + SetGame("COD5"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // For COD5, simply decompress from offset 12. + decompressedData = Compression::DecompressZLIB(aData.mid(12)); + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + ZoneFile_COD5_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod5_pc.h b/libs/fastfile/PC/fastfile_cod5_pc.h new file mode 100644 index 0000000..7251203 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod5_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD5_PC_H diff --git a/libs/fastfile/PC/fastfile_cod6_pc.cpp b/libs/fastfile/PC/fastfile_cod6_pc.cpp new file mode 100644 index 0000000..00413af --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod6_pc.cpp @@ -0,0 +1,90 @@ +#include "fastfile_cod6_pc.h" +#include "zonefile_cod6_pc.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD6_PC::FastFile_COD6_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetPlatform("PC"); + SetGame("COD6"); +} + +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() { + 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) { + StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000); + QByteArray decompressedData; + + // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. + const QByteArray compressedData = aData.mid(21); + decompressedData = Compression::DecompressZLIB(compressedData); + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + ZoneFile_COD6_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod6_pc.h b/libs/fastfile/PC/fastfile_cod6_pc.h new file mode 100644 index 0000000..8670c99 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod6_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD6_PC_H diff --git a/libs/fastfile/PC/fastfile_cod7_pc.cpp b/libs/fastfile/PC/fastfile_cod7_pc.cpp new file mode 100644 index 0000000..59f10b9 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod7_pc.cpp @@ -0,0 +1,170 @@ +#include "fastfile_cod7_pc.h" +#include "zonefile_cod7_pc.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD7_PC::FastFile_COD7_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD7"); + SetPlatform("PC"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD7"); + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD7_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Select key based on game. + QByteArray key; + fastFileStream.skipRawData(4); + if (GetPlatform() == "360") { + key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d"); + } else if (GetPlatform() == "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); + + // 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++; + } + + zoneFile.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod7_pc.h b/libs/fastfile/PC/fastfile_cod7_pc.h new file mode 100644 index 0000000..5372582 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod7_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD7_PC_H diff --git a/libs/fastfile/PC/fastfile_cod8_pc.cpp b/libs/fastfile/PC/fastfile_cod8_pc.cpp new file mode 100644 index 0000000..85629dd --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod8_pc.cpp @@ -0,0 +1,170 @@ +#include "fastfile_cod8_pc.h" +#include "zonefile_cod8_pc.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD8_PC::FastFile_COD8_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD8"); + SetPlatform("PC"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD7"); + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD8_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Select key based on game. + QByteArray key; + fastFileStream.skipRawData(4); + if (GetPlatform() == "360") { + key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d"); + } else if (GetPlatform() == "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); + + // 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++; + } + + zoneFile.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PC/fastfile_cod8_pc.h b/libs/fastfile/PC/fastfile_cod8_pc.h new file mode 100644 index 0000000..2476836 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod8_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD8_PC_H diff --git a/libs/fastfile/fastfile_cod9.cpp b/libs/fastfile/PC/fastfile_cod9_pc.cpp similarity index 72% rename from libs/fastfile/fastfile_cod9.cpp rename to libs/fastfile/PC/fastfile_cod9_pc.cpp index 353b0a0..7bb5b77 100644 --- a/libs/fastfile/fastfile_cod9.cpp +++ b/libs/fastfile/PC/fastfile_cod9_pc.cpp @@ -1,23 +1,46 @@ -#include "fastfile_cod9.h" -#include "zonefile_cod9.h" +#include "fastfile_cod9_pc.h" +#include "zonefile_cod9_pc.h" #include "encryption.h" #include #include -FastFile_COD9::FastFile_COD9() { +FastFile_COD9_PC::FastFile_COD9_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD9"); + SetPlatform("PC"); +} + +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() { } -FastFile_COD9::~FastFile_COD9() { - -} - -QByteArray FastFile_COD9::GetBinaryData() { +QByteArray FastFile_COD9_PC::GetBinaryData() { return QByteArray(); } -bool FastFile_COD9::Load(const QString aFilePath) { +bool FastFile_COD9_PC::Load(const QString aFilePath) { if (aFilePath.isEmpty()) { return false; } @@ -43,7 +66,7 @@ bool FastFile_COD9::Load(const QString aFilePath) { return true; } -bool FastFile_COD9::Load(const QByteArray aData) { +bool FastFile_COD9_PC::Load(const QByteArray aData) { QByteArray decompressedData; // Create a QDataStream on the input data. @@ -94,21 +117,21 @@ bool FastFile_COD9::Load(const QByteArray aData) { if (GetPlatform() == "360") { //decompressedData = Compressor::cod9_decryptFastFile(aData); } else if (GetPlatform() == "PC") { - decompressedData = Encryption::decryptFastFile(aData); + decompressedData = Encryption::decryptFastFile_BO2(aData); } // For COD9, write out the complete decompressed zone for testing. - QFile testFile("exports/" + GetStem() + ".zone"); + 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 zoneFile; - zoneFile.SetStem(GetStem()); - zoneFile.Load(decompressedData, FF_PLATFORM_PC); - SetZoneFile(std::make_shared(zoneFile)); + ZoneFile_COD9_PC zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); return true; } diff --git a/libs/fastfile/PC/fastfile_cod9_pc.h b/libs/fastfile/PC/fastfile_cod9_pc.h new file mode 100644 index 0000000..144e680 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod9_pc.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD9_PC_H diff --git a/libs/fastfile/PS3/fastfile_cod10_ps3.cpp b/libs/fastfile/PS3/fastfile_cod10_ps3.cpp new file mode 100644 index 0000000..b8535a3 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod10_ps3.cpp @@ -0,0 +1,137 @@ +#include "fastfile_cod10_ps3.h" +#include "zonefile_cod10_ps3.h" +#include "encryption.h" + +#include +#include + +FastFile_COD10_PS3::FastFile_COD10_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD10"); + SetPlatform("PS3"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod10_ps3.h b/libs/fastfile/PS3/fastfile_cod10_ps3.h new file mode 100644 index 0000000..885d4cc --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod10_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD10_PS3_H diff --git a/libs/fastfile/PS3/fastfile_cod11_ps3.cpp b/libs/fastfile/PS3/fastfile_cod11_ps3.cpp new file mode 100644 index 0000000..a2bc836 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod11_ps3.cpp @@ -0,0 +1,137 @@ +#include "fastfile_cod11_ps3.h" +#include "zonefile_cod11_ps3.h" +#include "encryption.h" + +#include +#include + +FastFile_COD11_PS3::FastFile_COD11_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD11"); + SetPlatform("PS3"); +} + +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() { + 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; +} + +bool FastFile_COD11_PS3::Load(const QByteArray aData) { + QByteArray decompressedData; + + // Create a QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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_COD11_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod11_ps3.h b/libs/fastfile/PS3/fastfile_cod11_ps3.h new file mode 100644 index 0000000..3424fb5 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod11_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD11_PS3_H diff --git a/libs/fastfile/PS3/fastfile_cod12_ps3.cpp b/libs/fastfile/PS3/fastfile_cod12_ps3.cpp new file mode 100644 index 0000000..36d0b04 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod12_ps3.cpp @@ -0,0 +1,137 @@ +#include "fastfile_cod12_ps3.h" +#include "zonefile_cod12_ps3.h" +#include "encryption.h" + +#include +#include + +FastFile_COD12_PS3::FastFile_COD12_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD12"); + SetPlatform("PS3"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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_COD12_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod12_ps3.h b/libs/fastfile/PS3/fastfile_cod12_ps3.h new file mode 100644 index 0000000..9f66318 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod12_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD12_PS3_H diff --git a/libs/fastfile/PS3/fastfile_cod4_ps3.cpp b/libs/fastfile/PS3/fastfile_cod4_ps3.cpp new file mode 100644 index 0000000..d21402a --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod4_ps3.cpp @@ -0,0 +1,120 @@ +#include "fastfile_cod4_ps3.h" +#include "zonefile_cod4_ps3.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD4_PS3::FastFile_COD4_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD4"); + SetPlatform("PS3"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + SetVersion(pParseFFVersion(&fastFileStream)); + + int pos = 12; + // Loop until EOF or invalid chunk + while (pos <= aData.size()) { + // Read 2-byte BIG-ENDIAN chunk size + quint16 chunkSize; + QDataStream chunkStream(aData.mid(pos, 2)); + chunkStream.setByteOrder(QDataStream::BigEndian); + chunkStream >> chunkSize; + + pos += 2; + + if (chunkSize == 0 || pos + chunkSize > aData.size()) { + qWarning() << "Invalid or incomplete chunk detected, stopping."; + break; + } + + const QByteArray compressedChunk = aData.mid(pos, chunkSize); + + decompressedData.append(Compression::DecompressDeflate(compressedChunk)); + + pos += chunkSize; + } + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + ZoneFile_COD4_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod4_ps3.h b/libs/fastfile/PS3/fastfile_cod4_ps3.h new file mode 100644 index 0000000..78cc865 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod4_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD4_PS3_H diff --git a/libs/fastfile/PS3/fastfile_cod5_ps3.cpp b/libs/fastfile/PS3/fastfile_cod5_ps3.cpp new file mode 100644 index 0000000..b341169 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod5_ps3.cpp @@ -0,0 +1,120 @@ +#include "fastfile_cod5_ps3.h" +#include "zonefile_cod5_ps3.h" + +#include "utils.h" +#include "compression.h" +#include "statusbarmanager.h" + +#include +#include + +FastFile_COD5_PS3::FastFile_COD5_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD5"); + SetPlatform("PS3"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + SetVersion(pParseFFVersion(&fastFileStream)); + + int pos = 12; + // Loop until EOF or invalid chunk + while (pos <= aData.size()) { + // Read 2-byte BIG-ENDIAN chunk size + quint16 chunkSize; + QDataStream chunkStream(aData.mid(pos, 2)); + chunkStream.setByteOrder(QDataStream::BigEndian); + chunkStream >> chunkSize; + + pos += 2; + + if (chunkSize == 0 || pos + chunkSize > aData.size()) { + qWarning() << "Invalid or incomplete chunk detected, stopping."; + break; + } + + const QByteArray compressedChunk = aData.mid(pos, chunkSize); + + decompressedData.append(Compression::DecompressDeflate(compressedChunk)); + + pos += chunkSize; + } + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + ZoneFile_COD5_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod5_ps3.h b/libs/fastfile/PS3/fastfile_cod5_ps3.h new file mode 100644 index 0000000..2714960 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod5_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD5_PS3_H diff --git a/libs/fastfile/fastfile_cod5.cpp b/libs/fastfile/PS3/fastfile_cod6_ps3.cpp similarity index 62% rename from libs/fastfile/fastfile_cod5.cpp rename to libs/fastfile/PS3/fastfile_cod6_ps3.cpp index 50d11f2..d6d1b7c 100644 --- a/libs/fastfile/fastfile_cod5.cpp +++ b/libs/fastfile/PS3/fastfile_cod6_ps3.cpp @@ -1,5 +1,5 @@ -#include "fastfile_cod5.h" -#include "zonefile_cod5.h" +#include "fastfile_cod6_ps3.h" +#include "zonefile_cod6_ps3.h" #include "utils.h" #include "compression.h" @@ -8,19 +8,42 @@ #include #include -FastFile_COD5::FastFile_COD5() { +FastFile_COD6_PS3::FastFile_COD6_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD6"); + SetPlatform("PS3"); +} + +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() { } -FastFile_COD5::~FastFile_COD5() { - -} - -QByteArray FastFile_COD5::GetBinaryData() { +QByteArray FastFile_COD6_PS3::GetBinaryData() { return QByteArray(); } -bool FastFile_COD5::Load(const QString aFilePath) { +bool FastFile_COD6_PS3::Load(const QString aFilePath) { StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/path", 1000); if (aFilePath.isEmpty()) { @@ -48,7 +71,7 @@ bool FastFile_COD5::Load(const QString aFilePath) { return true; } -bool FastFile_COD5::Load(const QByteArray aData) { +bool FastFile_COD6_PS3::Load(const QByteArray aData) { StatusBarManager::instance().updateStatus("Loading COD5 Fast File w/data", 1000); QByteArray decompressedData; @@ -70,19 +93,12 @@ bool FastFile_COD5::Load(const QByteArray aData) { // For COD5, simply decompress from offset 12. decompressedData = Compression::DecompressZLIB(aData.mid(12)); - Utils::ExportData(GetStem() + ".zone", decompressedData); + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); - FF_PLATFORM platform = FF_PLATFORM_NONE; - if (platformStr == "PC") { - platform = FF_PLATFORM_PC; - } else if (platformStr == "360") { - platform = FF_PLATFORM_XBOX; - } - - ZoneFile_COD5 zoneFile; - zoneFile.SetStem(GetStem()); - zoneFile.Load(decompressedData, platform); - SetZoneFile(std::make_shared(zoneFile)); + ZoneFile_COD6_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); return true; } diff --git a/libs/fastfile/PS3/fastfile_cod6_ps3.h b/libs/fastfile/PS3/fastfile_cod6_ps3.h new file mode 100644 index 0000000..aecd2b0 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod6_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD6_PS3_H diff --git a/libs/fastfile/fastfile_cod7.cpp b/libs/fastfile/PS3/fastfile_cod7_ps3.cpp similarity index 79% rename from libs/fastfile/fastfile_cod7.cpp rename to libs/fastfile/PS3/fastfile_cod7_ps3.cpp index 92f34c2..eefe0ff 100644 --- a/libs/fastfile/fastfile_cod7.cpp +++ b/libs/fastfile/PS3/fastfile_cod7_ps3.cpp @@ -1,5 +1,5 @@ -#include "fastfile_cod7.h" -#include "zonefile_cod7.h" +#include "fastfile_cod7_ps3.h" +#include "zonefile_cod7_ps3.h" #include "utils.h" #include "compression.h" @@ -8,19 +8,42 @@ #include #include -FastFile_COD7::FastFile_COD7() { +FastFile_COD7_PS3::FastFile_COD7_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD7"); + SetPlatform("PS3"); +} + +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() { } -FastFile_COD7::~FastFile_COD7() { - -} - -QByteArray FastFile_COD7::GetBinaryData() { +QByteArray FastFile_COD7_PS3::GetBinaryData() { return QByteArray(); } -bool FastFile_COD7::Load(const QString aFilePath) { +bool FastFile_COD7_PS3::Load(const QString aFilePath) { if (aFilePath.isEmpty()) { return false; } @@ -46,7 +69,7 @@ bool FastFile_COD7::Load(const QString aFilePath) { return true; } -bool FastFile_COD7::Load(const QByteArray aData) { +bool FastFile_COD7_PS3::Load(const QByteArray aData) { QByteArray decompressedData; // Create a QDataStream on the input data. @@ -64,8 +87,8 @@ bool FastFile_COD7::Load(const QByteArray aData) { SetGame("COD7"); // Load the zone file with the decompressed data (using an Xbox platform flag). - ZoneFile_COD7 zoneFile; - zoneFile.SetStem(GetStem()); + ZoneFile_COD7_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(QDataStream::BigEndian); @@ -141,28 +164,10 @@ bool FastFile_COD7::Load(const QByteArray aData) { sectionIndex++; } - zoneFile.Load(decompressedData, FF_PLATFORM_XBOX); - } else if (GetPlatform() == "Wii") { - // For COD7, simply decompress from offset 12. - decompressedData = Compression::DecompressZLIB(aData.mid(12)); - - Utils::ExportData(GetStem() + ".zone", decompressedData); - - QDir workingDir = QDir::currentPath(); - workingDir.mkdir("exports"); - - QFile outputFile("exports/" + GetStem() + ".zone"); - if (!outputFile.open(QIODevice::WriteOnly)) { - qDebug() << "Failed to extract IPAK file."; - } - qDebug() << " - File Name: " << outputFile.fileName(); - outputFile.write(decompressedData); - outputFile.close(); - - zoneFile.Load(decompressedData, FF_PLATFORM_WII); + zoneFile.Load(decompressedData); } - SetZoneFile(std::make_shared(zoneFile)); + SetZoneFile(std::make_shared(zoneFile)); return true; } diff --git a/libs/fastfile/PS3/fastfile_cod7_ps3.h b/libs/fastfile/PS3/fastfile_cod7_ps3.h new file mode 100644 index 0000000..3d1482d --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod7_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD7_PS3_H diff --git a/libs/fastfile/PS3/fastfile_cod8_ps3.cpp b/libs/fastfile/PS3/fastfile_cod8_ps3.cpp new file mode 100644 index 0000000..3d10fb5 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod8_ps3.cpp @@ -0,0 +1,173 @@ +#include "fastfile_cod8_ps3.h" +#include "zonefile_cod8_ps3.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD8_PS3::FastFile_COD8_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD8"); + SetPlatform("PS3"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD7"); + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD8_PS3 zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Select key based on game. + QByteArray key; + fastFileStream.skipRawData(4); + if (GetPlatform() == "360") { + key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d"); + } else if (GetPlatform() == "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); + + // 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++; + } + + zoneFile.Load(decompressedData); + } + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod8_ps3.h b/libs/fastfile/PS3/fastfile_cod8_ps3.h new file mode 100644 index 0000000..02570b0 --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod8_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD8_PS3_H diff --git a/libs/fastfile/PS3/fastfile_cod9_ps3.cpp b/libs/fastfile/PS3/fastfile_cod9_ps3.cpp new file mode 100644 index 0000000..e13fdef --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod9_ps3.cpp @@ -0,0 +1,137 @@ +#include "fastfile_cod9_ps3.h" +#include "zonefile_cod9_ps3.h" +#include "encryption.h" + +#include +#include + +FastFile_COD9_PS3::FastFile_COD9_PS3() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD9"); + SetPlatform("PS3"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/PS3/fastfile_cod9_ps3.h b/libs/fastfile/PS3/fastfile_cod9_ps3.h new file mode 100644 index 0000000..145f69f --- /dev/null +++ b/libs/fastfile/PS3/fastfile_cod9_ps3.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD9_PS3_H diff --git a/libs/fastfile/Wii/fastfile_cod4_wii.cpp b/libs/fastfile/Wii/fastfile_cod4_wii.cpp new file mode 100644 index 0000000..c2c920c --- /dev/null +++ b/libs/fastfile/Wii/fastfile_cod4_wii.cpp @@ -0,0 +1,86 @@ +#include "fastfile_cod4_wii.h" +#include "zonefile_cod4_wii.h" + +#include "utils.h" +#include "compression.h" + +#include +#include + +FastFile_COD4_Wii::FastFile_COD4_Wii() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD4"); + SetPlatform("Wii"); +} + +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() { + 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) { + QByteArray decompressedData; + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD4_Wii zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7, simply decompress from offset 12. + decompressedData = Compression::DecompressZLIB(aData.mid(12)); + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + zoneFile.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/Wii/fastfile_cod4_wii.h b/libs/fastfile/Wii/fastfile_cod4_wii.h new file mode 100644 index 0000000..d971c55 --- /dev/null +++ b/libs/fastfile/Wii/fastfile_cod4_wii.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD4_WII_H diff --git a/libs/fastfile/Wii/fastfile_cod7_wii.cpp b/libs/fastfile/Wii/fastfile_cod7_wii.cpp new file mode 100644 index 0000000..fed87bc --- /dev/null +++ b/libs/fastfile/Wii/fastfile_cod7_wii.cpp @@ -0,0 +1,113 @@ +#include "fastfile_cod7_wii.h" +#include "zonefile_cod7_wii.h" + +#include "utils.h" +#include "compression.h" + +#include +#include + +FastFile_COD7_Wii::FastFile_COD7_Wii() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD7"); + SetPlatform("Wii"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD7"); + + // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD7_Wii zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::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.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/Wii/fastfile_cod7_wii.h b/libs/fastfile/Wii/fastfile_cod7_wii.h new file mode 100644 index 0000000..7577422 --- /dev/null +++ b/libs/fastfile/Wii/fastfile_cod7_wii.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD7_WII_H diff --git a/libs/fastfile/Wii/fastfile_cod8_wii.cpp b/libs/fastfile/Wii/fastfile_cod8_wii.cpp new file mode 100644 index 0000000..aef0884 --- /dev/null +++ b/libs/fastfile/Wii/fastfile_cod8_wii.cpp @@ -0,0 +1,100 @@ +#include "fastfile_cod8_wii.h" +#include "zonefile_cod8_wii.h" + +#include "utils.h" +#include "compression.h" + +#include +#include + +FastFile_COD8_Wii::FastFile_COD8_Wii() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD8"); + SetPlatform("Wii"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::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_COD8_Wii zoneFile; + zoneFile.SetStem(GetBaseStem() + ".zone"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + + // For COD7, simply decompress from offset 12. + decompressedData = Compression::DecompressZLIB(aData.mid(25)); + + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + zoneFile.Load(decompressedData); + + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/Wii/fastfile_cod8_wii.h b/libs/fastfile/Wii/fastfile_cod8_wii.h new file mode 100644 index 0000000..e5a8bc2 --- /dev/null +++ b/libs/fastfile/Wii/fastfile_cod8_wii.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD8_WII_H diff --git a/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp b/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp new file mode 100644 index 0000000..1bab0e9 --- /dev/null +++ b/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp @@ -0,0 +1,135 @@ +#include "fastfile_cod10_wiiu.h" +#include "zonefile_cod10_wiiu.h" +#include "encryption.h" + +#include +#include + +FastFile_COD10_WiiU::FastFile_COD10_WiiU() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD10"); + SetPlatform("WiiU"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/WiiU/fastfile_cod10_wiiu.h b/libs/fastfile/WiiU/fastfile_cod10_wiiu.h new file mode 100644 index 0000000..85d209d --- /dev/null +++ b/libs/fastfile/WiiU/fastfile_cod10_wiiu.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD10_WIIU_H diff --git a/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp b/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp new file mode 100644 index 0000000..49e19e0 --- /dev/null +++ b/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp @@ -0,0 +1,135 @@ +#include "fastfile_cod9_wiiu.h" +#include "zonefile_cod9_wiiu.h" +#include "encryption.h" + +#include +#include + +FastFile_COD9_WiiU::FastFile_COD9_WiiU() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_UNSIGNED); + SetMagic(0); + SetVersion(0); + SetGame("COD9"); + SetPlatform("WiiU"); +} + +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() { + 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 QDataStream on the input data. + QDataStream fastFileStream(aData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse header values. + SetCompany(pParseFFCompany(&fastFileStream)); + SetType(pParseFFFileType(&fastFileStream)); + SetSignage(pParseFFSignage(&fastFileStream)); + SetMagic(pParseFFMagic(&fastFileStream)); + quint32 version = pParseFFVersion(&fastFileStream); + SetVersion(version); + SetPlatform(pCalculateFFPlatform(version)); + SetGame("COD9"); + + // For COD7/COD9, use BigEndian. + fastFileStream.setByteOrder(QDataStream::BigEndian); + if (GetPlatform() == "PC") { + fastFileStream.setByteOrder(QDataStream::LittleEndian); + } + + // Select key based on game. + QByteArray key; + if (GetPlatform() == "360") { + key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); + } else if (GetPlatform() == "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 (GetPlatform() == "360") { + //decompressedData = Compressor::cod9_decryptFastFile(aData); + } else if (GetPlatform() == "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; + zoneFile.SetStem(GetBaseStem() + ".zone"); + zoneFile.Load(decompressedData); + SetZoneFile(std::make_shared(zoneFile)); + + return true; +} diff --git a/libs/fastfile/WiiU/fastfile_cod9_wiiu.h b/libs/fastfile/WiiU/fastfile_cod9_wiiu.h new file mode 100644 index 0000000..3ac7f58 --- /dev/null +++ b/libs/fastfile/WiiU/fastfile_cod9_wiiu.h @@ -0,0 +1,20 @@ +#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() override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD9_WIIU_H diff --git a/libs/fastfile/fastfile.cpp b/libs/fastfile/fastfile.cpp index 6dcdcca..dd8f34b 100644 --- a/libs/fastfile/fastfile.cpp +++ b/libs/fastfile/fastfile.cpp @@ -1,9 +1,6 @@ #include "fastfile.h" -#include "fastfile_cod2.h" -#include "fastfile_cod5.h" -#include "fastfile_cod7.h" -#include "fastfile_cod9.h" +#include "fastfile_factory.h" #include "logmanager.h" #include @@ -22,6 +19,10 @@ FastFile::FastFile() } +FastFile::FastFile(const QByteArray &aData) { + Q_UNUSED(aData); +} + FastFile::FastFile(FastFile &fastFile) : mStem(fastFile.GetStem()), mType(fastFile.GetType()), @@ -43,6 +44,10 @@ QString FastFile::GetStem() const { return mStem; } +QString FastFile::GetBaseStem() const { + return mStem.split('.').first(); +} + FF_FILETYPE FastFile::GetType() const { return mType; } @@ -256,73 +261,16 @@ std::shared_ptr FastFile::Open(const QString &aFilePath) { LogManager::instance().addEntry("Contents read in"); LogManager::instance().addEntry(QString("- Size: %1 B").arg(data.size())); - LogManager::instance().addEntry("File closed"); file->close(); + LogManager::instance().addEntry("File closed"); - // Create a QDataStream on the input data. - QDataStream fastFileStream(data); - fastFileStream.setByteOrder(QDataStream::LittleEndian); - - quint32 companyInt; - FF_COMPANY company = pParseFFCompany(&fastFileStream, companyInt); - qDebug() << "Company: " << company; - FF_FILETYPE fileType; - FF_SIGNAGE signage; - QString magic; - quint32 version; - QString platform; - QString game; - - if ((company == COMPANY_NONE) && (companyInt == 0)) { - company = COMPANY_INFINITY_WARD; - game = "COD2"; - platform = "360"; - } else { - fileType = pParseFFFileType(&fastFileStream); - signage = pParseFFSignage(&fastFileStream); - magic = pParseFFMagic(&fastFileStream); - version = pParseFFVersion(&fastFileStream); - platform = pCalculateFFPlatform(version); - game = pCalculateFFGame(version); - - LogManager::instance().addEntry(QString("Type: %1").arg(fileType)); - LogManager::instance().addEntry(QString("Signage: %1").arg(signage)); - LogManager::instance().addEntry(QString("Magic: %1").arg(magic)); - LogManager::instance().addEntry(QString("Version: %1").arg(version)); - } - LogManager::instance().addEntry(QString("Company: %1").arg(company)); - LogManager::instance().addEntry(QString("Game: %1").arg(game)); - LogManager::instance().addEntry(QString("Platform: %1").arg(platform)); - - const QString fastFileStem = aFilePath.section("/", -1, -1).section('.', 0, 0); + const QString fastFileStem = aFilePath.section("/", -1, -1); LogManager::instance().addEntry(QString("Stem: %1").arg(fastFileStem)); - FastFile *fastFile; - bool validff = true; - if (game == "COD2") { - fastFile = new FastFile_COD2(); - } else if (game == "COD5") { - fastFile = new FastFile_COD5(); - } else if (game == "COD7") { - fastFile = new FastFile_COD7(); - } else if (game == "COD9") { - fastFile = new FastFile_COD9(); - } else { - validff = false; - } + std::shared_ptr fastFile = FastFileFactory::Create(data); + fastFile->SetStem(fastFileStem); - LogManager::instance().addLine(); - - if (validff) { - fastFile->SetCompany(company); - fastFile->SetStem(fastFileStem); - fastFile->Load(data); - return std::unique_ptr(fastFile); - } - - - // Open zone file after decompressing ff and writing - return nullptr; + return fastFile; } bool FastFile::ExportFastFile(const QString aFastFilePath) { QFile fastFile(aFastFilePath); diff --git a/libs/fastfile/fastfile.h b/libs/fastfile/fastfile.h index a1de1a2..a960917 100644 --- a/libs/fastfile/fastfile.h +++ b/libs/fastfile/fastfile.h @@ -6,12 +6,14 @@ #include #include -#include + +class ZoneFile; class FastFile { public: FastFile(); + FastFile(const QByteArray& aData); FastFile(FastFile &fastFile); ~FastFile(); @@ -23,6 +25,7 @@ public: virtual QByteArray GetBinaryData() = 0; virtual QString GetStem() const; + virtual QString GetBaseStem() const; virtual FF_FILETYPE GetType() const; virtual FF_COMPANY GetCompany() const; virtual FF_SIGNAGE GetSignage() const; diff --git a/libs/fastfile/fastfile.pro b/libs/fastfile/fastfile.pro index 9729134..756d37b 100644 --- a/libs/fastfile/fastfile.pro +++ b/libs/fastfile/fastfile.pro @@ -3,18 +3,89 @@ TEMPLATE = lib CONFIG += staticlib c++17 SOURCES += \ - fastfile_cod2.cpp \ - fastfile_cod5.cpp \ - fastfile_cod7.cpp \ - fastfile_cod9.cpp \ - fastfile.cpp + # Base class & factory + fastfile.cpp \ + # 360 classes + 360/fastfile_cod2_360.cpp \ + 360/fastfile_cod4_360.cpp \ + 360/fastfile_cod5_360.cpp \ + 360/fastfile_cod6_360.cpp \ + 360/fastfile_cod7_360.cpp \ + 360/fastfile_cod8_360.cpp \ + 360/fastfile_cod9_360.cpp \ + 360/fastfile_cod10_360.cpp \ + 360/fastfile_cod11_360.cpp \ + 360/fastfile_cod12_360.cpp \ + # PS3 classes + PS3/fastfile_cod4_ps3.cpp \ + PS3/fastfile_cod5_ps3.cpp \ + PS3/fastfile_cod6_ps3.cpp \ + PS3/fastfile_cod7_ps3.cpp \ + PS3/fastfile_cod8_ps3.cpp \ + PS3/fastfile_cod9_ps3.cpp \ + PS3/fastfile_cod10_ps3.cpp \ + PS3/fastfile_cod11_ps3.cpp \ + PS3/fastfile_cod12_ps3.cpp \ + # PC classes + PC/fastfile_cod4_pc.cpp \ + PC/fastfile_cod5_pc.cpp \ + PC/fastfile_cod6_pc.cpp \ + PC/fastfile_cod7_pc.cpp \ + PC/fastfile_cod8_pc.cpp \ + PC/fastfile_cod9_pc.cpp \ + PC/fastfile_cod10_pc.cpp \ + PC/fastfile_cod11_pc.cpp \ + PC/fastfile_cod12_pc.cpp \ + # Wii Classes + Wii/fastfile_cod4_wii.cpp \ + Wii/fastfile_cod7_wii.cpp \ + Wii/fastfile_cod8_wii.cpp \ + # WiiU Classes + WiiU/fastfile_cod9_wiiu.cpp \ + WiiU/fastfile_cod10_wiiu.cpp HEADERS += \ + # Base class & factory fastfile.h \ - fastfile_cod2.h \ - fastfile_cod5.h \ - fastfile_cod7.h \ - fastfile_cod9.h + fastfile_factory.h \ + # 360 classes + 360/fastfile_cod2_360.h \ + 360/fastfile_cod4_360.h \ + 360/fastfile_cod5_360.h \ + 360/fastfile_cod6_360.h \ + 360/fastfile_cod7_360.h \ + 360/fastfile_cod8_360.h \ + 360/fastfile_cod9_360.h \ + 360/fastfile_cod10_360.h \ + 360/fastfile_cod11_360.h \ + 360/fastfile_cod12_360.h \ + # PS3 classes + PS3/fastfile_cod4_ps3.h \ + PS3/fastfile_cod5_ps3.h \ + PS3/fastfile_cod6_ps3.h \ + PS3/fastfile_cod7_ps3.h \ + PS3/fastfile_cod8_ps3.h \ + PS3/fastfile_cod9_ps3.h \ + PS3/fastfile_cod10_ps3.h \ + PS3/fastfile_cod11_ps3.h \ + PS3/fastfile_cod12_ps3.h \ + # PC classes + PC/fastfile_cod4_pc.h \ + PC/fastfile_cod5_pc.h \ + PC/fastfile_cod6_pc.h \ + PC/fastfile_cod7_pc.h \ + PC/fastfile_cod8_pc.h \ + PC/fastfile_cod9_pc.h \ + PC/fastfile_cod10_pc.h \ + PC/fastfile_cod11_pc.h \ + PC/fastfile_cod12_pc.h \ + # Wii Classes + Wii/fastfile_cod4_wii.h \ + Wii/fastfile_cod7_wii.h \ + Wii/fastfile_cod8_wii.h \ + # WiiU classes + WiiU/fastfile_cod9_wiiu.h \ + WiiU/fastfile_cod10_wiiu.h LIBS += \ -L$$OUT_PWD/../libs/core -lcore \ @@ -26,7 +97,12 @@ INCLUDEPATH += \ $$PWD/../core \ $$PWD/../compression \ $$PWD/../encryption \ - $$PWD/../zonefile + $$PWD/../zonefile \ + $$PWD/../zonefile/360 \ + $$PWD/../zonefile/PC \ + $$PWD/../zonefile/PS3 \ + $$PWD/../zonefile/Wii \ + $$PWD/../zonefile/WiiU DEPENDPATH += \ $$PWD/../core \ diff --git a/libs/fastfile/fastfile_cod2.h b/libs/fastfile/fastfile_cod2.h deleted file mode 100644 index 91adfe9..0000000 --- a/libs/fastfile/fastfile_cod2.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FASTFILE_COD2_H -#define FASTFILE_COD2_H - -#include "fastfile.h" - -class FastFile_COD2 : public FastFile -{ -public: - FastFile_COD2(); - ~FastFile_COD2(); - - QByteArray GetBinaryData() override; - - bool Load(const QString aFilePath) override; - bool Load(const QByteArray aData) override; -}; - -#endif // FASTFILE_COD2_H diff --git a/libs/fastfile/fastfile_cod5.h b/libs/fastfile/fastfile_cod5.h deleted file mode 100644 index 0622ce3..0000000 --- a/libs/fastfile/fastfile_cod5.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FASTFILE_COD5_H -#define FASTFILE_COD5_H - -#include "fastfile.h" - -class FastFile_COD5 : public FastFile -{ -public: - FastFile_COD5(); - ~FastFile_COD5(); - - QByteArray GetBinaryData() override; - - bool Load(const QString aFilePath) override; - bool Load(const QByteArray aData) override; -}; - -#endif // FASTFILE_COD5_H diff --git a/libs/fastfile/fastfile_cod7.h b/libs/fastfile/fastfile_cod7.h deleted file mode 100644 index ae2d478..0000000 --- a/libs/fastfile/fastfile_cod7.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FASTFILE_COD7_H -#define FASTFILE_COD7_H - -#include "fastfile.h" - -class FastFile_COD7 : public FastFile -{ -public: - FastFile_COD7(); - ~FastFile_COD7(); - - QByteArray GetBinaryData() override; - - bool Load(const QString aFilePath) override; - bool Load(const QByteArray aData) override; -}; - -#endif // FASTFILE_COD7_H diff --git a/libs/fastfile/fastfile_cod9.h b/libs/fastfile/fastfile_cod9.h deleted file mode 100644 index fdc3d16..0000000 --- a/libs/fastfile/fastfile_cod9.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef FASTFILE_COD9_H -#define FASTFILE_COD9_H - -#include "fastfile.h" - -class FastFile_COD9 : public FastFile -{ -public: - FastFile_COD9(); - ~FastFile_COD9(); - - QByteArray GetBinaryData() override; - - bool Load(const QString aFilePath) override; - bool Load(const QByteArray aData) override; -}; - -#endif // FASTFILE_COD9_H diff --git a/libs/fastfile/fastfile_factory.h b/libs/fastfile/fastfile_factory.h new file mode 100644 index 0000000..2eb04b6 --- /dev/null +++ b/libs/fastfile/fastfile_factory.h @@ -0,0 +1,345 @@ +#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_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 "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 +#include +#include +#include +#include + +class FastFile; + +enum FastFile_Platform { + PLATFORM_NONE = 0x00, + PLATFORM_PC = 0x01, + PLATFORM_360 = 0x02, + PLATFORM_PS3 = 0x03, + PLATFORM_WII = 0x04, + PLATFORM_WIIU = 0x05 +}; + +enum FastFile_Game { + GAME_NONE = 0x00, + GAME_COD2 = 0x01, + GAME_COD4 = 0x02, + GAME_COD5 = 0x03, + GAME_COD6 = 0x04, + GAME_COD7 = 0x05, + GAME_COD8 = 0x06, + GAME_COD9 = 0x07, + GAME_COD10 = 0x08, + GAME_COD11 = 0x09, + GAME_COD12 = 0x010 +}; + +class FastFileFactory { +public: + static std::shared_ptr Create(const QString& aFilePath, bool aEmpty = false) { + 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 QString newPath = (aEmpty ? "" : aFilePath); + + const QByteArray data = fastFile.readAll(); + std::shared_ptr resultFF = nullptr; + + const FastFile_Platform platform = pGetPlatform(data); + const FastFile_Game game = pGetGame(data); + + if (platform == PLATFORM_360) { + if (game == GAME_COD2) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD4) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD5) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD6) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD9) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD11) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD12) { + resultFF = std::make_shared(newPath); + } + } else if (platform == PLATFORM_PC) { + if (game == GAME_COD4) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD5) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD6) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD9) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD11) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD12) { + resultFF = std::make_shared(newPath); + } + } else if (platform == PLATFORM_PS3) { + if (game == GAME_COD4) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD5) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD6) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD9) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD11) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD12) { + resultFF = std::make_shared(newPath); + } + } else if (platform == PLATFORM_WII) { + if (game == GAME_COD4) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(newPath); + } + } else if (platform == PLATFORM_WIIU) { + if (game == GAME_COD9) { + resultFF = std::make_shared(newPath); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(newPath); + } + } + return resultFF; + } + static std::shared_ptr Create(const QByteArray& aData, const QString aStem = "no_name") { + std::shared_ptr resultFF = nullptr; + + const FastFile_Platform platform = pGetPlatform(aData); + const FastFile_Game game = pGetGame(aData); + if (platform == PLATFORM_360) { + if (game == GAME_COD2) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD4) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD5) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD6) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD9) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD11) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD12) { + resultFF = std::make_shared(aData); + } + } else if (platform == PLATFORM_PC) { + if (game == GAME_COD4) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD5) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD6) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD9) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD11) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD12) { + resultFF = std::make_shared(aData); + } + } else if (platform == PLATFORM_PS3) { + if (game == GAME_COD4) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD5) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD6) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD9) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD11) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD12) { + resultFF = std::make_shared(aData); + } + } else if (platform == PLATFORM_WII) { + if (game == GAME_COD4) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD7) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD8) { + resultFF = std::make_shared(aData); + } + } else if (platform == PLATFORM_WIIU) { + if (game == GAME_COD9) { + resultFF = std::make_shared(aData); + } else if (game == GAME_COD10) { + resultFF = std::make_shared(aData); + } + } + if (resultFF) { + resultFF->SetStem(aStem); + } + 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 FastFile_Platform pGetPlatform(const QByteArray& aData) { + const QStringList sections = pGetDataSections(aData); + if (sections[0] == "0000") { + return PLATFORM_360; + } else if (sections[4] == "0000") { + if (sections[5] == "0001" && sections[6] == "78DA") { + return PLATFORM_360; + } else if (sections[5] == "0001" && sections[6] == "4957") { + return PLATFORM_360; + } else if (sections[5] == "0183" && sections[6] == "7801") { + return PLATFORM_360; + } else if (sections[6] == "0101" && sections[7] == "CA3E") { + return PLATFORM_360; + } else if (sections[6] == "0000" && sections[7] == "0001") { + return PLATFORM_360; + } else if (sections[6] == "0101" && sections[7] == "CC76") { + return PLATFORM_360; + } else if (sections[6] == "0101" && sections[7] == "0101") { + return PLATFORM_360; + } else if (sections[2] == "7831") { + return PLATFORM_360; + } else if (sections[0] == "5331" && sections[2] == "7531") { + return PLATFORM_360; + } else if (sections[2] == "3030" && sections[3] == "3030") { + return PLATFORM_360; + } 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 FastFile_Game 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[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; + } + return GAME_NONE; + } +}; + +#endif // FASTFILE_FACTORY_H diff --git a/libs/zonefile/360/zonefile_cod10_360.cpp b/libs/zonefile/360/zonefile_cod10_360.cpp new file mode 100644 index 0000000..aa722a2 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod10_360.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod10_360.h" + +#include +#include +#include + +ZoneFile_COD10_360::ZoneFile_COD10_360() +{ + +} + +ZoneFile_COD10_360::~ZoneFile_COD10_360() +{ + +} + +bool ZoneFile_COD10_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD10_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD10_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD10_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD10_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD10_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD10_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD10_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD10_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD10_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD10_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD10_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD10_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD10_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD10_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD10_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD10_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD10_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD10_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD10_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD10_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD10_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD10_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD10_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/zonefile_cod7.h b/libs/zonefile/360/zonefile_cod10_360.h similarity index 86% rename from libs/zonefile/zonefile_cod7.h rename to libs/zonefile/360/zonefile_cod10_360.h index 6509b4e..eae80e4 100644 --- a/libs/zonefile/zonefile_cod7.h +++ b/libs/zonefile/360/zonefile_cod10_360.h @@ -1,21 +1,21 @@ -#ifndef ZONEFILE_COD7_H -#define ZONEFILE_COD7_H +#ifndef ZONEFILE_COD10_360_H +#define ZONEFILE_COD10_360_H #include "zonefile.h" -class ZoneFile_COD7 : public ZoneFile +class ZoneFile_COD10_360 : public ZoneFile { public: - ZoneFile_COD7(); - ~ZoneFile_COD7(); + ZoneFile_COD10_360(); + ~ZoneFile_COD10_360(); - bool Load(const QByteArray aFileData, FF_PLATFORM aPlatform) override; - QString AssetTypeToString(const QString aAssetType); + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; QByteArray GetBinaryData() override; protected: - void pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) override; + void pParseZoneHeader(QDataStream *aZoneFileStream) override; quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; @@ -49,4 +49,4 @@ protected: StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; }; -#endif // ZONEFILE_COD7_H +#endif // ZONEFILE_COD10_360_H diff --git a/libs/zonefile/360/zonefile_cod11_360.cpp b/libs/zonefile/360/zonefile_cod11_360.cpp new file mode 100644 index 0000000..7b00a7b --- /dev/null +++ b/libs/zonefile/360/zonefile_cod11_360.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod11_360.h" + +#include +#include +#include + +ZoneFile_COD11_360::ZoneFile_COD11_360() +{ + +} + +ZoneFile_COD11_360::~ZoneFile_COD11_360() +{ + +} + +bool ZoneFile_COD11_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD11_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD11_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD11_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD11_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD11_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD11_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD11_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD11_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD11_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD11_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD11_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD11_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD11_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD11_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD11_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD11_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD11_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD11_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD11_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD11_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD11_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD11_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD11_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/zonefile_cod2.h b/libs/zonefile/360/zonefile_cod11_360.h similarity index 86% rename from libs/zonefile/zonefile_cod2.h rename to libs/zonefile/360/zonefile_cod11_360.h index 9d560f7..b916039 100644 --- a/libs/zonefile/zonefile_cod2.h +++ b/libs/zonefile/360/zonefile_cod11_360.h @@ -1,21 +1,21 @@ -#ifndef ZONEFILE_COD2_H -#define ZONEFILE_COD2_H +#ifndef ZONEFILE_COD11_360_H +#define ZONEFILE_COD11_360_H #include "zonefile.h" -class ZoneFile_COD2 : public ZoneFile +class ZoneFile_COD11_360 : public ZoneFile { public: - ZoneFile_COD2(); - ~ZoneFile_COD2(); + ZoneFile_COD11_360(); + ~ZoneFile_COD11_360(); - bool Load(const QByteArray aFileData, FF_PLATFORM aPlatform) override; - QString AssetTypeToString(const QString aAssetType); + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; QByteArray GetBinaryData() override; protected: - void pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) override; + void pParseZoneHeader(QDataStream *aZoneFileStream) override; quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; @@ -49,4 +49,4 @@ protected: StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; }; -#endif // ZONEFILE_COD2_H +#endif // ZONEFILE_COD11_360_H diff --git a/libs/zonefile/360/zonefile_cod12_360.cpp b/libs/zonefile/360/zonefile_cod12_360.cpp new file mode 100644 index 0000000..e82d6ef --- /dev/null +++ b/libs/zonefile/360/zonefile_cod12_360.cpp @@ -0,0 +1,1207 @@ +#include "zonefile_cod12_360.h" + +#include +#include +#include + +ZoneFile_COD12_360::ZoneFile_COD12_360() +{ + +} + +ZoneFile_COD12_360::~ZoneFile_COD12_360() +{ + +} + +bool ZoneFile_COD12_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD12_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + aZoneFileStream->skipRawData(7 * 4); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream) - 1; + SetRecordCount(recordCount); + + aZoneFileStream->skipRawData(5 * 4); + + if (tagCount) { + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } +} + +quint32 ZoneFile_COD12_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD12_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD12_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD12_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(8 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + if (aZoneFileStream->device()->peek(8).toHex().contains("00000000")) { + break; + } + + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD12_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(8, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 8); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(8); + } + return result; +} + +AssetMap ZoneFile_COD12_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // raw file + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_SCRIPT_PARSE_TREE) { // gsc + auto gscFile = pParseAsset_GSCFile(aZoneFileStream); + if (gscFile.length) { + result.gscFiles << gscFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD12_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD12_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +GscFile ZoneFile_COD12_360::pParseAsset_GSCFile(QDataStream *aZoneFileStream) { + GscFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(8); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(8); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD12_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD12_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD12_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD12_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD12_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD12_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD12_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + return result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD12_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD12_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD12_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD12_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD12_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD12_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "0000000000000000") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "0100000000000000") { + return ASSET_PHYS_CONSTRAINTS; + } else if (cleanedType == "0200000000000000") { + return ASSET_DESTRUCTIBLE_DEF; + } else if (cleanedType == "0300000000000000") { + return ASSET_ANIMATION; + } else if (cleanedType == "0400000000000000") { + return ASSET_MODEL; + } else if (cleanedType == "0500000000000000") { + return ASSET_MODEL_MESH; + } else if (cleanedType == "0600000000000000") { + return ASSET_MATERIAL; + } else if (cleanedType == "0700000000000000") { + return ASSET_COMPUTE_SHADER_SET; + } else if (cleanedType == "0800000000000000") { + return ASSET_TECH_SET; + } else if (cleanedType == "0900000000000000") { + return ASSET_IMAGE; + } else if (cleanedType == "0A00000000000000") { + return ASSET_SOUND; + } else if (cleanedType == "1100000000000000") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "1500000000000000") { + return ASSET_FONT_ICON; + } else if (cleanedType == "1700000000000000") { + return ASSET_WEAPON; + } else if (cleanedType == "1C00000000000000") { + return ASSET_PLAYER_SOUNDS_TABLE; + } else if (cleanedType == "1D00000000000000") { + return ASSET_PLAYER_FX_TABLE; + } else if (cleanedType == "1E00000000000000") { + return ASSET_SHARED_WEAPON_SOUNDS; + } else if (cleanedType == "1F00000000000000") { + return ASSET_ATTACHMENT; + } else if (cleanedType == "2000000000000000") { + return ASSET_ATTACHMENT_UNIQUE; + } else if (cleanedType == "2100000000000000") { + return ASSET_WEAPON_CAMO; + } else if (cleanedType == "2200000000000000") { + return ASSET_CUSTOMIZATION_TABLE; + } else if (cleanedType == "2300000000000000") { + return ASSET_CUSTOMIZATION_TABLE_FEIMAGES; + } else if (cleanedType == "2400000000000000") { + return ASSET_CUSTOMIZATION_TABLE_COLOR; + }else if (cleanedType == "2600000000000000") { + return ASSET_EFFECT; + } else if (cleanedType == "2F00000000000000") { + return ASSET_RAW_FILE; + } else if (cleanedType == "3000000000000000") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "3100000000000000") { + return ASSET_STRUCTURED_TABLE; + } else if (cleanedType == "3200000000000000") { + return ASSET_LEADERBOARD_DEF; + } else if (cleanedType == "3300000000000000") { + return ASSET_DDL; + } else if (cleanedType == "3600000000000000") { + return ASSET_SCRIPT_PARSE_TREE; + } else if (cleanedType == "3700000000000000") { + return ASSET_KEY_VALUE_PAIRS; + } else if (cleanedType == "3800000000000000") { + return ASSET_VEHICLE; + } else if (cleanedType == "3A00000000000000") { + return ASSET_VEHICLE_TRACER; + } else if (cleanedType == "3C00000000000000") { + return ASSET_SURFACE_FX_TABLE; + } else if (cleanedType == "3D00000000000000") { + return ASSET_SURFACE_SOUND_DEF; + } else if (cleanedType == "3E00000000000000") { + return ASSET_FOOTSTEP_TABLE; + } else if (cleanedType == "3F00000000000000") { + return ASSET_ENTITY_FX_IMPACTS; + } else if (cleanedType == "4000000000000000") { + return ASSET_ENTITY_SOUND_IMPACTS; + } else if (cleanedType == "4200000000000000") { + return ASSET_VEHICLE_FX_DEF; + } else if (cleanedType == "4300000000000000") { + return ASSET_VEHICLE_SOUND_DEF; + } else if (cleanedType == "4500000000000000") { + return ASSET_SCRIPT_BUNDLE; + } else if (cleanedType == "4600000000000000") { + return ASSET_SCRIPT_BUNDLE_LIST; + } else if (cleanedType == "4700000000000000") { + return ASSET_RUMBLE; + } else if (cleanedType == "4A00000000000000") { + return ASSET_AIM_TABLE; + } else if (cleanedType == "4B00000000000000") { + return ASSET_ANIM_SELECTOR_TABLE; + } else if (cleanedType == "4C00000000000000") { + return ASSET_ANIM_MAPPING_TABLE; + } else if (cleanedType == "4D00000000000000") { + return ASSET_ANIM_STATE_MACHINE; + } else if (cleanedType == "4E00000000000000") { + return ASSET_BEHAVIOR_TREE; + } else if (cleanedType == "4F00000000000000") { + return ASSET_BEHAVIOR_STATE_MACHINE; + } else if (cleanedType == "5100000000000000") { + return ASSET_S_ANIM; + } else if (cleanedType == "5200000000000000") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "5300000000000000") { + return ASSET_BIT_FIELD; + } else if (cleanedType == "5400000000000000") { + return ASSET_SURFACE_SOUND_DEF; + } else if (cleanedType == "5500000000000000") { + return ASSET_SURFACE_FX_TABLE; + } else if (cleanedType == "5600000000000000") { + return ASSET_RUMBLE; + } else if (cleanedType == "5900000000000000") { + return ASSET_AIM_TABLE; + } else if (cleanedType == "5A00000000000000") { + return ASSET_MAP_TABLE; + } else if (cleanedType == "5B00000000000000") { + return ASSET_MAP_TABLE_LOADING_IMAGES; + } else if (cleanedType == "5C00000000000000") { + return ASSET_MEDAL; + } else if (cleanedType == "5D00000000000000") { + return ASSET_MEDAL_TABLE; + } else if (cleanedType == "5E00000000000000") { + return ASSET_OBJECTIVE; + } else if (cleanedType == "5F00000000000000") { + return ASSET_OBJECTIVE_LIST; + } else if (cleanedType == "6400000000000000") { + return ASSET_LASER; + } else if (cleanedType == "6500000000000000") { + return ASSET_BEAM; + } else if (cleanedType == "6600000000000000") { + return ASSET_STREAMER_HINT; + } else if (cleanedType == "1B00000000000000") { + return ASSET_CG_MEDIA_TABLE; + } + + return ASSET_NONE; +} + +QByteArray ZoneFile_COD12_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/360/zonefile_cod12_360.h b/libs/zonefile/360/zonefile_cod12_360.h new file mode 100644 index 0000000..9aacabe --- /dev/null +++ b/libs/zonefile/360/zonefile_cod12_360.h @@ -0,0 +1,53 @@ +#ifndef ZONEFILE_COD12_360_H +#define ZONEFILE_COD12_360_H + +#include "zonefile.h" + +class ZoneFile_COD12_360: public ZoneFile +{ +public: + ZoneFile_COD12_360(); + ~ZoneFile_COD12_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + GscFile pParseAsset_GSCFile(QDataStream *aZoneFileStream) ; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD12_PC_H diff --git a/libs/zonefile/360/zonefile_cod2_360.cpp b/libs/zonefile/360/zonefile_cod2_360.cpp new file mode 100644 index 0000000..6a3f758 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod2_360.cpp @@ -0,0 +1,1133 @@ +#include "zonefile_cod2_360.h" + +#include +#include +#include + +ZoneFile_COD2_360::ZoneFile_COD2_360() +{ + +} + +ZoneFile_COD2_360::~ZoneFile_COD2_360() +{ + +} + +bool ZoneFile_COD2_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + + zoneFileStream.skipRawData(4 * GetMiscCount()); + pParseMiscTags(&zoneFileStream); + + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD2_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + + aZoneFileStream->skipRawData(4); + + SetMiscCount(pParseZoneTagCount(aZoneFileStream)); + + aZoneFileStream->skipRawData(4); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + aZoneFileStream->skipRawData(4); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD2_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD2_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD2_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD2_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD2_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD2_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD2_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * tagCount); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +QStringList ZoneFile_COD2_360::pParseMiscTags(QDataStream *aZoneFileStream) { + QStringList tags; + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + while (aZoneFileStream->device()->peek(8).right(4).toHex() != "ffffffff") { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD2_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + // Parse index & map found asset types + for (quint32 i = 0; i < recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD2_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + //aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType assetType = AssetStrToEnum(typeHex); + + if (assetType == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (assetType == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (assetType == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (assetType == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (assetType == ASSET_MATERIAL) { // material + result.materials << pParseAsset_Material(aZoneFileStream); + } else if (assetType == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (assetType == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (assetType == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (assetType == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (assetType == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (assetType == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (assetType == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (assetType == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (assetType == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (assetType == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (assetType == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (assetType == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (assetType == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (assetType == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (assetType == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (assetType == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (assetType == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD2_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD2_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + qint32 rawFilePtr; + *aZoneFileStream >> rawFilePtr; + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + const QStringList tags = GetTags(); + if (rawFilePtr == -1) { + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + } else if (rawFilePtr > 0 && rawFilePtr < tags.size() + 2) { + result.path = tags[rawFilePtr - 1]; + } + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + if (result.length) { + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } else { + aZoneFileStream->skipRawData(1); + } + return result; +} + +void ZoneFile_COD2_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD2_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Shader ZoneFile_COD2_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD2_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD2_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna + >> result.unknownb + >> result.unknownc + >> result.unknownd + >> result.unknowne + >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +Material ZoneFile_COD2_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Material result; + + *aZoneFileStream >> result.namePtr; + if (result.namePtr != quint32(-1) && result.namePtr > 0 && + GetTagCount() > static_cast(result.namePtr - 1)) { + result.name = GetTags()[result.namePtr - 1]; + } + *aZoneFileStream >> result.refNamePtr; + if (result.refNamePtr != 4294967295 && GetTagCount() > result.refNamePtr - 1) { + result.refName = GetTags()[result.refNamePtr - 1]; + } + aZoneFileStream->skipRawData(12); + + for (int i = 0; i < 13; i++) { + qint32 unknownPtr; + *aZoneFileStream >> unknownPtr; + result.pointers << unknownPtr; + } + + *aZoneFileStream >> result.stateBits[0] >> result.stateBits[1] + >> result.textureCount >> result.constCount >> result.techSetPtr + >> result.texturePtr >> result.constPtr; + + + return result; +} + +SoundAsset ZoneFile_COD2_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + qDebug() << "- " << aZoneFileStream->device()->pos(); + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD2_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD2_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD2_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD2_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD2_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD2_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD2_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "00000017") { + return ASSET_RAW_FILE; + } else if (cleanedType == "") { + return ASSET_EFFECT; + } else if (cleanedType == "") { + return ASSET_SOUND; + } else if (cleanedType == "") { + return ASSET_ANIMATION; + } else if (cleanedType == "") { + return ASSET_COLLISION_MAP; + } else if (cleanedType == "") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "") { + return ASSET_MENU; + } else if (cleanedType == "") { + return ASSET_TECH_SET; + } else if (cleanedType == "") { + return ASSET_LOCAL_STRING; + } else if (cleanedType == "") { + return ASSET_GFX_MAP; + } else if (cleanedType == "") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "") { + return ASSET_FONT; + } else if (cleanedType == "") { + return ASSET_MODEL; + } else if (cleanedType == "00000006") { + return ASSET_D3DBSP; + } else if (cleanedType == "00000002") { + return ASSET_MATERIAL; + } else if (cleanedType == "") { + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "") { + return ASSET_COL_MAP_SP; + } else if (cleanedType == "") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "") { + return ASSET_DESTRUCTIBLE; + } else if (cleanedType == "00000004") { + return ASSET_SHOCK_FILE; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD2_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/360/zonefile_cod2_360.h b/libs/zonefile/360/zonefile_cod2_360.h new file mode 100644 index 0000000..ac50d24 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod2_360.h @@ -0,0 +1,64 @@ +#ifndef ZONEFILE_COD2_360_H +#define ZONEFILE_COD2_360_H + +#include "zonefile.h" + +class ZoneFile_COD2_360 : public ZoneFile +{ +public: + ZoneFile_COD2_360(); + ~ZoneFile_COD2_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + + void SetMiscCount(quint32 aMiscCount) { + mMiscCount = aMiscCount; + } + + quint32 GetMiscCount() { + return mMiscCount; + } + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseMiscTags(QDataStream *aZoneFileStream); + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; + +private: + quint32 mMiscCount; +}; + +#endif // ZONEFILE_COD2_360_H diff --git a/libs/zonefile/360/zonefile_cod4_360.cpp b/libs/zonefile/360/zonefile_cod4_360.cpp new file mode 100644 index 0000000..d9ecb43 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod4_360.cpp @@ -0,0 +1,1197 @@ +#include "zonefile_cod4_360.h" +#include "utils.h" + +#include +#include +#include + +ZoneFile_COD4_360::ZoneFile_COD4_360() + : ZoneFile() { + +} + +ZoneFile_COD4_360::~ZoneFile_COD4_360() { + +} + +bool ZoneFile_COD4_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD4_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD4_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD4_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD4_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD4_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { + tags << zoneTag; + } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD4_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 1); + } + + // Parse index & map found asset types + for (quint32 i = 0; i < recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD4_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType assetType = AssetStrToEnum(typeHex); + const QString typeStr = AssetEnumToStr(assetType); + + if (assetType == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (assetType == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (assetType == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (assetType == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (assetType == ASSET_MATERIAL) { // material + result.materials << pParseAsset_Material(aZoneFileStream); + } else if (assetType == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (assetType == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (assetType == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (assetType == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (assetType == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (assetType == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (assetType == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (assetType == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (assetType == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (assetType == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (assetType == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (assetType == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (assetType == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (assetType == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (assetType == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (assetType == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (assetType == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD4_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + qint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == -1) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == -1) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD4_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + result.startPos = aZoneFileStream->device()->pos(); + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + + result.endPos = aZoneFileStream->device()->pos(); + return result; +} + +void ZoneFile_COD4_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD4_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + aZoneFileStream->skipRawData(4); + + QByteArray modelMagic(4, Qt::Uninitialized); + aZoneFileStream->readRawData(modelMagic.data(), 4); + if (modelMagic.toHex() != "01010200") { + qDebug() << "Invalid model magic: " << modelMagic.toHex(); + return result; + } + qDebug() << "Model Magic: " << modelMagic.toHex(); + + aZoneFileStream->skipRawData(8 * 4); + + for (int i = 0; i < 4; i++) { + + QByteArray lodData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(lodData.data(), 4); + + float levelOfDetail = qFromBigEndian(reinterpret_cast(lodData.constData())); + + quint16 surfacePresent; + *aZoneFileStream >> surfacePresent; + + quint16 surfaceIndex; + *aZoneFileStream >> surfaceIndex; + + if (surfacePresent) { + qDebug() << "Surface " << surfaceIndex << " detected"; + qDebug() << "- Level of Detail: " << levelOfDetail; + } + aZoneFileStream->skipRawData(4 * 4); + } + aZoneFileStream->skipRawData(17 * 4); + + qDebug() << "Name Char: " << aZoneFileStream->device()->pos(); + QString modelName; + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar != 0) { + modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + qDebug() << "Model Name: " << modelName; + + aZoneFileStream->skipRawData(4 * 9 + 1); + + quint16 vertCount, faceCount; + *aZoneFileStream >> vertCount >> faceCount; + qDebug() << "Vertex count 1: " << vertCount; + qDebug() << "Face count 1: " << faceCount; + + aZoneFileStream->skipRawData(57 * 4 - 2); + + qDebug() << "Vertex Listing: " << aZoneFileStream->device()->pos(); + for (int i = 0; i < vertCount; i++) { + qDebug() << "- Vertex " << i; + + QByteArray xOffData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(xOffData.data(), 4); + float xOff = qFromBigEndian(reinterpret_cast(xOffData.constData())); + + QByteArray yOffData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(yOffData.data(), 4); + float yOff = qFromBigEndian(reinterpret_cast(yOffData.constData())); + + QByteArray zOffData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(zOffData.data(), 4); + float zOff = qFromBigEndian(reinterpret_cast(zOffData.constData())); + + qDebug() << " - Offset: " << xOff << ", " << yOff << ", " << zOff; + aZoneFileStream->skipRawData(20); + } + + qDebug() << "Count 2: " << aZoneFileStream->device()->pos(); + quint32 vertCount1, faceCount1; + *aZoneFileStream >> vertCount1 >> faceCount1; + qDebug() << "Vertex count 2: " << vertCount1; + qDebug() << "Face count 2: " << faceCount1; + + aZoneFileStream->skipRawData(1968); + + for (int i = 0; i < faceCount - 6; i++) { + aZoneFileStream->skipRawData(64); + } + aZoneFileStream->skipRawData(224); + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() + aZoneFileStream->device()->peek(1024).toHex().indexOf("ffffffff")); + + return result; +} + +Material ZoneFile_COD4_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Material result; + + *aZoneFileStream >> result.namePtr; + + //aZoneFileStream->skipRawData(23 * 4); + + for (int i = 0; i < 23; i++) { + qint32 unknownPtr; + *aZoneFileStream >> unknownPtr; + result.pointers << unknownPtr; + } + + if (result.namePtr == -1) { + aZoneFileStream->skipRawData(1); + + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.name += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + return result; +} + +Shader ZoneFile_COD4_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD4_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + qint32 namePtr; + *aZoneFileStream >> namePtr; + + + for (int i = 0; i < 28; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + + if (namePtr == -1) { + aZoneFileStream->skipRawData(1); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + } + + //result.name.replace(",", ""); + return result; +} + +Image ZoneFile_COD4_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + qDebug() << "Header" << aZoneFileStream->device()->pos(); + qDebug() << "- Start Pos: " << aZoneFileStream->device()->pos(); + aZoneFileStream->skipRawData(14); + + QByteArray sectionCountData(1, Qt::Uninitialized); + aZoneFileStream->readRawData(sectionCountData.data(), 1); + + QString sectionCountStr = sectionCountData.toHex(); + std::reverse(sectionCountStr.begin(), sectionCountStr.end()); + + quint32 sectionCount = sectionCountStr.toInt(); + qDebug() << "- Section Count: " << sectionCountStr << " : " << sectionCount; + + aZoneFileStream->skipRawData(25); + + // Parse image name + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + result.materialName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + qDebug() << "- Name: " << result.name; + qDebug() << "- End Pos: " << aZoneFileStream->device()->pos(); + + qDebug() << "Chunks [" << sectionCount << "]"; + for (int i = 0; i < sectionCount; i++) { + qDebug() << "- Chunk " << sectionCount; + qDebug() << " - Header" << sectionCount; + qDebug() << " - Start Pos: " << aZoneFileStream->device()->pos(); + + // TODO: Parse header/index/pointers? + for (int j = 0; j < 60; j++) { + quint32 unknownPtr; + *aZoneFileStream >> unknownPtr; + + result.unknowns.append(unknownPtr); + } + + qDebug() << " - End Pos: " << aZoneFileStream->device()->pos(); + qDebug() << " - Data" << sectionCount; + qDebug() << " - Start Pos: " << aZoneFileStream->device()->pos(); + + // TODO: Parse data chunks + aZoneFileStream->skipRawData(3856); + qDebug() << " - End Pos: " << aZoneFileStream->device()->pos(); + } + + qDebug() << "Footer"; + qDebug() << "- Start Pos: " << aZoneFileStream->device()->pos(); + // TODO: Parse pointers/footer? + for (int k = 0; k < 17; k++) { + aZoneFileStream->skipRawData(4); + } + qDebug() << "- End Pos: " << aZoneFileStream->device()->pos(); + + return result; +} + +SoundAsset ZoneFile_COD4_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + // TODO Reimplement proper sound parsing + return result; + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD4_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD4_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD4_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD4_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD4_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD4_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "00000020") { + return ASSET_RAW_FILE; + } else if (cleanedType == "0000001A") { + return ASSET_EFFECT; + } else if (cleanedType == "00000017") { + return ASSET_LOCAL_STRING; + } else if (cleanedType == "00000002") { + return ASSET_ANIMATION; + } else if (cleanedType == "0000000C") { + return ASSET_COLLISION_MAP; + } else if (cleanedType == "00000021") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "00000015") { + return ASSET_MENU; + } else if (cleanedType == "00000006") { + return ASSET_TECH_SET; + } else if (cleanedType == "00000018") { + return ASSET_WEAPON; + } else if (cleanedType == "00000011") { + return ASSET_GFX_MAP; + } else if (cleanedType == "00000012") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "00000014") { + return ASSET_FONT; + } else if (cleanedType == "0000000D") { + return ASSET_D3DBSP; + } else if (cleanedType == "00000008") { + return ASSET_MATERIAL; + } else if (cleanedType == "0000000E") { + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0000000B") { + return ASSET_COL_MAP_SP; + } else if (cleanedType == "00000001") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "00000003") { + return ASSET_MODEL; + } else if (cleanedType == "00000016") { + return ASSET_MENU; + } else if (cleanedType == "0000001B") { + return ASSET_UI_MAP; + } else if (cleanedType == "00000007") { + return ASSET_IMAGE; + } else if (cleanedType == "00000009") { + return ASSET_SOUND_DRIVER_GLOBALS; + } else if (cleanedType == "00000019") { + return ASSET_SOUND; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD4_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/zonefile_cod5.h b/libs/zonefile/360/zonefile_cod4_360.h similarity index 86% rename from libs/zonefile/zonefile_cod5.h rename to libs/zonefile/360/zonefile_cod4_360.h index b7294fb..173db2d 100644 --- a/libs/zonefile/zonefile_cod5.h +++ b/libs/zonefile/360/zonefile_cod4_360.h @@ -1,23 +1,23 @@ -#ifndef ZONEFILE_COD5_H -#define ZONEFILE_COD5_H +#ifndef ZONEFILE_COD4_360_H +#define ZONEFILE_COD4_360_H #include #include "zonefile.h" -class ZoneFile_COD5 : public ZoneFile +class ZoneFile_COD4_360 : public ZoneFile { public: - ZoneFile_COD5(); - ~ZoneFile_COD5(); + ZoneFile_COD4_360(); + ~ZoneFile_COD4_360(); - bool Load(const QByteArray aFileData, FF_PLATFORM aPlatform) override; - QString AssetTypeToString(const QString aAssetType) override; + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; QByteArray GetBinaryData() override; private: - void pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) override; + void pParseZoneHeader(QDataStream *aZoneFileStream) override; quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; @@ -51,4 +51,4 @@ private: StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; }; -#endif // ZONEFILE_COD5_H +#endif // ZONEFILE_COD4_360_H diff --git a/libs/zonefile/360/zonefile_cod5_360.cpp b/libs/zonefile/360/zonefile_cod5_360.cpp new file mode 100644 index 0000000..b47b0b0 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod5_360.cpp @@ -0,0 +1,1151 @@ +#include "zonefile_cod5_360.h" + +#include +#include +#include + +ZoneFile_COD5_360::ZoneFile_COD5_360() + : ZoneFile() { + +} + +ZoneFile_COD5_360::~ZoneFile_COD5_360() { + +} + +bool ZoneFile_COD5_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD5_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD5_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD5_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD5_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD5_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD5_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD5_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD5_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount - 1; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { + if (!zoneTag.isEmpty()) { tags << zoneTag; } + } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD5_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + // Parse index & map found asset types + for (quint32 i = 0; i < recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD5_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType assetType = AssetStrToEnum(typeHex); + const QString typeStr = AssetEnumToStr(assetType); + + if (assetType == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (assetType == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (assetType == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (assetType == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (assetType == ASSET_MATERIAL) { // material + result.materials << pParseAsset_Material(aZoneFileStream); + } else if (assetType == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (assetType == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (assetType == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (assetType == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (assetType == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (assetType == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (assetType == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (assetType == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (assetType == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (assetType == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (assetType == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (assetType == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (assetType == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (assetType == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (assetType == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (assetType == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (assetType == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD5_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD5_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD5_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD5_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD5_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Material result; + + *aZoneFileStream >> result.namePtr; + + //aZoneFileStream->skipRawData(23 * 4); + + for (int i = 0; i < 23; i++) { + qint32 unknownPtr; + *aZoneFileStream >> unknownPtr; + result.pointers << unknownPtr; + } + + if (result.namePtr == -1) { + aZoneFileStream->skipRawData(1); + + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.name += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + return result; +} + +Shader ZoneFile_COD5_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD5_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + qint32 namePtr; + *aZoneFileStream >> namePtr; + + + for (int i = 0; i < 53; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + + //aZoneFileStream->skipRawData(53 * 4); + + if (namePtr == -1) { + aZoneFileStream->skipRawData(1); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + } + + //result.name.replace(",", ""); + return result; +} + +Image ZoneFile_COD5_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD5_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD5_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD5_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD5_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD5_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD5_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD5_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "00000021") { + return ASSET_RAW_FILE; + } else if (cleanedType == "0000001A") { + return ASSET_EFFECT; + } else if (cleanedType == "00000009") { + return ASSET_SOUND; + } else if (cleanedType == "00000004") { + return ASSET_ANIMATION; + } else if (cleanedType == "0000000C") { + return ASSET_COLLISION_MAP; + } else if (cleanedType == "00000021") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "00000015") { + return ASSET_MENU; + } else if (cleanedType == "00000008") { + return ASSET_TECH_SET; + } else if (cleanedType == "00000018") { + return ASSET_LOCAL_STRING; + } else if (cleanedType == "00000011") { + return ASSET_GFX_MAP; + } else if (cleanedType == "00000012") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "00000014") { + return ASSET_FONT; + } else if (cleanedType == "00000005") { + return ASSET_MODEL; + } else if (cleanedType == "0000000D") { + return ASSET_D3DBSP; + } else if (cleanedType == "00000006") { + return ASSET_MATERIAL; + } else if (cleanedType == "0000000E") { + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0000000B") { + return ASSET_COL_MAP_SP; + } else if (cleanedType == "00000001") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "00000003") { + return ASSET_DESTRUCTIBLE; + } else if (cleanedType == "00000016") { + return ASSET_MENU; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD5_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/360/zonefile_cod5_360.h b/libs/zonefile/360/zonefile_cod5_360.h new file mode 100644 index 0000000..b46409d --- /dev/null +++ b/libs/zonefile/360/zonefile_cod5_360.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD5_360_H +#define ZONEFILE_COD5_360_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD5_360 : public ZoneFile +{ +public: + ZoneFile_COD5_360(); + ~ZoneFile_COD5_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD5_360_H diff --git a/libs/zonefile/360/zonefile_cod6_360.cpp b/libs/zonefile/360/zonefile_cod6_360.cpp new file mode 100644 index 0000000..5ab538c --- /dev/null +++ b/libs/zonefile/360/zonefile_cod6_360.cpp @@ -0,0 +1,1153 @@ +#include "zonefile_cod6_360.h" + +#include +#include +#include + +ZoneFile_COD6_360::ZoneFile_COD6_360() + : ZoneFile() { + +} + +ZoneFile_COD6_360::~ZoneFile_COD6_360() { + +} + +bool ZoneFile_COD6_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD6_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + + aZoneFileStream->skipRawData(28); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD6_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 32; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD6_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD6_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD6_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount + 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { + if (!zoneTag.isEmpty()) { tags << zoneTag; } + } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD6_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + // Parse index & map found asset types + for (quint32 i = 0; i < recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD6_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType assetType = AssetStrToEnum(typeHex); + const QString typeStr = AssetEnumToStr(assetType); + + if (assetType == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (assetType == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (assetType == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (assetType == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (assetType == ASSET_MATERIAL) { // material + result.materials << pParseAsset_Material(aZoneFileStream); + } else if (assetType == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (assetType == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (assetType == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (assetType == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (assetType == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (assetType == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (assetType == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (assetType == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (assetType == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (assetType == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (assetType == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (assetType == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (assetType == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (assetType == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (assetType == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (assetType == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (assetType == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD6_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD6_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD6_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD6_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD6_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Material result; + + *aZoneFileStream >> result.namePtr; + + //aZoneFileStream->skipRawData(23 * 4); + + for (int i = 0; i < 23; i++) { + qint32 unknownPtr; + *aZoneFileStream >> unknownPtr; + result.pointers << unknownPtr; + } + + if (result.namePtr == -1) { + aZoneFileStream->skipRawData(1); + + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.name += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + return result; +} + +Shader ZoneFile_COD6_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD6_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + qint32 namePtr; + *aZoneFileStream >> namePtr; + + + for (int i = 0; i < 53; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + + //aZoneFileStream->skipRawData(53 * 4); + + if (namePtr == -1) { + aZoneFileStream->skipRawData(1); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + } + + //result.name.replace(",", ""); + return result; +} + +Image ZoneFile_COD6_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD6_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + return result; + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD6_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD6_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD6_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD6_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD6_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD6_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "00000021") { + return ASSET_RAW_FILE; + } else if (cleanedType == "0000001A") { + return ASSET_EFFECT; + } else if (cleanedType == "00000009") { + return ASSET_SOUND; + } else if (cleanedType == "00000004") { + return ASSET_ANIMATION; + } else if (cleanedType == "0000000C") { + return ASSET_COLLISION_MAP; + } else if (cleanedType == "00000021") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "00000015") { + return ASSET_MENU; + } else if (cleanedType == "00000008") { + return ASSET_TECH_SET; + } else if (cleanedType == "00000018") { + return ASSET_LOCAL_STRING; + } else if (cleanedType == "00000011") { + return ASSET_GFX_MAP; + } else if (cleanedType == "00000012") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "00000014") { + return ASSET_FONT; + } else if (cleanedType == "00000005") { + return ASSET_MODEL; + } else if (cleanedType == "0000000D") { + return ASSET_D3DBSP; + } else if (cleanedType == "00000006") { + return ASSET_MATERIAL; + } else if (cleanedType == "0000000E") { + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0000000B") { + return ASSET_COL_MAP_SP; + } else if (cleanedType == "00000001") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "00000003") { + return ASSET_DESTRUCTIBLE; + } else if (cleanedType == "00000016") { + return ASSET_MENU; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD6_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/360/zonefile_cod6_360.h b/libs/zonefile/360/zonefile_cod6_360.h new file mode 100644 index 0000000..3086068 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod6_360.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD6_360_H +#define ZONEFILE_COD6_360_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD6_360 : public ZoneFile +{ +public: + ZoneFile_COD6_360(); + ~ZoneFile_COD6_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD6_360_H diff --git a/libs/zonefile/360/zonefile_cod7_360.cpp b/libs/zonefile/360/zonefile_cod7_360.cpp new file mode 100644 index 0000000..f3a173c --- /dev/null +++ b/libs/zonefile/360/zonefile_cod7_360.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod7_360.h" + +#include +#include +#include + +ZoneFile_COD7_360::ZoneFile_COD7_360() +{ + +} + +ZoneFile_COD7_360::~ZoneFile_COD7_360() +{ + +} + +bool ZoneFile_COD7_360::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD7_360::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + pParseZoneUnknownsA(aZoneFileStream); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD7_360::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD7_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD7_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD7_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD7_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD7_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD7_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD7_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD7_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD7_360::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD7_360::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD7_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD7_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD7_360::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD7_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD7_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD7_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD7_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD7_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD7_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD7_360::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD7_360::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/360/zonefile_cod7_360.h b/libs/zonefile/360/zonefile_cod7_360.h new file mode 100644 index 0000000..f61f040 --- /dev/null +++ b/libs/zonefile/360/zonefile_cod7_360.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD7_360_H +#define ZONEFILE_COD7_360_H + +#include "zonefile.h" + +class ZoneFile_COD7_360 : public ZoneFile +{ +public: + ZoneFile_COD7_360(); + ~ZoneFile_COD7_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD7_360_H diff --git a/libs/zonefile/zonefile_cod7.cpp b/libs/zonefile/360/zonefile_cod8_360.cpp similarity index 86% rename from libs/zonefile/zonefile_cod7.cpp rename to libs/zonefile/360/zonefile_cod8_360.cpp index a6d6988..76eba46 100644 --- a/libs/zonefile/zonefile_cod7.cpp +++ b/libs/zonefile/360/zonefile_cod8_360.cpp @@ -1,30 +1,26 @@ -#include "zonefile_cod7.h" +#include "zonefile_cod8_360.h" #include #include #include -ZoneFile_COD7::ZoneFile_COD7() +ZoneFile_COD8_360::ZoneFile_COD8_360() { } -ZoneFile_COD7::~ZoneFile_COD7() +ZoneFile_COD8_360::~ZoneFile_COD8_360() { } -bool ZoneFile_COD7::Load(const QByteArray aFileData, FF_PLATFORM aPlatform) { +bool ZoneFile_COD8_360::Load(const QByteArray aFileData) { // Open zone file as little endian stream QDataStream zoneFileStream(aFileData); - if (aPlatform == FF_PLATFORM_PC) { - zoneFileStream.setByteOrder(QDataStream::LittleEndian); - } else { - zoneFileStream.setByteOrder(QDataStream::BigEndian); - } + zoneFileStream.setByteOrder(QDataStream::BigEndian); // Parse data from zone file header - pParseZoneHeader(&zoneFileStream, aPlatform); + pParseZoneHeader(&zoneFileStream); zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); @@ -32,21 +28,14 @@ bool ZoneFile_COD7::Load(const QByteArray aFileData, FF_PLATFORM aPlatform) { return true; } -void ZoneFile_COD7::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) { +void ZoneFile_COD8_360::pParseZoneHeader(QDataStream *aZoneFileStream) { quint32 size = pParseZoneSize(aZoneFileStream); SetSize(size); - if (aPlatform == FF_PLATFORM_WII) { - aZoneFileStream->skipRawData(36); - } else { - pParseZoneUnknownsA(aZoneFileStream); - } + pParseZoneUnknownsA(aZoneFileStream); quint32 tagCount = pParseZoneTagCount(aZoneFileStream); SetTagCount(tagCount); - if (aPlatform == FF_PLATFORM_WII) { - SetTagCount(GetTagCount() - 1); - } pParseZoneUnknownsB(aZoneFileStream); @@ -61,7 +50,7 @@ void ZoneFile_COD7::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM a } } -quint32 ZoneFile_COD7::pParseZoneSize(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD8_360::pParseZoneSize(QDataStream *aZoneFileStream) { quint32 zoneFileSize; *aZoneFileStream >> zoneFileSize; if (zoneFileSize <= 0) { @@ -77,7 +66,7 @@ quint32 ZoneFile_COD7::pParseZoneSize(QDataStream *aZoneFileStream) { Parses the 1st section of unknowns as hex vals and uint32s */ -void ZoneFile_COD7::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { // Byte 4-7, 8-11, 12-15: unknown QByteArray unknown1(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown1.data(), 4); @@ -112,7 +101,7 @@ void ZoneFile_COD7::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { Parses the number of string tags in the zone index */ -quint32 ZoneFile_COD7::pParseZoneTagCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD8_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { quint32 tagCount; *aZoneFileStream >> tagCount; return tagCount; @@ -123,7 +112,7 @@ quint32 ZoneFile_COD7::pParseZoneTagCount(QDataStream *aZoneFileStream) { Parses the number of records in the zone index */ -quint32 ZoneFile_COD7::pParseZoneRecordCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD8_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { quint32 recordCount; *aZoneFileStream >> recordCount; return recordCount; @@ -134,7 +123,7 @@ quint32 ZoneFile_COD7::pParseZoneRecordCount(QDataStream *aZoneFileStream) { Parses the 2nd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD7::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { // Byte 44-47: Unknown/empty? QByteArray unknown9(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown9.data(), 4); @@ -145,7 +134,7 @@ void ZoneFile_COD7::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { Parses the 3rd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD7::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { // Byte 40-43: Unknown/empty? QByteArray unknown10(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown10.data(), 4); @@ -160,7 +149,7 @@ void ZoneFile_COD7::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { Parses the string tags ate the start of zone file */ -QStringList ZoneFile_COD7::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { +QStringList ZoneFile_COD8_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { QStringList tags; // Byte 48-51: Repeated separators? ÿÿÿÿ x i @@ -175,7 +164,7 @@ QStringList ZoneFile_COD7::pParseZoneTags(QDataStream *aZoneFileStream, quint32 zoneTag += zoneTagChar; *aZoneFileStream >> zoneTagChar; } - tags << zoneTag; + if (!zoneTag.isEmpty()) { tags << zoneTag; } zoneTag.clear(); } return tags; @@ -186,7 +175,7 @@ QStringList ZoneFile_COD7::pParseZoneTags(QDataStream *aZoneFileStream, quint32 Parse the binary zone index data and populate table */ -QStringList ZoneFile_COD7::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { +QStringList ZoneFile_COD8_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { QStringList result; // Don't parse if no records @@ -209,70 +198,68 @@ QStringList ZoneFile_COD7::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 return result; } -AssetMap ZoneFile_COD7::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { +AssetMap ZoneFile_COD8_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { AssetMap result; aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); for (int i = 0; i < assetOrder.size(); i++) { const QString typeHex = assetOrder[i]; - const QString typeStr = AssetTypeToString(typeHex); + const AssetType typeStr = AssetStrToEnum(typeHex); - if (typeStr == "LOCAL STRING") { // localized string asset + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset result.localStrings << pParseAsset_LocalString(aZoneFileStream); - } else if (typeStr == "RAW FILE") { // gsc + } else if (typeStr == ASSET_RAW_FILE) { // gsc auto rawFile = pParseAsset_RawFile(aZoneFileStream); if (rawFile.length) { result.rawFiles << rawFile; } - } else if (typeStr == "PHYS PRESET") { // physpreset + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset pParseAsset_PhysPreset(aZoneFileStream); - } else if (typeStr == "MODEL") { // xmodel + } else if (typeStr == ASSET_MODEL) { // xmodel result.models << pParseAsset_Model(aZoneFileStream); - } else if (typeStr == "MATERIAL") { // material + } else if (typeStr == ASSET_MATERIAL) { // material pParseAsset_Material(aZoneFileStream); - } else if (typeStr == "SHADER") { // pixelshader + } else if (typeStr == ASSET_SHADER) { // pixelshader pParseAsset_Shader(aZoneFileStream); - } else if (typeStr == "TECH SET") { // techset include + } else if (typeStr == ASSET_TECH_SET) { // techset include result.techSets << pParseAsset_TechSet(aZoneFileStream); - } else if (typeStr == "IMAGE") { // image + } else if (typeStr == ASSET_IMAGE) { // image result.images << pParseAsset_Image(aZoneFileStream); - } else if (typeStr == "SOUND") { // loaded_sound + } else if (typeStr == ASSET_SOUND) { // loaded_sound result.sounds << pParseAsset_Sound(aZoneFileStream); - } else if (typeStr == "COLLISION MAP") { // col_map_mp + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp pParseAsset_ColMapMP(aZoneFileStream); - } else if (typeStr == "MP MAP") { // game_map_sp + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp pParseAsset_GameMapSP(aZoneFileStream); - } else if (typeStr == "SP MAP") { // game_map_mp + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp pParseAsset_GameMapMP(aZoneFileStream); - } else if (typeStr == "LIGHT DEF") { // lightdef + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef pParseAsset_LightDef(aZoneFileStream); - } else if (typeStr == "UI MAP") { // ui_map + } else if (typeStr == ASSET_UI_MAP) { // ui_map pParseAsset_UIMap(aZoneFileStream); - } else if (typeStr == "SND DRIVER GLOBALS") { // snddriverglobals + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals pParseAsset_SNDDriverGlobals(aZoneFileStream); - } else if (typeStr == "AI TYPE") { // aitype + } else if (typeStr == ASSET_AI_TYPE) { // aitype pParseAsset_AIType(aZoneFileStream); - } else if (typeStr == "EFFECT") { // aitype + } else if (typeStr == ASSET_EFFECT) { // aitype pParseAsset_FX(aZoneFileStream); - } else if (typeStr == "ANIMATION") { // aitype + } else if (typeStr == ASSET_ANIMATION) { // aitype result.animations << pParseAsset_Animation(aZoneFileStream); - } else if (typeStr == "STRING TABLE") { // string_table + } else if (typeStr == ASSET_STRING_TABLE) { // string_table result.stringTables << pParseAsset_StringTable(aZoneFileStream); - } else if (typeStr == "MENU") { // string_table + } else if (typeStr == ASSET_MENU) { // string_table result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); - } else if (typeStr == "WEAPON") { // string_table + } else if (typeStr == ASSET_WEAPON) { // string_table pParseAsset_Weapon(aZoneFileStream); - } else if (typeStr == "D3DBSP DUMP") { // string_table + } else if (typeStr == ASSET_D3DBSP) { // string_table pParseAsset_D3DBSP(aZoneFileStream); - } else if (typeStr != "UNKNOWN") { - qDebug() << "Found bad asset type!" << typeStr; } } return result; } -LocalString ZoneFile_COD7::pParseAsset_LocalString(QDataStream *aZoneFileStream) { +LocalString ZoneFile_COD8_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { LocalString result; quint32 stringPtr, aliasPtr; @@ -306,7 +293,7 @@ LocalString ZoneFile_COD7::pParseAsset_LocalString(QDataStream *aZoneFileStream) return result; } -RawFile ZoneFile_COD7::pParseAsset_RawFile(QDataStream *aZoneFileStream) { +RawFile ZoneFile_COD8_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { RawFile result; // Skip start separator FF FF FF FF (pointer?) @@ -341,15 +328,13 @@ RawFile ZoneFile_COD7::pParseAsset_RawFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD7::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Model ZoneFile_COD7::pParseAsset_Model(QDataStream *aZoneFileStream) { +Model ZoneFile_COD8_360::pParseAsset_Model(QDataStream *aZoneFileStream) { Model result; - qDebug() << "Model Info:"; - *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount >> result.surfCount >> result.unknownCount >> result.boneNamePtr >> result.parentListPtr >> result.quatsPtr >> result.transPtr @@ -358,8 +343,6 @@ Model ZoneFile_COD7::pParseAsset_Model(QDataStream *aZoneFileStream) { // Parse XModelLodInfo for (int i = 1; i <= 4; i++) { - qDebug() << "- Lod Info " << i; - quint32 intDist; *aZoneFileStream >> intDist; @@ -406,13 +389,13 @@ Model ZoneFile_COD7::pParseAsset_Model(QDataStream *aZoneFileStream) { return result; } -Material ZoneFile_COD7::pParseAsset_Material(QDataStream *aZoneFileStream) { +Material ZoneFile_COD8_360::pParseAsset_Material(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); return Material(); } -Shader ZoneFile_COD7::pParseAsset_Shader(QDataStream *aZoneFileStream) { +Shader ZoneFile_COD8_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { Shader result = Shader(); quint8 minorVersion, majorVersion; @@ -455,7 +438,7 @@ Shader ZoneFile_COD7::pParseAsset_Shader(QDataStream *aZoneFileStream) { return result; } -TechSet ZoneFile_COD7::pParseAsset_TechSet(QDataStream *aZoneFileStream) { +TechSet ZoneFile_COD8_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { TechSet result; for (int i = 1; i <= 62; i++) { @@ -478,7 +461,7 @@ TechSet ZoneFile_COD7::pParseAsset_TechSet(QDataStream *aZoneFileStream) { return result; } -Image ZoneFile_COD7::pParseAsset_Image(QDataStream *aZoneFileStream) { +Image ZoneFile_COD8_360::pParseAsset_Image(QDataStream *aZoneFileStream) { Image result; aZoneFileStream->skipRawData(4); @@ -547,14 +530,13 @@ Image ZoneFile_COD7::pParseAsset_Image(QDataStream *aZoneFileStream) { return result; } -SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { +SoundAsset ZoneFile_COD8_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { SoundAsset result; qDebug() << aZoneFileStream->device()->pos(); QByteArray rootNamePtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(rootNamePtr.data(), 4); - qDebug() << "Root name ptr: " << (QString)rootNamePtr.toHex(); aZoneFileStream->skipRawData(4); @@ -579,7 +561,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(tagPtr.data(), 4); if (tagPtr.toHex() == "ffffffff") { - qDebug() << "Tag Ptr: " << tagPtr.toHex(); tagCount++; } aZoneFileStream->skipRawData(4); @@ -588,7 +569,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(pathPtr.data(), 4); if (pathPtr.toHex() == "ffffffff") { - qDebug() << "Path Ptr: " << pathPtr.toHex(); resultCount++; } @@ -604,7 +584,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { tag += tagChar; *aZoneFileStream >> tagChar; } - qDebug() << "Tag: " << tag; } for (int i = 0; i < resultCount; i++) { @@ -616,7 +595,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->skipRawData(8); - qDebug() << "- " << aZoneFileStream->device()->pos(); QByteArray aliasPtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(aliasPtr.data(), 4); @@ -624,7 +602,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(namePtr.data(), 4); *aZoneFileStream >> sound.dataLength; - qDebug() << "- Data length: " << sound.dataLength; if (aliasPtr.toHex() == "ffffffff") { // Read in sound alias name @@ -634,7 +611,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { sound.alias += soundAliasChar; *aZoneFileStream >> soundAliasChar; } - qDebug() << "- Alias: " << sound.alias; } if (aZoneFileStream->device()->peek(4) == "RIFF") { @@ -649,7 +625,6 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { *aZoneFileStream >> soundPathChar; } sound.path.replace(",", ""); - qDebug() << "- Path: " << sound.path; } if (sound.dataLength) { @@ -659,44 +634,43 @@ SoundAsset ZoneFile_COD7::pParseAsset_Sound(QDataStream *aZoneFileStream) { } result.sounds.append(sound); } - qDebug() << "- " << aZoneFileStream->device()->pos(); return result; } -void ZoneFile_COD7::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_LightDef(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_UIMap(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_AIType(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_FX(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_FX(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Animation ZoneFile_COD7::pParseAsset_Animation(QDataStream *aZoneFileStream) { +Animation ZoneFile_COD8_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { Animation result; aZoneFileStream->skipRawData(4); @@ -764,7 +738,7 @@ Animation ZoneFile_COD7::pParseAsset_Animation(QDataStream *aZoneFileStream) { return result; } -MenuFile ZoneFile_COD7::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { +MenuFile ZoneFile_COD8_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { //MENU_FILE MenuFile result; @@ -988,17 +962,17 @@ MenuFile ZoneFile_COD7::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD7::pParseAsset_Weapon(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { //WEAPON_FILE Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD7::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD8_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { //D3DBSP_DUMP Q_UNUSED(aZoneFileStream); } -StringTable ZoneFile_COD7::pParseAsset_StringTable(QDataStream *aZoneFileStream) { +StringTable ZoneFile_COD8_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { StringTable result; aZoneFileStream->skipRawData(4); @@ -1054,49 +1028,49 @@ StringTable ZoneFile_COD7::pParseAsset_StringTable(QDataStream *aZoneFileStream) return result; } -QString ZoneFile_COD7::AssetTypeToString(const QString aAssetType) { +AssetType ZoneFile_COD8_360::AssetStrToEnum(const QString aAssetType) { const QString cleanedType = aAssetType.toUpper(); if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED - return "LOCAL STRING"; + return ASSET_LOCAL_STRING; } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED - return "RAW FILE"; + return ASSET_RAW_FILE; } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED - return "EFFECT"; + return ASSET_EFFECT; } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED - return "SOUND"; + return ASSET_SOUND; } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED - return "ANIMATION"; + return ASSET_ANIMATION; } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED - return "COLLISION MAP"; + return ASSET_COLLISION_MAP; } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED - return "STRING TABLE"; + return ASSET_STRING_TABLE; } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED - return "MENU"; + return ASSET_MENU; } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED - return "TECH SET"; + return ASSET_TECH_SET; } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED - return "WEAPON"; + return ASSET_WEAPON; } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED - return "GFX MAP"; + return ASSET_GFX_MAP; } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED - return "LIGHT DEF"; + return ASSET_LIGHT_DEF; } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED - return "FONT"; + return ASSET_FONT; } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED - return "MODEL"; + return ASSET_MODEL; } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED - return "D3DBSP"; + return ASSET_D3DBSP; } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED - return "IMAGE"; + return ASSET_IMAGE; } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED - return "GAME MAP SP"; + return ASSET_GAME_MAP_SP; } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED - return "COL MAP SP"; + return ASSET_COL_MAP_SP; } - return aAssetType; + return ASSET_NONE; } -QByteArray ZoneFile_COD7::GetBinaryData() { +QByteArray ZoneFile_COD8_360::GetBinaryData() { QByteArray result; return result; diff --git a/libs/zonefile/360/zonefile_cod8_360.h b/libs/zonefile/360/zonefile_cod8_360.h new file mode 100644 index 0000000..13c419e --- /dev/null +++ b/libs/zonefile/360/zonefile_cod8_360.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD8_360_H +#define ZONEFILE_COD8_360_H + +#include "zonefile.h" + +class ZoneFile_COD8_360 : public ZoneFile +{ +public: + ZoneFile_COD8_360(); + ~ZoneFile_COD8_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD8_360_H diff --git a/libs/zonefile/zonefile_cod9.cpp b/libs/zonefile/360/zonefile_cod9_360.cpp similarity index 86% rename from libs/zonefile/zonefile_cod9.cpp rename to libs/zonefile/360/zonefile_cod9_360.cpp index 9943633..c944b25 100644 --- a/libs/zonefile/zonefile_cod9.cpp +++ b/libs/zonefile/360/zonefile_cod9_360.cpp @@ -1,39 +1,33 @@ -#include "zonefile_cod9.h" +#include "zonefile_cod9_360.h" #include #include #include -ZoneFile_COD9::ZoneFile_COD9() +ZoneFile_COD9_360::ZoneFile_COD9_360() { } -ZoneFile_COD9::~ZoneFile_COD9() +ZoneFile_COD9_360::~ZoneFile_COD9_360() { } -bool ZoneFile_COD9::Load(const QByteArray aFileData, FF_PLATFORM aPlatform) { +bool ZoneFile_COD9_360::Load(const QByteArray aFileData) { // Open zone file as little endian stream QDataStream zoneFileStream(aFileData); - if (aPlatform == FF_PLATFORM_PC) { - zoneFileStream.setByteOrder(QDataStream::LittleEndian); - } else { - zoneFileStream.setByteOrder(QDataStream::BigEndian); - } + zoneFileStream.setByteOrder(QDataStream::BigEndian); // Parse data from zone file header - pParseZoneHeader(&zoneFileStream, aPlatform); + pParseZoneHeader(&zoneFileStream); SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); return true; } -void ZoneFile_COD9::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) { - Q_UNUSED(aPlatform); - +void ZoneFile_COD9_360::pParseZoneHeader(QDataStream *aZoneFileStream) { SetSize(pParseZoneSize(aZoneFileStream)); pParseZoneUnknownsA(aZoneFileStream); @@ -51,7 +45,7 @@ void ZoneFile_COD9::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM a } } -quint32 ZoneFile_COD9::pParseZoneSize(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD9_360::pParseZoneSize(QDataStream *aZoneFileStream) { quint32 zoneFileSize; *aZoneFileStream >> zoneFileSize; if (zoneFileSize <= 0) { @@ -67,7 +61,7 @@ quint32 ZoneFile_COD9::pParseZoneSize(QDataStream *aZoneFileStream) { Parses the 1st section of unknowns as hex vals and uint32s */ -void ZoneFile_COD9::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { // Byte 4-7, 8-11, 12-15: unknown QByteArray unknown1(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown1.data(), 4); @@ -102,7 +96,7 @@ void ZoneFile_COD9::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { Parses the number of string tags in the zone index */ -quint32 ZoneFile_COD9::pParseZoneTagCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD9_360::pParseZoneTagCount(QDataStream *aZoneFileStream) { quint32 tagCount; *aZoneFileStream >> tagCount; return tagCount; @@ -113,7 +107,7 @@ quint32 ZoneFile_COD9::pParseZoneTagCount(QDataStream *aZoneFileStream) { Parses the number of records in the zone index */ -quint32 ZoneFile_COD9::pParseZoneRecordCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD9_360::pParseZoneRecordCount(QDataStream *aZoneFileStream) { quint32 recordCount; *aZoneFileStream >> recordCount; return recordCount; @@ -124,7 +118,7 @@ quint32 ZoneFile_COD9::pParseZoneRecordCount(QDataStream *aZoneFileStream) { Parses the 2nd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD9::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { // Byte 44-47: Unknown/empty? QByteArray unknown9(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown9.data(), 4); @@ -135,7 +129,7 @@ void ZoneFile_COD9::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { Parses the 3rd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD9::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { // Byte 40-43: Unknown/empty? QByteArray unknown10(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown10.data(), 4); @@ -150,7 +144,7 @@ void ZoneFile_COD9::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { Parses the string tags ate the start of zone file */ -QStringList ZoneFile_COD9::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { +QStringList ZoneFile_COD9_360::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { QStringList tags; // Byte 48-51: Repeated separators? ÿÿÿÿ x i @@ -165,7 +159,7 @@ QStringList ZoneFile_COD9::pParseZoneTags(QDataStream *aZoneFileStream, quint32 zoneTag += zoneTagChar; *aZoneFileStream >> zoneTagChar; } - tags << zoneTag; + if (!zoneTag.isEmpty()) { tags << zoneTag; } zoneTag.clear(); } return tags; @@ -176,7 +170,7 @@ QStringList ZoneFile_COD9::pParseZoneTags(QDataStream *aZoneFileStream, quint32 Parse the binary zone index data and populate table */ -QStringList ZoneFile_COD9::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { +QStringList ZoneFile_COD9_360::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { QStringList result; // Don't parse if no records @@ -199,70 +193,68 @@ QStringList ZoneFile_COD9::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 return result; } -AssetMap ZoneFile_COD9::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { +AssetMap ZoneFile_COD9_360::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { AssetMap result; aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); for (int i = 0; i < assetOrder.size(); i++) { const QString typeHex = assetOrder[i]; - const QString typeStr = AssetTypeToString(typeHex); + const AssetType typeStr = AssetStrToEnum(typeHex); - if (typeStr == "LOCAL STRING") { // localized string asset + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset result.localStrings << pParseAsset_LocalString(aZoneFileStream); - } else if (typeStr == "RAW FILE") { // gsc + } else if (typeStr == ASSET_RAW_FILE) { // gsc auto rawFile = pParseAsset_RawFile(aZoneFileStream); if (rawFile.length) { result.rawFiles << rawFile; } - } else if (typeStr == "PHYS PRESET") { // physpreset + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset pParseAsset_PhysPreset(aZoneFileStream); - } else if (typeStr == "MODEL") { // xmodel + } else if (typeStr == ASSET_MODEL) { // xmodel result.models << pParseAsset_Model(aZoneFileStream); - } else if (typeStr == "MATERIAL") { // material + } else if (typeStr == ASSET_MATERIAL) { // material pParseAsset_Material(aZoneFileStream); - } else if (typeStr == "SHADER") { // pixelshader + } else if (typeStr == ASSET_SHADER) { // pixelshader pParseAsset_Shader(aZoneFileStream); - } else if (typeStr == "TECH SET") { // techset include + } else if (typeStr == ASSET_TECH_SET) { // techset include result.techSets << pParseAsset_TechSet(aZoneFileStream); - } else if (typeStr == "IMAGE") { // image + } else if (typeStr == ASSET_IMAGE) { // image result.images << pParseAsset_Image(aZoneFileStream); - } else if (typeStr == "SOUND") { // loaded_sound + } else if (typeStr == ASSET_SOUND) { // loaded_sound result.sounds << pParseAsset_Sound(aZoneFileStream); - } else if (typeStr == "COLLISION MAP") { // col_map_mp + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp pParseAsset_ColMapMP(aZoneFileStream); - } else if (typeStr == "MP MAP") { // game_map_sp + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp pParseAsset_GameMapSP(aZoneFileStream); - } else if (typeStr == "SP MAP") { // game_map_mp + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp pParseAsset_GameMapMP(aZoneFileStream); - } else if (typeStr == "LIGHT DEF") { // lightdef + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef pParseAsset_LightDef(aZoneFileStream); - } else if (typeStr == "UI MAP") { // ui_map + } else if (typeStr == ASSET_UI_MAP) { // ui_map pParseAsset_UIMap(aZoneFileStream); - } else if (typeStr == "SND DRIVER GLOBALS") { // snddriverglobals + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals pParseAsset_SNDDriverGlobals(aZoneFileStream); - } else if (typeStr == "AI TYPE") { // aitype + } else if (typeStr == ASSET_AI_TYPE) { // aitype pParseAsset_AIType(aZoneFileStream); - } else if (typeStr == "EFFECT") { // aitype + } else if (typeStr == ASSET_EFFECT) { // aitype pParseAsset_FX(aZoneFileStream); - } else if (typeStr == "ANIMATION") { // aitype + } else if (typeStr == ASSET_ANIMATION) { // aitype result.animations << pParseAsset_Animation(aZoneFileStream); - } else if (typeStr == "STRING TABLE") { // string_table + } else if (typeStr == ASSET_STRING_TABLE) { // string_table result.stringTables << pParseAsset_StringTable(aZoneFileStream); - } else if (typeStr == "MENU") { // string_table + } else if (typeStr == ASSET_MENU) { // string_table result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); - } else if (typeStr == "WEAPON") { // string_table + } else if (typeStr == ASSET_WEAPON) { // string_table pParseAsset_Weapon(aZoneFileStream); - } else if (typeStr == "D3DBSP DUMP") { // string_table + } else if (typeStr == ASSET_D3DBSP) { // string_table pParseAsset_D3DBSP(aZoneFileStream); - } else if (typeStr != "UNKNOWN") { - qDebug() << "Found bad asset type!" << typeStr; } } return result; } -LocalString ZoneFile_COD9::pParseAsset_LocalString(QDataStream *aZoneFileStream) { +LocalString ZoneFile_COD9_360::pParseAsset_LocalString(QDataStream *aZoneFileStream) { LocalString result; quint32 stringPtr, aliasPtr; @@ -296,7 +288,7 @@ LocalString ZoneFile_COD9::pParseAsset_LocalString(QDataStream *aZoneFileStream) return result; } -RawFile ZoneFile_COD9::pParseAsset_RawFile(QDataStream *aZoneFileStream) { +RawFile ZoneFile_COD9_360::pParseAsset_RawFile(QDataStream *aZoneFileStream) { RawFile result; // Skip start separator FF FF FF FF (pointer?) @@ -331,15 +323,13 @@ RawFile ZoneFile_COD9::pParseAsset_RawFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD9::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Model ZoneFile_COD9::pParseAsset_Model(QDataStream *aZoneFileStream) { +Model ZoneFile_COD9_360::pParseAsset_Model(QDataStream *aZoneFileStream) { Model result; - qDebug() << "Model Info:"; - *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount >> result.surfCount >> result.unknownCount >> result.boneNamePtr >> result.parentListPtr >> result.quatsPtr >> result.transPtr @@ -348,8 +338,6 @@ Model ZoneFile_COD9::pParseAsset_Model(QDataStream *aZoneFileStream) { // Parse XModelLodInfo for (int i = 1; i <= 4; i++) { - qDebug() << "- Lod Info " << i; - quint32 intDist; *aZoneFileStream >> intDist; @@ -396,13 +384,13 @@ Model ZoneFile_COD9::pParseAsset_Model(QDataStream *aZoneFileStream) { return result; } -Material ZoneFile_COD9::pParseAsset_Material(QDataStream *aZoneFileStream) { +Material ZoneFile_COD9_360::pParseAsset_Material(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); return Material(); } -Shader ZoneFile_COD9::pParseAsset_Shader(QDataStream *aZoneFileStream) { +Shader ZoneFile_COD9_360::pParseAsset_Shader(QDataStream *aZoneFileStream) { Shader result = Shader(); quint8 minorVersion, majorVersion; @@ -445,7 +433,7 @@ Shader ZoneFile_COD9::pParseAsset_Shader(QDataStream *aZoneFileStream) { return result; } -TechSet ZoneFile_COD9::pParseAsset_TechSet(QDataStream *aZoneFileStream) { +TechSet ZoneFile_COD9_360::pParseAsset_TechSet(QDataStream *aZoneFileStream) { TechSet result; for (int i = 1; i <= 62; i++) { @@ -468,7 +456,7 @@ TechSet ZoneFile_COD9::pParseAsset_TechSet(QDataStream *aZoneFileStream) { return result; } -Image ZoneFile_COD9::pParseAsset_Image(QDataStream *aZoneFileStream) { +Image ZoneFile_COD9_360::pParseAsset_Image(QDataStream *aZoneFileStream) { Image result; aZoneFileStream->skipRawData(4); @@ -537,14 +525,13 @@ Image ZoneFile_COD9::pParseAsset_Image(QDataStream *aZoneFileStream) { return result; } -SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { +SoundAsset ZoneFile_COD9_360::pParseAsset_Sound(QDataStream *aZoneFileStream) { SoundAsset result; qDebug() << aZoneFileStream->device()->pos(); QByteArray rootNamePtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(rootNamePtr.data(), 4); - qDebug() << "Root name ptr: " << (QString)rootNamePtr.toHex(); aZoneFileStream->skipRawData(4); @@ -569,7 +556,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(tagPtr.data(), 4); if (tagPtr.toHex() == "ffffffff") { - qDebug() << "Tag Ptr: " << tagPtr.toHex(); tagCount++; } aZoneFileStream->skipRawData(4); @@ -578,7 +564,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(pathPtr.data(), 4); if (pathPtr.toHex() == "ffffffff") { - qDebug() << "Path Ptr: " << pathPtr.toHex(); resultCount++; } @@ -594,7 +579,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { tag += tagChar; *aZoneFileStream >> tagChar; } - qDebug() << "Tag: " << tag; } for (int i = 0; i < resultCount; i++) { @@ -606,7 +590,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->skipRawData(8); - qDebug() << "- " << aZoneFileStream->device()->pos(); QByteArray aliasPtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(aliasPtr.data(), 4); @@ -614,7 +597,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(namePtr.data(), 4); *aZoneFileStream >> sound.dataLength; - qDebug() << "- Data length: " << sound.dataLength; if (aliasPtr.toHex() == "ffffffff") { // Read in sound alias name @@ -624,7 +606,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { sound.alias += soundAliasChar; *aZoneFileStream >> soundAliasChar; } - qDebug() << "- Alias: " << sound.alias; } if (aZoneFileStream->device()->peek(4) == "RIFF") { @@ -639,7 +620,6 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { *aZoneFileStream >> soundPathChar; } sound.path.replace(",", ""); - qDebug() << "- Path: " << sound.path; } if (sound.dataLength) { @@ -649,44 +629,43 @@ SoundAsset ZoneFile_COD9::pParseAsset_Sound(QDataStream *aZoneFileStream) { } result.sounds.append(sound); } - qDebug() << "- " << aZoneFileStream->device()->pos(); return result; } -void ZoneFile_COD9::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_LightDef(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_LightDef(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_UIMap(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_UIMap(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_AIType(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_AIType(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_FX(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_FX(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Animation ZoneFile_COD9::pParseAsset_Animation(QDataStream *aZoneFileStream) { +Animation ZoneFile_COD9_360::pParseAsset_Animation(QDataStream *aZoneFileStream) { Animation result; aZoneFileStream->skipRawData(4); @@ -754,7 +733,7 @@ Animation ZoneFile_COD9::pParseAsset_Animation(QDataStream *aZoneFileStream) { return result; } -MenuFile ZoneFile_COD9::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { +MenuFile ZoneFile_COD9_360::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { //MENU_FILE MenuFile result; @@ -978,17 +957,17 @@ MenuFile ZoneFile_COD9::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD9::pParseAsset_Weapon(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_Weapon(QDataStream *aZoneFileStream) { //WEAPON_FILE Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD9::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_360::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { //D3DBSP_DUMP Q_UNUSED(aZoneFileStream); } -StringTable ZoneFile_COD9::pParseAsset_StringTable(QDataStream *aZoneFileStream) { +StringTable ZoneFile_COD9_360::pParseAsset_StringTable(QDataStream *aZoneFileStream) { StringTable result; aZoneFileStream->skipRawData(4); @@ -1044,49 +1023,49 @@ StringTable ZoneFile_COD9::pParseAsset_StringTable(QDataStream *aZoneFileStream) return result; } -QString ZoneFile_COD9::AssetTypeToString(const QString aAssetType) { +AssetType ZoneFile_COD9_360::AssetStrToEnum(const QString aAssetType) { const QString cleanedType = aAssetType.toUpper(); if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED - return "LOCAL STRING"; + return ASSET_LOCAL_STRING; } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED - return "RAW FILE"; + return ASSET_RAW_FILE; } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED - return "EFFECT"; + return ASSET_EFFECT; } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED - return "SOUND"; + return ASSET_SOUND; } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED - return "ANIMATION"; + return ASSET_ANIMATION; } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED - return "COLLISION MAP"; + return ASSET_COLLISION_MAP; } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED - return "STRING TABLE"; + return ASSET_STRING_TABLE; } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED - return "MENU"; + return ASSET_MENU; } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED - return "TECH SET"; + return ASSET_TECH_SET; } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED - return "WEAPON"; + return ASSET_WEAPON; } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED - return "GFX MAP"; + return ASSET_GFX_MAP; } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED - return "LIGHT DEF"; + return ASSET_LIGHT_DEF; } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED - return "FONT"; + return ASSET_FONT; } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED - return "MODEL"; + return ASSET_MODEL; } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED - return "D3DBSP"; + return ASSET_D3DBSP; } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED - return "IMAGE"; + return ASSET_IMAGE; } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED - return "GAME MAP SP"; + return ASSET_GAME_MAP_SP; } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED - return "COL MAP SP"; + return ASSET_COL_MAP_SP; } - return aAssetType; + return ASSET_NONE; } -QByteArray ZoneFile_COD9::GetBinaryData() { +QByteArray ZoneFile_COD9_360::GetBinaryData() { QByteArray result; return result; diff --git a/libs/zonefile/360/zonefile_cod9_360.h b/libs/zonefile/360/zonefile_cod9_360.h new file mode 100644 index 0000000..f52fcde --- /dev/null +++ b/libs/zonefile/360/zonefile_cod9_360.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD9_360_H +#define ZONEFILE_COD9_360_H + +#include "zonefile.h" + +class ZoneFile_COD9_360 : public ZoneFile +{ +public: + ZoneFile_COD9_360(); + ~ZoneFile_COD9_360(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD9_360_H diff --git a/libs/zonefile/PC/zonefile_cod10_pc.cpp b/libs/zonefile/PC/zonefile_cod10_pc.cpp new file mode 100644 index 0000000..3cedc33 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod10_pc.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod10_pc.h" + +#include +#include +#include + +ZoneFile_COD10_PC::ZoneFile_COD10_PC() +{ + +} + +ZoneFile_COD10_PC::~ZoneFile_COD10_PC() +{ + +} + +bool ZoneFile_COD10_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD10_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD10_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD10_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD10_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD10_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD10_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD10_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD10_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD10_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD10_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD10_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD10_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD10_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD10_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD10_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD10_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD10_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD10_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD10_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD10_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD10_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD10_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD10_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod10_pc.h b/libs/zonefile/PC/zonefile_cod10_pc.h new file mode 100644 index 0000000..8443654 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod10_pc.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD10_PC_H +#define ZONEFILE_COD10_PC_H + +#include "zonefile.h" + +class ZoneFile_COD10_PC : public ZoneFile +{ +public: + ZoneFile_COD10_PC(); + ~ZoneFile_COD10_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD10_PC_H diff --git a/libs/zonefile/PC/zonefile_cod11_pc.cpp b/libs/zonefile/PC/zonefile_cod11_pc.cpp new file mode 100644 index 0000000..02969da --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod11_pc.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod11_pc.h" + +#include +#include +#include + +ZoneFile_COD11_PC::ZoneFile_COD11_PC() +{ + +} + +ZoneFile_COD11_PC::~ZoneFile_COD11_PC() +{ + +} + +bool ZoneFile_COD11_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD11_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD11_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD11_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD11_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD11_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD11_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD11_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD11_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD11_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD11_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD11_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD11_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD11_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD11_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD11_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD11_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD11_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD11_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD11_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD11_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD11_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD11_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD11_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod11_pc.h b/libs/zonefile/PC/zonefile_cod11_pc.h new file mode 100644 index 0000000..27f0003 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod11_pc.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD11_H +#define ZONEFILE_COD11_H + +#include "zonefile.h" + +class ZoneFile_COD11_PC : public ZoneFile +{ +public: + ZoneFile_COD11_PC(); + ~ZoneFile_COD11_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD11_H diff --git a/libs/zonefile/PC/zonefile_cod12_pc.cpp b/libs/zonefile/PC/zonefile_cod12_pc.cpp new file mode 100644 index 0000000..175bccc --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod12_pc.cpp @@ -0,0 +1,1207 @@ +#include "zonefile_cod12_pc.h" + +#include +#include +#include + +ZoneFile_COD12_PC::ZoneFile_COD12_PC() +{ + +} + +ZoneFile_COD12_PC::~ZoneFile_COD12_PC() +{ + +} + +bool ZoneFile_COD12_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD12_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + aZoneFileStream->skipRawData(7 * 4); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream) - 1; + SetRecordCount(recordCount); + + aZoneFileStream->skipRawData(5 * 4); + + if (tagCount) { + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } +} + +quint32 ZoneFile_COD12_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD12_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD12_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD12_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(8 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + if (aZoneFileStream->device()->peek(8).toHex().contains("00000000")) { + break; + } + + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD12_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(8, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 8); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(8); + } + return result; +} + +AssetMap ZoneFile_COD12_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // raw file + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_SCRIPT_PARSE_TREE) { // gsc + auto gscFile = pParseAsset_GSCFile(aZoneFileStream); + if (gscFile.length) { + result.gscFiles << gscFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD12_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD12_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +GscFile ZoneFile_COD12_PC::pParseAsset_GSCFile(QDataStream *aZoneFileStream) { + GscFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(8); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(8); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD12_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD12_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD12_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD12_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD12_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD12_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD12_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + return result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD12_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD12_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD12_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD12_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD12_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD12_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "0000000000000000") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "0100000000000000") { + return ASSET_PHYS_CONSTRAINTS; + } else if (cleanedType == "0200000000000000") { + return ASSET_DESTRUCTIBLE_DEF; + } else if (cleanedType == "0300000000000000") { + return ASSET_ANIMATION; + } else if (cleanedType == "0400000000000000") { + return ASSET_MODEL; + } else if (cleanedType == "0500000000000000") { + return ASSET_MODEL_MESH; + } else if (cleanedType == "0600000000000000") { + return ASSET_MATERIAL; + } else if (cleanedType == "0700000000000000") { + return ASSET_COMPUTE_SHADER_SET; + } else if (cleanedType == "0800000000000000") { + return ASSET_TECH_SET; + } else if (cleanedType == "0900000000000000") { + return ASSET_IMAGE; + } else if (cleanedType == "0A00000000000000") { + return ASSET_SOUND; + } else if (cleanedType == "1100000000000000") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "1500000000000000") { + return ASSET_FONT_ICON; + } else if (cleanedType == "1700000000000000") { + return ASSET_WEAPON; + } else if (cleanedType == "1C00000000000000") { + return ASSET_PLAYER_SOUNDS_TABLE; + } else if (cleanedType == "1D00000000000000") { + return ASSET_PLAYER_FX_TABLE; + } else if (cleanedType == "1E00000000000000") { + return ASSET_SHARED_WEAPON_SOUNDS; + } else if (cleanedType == "1F00000000000000") { + return ASSET_ATTACHMENT; + } else if (cleanedType == "2000000000000000") { + return ASSET_ATTACHMENT_UNIQUE; + } else if (cleanedType == "2100000000000000") { + return ASSET_WEAPON_CAMO; + } else if (cleanedType == "2200000000000000") { + return ASSET_CUSTOMIZATION_TABLE; + } else if (cleanedType == "2300000000000000") { + return ASSET_CUSTOMIZATION_TABLE_FEIMAGES; + } else if (cleanedType == "2400000000000000") { + return ASSET_CUSTOMIZATION_TABLE_COLOR; + }else if (cleanedType == "2600000000000000") { + return ASSET_EFFECT; + } else if (cleanedType == "2F00000000000000") { + return ASSET_RAW_FILE; + } else if (cleanedType == "3000000000000000") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "3100000000000000") { + return ASSET_STRUCTURED_TABLE; + } else if (cleanedType == "3200000000000000") { + return ASSET_LEADERBOARD_DEF; + } else if (cleanedType == "3300000000000000") { + return ASSET_DDL; + } else if (cleanedType == "3600000000000000") { + return ASSET_SCRIPT_PARSE_TREE; + } else if (cleanedType == "3700000000000000") { + return ASSET_KEY_VALUE_PAIRS; + } else if (cleanedType == "3800000000000000") { + return ASSET_VEHICLE; + } else if (cleanedType == "3A00000000000000") { + return ASSET_VEHICLE_TRACER; + } else if (cleanedType == "3C00000000000000") { + return ASSET_SURFACE_FX_TABLE; + } else if (cleanedType == "3D00000000000000") { + return ASSET_SURFACE_SOUND_DEF; + } else if (cleanedType == "3E00000000000000") { + return ASSET_FOOTSTEP_TABLE; + } else if (cleanedType == "3F00000000000000") { + return ASSET_ENTITY_FX_IMPACTS; + } else if (cleanedType == "4000000000000000") { + return ASSET_ENTITY_SOUND_IMPACTS; + } else if (cleanedType == "4200000000000000") { + return ASSET_VEHICLE_FX_DEF; + } else if (cleanedType == "4300000000000000") { + return ASSET_VEHICLE_SOUND_DEF; + } else if (cleanedType == "4500000000000000") { + return ASSET_SCRIPT_BUNDLE; + } else if (cleanedType == "4600000000000000") { + return ASSET_SCRIPT_BUNDLE_LIST; + } else if (cleanedType == "4700000000000000") { + return ASSET_RUMBLE; + } else if (cleanedType == "4A00000000000000") { + return ASSET_AIM_TABLE; + } else if (cleanedType == "4B00000000000000") { + return ASSET_ANIM_SELECTOR_TABLE; + } else if (cleanedType == "4C00000000000000") { + return ASSET_ANIM_MAPPING_TABLE; + } else if (cleanedType == "4D00000000000000") { + return ASSET_ANIM_STATE_MACHINE; + } else if (cleanedType == "4E00000000000000") { + return ASSET_BEHAVIOR_TREE; + } else if (cleanedType == "4F00000000000000") { + return ASSET_BEHAVIOR_STATE_MACHINE; + } else if (cleanedType == "5100000000000000") { + return ASSET_S_ANIM; + } else if (cleanedType == "5200000000000000") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "5300000000000000") { + return ASSET_BIT_FIELD; + } else if (cleanedType == "5400000000000000") { + return ASSET_SURFACE_SOUND_DEF; + } else if (cleanedType == "5500000000000000") { + return ASSET_SURFACE_FX_TABLE; + } else if (cleanedType == "5600000000000000") { + return ASSET_RUMBLE; + } else if (cleanedType == "5900000000000000") { + return ASSET_AIM_TABLE; + } else if (cleanedType == "5A00000000000000") { + return ASSET_MAP_TABLE; + } else if (cleanedType == "5B00000000000000") { + return ASSET_MAP_TABLE_LOADING_IMAGES; + } else if (cleanedType == "5C00000000000000") { + return ASSET_MEDAL; + } else if (cleanedType == "5D00000000000000") { + return ASSET_MEDAL_TABLE; + } else if (cleanedType == "5E00000000000000") { + return ASSET_OBJECTIVE; + } else if (cleanedType == "5F00000000000000") { + return ASSET_OBJECTIVE_LIST; + } else if (cleanedType == "6400000000000000") { + return ASSET_LASER; + } else if (cleanedType == "6500000000000000") { + return ASSET_BEAM; + } else if (cleanedType == "6600000000000000") { + return ASSET_STREAMER_HINT; + } else if (cleanedType == "1B00000000000000") { + return ASSET_CG_MEDIA_TABLE; + } + + return ASSET_NONE; +} + +QByteArray ZoneFile_COD12_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod12_pc.h b/libs/zonefile/PC/zonefile_cod12_pc.h new file mode 100644 index 0000000..5d246a1 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod12_pc.h @@ -0,0 +1,53 @@ +#ifndef ZONEFILE_COD12_PC_H +#define ZONEFILE_COD12_PC_H + +#include "zonefile.h" + +class ZoneFile_COD12_PC : public ZoneFile +{ +public: + ZoneFile_COD12_PC(); + ~ZoneFile_COD12_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + GscFile pParseAsset_GSCFile(QDataStream *aZoneFileStream) ; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD12_PC_H diff --git a/libs/zonefile/PC/zonefile_cod4_pc.cpp b/libs/zonefile/PC/zonefile_cod4_pc.cpp new file mode 100644 index 0000000..2b12310 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod4_pc.cpp @@ -0,0 +1,1148 @@ +#include "zonefile_cod4_pc.h" + +#include +#include +#include + +ZoneFile_COD4_PC::ZoneFile_COD4_PC() + : ZoneFile() { + +} + +ZoneFile_COD4_PC::~ZoneFile_COD4_PC() { + +} + +bool ZoneFile_COD4_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD4_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + + aZoneFileStream->skipRawData(40); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream) - 1); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD4_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD4_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD4_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD4_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD4_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD4_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD4_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD4_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + qDebug() << "rawFileLength: " << result.length; + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD4_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD4_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD4_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + aZoneFileStream->skipRawData(27 * 4); + + qint32 materialNamePtr; + *aZoneFileStream >> materialNamePtr; + if (materialNamePtr == -1) { + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + // TODO: Fill out this material + return Material(); +} + +Shader ZoneFile_COD4_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD4_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD4_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD4_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + // TODO Reimplement proper sound parsing + return result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD4_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD4_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD4_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD4_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD4_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD4_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "1F000000") { + return ASSET_RAW_FILE; + } else if (cleanedType == "20000000") { + return ASSET_SCRIPT_PARSE_TREE; + } else if (cleanedType == "19000000") { + return ASSET_EFFECT; + } else if (cleanedType == "16000000") { + return ASSET_SOUND; + } else if (cleanedType == "02000000") { + return ASSET_ANIMATION; + } else if (cleanedType == "0B000000") { + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { + return ASSET_STRING_TABLE; + } else if (cleanedType == "14000000") { + return ASSET_MENU; + } else if (cleanedType == "07000000") { + return ASSET_TECH_SET; + } else if (cleanedType == "17000000") { + return ASSET_WEAPON; + } else if (cleanedType == "10000000") { + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { + return ASSET_LIGHT_DEF; + } else if (cleanedType == "15000000") { + return ASSET_FONT; + } else if (cleanedType == "03000000") { + return ASSET_MODEL; + } else if (cleanedType == "0C000000") { + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { + return ASSET_IMAGE; + } else if (cleanedType == "0D000000") { + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0A000000") { + return ASSET_COL_MAP_SP; + } else if (cleanedType == "01000000") { + return ASSET_PHYS_PRESET; + } else if (cleanedType == "05000000") { + return ASSET_DESTRUCTIBLE; + } else if (cleanedType == "18000000") { + return ASSET_LOCAL_STRING; + } else if (cleanedType == "1A000000") { + return ASSET_UI_MAP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD4_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod4_pc.h b/libs/zonefile/PC/zonefile_cod4_pc.h new file mode 100644 index 0000000..be47e4f --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod4_pc.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD4_PC_H +#define ZONEFILE_COD4_PC_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD4_PC : public ZoneFile +{ +public: + ZoneFile_COD4_PC(); + ~ZoneFile_COD4_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD4_PC_H diff --git a/libs/zonefile/PC/zonefile_cod5_pc.cpp b/libs/zonefile/PC/zonefile_cod5_pc.cpp new file mode 100644 index 0000000..2a1ab72 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod5_pc.cpp @@ -0,0 +1,1140 @@ +#include "zonefile_cod5_pc.h" + +#include +#include +#include + +ZoneFile_COD5_PC::ZoneFile_COD5_PC() + : ZoneFile() { + +} + +ZoneFile_COD5_PC::~ZoneFile_COD5_PC() { + +} + +bool ZoneFile_COD5_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD5_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD5_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD5_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD5_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD5_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD5_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD5_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD5_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD5_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD5_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD5_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD5_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + qDebug() << "rawFileLength: " << result.length; + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD5_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD5_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD5_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + aZoneFileStream->skipRawData(27 * 4); + + qint32 materialNamePtr; + *aZoneFileStream >> materialNamePtr; + if (materialNamePtr == -1) { + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + // TODO: Fill out this material + return Material(); +} + +Shader ZoneFile_COD5_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD5_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD5_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD5_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD5_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD5_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD5_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD5_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD5_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD5_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD5_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_SCRIPT_PARSE_TREE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } else if (cleanedType == "01000000") { // physics preset PARTIALLY VERIFIED + return ASSET_PHYS_PRESET; + } else if (cleanedType == "03000000") { // destructible def PARTIALLY VERIFIED + return ASSET_DESTRUCTIBLE; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD5_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod5_pc.h b/libs/zonefile/PC/zonefile_cod5_pc.h new file mode 100644 index 0000000..5125441 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod5_pc.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD5_PC_H +#define ZONEFILE_COD5_PC_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD5_PC : public ZoneFile +{ +public: + ZoneFile_COD5_PC(); + ~ZoneFile_COD5_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD5_PC_H diff --git a/libs/zonefile/PC/zonefile_cod6_pc.cpp b/libs/zonefile/PC/zonefile_cod6_pc.cpp new file mode 100644 index 0000000..29e99d4 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod6_pc.cpp @@ -0,0 +1,1140 @@ +#include "zonefile_cod6_pc.h" + +#include +#include +#include + +ZoneFile_COD6_PC::ZoneFile_COD6_PC() + : ZoneFile() { + +} + +ZoneFile_COD6_PC::~ZoneFile_COD6_PC() { + +} + +bool ZoneFile_COD6_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD6_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD6_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD6_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD6_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD6_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD6_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD6_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD6_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD6_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + qDebug() << "rawFileLength: " << result.length; + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD6_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD6_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD6_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + aZoneFileStream->skipRawData(27 * 4); + + qint32 materialNamePtr; + *aZoneFileStream >> materialNamePtr; + if (materialNamePtr == -1) { + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + // TODO: Fill out this material + return Material(); +} + +Shader ZoneFile_COD6_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD6_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD6_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD6_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD6_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD6_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD6_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD6_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD6_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD6_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_SCRIPT_PARSE_TREE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } else if (cleanedType == "01000000") { // physics preset PARTIALLY VERIFIED + return ASSET_PHYS_PRESET; + } else if (cleanedType == "03000000") { // destructible def PARTIALLY VERIFIED + return ASSET_DESTRUCTIBLE; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD6_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod6_pc.h b/libs/zonefile/PC/zonefile_cod6_pc.h new file mode 100644 index 0000000..4ecfed3 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod6_pc.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD6_PC_H +#define ZONEFILE_COD6_PC_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD6_PC : public ZoneFile +{ +public: + ZoneFile_COD6_PC(); + ~ZoneFile_COD6_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD6_PC_H diff --git a/libs/zonefile/PC/zonefile_cod7_pc.cpp b/libs/zonefile/PC/zonefile_cod7_pc.cpp new file mode 100644 index 0000000..a6f83bd --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod7_pc.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod7_pc.h" + +#include +#include +#include + +ZoneFile_COD7_PC::ZoneFile_COD7_PC() +{ + +} + +ZoneFile_COD7_PC::~ZoneFile_COD7_PC() +{ + +} + +bool ZoneFile_COD7_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD7_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + pParseZoneUnknownsA(aZoneFileStream); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD7_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD7_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD7_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD7_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD7_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD7_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD7_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD7_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD7_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD7_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD7_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD7_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD7_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD7_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD7_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD7_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD7_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD7_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD7_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD7_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD7_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD7_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod7_pc.h b/libs/zonefile/PC/zonefile_cod7_pc.h new file mode 100644 index 0000000..dec60e4 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod7_pc.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD7_PC_H +#define ZONEFILE_COD7_PC_H + +#include "zonefile.h" + +class ZoneFile_COD7_PC : public ZoneFile +{ +public: + ZoneFile_COD7_PC(); + ~ZoneFile_COD7_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD7_PC_H diff --git a/libs/zonefile/PC/zonefile_cod8_pc.cpp b/libs/zonefile/PC/zonefile_cod8_pc.cpp new file mode 100644 index 0000000..9b7d341 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod8_pc.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod8_pc.h" + +#include +#include +#include + +ZoneFile_COD8_PC::ZoneFile_COD8_PC() +{ + +} + +ZoneFile_COD8_PC::~ZoneFile_COD8_PC() +{ + +} + +bool ZoneFile_COD8_PC::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::LittleEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD8_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + pParseZoneUnknownsA(aZoneFileStream); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD8_PC::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD8_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD8_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD8_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD8_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD8_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD8_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD8_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD8_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD8_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD8_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD8_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD8_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD8_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD8_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD8_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD8_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD8_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD8_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD8_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD8_PC::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD8_PC::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PC/zonefile_cod8_pc.h b/libs/zonefile/PC/zonefile_cod8_pc.h new file mode 100644 index 0000000..5ba5f15 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod8_pc.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD7_PC_H +#define ZONEFILE_COD7_PC_H + +#include "zonefile.h" + +class ZoneFile_COD8_PC : public ZoneFile +{ +public: + ZoneFile_COD8_PC(); + ~ZoneFile_COD8_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD7_PC_H diff --git a/libs/zonefile/zonefile_cod2.cpp b/libs/zonefile/PC/zonefile_cod9_pc.cpp similarity index 82% rename from libs/zonefile/zonefile_cod2.cpp rename to libs/zonefile/PC/zonefile_cod9_pc.cpp index 3e49715..a278b0a 100644 --- a/libs/zonefile/zonefile_cod2.cpp +++ b/libs/zonefile/PC/zonefile_cod9_pc.cpp @@ -1,55 +1,51 @@ -#include "zonefile_cod2.h" +#include "zonefile_cod9_pc.h" #include #include #include -ZoneFile_COD2::ZoneFile_COD2() +ZoneFile_COD9_PC::ZoneFile_COD9_PC() { } -ZoneFile_COD2::~ZoneFile_COD2() +ZoneFile_COD9_PC::~ZoneFile_COD9_PC() { } -bool ZoneFile_COD2::Load(const QByteArray aFileData, FF_PLATFORM aPlatform) { +bool ZoneFile_COD9_PC::Load(const QByteArray aFileData) { // Open zone file as little endian stream QDataStream zoneFileStream(aFileData); - if (aPlatform == FF_PLATFORM_PC) { - zoneFileStream.setByteOrder(QDataStream::LittleEndian); - } else { - zoneFileStream.setByteOrder(QDataStream::BigEndian); - } + zoneFileStream.setByteOrder(QDataStream::LittleEndian); // Parse data from zone file header - pParseZoneHeader(&zoneFileStream, aPlatform); + pParseZoneHeader(&zoneFileStream); SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); return true; } -void ZoneFile_COD2::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) { - Q_UNUSED(aPlatform); +void ZoneFile_COD9_PC::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); SetTagCount(pParseZoneTagCount(aZoneFileStream)); pParseZoneUnknownsB(aZoneFileStream); - pParseZoneUnknownsC(aZoneFileStream); - SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); - aZoneFileStream->skipRawData(4); + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); quint32 tagCount = GetTagCount(); if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); SetTags(pParseZoneTags(aZoneFileStream, tagCount)); } else { aZoneFileStream->skipRawData(4); } } -quint32 ZoneFile_COD2::pParseZoneSize(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD9_PC::pParseZoneSize(QDataStream *aZoneFileStream) { quint32 zoneFileSize; *aZoneFileStream >> zoneFileSize; if (zoneFileSize <= 0) { @@ -65,7 +61,7 @@ quint32 ZoneFile_COD2::pParseZoneSize(QDataStream *aZoneFileStream) { Parses the 1st section of unknowns as hex vals and uint32s */ -void ZoneFile_COD2::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { // Byte 4-7, 8-11, 12-15: unknown QByteArray unknown1(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown1.data(), 4); @@ -100,7 +96,7 @@ void ZoneFile_COD2::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { Parses the number of string tags in the zone index */ -quint32 ZoneFile_COD2::pParseZoneTagCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD9_PC::pParseZoneTagCount(QDataStream *aZoneFileStream) { quint32 tagCount; *aZoneFileStream >> tagCount; return tagCount; @@ -111,7 +107,7 @@ quint32 ZoneFile_COD2::pParseZoneTagCount(QDataStream *aZoneFileStream) { Parses the number of records in the zone index */ -quint32 ZoneFile_COD2::pParseZoneRecordCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD9_PC::pParseZoneRecordCount(QDataStream *aZoneFileStream) { quint32 recordCount; *aZoneFileStream >> recordCount; return recordCount; @@ -122,7 +118,7 @@ quint32 ZoneFile_COD2::pParseZoneRecordCount(QDataStream *aZoneFileStream) { Parses the 2nd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD2::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { // Byte 44-47: Unknown/empty? QByteArray unknown9(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown9.data(), 4); @@ -133,7 +129,7 @@ void ZoneFile_COD2::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { Parses the 3rd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD2::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { // Byte 40-43: Unknown/empty? QByteArray unknown10(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown10.data(), 4); @@ -148,11 +144,11 @@ void ZoneFile_COD2::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { Parses the string tags ate the start of zone file */ -QStringList ZoneFile_COD2::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { +QStringList ZoneFile_COD9_PC::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { QStringList tags; // Byte 48-51: Repeated separators? ÿÿÿÿ x i - aZoneFileStream->skipRawData(4 * tagCount); + aZoneFileStream->skipRawData(4 * (tagCount - 1)); // Parse tags/strings before index QString zoneTag; @@ -163,7 +159,7 @@ QStringList ZoneFile_COD2::pParseZoneTags(QDataStream *aZoneFileStream, quint32 zoneTag += zoneTagChar; *aZoneFileStream >> zoneTagChar; } - tags << zoneTag; + if (!zoneTag.isEmpty()) { tags << zoneTag; } zoneTag.clear(); } return tags; @@ -174,14 +170,18 @@ QStringList ZoneFile_COD2::pParseZoneTags(QDataStream *aZoneFileStream, quint32 Parse the binary zone index data and populate table */ -QStringList ZoneFile_COD2::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { +QStringList ZoneFile_COD9_PC::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { QStringList result; // Don't parse if no records if (!recordCount) { return result; } + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + // Parse index & map found asset types - for (quint32 i = 0; i < recordCount; i++) { + for (quint32 i = 0; i <= recordCount; i++) { // Skip record start QByteArray rawAssetType(4, Qt::Uninitialized); aZoneFileStream->readRawData(rawAssetType.data(), 4); @@ -193,70 +193,68 @@ QStringList ZoneFile_COD2::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 return result; } -AssetMap ZoneFile_COD2::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { +AssetMap ZoneFile_COD9_PC::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { AssetMap result; - //aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); for (int i = 0; i < assetOrder.size(); i++) { const QString typeHex = assetOrder[i]; - const QString typeStr = AssetTypeToString(typeHex); + const AssetType typeStr = AssetStrToEnum(typeHex); - if (typeStr == "LOCAL STRING") { // localized string asset + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset result.localStrings << pParseAsset_LocalString(aZoneFileStream); - } else if (typeStr == "RAW FILE") { // gsc + } else if (typeStr == ASSET_RAW_FILE) { // gsc auto rawFile = pParseAsset_RawFile(aZoneFileStream); if (rawFile.length) { result.rawFiles << rawFile; } - } else if (typeStr == "PHYS PRESET") { // physpreset + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset pParseAsset_PhysPreset(aZoneFileStream); - } else if (typeStr == "MODEL") { // xmodel + } else if (typeStr == ASSET_MODEL) { // xmodel result.models << pParseAsset_Model(aZoneFileStream); - } else if (typeStr == "MATERIAL") { // material - result.materials << pParseAsset_Material(aZoneFileStream); - } else if (typeStr == "SHADER") { // pixelshader + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader pParseAsset_Shader(aZoneFileStream); - } else if (typeStr == "TECH SET") { // techset include + } else if (typeStr == ASSET_TECH_SET) { // techset include result.techSets << pParseAsset_TechSet(aZoneFileStream); - } else if (typeStr == "IMAGE") { // image + } else if (typeStr == ASSET_IMAGE) { // image result.images << pParseAsset_Image(aZoneFileStream); - } else if (typeStr == "SOUND") { // loaded_sound + } else if (typeStr == ASSET_SOUND) { // loaded_sound result.sounds << pParseAsset_Sound(aZoneFileStream); - } else if (typeStr == "COLLISION MAP") { // col_map_mp + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp pParseAsset_ColMapMP(aZoneFileStream); - } else if (typeStr == "MP MAP") { // game_map_sp + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp pParseAsset_GameMapSP(aZoneFileStream); - } else if (typeStr == "SP MAP") { // game_map_mp + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp pParseAsset_GameMapMP(aZoneFileStream); - } else if (typeStr == "LIGHT DEF") { // lightdef + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef pParseAsset_LightDef(aZoneFileStream); - } else if (typeStr == "UI MAP") { // ui_map + } else if (typeStr == ASSET_UI_MAP) { // ui_map pParseAsset_UIMap(aZoneFileStream); - } else if (typeStr == "SND DRIVER GLOBALS") { // snddriverglobals + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals pParseAsset_SNDDriverGlobals(aZoneFileStream); - } else if (typeStr == "AI TYPE") { // aitype + } else if (typeStr == ASSET_AI_TYPE) { // aitype pParseAsset_AIType(aZoneFileStream); - } else if (typeStr == "EFFECT") { // aitype + } else if (typeStr == ASSET_EFFECT) { // aitype pParseAsset_FX(aZoneFileStream); - } else if (typeStr == "ANIMATION") { // aitype + } else if (typeStr == ASSET_ANIMATION) { // aitype result.animations << pParseAsset_Animation(aZoneFileStream); - } else if (typeStr == "STRING TABLE") { // string_table + } else if (typeStr == ASSET_STRING_TABLE) { // string_table result.stringTables << pParseAsset_StringTable(aZoneFileStream); - } else if (typeStr == "MENU") { // string_table + } else if (typeStr == ASSET_MENU) { // string_table result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); - } else if (typeStr == "WEAPON") { // string_table + } else if (typeStr == ASSET_WEAPON) { // string_table pParseAsset_Weapon(aZoneFileStream); - } else if (typeStr == "D3DBSP DUMP") { // string_table + } else if (typeStr == ASSET_D3DBSP) { // string_table pParseAsset_D3DBSP(aZoneFileStream); - } else if (typeStr != "UNKNOWN") { - qDebug() << "Found bad asset type!" << typeStr; } } return result; } -LocalString ZoneFile_COD2::pParseAsset_LocalString(QDataStream *aZoneFileStream) { +LocalString ZoneFile_COD9_PC::pParseAsset_LocalString(QDataStream *aZoneFileStream) { LocalString result; quint32 stringPtr, aliasPtr; @@ -290,7 +288,7 @@ LocalString ZoneFile_COD2::pParseAsset_LocalString(QDataStream *aZoneFileStream) return result; } -RawFile ZoneFile_COD2::pParseAsset_RawFile(QDataStream *aZoneFileStream) { +RawFile ZoneFile_COD9_PC::pParseAsset_RawFile(QDataStream *aZoneFileStream) { RawFile result; // Skip start separator FF FF FF FF (pointer?) @@ -325,15 +323,13 @@ RawFile ZoneFile_COD2::pParseAsset_RawFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD2::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Model ZoneFile_COD2::pParseAsset_Model(QDataStream *aZoneFileStream) { +Model ZoneFile_COD9_PC::pParseAsset_Model(QDataStream *aZoneFileStream) { Model result; - qDebug() << "Model Info:"; - *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount >> result.surfCount >> result.unknownCount >> result.boneNamePtr >> result.parentListPtr >> result.quatsPtr >> result.transPtr @@ -342,8 +338,6 @@ Model ZoneFile_COD2::pParseAsset_Model(QDataStream *aZoneFileStream) { // Parse XModelLodInfo for (int i = 1; i <= 4; i++) { - qDebug() << "- Lod Info " << i; - quint32 intDist; *aZoneFileStream >> intDist; @@ -390,7 +384,13 @@ Model ZoneFile_COD2::pParseAsset_Model(QDataStream *aZoneFileStream) { return result; } -Shader ZoneFile_COD2::pParseAsset_Shader(QDataStream *aZoneFileStream) { +Material ZoneFile_COD9_PC::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD9_PC::pParseAsset_Shader(QDataStream *aZoneFileStream) { Shader result = Shader(); quint8 minorVersion, majorVersion; @@ -433,7 +433,7 @@ Shader ZoneFile_COD2::pParseAsset_Shader(QDataStream *aZoneFileStream) { return result; } -TechSet ZoneFile_COD2::pParseAsset_TechSet(QDataStream *aZoneFileStream) { +TechSet ZoneFile_COD9_PC::pParseAsset_TechSet(QDataStream *aZoneFileStream) { TechSet result; for (int i = 1; i <= 62; i++) { @@ -456,7 +456,7 @@ TechSet ZoneFile_COD2::pParseAsset_TechSet(QDataStream *aZoneFileStream) { return result; } -Image ZoneFile_COD2::pParseAsset_Image(QDataStream *aZoneFileStream) { +Image ZoneFile_COD9_PC::pParseAsset_Image(QDataStream *aZoneFileStream) { Image result; aZoneFileStream->skipRawData(4); @@ -525,41 +525,13 @@ Image ZoneFile_COD2::pParseAsset_Image(QDataStream *aZoneFileStream) { return result; } -Material ZoneFile_COD2::pParseAsset_Material(QDataStream *aZoneFileStream) { - Material result; - - *aZoneFileStream >> result.namePtr; - if (result.namePtr != 4294967295 && GetTagCount() > result.namePtr - 1) { - result.name = GetTags()[result.namePtr - 1]; - } - *aZoneFileStream >> result.refNamePtr; - if (result.refNamePtr != 4294967295 && GetTagCount() > result.refNamePtr - 1) { - result.refName = GetTags()[result.refNamePtr - 1]; - } - aZoneFileStream->skipRawData(12); - - *aZoneFileStream >> result.unknownA[0] >> result.unknownA[0] - >> result.unknownA[1] >> result.unknownA[2] >> result.unknownA[3] - >> result.unknownA[4] >> result.unknownA[5] >> result.unknownA[6] - >> result.unknownA[7] >> result.unknownA[8] >> result.unknownA[9] - >> result.unknownA[10] >> result.unknownA[11]; - - *aZoneFileStream >> result.stateBits[0] >> result.stateBits[1] - >> result.textureCount >> result.constCount >> result.techSetPtr - >> result.texturePtr >> result.constPtr; - - - return result; -} - -SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { +SoundAsset ZoneFile_COD9_PC::pParseAsset_Sound(QDataStream *aZoneFileStream) { SoundAsset result; qDebug() << aZoneFileStream->device()->pos(); QByteArray rootNamePtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(rootNamePtr.data(), 4); - qDebug() << "Root name ptr: " << (QString)rootNamePtr.toHex(); aZoneFileStream->skipRawData(4); @@ -584,7 +556,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(tagPtr.data(), 4); if (tagPtr.toHex() == "ffffffff") { - qDebug() << "Tag Ptr: " << tagPtr.toHex(); tagCount++; } aZoneFileStream->skipRawData(4); @@ -593,7 +564,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(pathPtr.data(), 4); if (pathPtr.toHex() == "ffffffff") { - qDebug() << "Path Ptr: " << pathPtr.toHex(); resultCount++; } @@ -609,7 +579,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { tag += tagChar; *aZoneFileStream >> tagChar; } - qDebug() << "Tag: " << tag; } for (int i = 0; i < resultCount; i++) { @@ -621,7 +590,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->skipRawData(8); - qDebug() << "- " << aZoneFileStream->device()->pos(); QByteArray aliasPtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(aliasPtr.data(), 4); @@ -629,7 +597,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(namePtr.data(), 4); *aZoneFileStream >> sound.dataLength; - qDebug() << "- Data length: " << sound.dataLength; if (aliasPtr.toHex() == "ffffffff") { // Read in sound alias name @@ -639,7 +606,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { sound.alias += soundAliasChar; *aZoneFileStream >> soundAliasChar; } - qDebug() << "- Alias: " << sound.alias; } if (aZoneFileStream->device()->peek(4) == "RIFF") { @@ -654,7 +620,6 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { *aZoneFileStream >> soundPathChar; } sound.path.replace(",", ""); - qDebug() << "- Path: " << sound.path; } if (sound.dataLength) { @@ -664,44 +629,43 @@ SoundAsset ZoneFile_COD2::pParseAsset_Sound(QDataStream *aZoneFileStream) { } result.sounds.append(sound); } - qDebug() << "- " << aZoneFileStream->device()->pos(); return result; } -void ZoneFile_COD2::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_LightDef(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_LightDef(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_UIMap(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_UIMap(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_AIType(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_AIType(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_FX(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_FX(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Animation ZoneFile_COD2::pParseAsset_Animation(QDataStream *aZoneFileStream) { +Animation ZoneFile_COD9_PC::pParseAsset_Animation(QDataStream *aZoneFileStream) { Animation result; aZoneFileStream->skipRawData(4); @@ -769,7 +733,7 @@ Animation ZoneFile_COD2::pParseAsset_Animation(QDataStream *aZoneFileStream) { return result; } -MenuFile ZoneFile_COD2::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { +MenuFile ZoneFile_COD9_PC::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { //MENU_FILE MenuFile result; @@ -993,17 +957,17 @@ MenuFile ZoneFile_COD2::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD2::pParseAsset_Weapon(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_Weapon(QDataStream *aZoneFileStream) { //WEAPON_FILE Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD2::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD9_PC::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { //D3DBSP_DUMP Q_UNUSED(aZoneFileStream); } -StringTable ZoneFile_COD2::pParseAsset_StringTable(QDataStream *aZoneFileStream) { +StringTable ZoneFile_COD9_PC::pParseAsset_StringTable(QDataStream *aZoneFileStream) { StringTable result; aZoneFileStream->skipRawData(4); @@ -1058,35 +1022,50 @@ StringTable ZoneFile_COD2::pParseAsset_StringTable(QDataStream *aZoneFileStream) } return result; } -// "parts", -// "model", -// "material", -// "image", -// "sound", -// "sndCurve", -// "clipMap", -// "world", -// "lightDef", -// "font", -// "menuList", -// "menu", -// "localize", -// "weapon", -// "sndDriverGlobals", -// "fx", -// "impactFx", -// "rawfile", -// "data" -QString ZoneFile_COD2::AssetTypeToString(const QString aAssetType) { +AssetType ZoneFile_COD9_PC::AssetStrToEnum(const QString aAssetType) { const QString cleanedType = aAssetType.toUpper(); - if (cleanedType == "") { // localized string PARTIALLY VERIFIED - return ""; + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; } - return aAssetType; + return ASSET_NONE; } -QByteArray ZoneFile_COD2::GetBinaryData() { +QByteArray ZoneFile_COD9_PC::GetBinaryData() { QByteArray result; return result; diff --git a/libs/zonefile/PC/zonefile_cod9_pc.h b/libs/zonefile/PC/zonefile_cod9_pc.h new file mode 100644 index 0000000..e71ac54 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod9_pc.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD9_PC_H +#define ZONEFILE_COD9_PC_H + +#include "zonefile.h" + +class ZoneFile_COD9_PC : public ZoneFile +{ +public: + ZoneFile_COD9_PC(); + ~ZoneFile_COD9_PC(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD9_PC_H diff --git a/libs/zonefile/PS3/zonefile_cod10_ps3.cpp b/libs/zonefile/PS3/zonefile_cod10_ps3.cpp new file mode 100644 index 0000000..8b92f1b --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod10_ps3.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod10_ps3.h" + +#include +#include +#include + +ZoneFile_COD10_PS3::ZoneFile_COD10_PS3() +{ + +} + +ZoneFile_COD10_PS3::~ZoneFile_COD10_PS3() +{ + +} + +bool ZoneFile_COD10_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD10_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD10_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD10_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD10_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD10_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD10_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD10_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD10_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD10_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD10_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD10_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD10_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD10_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD10_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD10_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD10_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD10_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD10_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD10_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD10_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD10_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD10_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD10_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod10_ps3.h b/libs/zonefile/PS3/zonefile_cod10_ps3.h new file mode 100644 index 0000000..90c07f8 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod10_ps3.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD10_PS3_H +#define ZONEFILE_COD10_PS3_H + +#include "zonefile.h" + +class ZoneFile_COD10_PS3 : public ZoneFile +{ +public: + ZoneFile_COD10_PS3(); + ~ZoneFile_COD10_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD10_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod11_ps3.cpp b/libs/zonefile/PS3/zonefile_cod11_ps3.cpp new file mode 100644 index 0000000..47f395a --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod11_ps3.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod11_ps3.h" + +#include +#include +#include + +ZoneFile_COD11_PS3::ZoneFile_COD11_PS3() +{ + +} + +ZoneFile_COD11_PS3::~ZoneFile_COD11_PS3() +{ + +} + +bool ZoneFile_COD11_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD11_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD11_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD11_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD11_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD11_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD11_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD11_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD11_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD11_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD11_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD11_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD11_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD11_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD11_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD11_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD11_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD11_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD11_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD11_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD11_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD11_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD11_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD11_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD11_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD11_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod11_ps3.h b/libs/zonefile/PS3/zonefile_cod11_ps3.h new file mode 100644 index 0000000..a8c16f3 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod11_ps3.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD11_PS3_H +#define ZONEFILE_COD11_PS3_H + +#include "zonefile.h" + +class ZoneFile_COD11_PS3 : public ZoneFile +{ +public: + ZoneFile_COD11_PS3(); + ~ZoneFile_COD11_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD11_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod12_ps3.cpp b/libs/zonefile/PS3/zonefile_cod12_ps3.cpp new file mode 100644 index 0000000..d764d52 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod12_ps3.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod12_ps3.h" + +#include +#include +#include + +ZoneFile_COD12_PS3::ZoneFile_COD12_PS3() +{ + +} + +ZoneFile_COD12_PS3::~ZoneFile_COD12_PS3() +{ + +} + +bool ZoneFile_COD12_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD12_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD12_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD12_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD12_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD12_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD12_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD12_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD12_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD12_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD12_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD12_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD12_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD12_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD12_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD12_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD12_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD12_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD12_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD12_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD12_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD12_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD12_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD12_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD12_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD12_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod12_ps3.h b/libs/zonefile/PS3/zonefile_cod12_ps3.h new file mode 100644 index 0000000..98c1b09 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod12_ps3.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD12_PS3_H +#define ZONEFILE_COD12_PS3_H + +#include "zonefile.h" + +class ZoneFile_COD12_PS3 : public ZoneFile +{ +public: + ZoneFile_COD12_PS3(); + ~ZoneFile_COD12_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD12_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod4_ps3.cpp b/libs/zonefile/PS3/zonefile_cod4_ps3.cpp new file mode 100644 index 0000000..9cf17c4 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod4_ps3.cpp @@ -0,0 +1,1125 @@ +#include "zonefile_cod4_ps3.h" + +#include +#include +#include + +ZoneFile_COD4_PS3::ZoneFile_COD4_PS3() + : ZoneFile() { + +} + +ZoneFile_COD4_PS3::~ZoneFile_COD4_PS3() { + +} + +bool ZoneFile_COD4_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD4_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + + aZoneFileStream->skipRawData(32); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream) - 1); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD4_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD4_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD4_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD4_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i <= tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD4_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD4_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD4_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD4_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + qDebug() << "rawFileLength: " << result.length; + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD4_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD4_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD4_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + aZoneFileStream->skipRawData(27 * 4); + + qint32 materialNamePtr; + *aZoneFileStream >> materialNamePtr; + if (materialNamePtr == -1) { + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + // TODO: Fill out this material + return Material(); +} + +Shader ZoneFile_COD4_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD4_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD4_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD4_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + // TODO Reimplement proper sound parsing + return result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD4_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD4_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD4_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD4_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD4_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD4_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "00000003") { + return ASSET_MODEL; + } else if (cleanedType == "00000002") { + return ASSET_ANIMATION; + } else if (cleanedType == "00000007") { + return ASSET_MATERIAL; + } else if (cleanedType == "00000009") { + return ASSET_TECH_SET; + } else if (cleanedType == "0000000C") { + return ASSET_COL_MAP_SP; + } else if (cleanedType == "0000000E") { + return ASSET_D3DBSP; + } else if (cleanedType == "0000000F") { + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "00000012") { + return ASSET_GFX_MAP; + } else if (cleanedType == "00000019") { + return ASSET_WEAPON; + } else if (cleanedType == "0000001B") { + return ASSET_EFFECT; + } else if (cleanedType == "00000018") { + return ASSET_SOUND; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD4_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod4_ps3.h b/libs/zonefile/PS3/zonefile_cod4_ps3.h new file mode 100644 index 0000000..90033c2 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod4_ps3.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD4_PS3_H +#define ZONEFILE_COD4_PS3_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD4_PS3 : public ZoneFile +{ +public: + ZoneFile_COD4_PS3(); + ~ZoneFile_COD4_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD4_PS3_H diff --git a/libs/zonefile/zonefile_cod5.cpp b/libs/zonefile/PS3/zonefile_cod5_ps3.cpp similarity index 86% rename from libs/zonefile/zonefile_cod5.cpp rename to libs/zonefile/PS3/zonefile_cod5_ps3.cpp index 75f9dbe..f97aa04 100644 --- a/libs/zonefile/zonefile_cod5.cpp +++ b/libs/zonefile/PS3/zonefile_cod5_ps3.cpp @@ -1,38 +1,32 @@ -#include "zonefile_cod5.h" +#include "zonefile_cod5_ps3.h" #include #include #include -ZoneFile_COD5::ZoneFile_COD5() +ZoneFile_COD5_PS3::ZoneFile_COD5_PS3() : ZoneFile() { } -ZoneFile_COD5::~ZoneFile_COD5() { +ZoneFile_COD5_PS3::~ZoneFile_COD5_PS3() { } -bool ZoneFile_COD5::Load(const QByteArray aFileData, FF_PLATFORM aPlatform) { +bool ZoneFile_COD5_PS3::Load(const QByteArray aFileData) { // Open zone file as little endian stream QDataStream zoneFileStream(aFileData); - if (aPlatform == FF_PLATFORM_PC) { - zoneFileStream.setByteOrder(QDataStream::LittleEndian); - } else { - zoneFileStream.setByteOrder(QDataStream::BigEndian); - } + zoneFileStream.setByteOrder(QDataStream::BigEndian); // Parse data from zone file header - pParseZoneHeader(&zoneFileStream, aPlatform); + pParseZoneHeader(&zoneFileStream); SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); return true; } -void ZoneFile_COD5::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) { - Q_UNUSED(aPlatform); - +void ZoneFile_COD5_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { SetSize(pParseZoneSize(aZoneFileStream)); pParseZoneUnknownsA(aZoneFileStream); @@ -50,7 +44,7 @@ void ZoneFile_COD5::pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM a } } -quint32 ZoneFile_COD5::pParseZoneSize(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD5_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { quint32 zoneFileSize; *aZoneFileStream >> zoneFileSize; if (zoneFileSize <= 0) { @@ -66,7 +60,7 @@ quint32 ZoneFile_COD5::pParseZoneSize(QDataStream *aZoneFileStream) { Parses the 1st section of unknowns as hex vals and uint32s */ -void ZoneFile_COD5::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { // Byte 4-7, 8-11, 12-15: unknown QByteArray unknown1(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown1.data(), 4); @@ -101,7 +95,7 @@ void ZoneFile_COD5::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { Parses the number of string tags in the zone index */ -quint32 ZoneFile_COD5::pParseZoneTagCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD5_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { quint32 tagCount; *aZoneFileStream >> tagCount; return tagCount; @@ -112,7 +106,7 @@ quint32 ZoneFile_COD5::pParseZoneTagCount(QDataStream *aZoneFileStream) { Parses the number of records in the zone index */ -quint32 ZoneFile_COD5::pParseZoneRecordCount(QDataStream *aZoneFileStream) { +quint32 ZoneFile_COD5_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { quint32 recordCount; *aZoneFileStream >> recordCount; return recordCount; @@ -123,7 +117,7 @@ quint32 ZoneFile_COD5::pParseZoneRecordCount(QDataStream *aZoneFileStream) { Parses the 2nd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD5::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { // Byte 44-47: Unknown/empty? QByteArray unknown9(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown9.data(), 4); @@ -134,7 +128,7 @@ void ZoneFile_COD5::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { Parses the 3rd section of unknowns as hex vals and uint32s */ -void ZoneFile_COD5::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { // Byte 40-43: Unknown/empty? QByteArray unknown10(4, Qt::Uninitialized); aZoneFileStream->readRawData(unknown10.data(), 4); @@ -149,7 +143,7 @@ void ZoneFile_COD5::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { Parses the string tags ate the start of zone file */ -QStringList ZoneFile_COD5::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { +QStringList ZoneFile_COD5_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { QStringList tags; // Byte 48-51: Repeated separators? ÿÿÿÿ x i @@ -164,7 +158,7 @@ QStringList ZoneFile_COD5::pParseZoneTags(QDataStream *aZoneFileStream, quint32 zoneTag += zoneTagChar; *aZoneFileStream >> zoneTagChar; } - tags << zoneTag; + if (!zoneTag.isEmpty()) { tags << zoneTag; } zoneTag.clear(); } return tags; @@ -175,7 +169,7 @@ QStringList ZoneFile_COD5::pParseZoneTags(QDataStream *aZoneFileStream, quint32 Parse the binary zone index data and populate table */ -QStringList ZoneFile_COD5::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { +QStringList ZoneFile_COD5_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { QStringList result; // Don't parse if no records @@ -198,70 +192,68 @@ QStringList ZoneFile_COD5::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 return result; } -AssetMap ZoneFile_COD5::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { +AssetMap ZoneFile_COD5_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { AssetMap result; aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); for (int i = 0; i < assetOrder.size(); i++) { const QString typeHex = assetOrder[i]; - const QString typeStr = AssetTypeToString(typeHex); + const AssetType typeStr = AssetStrToEnum(typeHex); - if (typeStr == "LOCAL STRING") { // localized string asset + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset result.localStrings << pParseAsset_LocalString(aZoneFileStream); - } else if (typeStr == "RAW FILE") { // gsc + } else if (typeStr == ASSET_RAW_FILE) { // gsc auto rawFile = pParseAsset_RawFile(aZoneFileStream); if (rawFile.length) { result.rawFiles << rawFile; } - } else if (typeStr == "PHYS PRESET") { // physpreset + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset pParseAsset_PhysPreset(aZoneFileStream); - } else if (typeStr == "MODEL") { // xmodel + } else if (typeStr == ASSET_MODEL) { // xmodel result.models << pParseAsset_Model(aZoneFileStream); - } else if (typeStr == "MATERIAL") { // material + } else if (typeStr == ASSET_MATERIAL) { // material pParseAsset_Material(aZoneFileStream); - } else if (typeStr == "SHADER") { // pixelshader + } else if (typeStr == ASSET_SHADER) { // pixelshader pParseAsset_Shader(aZoneFileStream); - } else if (typeStr == "TECH SET") { // techset include + } else if (typeStr == ASSET_TECH_SET) { // techset include result.techSets << pParseAsset_TechSet(aZoneFileStream); - } else if (typeStr == "IMAGE") { // image + } else if (typeStr == ASSET_IMAGE) { // image result.images << pParseAsset_Image(aZoneFileStream); - } else if (typeStr == "SOUND") { // loaded_sound + } else if (typeStr == ASSET_SOUND) { // loaded_sound result.sounds << pParseAsset_Sound(aZoneFileStream); - } else if (typeStr == "COLLISION MAP") { // col_map_mp + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp pParseAsset_ColMapMP(aZoneFileStream); - } else if (typeStr == "MP MAP") { // game_map_sp + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp pParseAsset_GameMapSP(aZoneFileStream); - } else if (typeStr == "SP MAP") { // game_map_mp + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp pParseAsset_GameMapMP(aZoneFileStream); - } else if (typeStr == "LIGHT DEF") { // lightdef + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef pParseAsset_LightDef(aZoneFileStream); - } else if (typeStr == "UI MAP") { // ui_map + } else if (typeStr == ASSET_UI_MAP) { // ui_map pParseAsset_UIMap(aZoneFileStream); - } else if (typeStr == "SND DRIVER GLOBALS") { // snddriverglobals + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals pParseAsset_SNDDriverGlobals(aZoneFileStream); - } else if (typeStr == "AI TYPE") { // aitype + } else if (typeStr == ASSET_AI_TYPE) { // aitype pParseAsset_AIType(aZoneFileStream); - } else if (typeStr == "EFFECT") { // aitype + } else if (typeStr == ASSET_EFFECT) { // aitype pParseAsset_FX(aZoneFileStream); - } else if (typeStr == "ANIMATION") { // aitype + } else if (typeStr == ASSET_ANIMATION) { // aitype result.animations << pParseAsset_Animation(aZoneFileStream); - } else if (typeStr == "STRING TABLE") { // string_table + } else if (typeStr == ASSET_STRING_TABLE) { // string_table result.stringTables << pParseAsset_StringTable(aZoneFileStream); - } else if (typeStr == "MENU") { // string_table + } else if (typeStr == ASSET_MENU) { // string_table result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); - } else if (typeStr == "WEAPON") { // string_table + } else if (typeStr == ASSET_WEAPON) { // string_table pParseAsset_Weapon(aZoneFileStream); - } else if (typeStr == "D3DBSP DUMP") { // string_table + } else if (typeStr == ASSET_D3DBSP) { // string_table pParseAsset_D3DBSP(aZoneFileStream); - } else if (typeStr != "UNKNOWN") { - qDebug() << "Found bad asset type!" << typeStr; } } return result; } -LocalString ZoneFile_COD5::pParseAsset_LocalString(QDataStream *aZoneFileStream) { +LocalString ZoneFile_COD5_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { LocalString result; quint32 stringPtr, aliasPtr; @@ -295,7 +287,7 @@ LocalString ZoneFile_COD5::pParseAsset_LocalString(QDataStream *aZoneFileStream) return result; } -RawFile ZoneFile_COD5::pParseAsset_RawFile(QDataStream *aZoneFileStream) { +RawFile ZoneFile_COD5_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { RawFile result; // Skip start separator FF FF FF FF (pointer?) @@ -345,15 +337,13 @@ RawFile ZoneFile_COD5::pParseAsset_RawFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD5::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Model ZoneFile_COD5::pParseAsset_Model(QDataStream *aZoneFileStream) { +Model ZoneFile_COD5_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { Model result; - qDebug() << "Model Info:"; - *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount >> result.surfCount >> result.unknownCount >> result.boneNamePtr >> result.parentListPtr >> result.quatsPtr >> result.transPtr @@ -362,8 +352,6 @@ Model ZoneFile_COD5::pParseAsset_Model(QDataStream *aZoneFileStream) { // Parse XModelLodInfo for (int i = 1; i <= 4; i++) { - qDebug() << "- Lod Info " << i; - quint32 intDist; *aZoneFileStream >> intDist; @@ -410,12 +398,11 @@ Model ZoneFile_COD5::pParseAsset_Model(QDataStream *aZoneFileStream) { return result; } -Material ZoneFile_COD5::pParseAsset_Material(QDataStream *aZoneFileStream) { +Material ZoneFile_COD5_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { aZoneFileStream->skipRawData(27 * 4); qint32 materialNamePtr; *aZoneFileStream >> materialNamePtr; - qDebug() << "materialNamePtr: " << materialNamePtr; if (materialNamePtr == -1) { QString materialName; char materialNameChar; @@ -424,20 +411,16 @@ Material ZoneFile_COD5::pParseAsset_Material(QDataStream *aZoneFileStream) { materialName += materialNameChar; *aZoneFileStream >> materialNameChar; } - qDebug() << "Parsing Material: " << materialName; } aZoneFileStream->skipRawData(3 * 4); qint32 compressionPtr, compression, unknownSectionPtr; *aZoneFileStream >> compressionPtr; - qDebug() << "compressionPtr: " << compressionPtr; if (compressionPtr == -1) { *aZoneFileStream >> compression; - qDebug() << QString("Found material with DXT%1 compression!").arg(compression); *aZoneFileStream >> unknownSectionPtr; - qDebug() << "unknownSectionPtr: " << unknownSectionPtr; if (unknownSectionPtr == -2) { aZoneFileStream->skipRawData(6 * 4); } @@ -445,7 +428,6 @@ Material ZoneFile_COD5::pParseAsset_Material(QDataStream *aZoneFileStream) { qint32 imageNamePtr; *aZoneFileStream >> imageNamePtr; - qDebug() << "imageNamePtr: " << imageNamePtr; if (imageNamePtr == -1) { QString imageName; char imageNameChar; @@ -454,7 +436,6 @@ Material ZoneFile_COD5::pParseAsset_Material(QDataStream *aZoneFileStream) { imageName += imageNameChar; *aZoneFileStream >> imageNameChar; } - qDebug() << "- Embeded image: " << imageName; } QByteArray compressionData(4, Qt::Uninitialized); @@ -472,7 +453,7 @@ Material ZoneFile_COD5::pParseAsset_Material(QDataStream *aZoneFileStream) { return Material(); } -Shader ZoneFile_COD5::pParseAsset_Shader(QDataStream *aZoneFileStream) { +Shader ZoneFile_COD5_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { Shader result = Shader(); quint8 minorVersion, majorVersion; @@ -515,7 +496,7 @@ Shader ZoneFile_COD5::pParseAsset_Shader(QDataStream *aZoneFileStream) { return result; } -TechSet ZoneFile_COD5::pParseAsset_TechSet(QDataStream *aZoneFileStream) { +TechSet ZoneFile_COD5_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { TechSet result; for (int i = 1; i <= 62; i++) { @@ -538,7 +519,7 @@ TechSet ZoneFile_COD5::pParseAsset_TechSet(QDataStream *aZoneFileStream) { return result; } -Image ZoneFile_COD5::pParseAsset_Image(QDataStream *aZoneFileStream) { +Image ZoneFile_COD5_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { Image result; aZoneFileStream->skipRawData(4); @@ -607,14 +588,13 @@ Image ZoneFile_COD5::pParseAsset_Image(QDataStream *aZoneFileStream) { return result; } -SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { +SoundAsset ZoneFile_COD5_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { SoundAsset result; qDebug() << aZoneFileStream->device()->pos(); QByteArray rootNamePtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(rootNamePtr.data(), 4); - qDebug() << "Root name ptr: " << (QString)rootNamePtr.toHex(); aZoneFileStream->skipRawData(4); @@ -639,7 +619,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(tagPtr.data(), 4); if (tagPtr.toHex() == "ffffffff") { - qDebug() << "Tag Ptr: " << tagPtr.toHex(); tagCount++; } aZoneFileStream->skipRawData(4); @@ -648,7 +627,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(pathPtr.data(), 4); if (pathPtr.toHex() == "ffffffff") { - qDebug() << "Path Ptr: " << pathPtr.toHex(); resultCount++; } @@ -664,7 +642,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { tag += tagChar; *aZoneFileStream >> tagChar; } - qDebug() << "Tag: " << tag; } for (int i = 0; i < resultCount; i++) { @@ -676,7 +653,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->skipRawData(8); - qDebug() << "- " << aZoneFileStream->device()->pos(); QByteArray aliasPtr(4, Qt::Uninitialized); aZoneFileStream->readRawData(aliasPtr.data(), 4); @@ -684,7 +660,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { aZoneFileStream->readRawData(namePtr.data(), 4); *aZoneFileStream >> sound.dataLength; - qDebug() << "- Data length: " << sound.dataLength; if (aliasPtr.toHex() == "ffffffff") { // Read in sound alias name @@ -694,7 +669,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { sound.alias += soundAliasChar; *aZoneFileStream >> soundAliasChar; } - qDebug() << "- Alias: " << sound.alias; } if (aZoneFileStream->device()->peek(4) == "RIFF") { @@ -709,7 +683,6 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { *aZoneFileStream >> soundPathChar; } sound.path.replace(",", ""); - qDebug() << "- Path: " << sound.path; } if (sound.dataLength) { @@ -719,44 +692,43 @@ SoundAsset ZoneFile_COD5::pParseAsset_Sound(QDataStream *aZoneFileStream) { } result.sounds.append(sound); } - qDebug() << "- " << aZoneFileStream->device()->pos(); return result; } -void ZoneFile_COD5::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_LightDef(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_UIMap(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_AIType(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_FX(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { Q_UNUSED(aZoneFileStream); } -Animation ZoneFile_COD5::pParseAsset_Animation(QDataStream *aZoneFileStream) { +Animation ZoneFile_COD5_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { Animation result; aZoneFileStream->skipRawData(4); @@ -824,7 +796,7 @@ Animation ZoneFile_COD5::pParseAsset_Animation(QDataStream *aZoneFileStream) { return result; } -MenuFile ZoneFile_COD5::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { +MenuFile ZoneFile_COD5_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { //MENU_FILE MenuFile result; @@ -1048,17 +1020,17 @@ MenuFile ZoneFile_COD5::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { return result; } -void ZoneFile_COD5::pParseAsset_Weapon(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { //WEAPON_FILE Q_UNUSED(aZoneFileStream); } -void ZoneFile_COD5::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { +void ZoneFile_COD5_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { //D3DBSP_DUMP Q_UNUSED(aZoneFileStream); } -StringTable ZoneFile_COD5::pParseAsset_StringTable(QDataStream *aZoneFileStream) { +StringTable ZoneFile_COD5_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { StringTable result; aZoneFileStream->skipRawData(4); @@ -1114,53 +1086,53 @@ StringTable ZoneFile_COD5::pParseAsset_StringTable(QDataStream *aZoneFileStream) return result; } -QString ZoneFile_COD5::AssetTypeToString(const QString aAssetType) { +AssetType ZoneFile_COD5_PS3::AssetStrToEnum(const QString aAssetType) { const QString cleanedType = aAssetType.toUpper(); if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED - return "RAW FILE"; + return ASSET_RAW_FILE; } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED - return "GSC FILE"; + return ASSET_SCRIPT_PARSE_TREE; } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED - return "EFFECT"; + return ASSET_EFFECT; } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED - return "SOUND"; + return ASSET_SOUND; } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED - return "ANIMATION"; + return ASSET_ANIMATION; } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED - return "COLLISION MAP"; + return ASSET_COLLISION_MAP; } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED - return "STRING TABLE"; + return ASSET_STRING_TABLE; } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED - return "MENU"; + return ASSET_MENU; } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED - return "TECH SET"; + return ASSET_TECH_SET; } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED - return "WEAPON"; + return ASSET_WEAPON; } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED - return "GFX MAP"; + return ASSET_GFX_MAP; } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED - return "LIGHT DEF"; + return ASSET_LIGHT_DEF; } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED - return "FONT"; + return ASSET_FONT; } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED - return "MODEL"; + return ASSET_MODEL; } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED - return "D3DBSP"; + return ASSET_D3DBSP; } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED - return "IMAGE"; + return ASSET_IMAGE; } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED - return "GAME MAP SP"; + return ASSET_GAME_MAP_SP; } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED - return "COL MAP SP"; + return ASSET_COL_MAP_SP; } else if (cleanedType == "01000000") { // physics preset PARTIALLY VERIFIED - return "PHYS PRESET"; + return ASSET_PHYS_PRESET; } else if (cleanedType == "03000000") { // destructible def PARTIALLY VERIFIED - return "DESTRUCTIBLE"; + return ASSET_DESTRUCTIBLE; } - return aAssetType; + return ASSET_NONE; } -QByteArray ZoneFile_COD5::GetBinaryData() { +QByteArray ZoneFile_COD5_PS3::GetBinaryData() { QByteArray result; return result; diff --git a/libs/zonefile/PS3/zonefile_cod5_ps3.h b/libs/zonefile/PS3/zonefile_cod5_ps3.h new file mode 100644 index 0000000..62260e0 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod5_ps3.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD5_PS3_H +#define ZONEFILE_COD5_PS3_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD5_PS3 : public ZoneFile +{ +public: + ZoneFile_COD5_PS3(); + ~ZoneFile_COD5_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD5_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod6_ps3.cpp b/libs/zonefile/PS3/zonefile_cod6_ps3.cpp new file mode 100644 index 0000000..21c7506 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod6_ps3.cpp @@ -0,0 +1,1139 @@ +#include "zonefile_cod6_ps3.h" + +#include +#include +#include + +ZoneFile_COD6_PS3::ZoneFile_COD6_PS3() + : ZoneFile() { + +} + +ZoneFile_COD6_PS3::~ZoneFile_COD6_PS3() { + +} + +bool ZoneFile_COD6_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD6_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD6_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD6_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD6_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD6_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD6_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD6_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD6_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD6_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD6_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + if (result.path.contains(".bik")) { + qDebug() << "rawFileLength: " << result.length; + QByteArray bikData(result.length, Qt::Uninitialized); + aZoneFileStream->readRawData(bikData.data(), result.length); + + //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last()); + //qDebug() << bikFile.fileName(); + //if (!bikFile.open(QIODevice::WriteOnly)) { + // qWarning() << "Failed to open .bik file for writing!"; + // return; + //} + //qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName()); + //bikFile.write(bikData); + } else { + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + } + return result; +} + +void ZoneFile_COD6_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD6_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD6_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + aZoneFileStream->skipRawData(27 * 4); + + qint32 materialNamePtr; + *aZoneFileStream >> materialNamePtr; + if (materialNamePtr == -1) { + QString materialName; + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + } + + aZoneFileStream->skipRawData(3 * 4); + + qint32 compressionPtr, compression, unknownSectionPtr; + *aZoneFileStream >> compressionPtr; + if (compressionPtr == -1) { + *aZoneFileStream >> compression; + + *aZoneFileStream >> unknownSectionPtr; + if (unknownSectionPtr == -2) { + aZoneFileStream->skipRawData(6 * 4); + } + } + + qint32 imageNamePtr; + *aZoneFileStream >> imageNamePtr; + if (imageNamePtr == -1) { + QString imageName; + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + imageName += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + } + + QByteArray compressionData(4, Qt::Uninitialized); + QString compressionStr; + if (compressionPtr == -1) { + aZoneFileStream->skipRawData(2 * 4); + aZoneFileStream->readRawData(compressionData.data(), 4); + aZoneFileStream->skipRawData(4); + compressionStr = QString::fromUtf8(compressionData); + aZoneFileStream->skipRawData(4); + } + aZoneFileStream->skipRawData(4); + + // TODO: Fill out this material + return Material(); +} + +Shader ZoneFile_COD6_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD6_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD6_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD6_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD6_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD6_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD6_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD6_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD6_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD6_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD6_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_SCRIPT_PARSE_TREE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } else if (cleanedType == "01000000") { // physics preset PARTIALLY VERIFIED + return ASSET_PHYS_PRESET; + } else if (cleanedType == "03000000") { // destructible def PARTIALLY VERIFIED + return ASSET_DESTRUCTIBLE; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD6_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod6_ps3.h b/libs/zonefile/PS3/zonefile_cod6_ps3.h new file mode 100644 index 0000000..4be12ec --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod6_ps3.h @@ -0,0 +1,54 @@ +#ifndef ZONEFILE_COD6_PS3_H +#define ZONEFILE_COD6_PS3_H + +#include + +#include "zonefile.h" + +class ZoneFile_COD6_PS3 : public ZoneFile +{ +public: + ZoneFile_COD6_PS3(); + ~ZoneFile_COD6_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +private: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD6_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod7_ps3.cpp b/libs/zonefile/PS3/zonefile_cod7_ps3.cpp new file mode 100644 index 0000000..9a4c6b1 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod7_ps3.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod7_ps3.h" + +#include +#include +#include + +ZoneFile_COD7_PS3::ZoneFile_COD7_PS3() +{ + +} + +ZoneFile_COD7_PS3::~ZoneFile_COD7_PS3() +{ + +} + +bool ZoneFile_COD7_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD7_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + pParseZoneUnknownsA(aZoneFileStream); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD7_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD7_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD7_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD7_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD7_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD7_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD7_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD7_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD7_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD7_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD7_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD7_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD7_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD7_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD7_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD7_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD7_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD7_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD7_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD7_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD7_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD7_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod7_ps3.h b/libs/zonefile/PS3/zonefile_cod7_ps3.h new file mode 100644 index 0000000..73ddd3e --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod7_ps3.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD7_PS3_H +#define ZONEFILE_COD7_PS3_H + +#include "zonefile.h" + +class ZoneFile_COD7_PS3 : public ZoneFile +{ +public: + ZoneFile_COD7_PS3(); + ~ZoneFile_COD7_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD7_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod8_ps3.cpp b/libs/zonefile/PS3/zonefile_cod8_ps3.cpp new file mode 100644 index 0000000..ec47ada --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod8_ps3.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod8_ps3.h" + +#include +#include +#include + +ZoneFile_COD8_PS3::ZoneFile_COD8_PS3() +{ + +} + +ZoneFile_COD8_PS3::~ZoneFile_COD8_PS3() +{ + +} + +bool ZoneFile_COD8_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD8_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + pParseZoneUnknownsA(aZoneFileStream); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD8_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD8_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD8_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD8_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD8_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD8_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD8_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD8_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD8_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD8_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD8_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD8_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD8_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD8_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD8_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD8_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD8_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD8_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD8_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD8_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD8_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD8_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod8_ps3.h b/libs/zonefile/PS3/zonefile_cod8_ps3.h new file mode 100644 index 0000000..5787d58 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod8_ps3.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD8_PS3_H +#define ZONEFILE_COD8_PS3_H + +#include "zonefile.h" + +class ZoneFile_COD8_PS3 : public ZoneFile +{ +public: + ZoneFile_COD8_PS3(); + ~ZoneFile_COD8_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD8_PS3_H diff --git a/libs/zonefile/PS3/zonefile_cod9_ps3.cpp b/libs/zonefile/PS3/zonefile_cod9_ps3.cpp new file mode 100644 index 0000000..abe6096 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod9_ps3.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod9_ps3.h" + +#include +#include +#include + +ZoneFile_COD9_PS3::ZoneFile_COD9_PS3() +{ + +} + +ZoneFile_COD9_PS3::~ZoneFile_COD9_PS3() +{ + +} + +bool ZoneFile_COD9_PS3::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD9_PS3::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD9_PS3::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD9_PS3::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD9_PS3::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD9_PS3::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD9_PS3::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD9_PS3::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD9_PS3::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD9_PS3::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD9_PS3::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD9_PS3::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD9_PS3::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD9_PS3::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD9_PS3::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD9_PS3::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD9_PS3::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD9_PS3::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD9_PS3::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD9_PS3::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD9_PS3::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD9_PS3::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD9_PS3::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD9_PS3::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_PS3::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD9_PS3::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD9_PS3::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD9_PS3::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/PS3/zonefile_cod9_ps3.h b/libs/zonefile/PS3/zonefile_cod9_ps3.h new file mode 100644 index 0000000..cba7420 --- /dev/null +++ b/libs/zonefile/PS3/zonefile_cod9_ps3.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD9_PS3_H +#define ZONEFILE_COD9_PS3_H + +#include "zonefile.h" + +class ZoneFile_COD9_PS3 : public ZoneFile +{ +public: + ZoneFile_COD9_PS3(); + ~ZoneFile_COD9_PS3(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD9_PS3_H diff --git a/libs/zonefile/Wii/zonefile_cod4_wii.cpp b/libs/zonefile/Wii/zonefile_cod4_wii.cpp new file mode 100644 index 0000000..d3d043f --- /dev/null +++ b/libs/zonefile/Wii/zonefile_cod4_wii.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod4_wii.h" + +#include +#include +#include + +ZoneFile_COD4_Wii::ZoneFile_COD4_Wii() +{ + +} + +ZoneFile_COD4_Wii::~ZoneFile_COD4_Wii() +{ + +} + +bool ZoneFile_COD4_Wii::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD4_Wii::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + aZoneFileStream->skipRawData(36); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount - 1); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD4_Wii::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 40; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_Wii::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD4_Wii::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD4_Wii::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_Wii::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD4_Wii::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD4_Wii::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + *aZoneFileStream >> zoneTagChar; + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD4_Wii::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i < recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD4_Wii::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD4_Wii::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD4_Wii::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD4_Wii::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD4_Wii::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD4_Wii::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD4_Wii::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD4_Wii::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD4_Wii::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD4_Wii::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD4_Wii::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD4_Wii::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD4_Wii::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD4_Wii::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD4_Wii::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD4_Wii::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD4_Wii::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD4_Wii::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/Wii/zonefile_cod4_wii.h b/libs/zonefile/Wii/zonefile_cod4_wii.h new file mode 100644 index 0000000..5f7d588 --- /dev/null +++ b/libs/zonefile/Wii/zonefile_cod4_wii.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD4_WII_H +#define ZONEFILE_COD4_WII_H + +#include "zonefile.h" + +class ZoneFile_COD4_Wii : public ZoneFile +{ +public: + ZoneFile_COD4_Wii(); + ~ZoneFile_COD4_Wii(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD4_WII_H diff --git a/libs/zonefile/Wii/zonefile_cod7_wii.cpp b/libs/zonefile/Wii/zonefile_cod7_wii.cpp new file mode 100644 index 0000000..19da359 --- /dev/null +++ b/libs/zonefile/Wii/zonefile_cod7_wii.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod7_wii.h" + +#include +#include +#include + +ZoneFile_COD7_Wii::ZoneFile_COD7_Wii() +{ + +} + +ZoneFile_COD7_Wii::~ZoneFile_COD7_Wii() +{ + +} + +bool ZoneFile_COD7_Wii::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD7_Wii::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + aZoneFileStream->skipRawData(36); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount - 1); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD7_Wii::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_Wii::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD7_Wii::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD7_Wii::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_Wii::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD7_Wii::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD7_Wii::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD7_Wii::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD7_Wii::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD7_Wii::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD7_Wii::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD7_Wii::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD7_Wii::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD7_Wii::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD7_Wii::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD7_Wii::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD7_Wii::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD7_Wii::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD7_Wii::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD7_Wii::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD7_Wii::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD7_Wii::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD7_Wii::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD7_Wii::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD7_Wii::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD7_Wii::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/Wii/zonefile_cod7_wii.h b/libs/zonefile/Wii/zonefile_cod7_wii.h new file mode 100644 index 0000000..da140df --- /dev/null +++ b/libs/zonefile/Wii/zonefile_cod7_wii.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD7_WII_H +#define ZONEFILE_COD7_WII_H + +#include "zonefile.h" + +class ZoneFile_COD7_Wii : public ZoneFile +{ +public: + ZoneFile_COD7_Wii(); + ~ZoneFile_COD7_Wii(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD7_WII_H diff --git a/libs/zonefile/Wii/zonefile_cod8_wii.cpp b/libs/zonefile/Wii/zonefile_cod8_wii.cpp new file mode 100644 index 0000000..2585e96 --- /dev/null +++ b/libs/zonefile/Wii/zonefile_cod8_wii.cpp @@ -0,0 +1,1077 @@ +#include "zonefile_cod8_wii.h" + +#include +#include +#include + +ZoneFile_COD8_Wii::ZoneFile_COD8_Wii() +{ + +} + +ZoneFile_COD8_Wii::~ZoneFile_COD8_Wii() +{ + +} + +bool ZoneFile_COD8_Wii::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + zoneFileStream.device()->seek(zoneFileStream.device()->pos() - 1); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD8_Wii::pParseZoneHeader(QDataStream *aZoneFileStream) { + quint32 size = pParseZoneSize(aZoneFileStream); + SetSize(size); + + aZoneFileStream->skipRawData(36); + + quint32 tagCount = pParseZoneTagCount(aZoneFileStream); + SetTagCount(tagCount - 1); + + pParseZoneUnknownsB(aZoneFileStream); + + quint32 recordCount = pParseZoneRecordCount(aZoneFileStream); + SetRecordCount(recordCount); + + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD8_Wii::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_Wii::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD8_Wii::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD8_Wii::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_Wii::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD8_Wii::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD8_Wii::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD8_Wii::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD8_Wii::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD8_Wii::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD8_Wii::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD8_Wii::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD8_Wii::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD8_Wii::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD8_Wii::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD8_Wii::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD8_Wii::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD8_Wii::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD8_Wii::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD8_Wii::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD8_Wii::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD8_Wii::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD8_Wii::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD8_Wii::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD8_Wii::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD8_Wii::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/Wii/zonefile_cod8_wii.h b/libs/zonefile/Wii/zonefile_cod8_wii.h new file mode 100644 index 0000000..14284e0 --- /dev/null +++ b/libs/zonefile/Wii/zonefile_cod8_wii.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD8_WII_H +#define ZONEFILE_COD8_WII_H + +#include "zonefile.h" + +class ZoneFile_COD8_Wii : public ZoneFile +{ +public: + ZoneFile_COD8_Wii(); + ~ZoneFile_COD8_Wii(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD8_WII_H diff --git a/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp b/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp new file mode 100644 index 0000000..8ec25a4 --- /dev/null +++ b/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod10_wiiu.h" + +#include +#include +#include + +ZoneFile_COD10_WiiU::ZoneFile_COD10_WiiU() +{ + +} + +ZoneFile_COD10_WiiU::~ZoneFile_COD10_WiiU() +{ + +} + +bool ZoneFile_COD10_WiiU::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD10_WiiU::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD10_WiiU::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_WiiU::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD10_WiiU::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD10_WiiU::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_WiiU::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD10_WiiU::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD10_WiiU::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD10_WiiU::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD10_WiiU::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD10_WiiU::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD10_WiiU::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD10_WiiU::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD10_WiiU::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD10_WiiU::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD10_WiiU::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD10_WiiU::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD10_WiiU::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD10_WiiU::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD10_WiiU::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD10_WiiU::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD10_WiiU::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD10_WiiU::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD10_WiiU::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD10_WiiU::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD10_WiiU::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD10_WiiU::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/WiiU/zonefile_cod10_wiiu.h b/libs/zonefile/WiiU/zonefile_cod10_wiiu.h new file mode 100644 index 0000000..b51d706 --- /dev/null +++ b/libs/zonefile/WiiU/zonefile_cod10_wiiu.h @@ -0,0 +1,52 @@ +#ifndef ZONEFILE_COD10_WIIU_H +#define ZONEFILE_COD10_WIIU_H + +#include "zonefile.h" + +class ZoneFile_COD10_WiiU : public ZoneFile +{ +public: + ZoneFile_COD10_WiiU(); + ~ZoneFile_COD10_WiiU(); + + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; + + QByteArray GetBinaryData() override; + +protected: + void pParseZoneHeader(QDataStream *aZoneFileStream) override; + quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; + quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; + quint32 pParseZoneRecordCount(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsB(QDataStream *aZoneFileStream) override; + void pParseZoneUnknownsC(QDataStream *aZoneFileStream) override; + QStringList pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) override; + QStringList pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) override; + AssetMap pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) override; + LocalString pParseAsset_LocalString(QDataStream *aZoneFileStream) override; + RawFile pParseAsset_RawFile(QDataStream *aZoneFileStream) override; + void pParseAsset_PhysPreset(QDataStream *aZoneFileStream) override; + Model pParseAsset_Model(QDataStream *aZoneFileStream) override; + Material pParseAsset_Material(QDataStream *aZoneFileStream) override; + Shader pParseAsset_Shader(QDataStream *aZoneFileStream) override; + TechSet pParseAsset_TechSet(QDataStream *aZoneFileStream) override; + Image pParseAsset_Image(QDataStream *aZoneFileStream) override; + SoundAsset pParseAsset_Sound(QDataStream *aZoneFileStream) override; + void pParseAsset_ColMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapSP(QDataStream *aZoneFileStream) override; + void pParseAsset_GameMapMP(QDataStream *aZoneFileStream) override; + void pParseAsset_LightDef(QDataStream *aZoneFileStream) override; + void pParseAsset_UIMap(QDataStream *aZoneFileStream) override; + void pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) override; + void pParseAsset_AIType(QDataStream *aZoneFileStream) override; + void pParseAsset_FX(QDataStream *aZoneFileStream) override; + Animation pParseAsset_Animation(QDataStream *aZoneFileStream) override; + MenuFile pParseAsset_MenuFile(QDataStream *aZoneFileStream) override; + void pParseAsset_Weapon(QDataStream *aZoneFileStream) override; + void pParseAsset_D3DBSP(QDataStream *aZoneFileStream) override; + StringTable pParseAsset_StringTable(QDataStream *aZoneFileStream) override; +}; + +#endif // ZONEFILE_COD10_WIIU_H diff --git a/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp b/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp new file mode 100644 index 0000000..100c0c6 --- /dev/null +++ b/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp @@ -0,0 +1,1072 @@ +#include "zonefile_cod9_wiiu.h" + +#include +#include +#include + +ZoneFile_COD9_WiiU::ZoneFile_COD9_WiiU() +{ + +} + +ZoneFile_COD9_WiiU::~ZoneFile_COD9_WiiU() +{ + +} + +bool ZoneFile_COD9_WiiU::Load(const QByteArray aFileData) { + // Open zone file as little endian stream + QDataStream zoneFileStream(aFileData); + zoneFileStream.setByteOrder(QDataStream::BigEndian); + + // Parse data from zone file header + pParseZoneHeader(&zoneFileStream); + SetRecords(pParseZoneIndex(&zoneFileStream, GetRecordCount())); + SetAssetMap(pParseAssets(&zoneFileStream, GetRecords())); + + return true; +} + +void ZoneFile_COD9_WiiU::pParseZoneHeader(QDataStream *aZoneFileStream) { + SetSize(pParseZoneSize(aZoneFileStream)); + pParseZoneUnknownsA(aZoneFileStream); + + SetTagCount(pParseZoneTagCount(aZoneFileStream)); + pParseZoneUnknownsB(aZoneFileStream); + + SetRecordCount(pParseZoneRecordCount(aZoneFileStream)); + + quint32 tagCount = GetTagCount(); + if (tagCount) { + pParseZoneUnknownsC(aZoneFileStream); + SetTags(pParseZoneTags(aZoneFileStream, tagCount)); + } else { + aZoneFileStream->skipRawData(4); + } +} + +quint32 ZoneFile_COD9_WiiU::pParseZoneSize(QDataStream *aZoneFileStream) { + quint32 zoneFileSize; + *aZoneFileStream >> zoneFileSize; + if (zoneFileSize <= 0) { + qDebug() << "Tried to open empty zone file!"; + exit(-1); + } + zoneFileSize += 36; + return zoneFileSize; +} + +/* + ParseZoneUnknownsA() + + Parses the 1st section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD9_WiiU::pParseZoneUnknownsA(QDataStream *aZoneFileStream) { + // Byte 4-7, 8-11, 12-15: unknown + QByteArray unknown1(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown1.data(), 4); + + QByteArray unknown2(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown2.data(), 4); + + QByteArray unknown3(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown3.data(), 4); + + // Byte 16-19, 20-23: empty/unknown + QByteArray unknown4(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown4.data(), 4); + + QByteArray unknown5(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown5.data(), 4); + + // Byte 24-27: somehow related to the filesize, but smaller value + QByteArray unknown6(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown6.data(), 4); + + // Byte 28-31, 32-35: unknown + QByteArray unknown7(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown7.data(), 4); + + QByteArray unknown8(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown8.data(), 4); +} + +/* + ParseZoneTagCount() + + Parses the number of string tags in the zone index +*/ +quint32 ZoneFile_COD9_WiiU::pParseZoneTagCount(QDataStream *aZoneFileStream) { + quint32 tagCount; + *aZoneFileStream >> tagCount; + return tagCount; +} + +/* + ParseZoneRecordCount() + + Parses the number of records in the zone index +*/ +quint32 ZoneFile_COD9_WiiU::pParseZoneRecordCount(QDataStream *aZoneFileStream) { + quint32 recordCount; + *aZoneFileStream >> recordCount; + return recordCount; +} + +/* + ParseZoneUnknownsB() + + Parses the 2nd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD9_WiiU::pParseZoneUnknownsB(QDataStream *aZoneFileStream) { + // Byte 44-47: Unknown/empty? + QByteArray unknown9(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown9.data(), 4); +} + +/* + pParseZoneUnknownsC() + + Parses the 3rd section of unknowns as hex vals and uint32s +*/ +void ZoneFile_COD9_WiiU::pParseZoneUnknownsC(QDataStream *aZoneFileStream) { + // Byte 40-43: Unknown/empty? + QByteArray unknown10(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown10.data(), 4); + + // Byte 44-47: Unknown/empty? + QByteArray unknown11(4, Qt::Uninitialized); + aZoneFileStream->readRawData(unknown11.data(), 4); +} + +/* + ParseZoneTags() + + Parses the string tags ate the start of zone file +*/ +QStringList ZoneFile_COD9_WiiU::pParseZoneTags(QDataStream *aZoneFileStream, quint32 tagCount) { + QStringList tags; + + // Byte 48-51: Repeated separators? ÿÿÿÿ x i + aZoneFileStream->skipRawData(4 * (tagCount - 1)); + + // Parse tags/strings before index + QString zoneTag; + char zoneTagChar; + for (quint32 i = 0; i < tagCount; i++) { + *aZoneFileStream >> zoneTagChar; + while (zoneTagChar != 0) { + zoneTag += zoneTagChar; + *aZoneFileStream >> zoneTagChar; + } + if (!zoneTag.isEmpty()) { tags << zoneTag; } + zoneTag.clear(); + } + return tags; +} + +/* + ParseZoneIndex() + + Parse the binary zone index data and populate table +*/ +QStringList ZoneFile_COD9_WiiU::pParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) { + QStringList result; + + // Don't parse if no records + if (!recordCount) { return result; } + + if (aZoneFileStream->device()->peek(4).toHex().contains("ffff")) { + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 2); + } + + // Parse index & map found asset types + for (quint32 i = 0; i <= recordCount; i++) { + // Skip record start + QByteArray rawAssetType(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rawAssetType.data(), 4); + result << rawAssetType.toHex(); + + // Skip separator + aZoneFileStream->skipRawData(4); + } + return result; +} + +AssetMap ZoneFile_COD9_WiiU::pParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) { + AssetMap result; + + aZoneFileStream->device()->seek(aZoneFileStream->device()->pos() - 8); + + for (int i = 0; i < assetOrder.size(); i++) { + const QString typeHex = assetOrder[i]; + const AssetType typeStr = AssetStrToEnum(typeHex); + + if (typeStr == ASSET_LOCAL_STRING) { // localized string asset + result.localStrings << pParseAsset_LocalString(aZoneFileStream); + } else if (typeStr == ASSET_RAW_FILE) { // gsc + auto rawFile = pParseAsset_RawFile(aZoneFileStream); + if (rawFile.length) { + result.rawFiles << rawFile; + } + } else if (typeStr == ASSET_PHYS_PRESET) { // physpreset + pParseAsset_PhysPreset(aZoneFileStream); + } else if (typeStr == ASSET_MODEL) { // xmodel + result.models << pParseAsset_Model(aZoneFileStream); + } else if (typeStr == ASSET_MATERIAL) { // material + pParseAsset_Material(aZoneFileStream); + } else if (typeStr == ASSET_SHADER) { // pixelshader + pParseAsset_Shader(aZoneFileStream); + } else if (typeStr == ASSET_TECH_SET) { // techset include + result.techSets << pParseAsset_TechSet(aZoneFileStream); + } else if (typeStr == ASSET_IMAGE) { // image + result.images << pParseAsset_Image(aZoneFileStream); + } else if (typeStr == ASSET_SOUND) { // loaded_sound + result.sounds << pParseAsset_Sound(aZoneFileStream); + } else if (typeStr == ASSET_COLLISION_MAP) { // col_map_mp + pParseAsset_ColMapMP(aZoneFileStream); + } else if (typeStr == ASSET_MP_MAP) { // game_map_sp + pParseAsset_GameMapSP(aZoneFileStream); + } else if (typeStr == ASSET_SP_MAP) { // game_map_mp + pParseAsset_GameMapMP(aZoneFileStream); + } else if (typeStr == ASSET_LIGHT_DEF) { // lightdef + pParseAsset_LightDef(aZoneFileStream); + } else if (typeStr == ASSET_UI_MAP) { // ui_map + pParseAsset_UIMap(aZoneFileStream); + } else if (typeStr == ASSET_SND_DRIVER_GLOBALS) { // snddriverglobals + pParseAsset_SNDDriverGlobals(aZoneFileStream); + } else if (typeStr == ASSET_AI_TYPE) { // aitype + pParseAsset_AIType(aZoneFileStream); + } else if (typeStr == ASSET_EFFECT) { // aitype + pParseAsset_FX(aZoneFileStream); + } else if (typeStr == ASSET_ANIMATION) { // aitype + result.animations << pParseAsset_Animation(aZoneFileStream); + } else if (typeStr == ASSET_STRING_TABLE) { // string_table + result.stringTables << pParseAsset_StringTable(aZoneFileStream); + } else if (typeStr == ASSET_MENU) { // string_table + result.menuFiles << pParseAsset_MenuFile(aZoneFileStream); + } else if (typeStr == ASSET_WEAPON) { // string_table + pParseAsset_Weapon(aZoneFileStream); + } else if (typeStr == ASSET_D3DBSP) { // string_table + pParseAsset_D3DBSP(aZoneFileStream); + } + } + return result; +} + +LocalString ZoneFile_COD9_WiiU::pParseAsset_LocalString(QDataStream *aZoneFileStream) { + LocalString result; + + quint32 stringPtr, aliasPtr; + *aZoneFileStream >> stringPtr >> aliasPtr; + if (stringPtr == 4294967295) { + // Parse local string asset contents + QString localStr; + char localStrChar; + *aZoneFileStream >> localStrChar; + while (localStrChar != 0) { + result.string += localStrChar; + *aZoneFileStream >> localStrChar; + } + } else { + result.string = "String Ptr: " + QString::number(stringPtr); + } + + if (aliasPtr == 4294967295) { + // Parse rawfile name + QString aliasName; + char aliasNameChar; + *aZoneFileStream >> aliasNameChar; + while (aliasNameChar != 0) { + result.alias += aliasNameChar; + *aZoneFileStream >> aliasNameChar; + } + } else { + result.string = "Alias Ptr: " + QString::number(aliasPtr); + } + + return result; +} + +RawFile ZoneFile_COD9_WiiU::pParseAsset_RawFile(QDataStream *aZoneFileStream) { + RawFile result; + + // Skip start separator FF FF FF FF (pointer?) + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.length; + + // Skip unknown 4 byte data + aZoneFileStream->skipRawData(4); + + // Parse rawfile path + char scriptPathChar; + *aZoneFileStream >> scriptPathChar; + while (scriptPathChar != 0) { + result.path += scriptPathChar; + *aZoneFileStream >> scriptPathChar; + } + result.path.replace(",", ""); + const QStringList pathParts = result.path.split('/'); + if (pathParts.size() == 0) { + qDebug() << "Failed to parse ff path! " << result.path; + exit(-1); + } + + // Parse gsc contents + char rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { + result.contents += rawFileContentsChar; + *aZoneFileStream >> rawFileContentsChar; + } + return result; +} + +void ZoneFile_COD9_WiiU::pParseAsset_PhysPreset(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Model ZoneFile_COD9_WiiU::pParseAsset_Model(QDataStream *aZoneFileStream) { + Model result; + + *aZoneFileStream >> result.namePtr >> result.tagCount >> result.rootTagCount + >> result.surfCount >> result.unknownCount >> result.boneNamePtr + >> result.parentListPtr >> result.quatsPtr >> result.transPtr + >> result.partClassPtr >> result.baseMatPtr + >> result.surfsPtr >> result.materialHandlesPtr; + + // Parse XModelLodInfo + for (int i = 1; i <= 4; i++) { + quint32 intDist; + *aZoneFileStream >> intDist; + + std::memcpy(&result.lodInfo[i].dist, &intDist, sizeof(result.lodInfo[i].dist)); + *aZoneFileStream >> result.lodInfo[i].numsurfs >> result.lodInfo[i].surfIndex; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.lodInfo[i].partBits[0] + >> result.lodInfo[i].partBits[1] + >> result.lodInfo[i].partBits[2] + >> result.lodInfo[i].partBits[3]; + } + + *aZoneFileStream >> result.collSurfsPtr >> result.numCollSurfs >> result.contents >> result.boneInfoPtr; + + quint32 intRadius, intMins[3], intMaxs[3]; + *aZoneFileStream >> intRadius >> intMins[0] >> intMins[1] + >> intMins[2] >> intMaxs[0] >> intMaxs[1] >> intMaxs[2]; + + std::memcpy(&result.radius, &intRadius, sizeof(result.radius)); + + std::memcpy(&result.mins[0], &intMins[0], sizeof(result.mins[0])); + std::memcpy(&result.mins[1], &intMins[1], sizeof(result.mins[1])); + std::memcpy(&result.mins[2], &intMins[2], sizeof(result.mins[2])); + + std::memcpy(&result.maxs[0], &intMaxs[0], sizeof(result.maxs[0])); + std::memcpy(&result.maxs[1], &intMaxs[1], sizeof(result.maxs[2])); + std::memcpy(&result.maxs[2], &intMaxs[2], sizeof(result.maxs[3])); + + *aZoneFileStream >> result.numLods >> result.collLod >> result.streamInfoPtr + >> result.memUsage >> result.flags >> result.physPresetPtr >> result.physGeomsPtr; + + // Parse model name + char modelNameChar; + *aZoneFileStream >> modelNameChar; + while (modelNameChar == 0) { + *aZoneFileStream >> modelNameChar; + } + while (modelNameChar != 0) { + result.modelName += modelNameChar; + *aZoneFileStream >> modelNameChar; + } + return result; +} + +Material ZoneFile_COD9_WiiU::pParseAsset_Material(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); + + return Material(); +} + +Shader ZoneFile_COD9_WiiU::pParseAsset_Shader(QDataStream *aZoneFileStream) { + Shader result = Shader(); + + quint8 minorVersion, majorVersion; + *aZoneFileStream >> minorVersion >> majorVersion; + + quint32 magic; + *aZoneFileStream >> magic; + + // Verify .fxc magic + if (magic != 65534 && magic != 65535) { return result; } + + SHADER_TYPE type = SHADER_NONE; + quint16 rawShaderType; + *aZoneFileStream >> rawShaderType; + if (rawShaderType == 65535) { // Pixel shader + type = SHADER_PIXEL; + } else if (rawShaderType == 65534) { // Vertex shader + type = SHADER_VERTEX; + } + Q_UNUSED(type); + + while (true) { + quint32 instructionToken; + *aZoneFileStream >> instructionToken; + + SHADER_OPCODE opCode = (SHADER_OPCODE)(instructionToken & 0xffff); + + int size; + if (opCode == OPCODE_End) { + break; + } else if (opCode == OPCODE_Comment) { + size = (int)((instructionToken >> 16) & 0x7FFF); + } else { + size = (int)((instructionToken >> 24) & 0x0f); + } + Q_UNUSED(size); + } + + + return result; +} + +TechSet ZoneFile_COD9_WiiU::pParseAsset_TechSet(QDataStream *aZoneFileStream) { + TechSet result; + + for (int i = 1; i <= 62; i++) { + quint32 ptr; + *aZoneFileStream >> ptr; + + result.pointers << ptr; + } + qDebug() << aZoneFileStream->device()->pos(); + + // Parse techset name + char techSetNameChar; + *aZoneFileStream >> techSetNameChar; + while (techSetNameChar != 0) { + result.name += techSetNameChar; + *aZoneFileStream >> techSetNameChar; + } + result.name.replace(",", ""); + + return result; +} + +Image ZoneFile_COD9_WiiU::pParseAsset_Image(QDataStream *aZoneFileStream) { + Image result; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknowna >> result.unknownb + >> result.unknownc >> result.unknownd + >> result.unknowne >> result.unknownf + >> result.unknowng; + + aZoneFileStream->skipRawData(15 * 4); + *aZoneFileStream >> result.unknownh >> result.unknowni; + + aZoneFileStream->skipRawData(4); + *aZoneFileStream >> result.unknownj; + + aZoneFileStream->skipRawData(4); + + char materialNameChar; + *aZoneFileStream >> materialNameChar; + while (materialNameChar != 0) { + result.materialName += materialNameChar; + *aZoneFileStream >> materialNameChar; + } + result.materialName.replace(",", ""); + + if (result.unknowna) { + *aZoneFileStream >> result.unknownk; + *aZoneFileStream >> result.unknownl; + *aZoneFileStream >> result.unknownm; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown1; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.unknown2 >> result.unknown3 + >> result.size1 >> result.size2 + >> result.unknown4 >> result.unknown5; + + aZoneFileStream->skipRawData(4); + + char imageNameChar; + *aZoneFileStream >> imageNameChar; + while (imageNameChar != 0) { + result.name += imageNameChar; + *aZoneFileStream >> imageNameChar; + } + + *aZoneFileStream >> result.unknown6 >> result.unknown7; + + QByteArray compressionData(8, Qt::Uninitialized); + aZoneFileStream->readRawData(compressionData.data(), 8); + if (compressionData.contains("DXT1")) { + result.compression = COMPRESSION_DXT1; + } else if (compressionData.contains("DXT3")) { + result.compression = COMPRESSION_DXT3; + } else if (compressionData.contains("DXT5")) { + result.compression = COMPRESSION_DXT5; + } else { + result.compression = COMPRESSION_NONE; + } + + *aZoneFileStream >> result.unknown8 >> result.unknown9; + } + + return result; +} + +SoundAsset ZoneFile_COD9_WiiU::pParseAsset_Sound(QDataStream *aZoneFileStream) { + SoundAsset result; + + qDebug() << aZoneFileStream->device()->pos(); + + QByteArray rootNamePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(rootNamePtr.data(), 4); + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream >> result.count; + + if (rootNamePtr.toHex() == "ffffffff") { + // Read in sound file name + char soundNameChar; + *aZoneFileStream >> soundNameChar; + while (soundNameChar != 0) { + result.name += soundNameChar; + *aZoneFileStream >> soundNameChar; + } + } + + int tagCount = 0; + int resultCount = 0; + for (quint32 i = 0; i < result.count; i++) { + aZoneFileStream->skipRawData(12); + + QByteArray tagPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(tagPtr.data(), 4); + + if (tagPtr.toHex() == "ffffffff") { + tagCount++; + } + aZoneFileStream->skipRawData(4); + + QByteArray pathPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pathPtr.data(), 4); + + if (pathPtr.toHex() == "ffffffff") { + resultCount++; + } + + aZoneFileStream->skipRawData(160); + } + + for (int i = 0; i < tagCount; i++) { + // Read in tag? + QString tag; + char tagChar; + *aZoneFileStream >> tagChar; + while (tagChar != 0) { + tag += tagChar; + *aZoneFileStream >> tagChar; + } + } + + for (int i = 0; i < resultCount; i++) { + Sound sound; + + if (aZoneFileStream->device()->peek(12).toHex().contains("ffffffff00000000")) { + aZoneFileStream->skipRawData(12); + } + + aZoneFileStream->skipRawData(8); + + QByteArray aliasPtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(aliasPtr.data(), 4); + + QByteArray namePtr(4, Qt::Uninitialized); + aZoneFileStream->readRawData(namePtr.data(), 4); + + *aZoneFileStream >> sound.dataLength; + + if (aliasPtr.toHex() == "ffffffff") { + // Read in sound alias name + char soundAliasChar; + *aZoneFileStream >> soundAliasChar; + while (soundAliasChar != 0) { + sound.alias += soundAliasChar; + *aZoneFileStream >> soundAliasChar; + } + } + + if (aZoneFileStream->device()->peek(4) == "RIFF") { + sound.path = sound.alias; + sound.alias = ""; + } else if (namePtr.toHex() == "ffffffff") { + // Read in sound file path + char soundPathChar; + *aZoneFileStream >> soundPathChar; + while (soundPathChar != 0) { + sound.path += soundPathChar; + *aZoneFileStream >> soundPathChar; + } + sound.path.replace(",", ""); + } + + if (sound.dataLength) { + QByteArray data(sound.dataLength, Qt::Uninitialized); + aZoneFileStream->readRawData(data.data(), sound.dataLength); + sound.data = data; + } + result.sounds.append(sound); + } + + return result; +} + +void ZoneFile_COD9_WiiU::pParseAsset_ColMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_GameMapSP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_GameMapMP(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_LightDef(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_UIMap(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_AIType(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_FX(QDataStream *aZoneFileStream) { + Q_UNUSED(aZoneFileStream); +} + +Animation ZoneFile_COD9_WiiU::pParseAsset_Animation(QDataStream *aZoneFileStream) { + Animation result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.dataByteCount + >> result.dataShortCount + >> result.dataIntCount + >> result.randomDataByteCount + >> result.randomDataIntCount + >> result.numframes + >> result.isLooped + >> result.isDelta + >> result.noneRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.twoDRotatedBoneCount + >> result.normalRotatedBoneCount + >> result.normalTranslatedBoneCount + >> result.preciseTranslatedBoneCount + >> result.staticTranslatedBoneCount + >> result.noneTranslatedBoneCount + >> result.totalBoneCount + >> result.otherBoneCount1 + >> result.otherBoneCount2 + >> result.notifyCount + >> result.assetType + >> result.pad + >> result.randomDataShortCount + >> result.indexCount + >> result.frameRate + >> result.frequency + >> result.boneIDsPtr + >> result.dataBytePtr + >> result.dataShortPtr + >> result.dataIntPtr + >> result.randomDataShortPtr + >> result.randomDataBytePtr + >> result.randomDataIntPtr + >> result.longIndiciesPtr + >> result.notificationsPtr + >> result.deltaPartsPtr; + + // Read in x_anim file name + QString xAnimName; + char xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + while (xAnimNameChar != 0) { + result.name += xAnimNameChar; + *aZoneFileStream >> xAnimNameChar; + } + + // Parse x_anim index header + QVector sectionLengths; + for (int i = 0; i < result.numframes; i++) { + quint8 sectionlength; + *aZoneFileStream >> sectionlength; + sectionLengths.push_back(sectionlength); + // Skip padding + aZoneFileStream->skipRawData(1); + } + // Skip unknown section + aZoneFileStream->skipRawData(2 * 8); + + return result; +} + +MenuFile ZoneFile_COD9_WiiU::pParseAsset_MenuFile(QDataStream *aZoneFileStream) { + //MENU_FILE + MenuFile result; + + aZoneFileStream->skipRawData(4); // Separator + + // Parse menu def count + *aZoneFileStream >> result.menuCount; + + // Clearly misparsed, never have this much + if (result.menuCount > 1000) { + qDebug() << "Failure reported when parsing menu file."; + return result; + } + for (uint i = 0; i < result.menuCount; i++) { + Menu menu; + + aZoneFileStream->skipRawData(4); // Separator + + // Read in x_anim file name + char menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + while (menuFilepathChar != 0) { + menu.filePath += menuFilepathChar; + *aZoneFileStream >> menuFilepathChar; + } + aZoneFileStream->skipRawData(4); // Separator + + *aZoneFileStream >> menu.menuNamePtr; + + float menuRectX, menuRectY, menuRectWidth, menuRectHeight; + *aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight; + menu.rect = QRectF(menuRectX, menuRectY, menuRectWidth, menuRectHeight); + + quint32 hAlignInt, vAlignInt; + *aZoneFileStream >> hAlignInt >> vAlignInt; + menu.hAlign = (MENU_H_ALIGNMENT)hAlignInt; + menu.vAlign = (MENU_V_ALIGNMENT)vAlignInt; + + float rectClientX, rectClientY, rectClientWidth, rectClientHeight; + *aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight; + menu.clientRect = QRectF(rectClientX, rectClientY, rectClientWidth, rectClientHeight); + + quint32 hClientAlignInt, vClientAlignInt, styleInt, borderInt; + *aZoneFileStream >> hClientAlignInt >> vClientAlignInt >> menu.groupPtr + >> styleInt >> borderInt >> menu.ownerDraw >> menu.ownerDrawFlags + >> menu.borderSize >> menu.staticFlags >> menu.dynamicFlags >> menu.nextTime; + menu.hClientAlign = (MENU_H_ALIGNMENT)hClientAlignInt; + menu.vClientAlign = (MENU_V_ALIGNMENT)vClientAlignInt; + menu.style = (MENU_WINDOW_STYLE)styleInt; + menu.border = (MENU_WINDOW_BORDER)borderInt; + + float foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA, + backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA, + borderColorR, borderColorG, borderColorB, borderColorA, + outlineColorR, outlineColorG, outlineColorB, outlineColorA; + *aZoneFileStream >> foregroundColorR >> foregroundColorG >> foregroundColorB >> foregroundColorA + >> backgroundColorR >> backgroundColorG >> backgroundColorB >> backgroundColorA + >> borderColorR >> borderColorG >> borderColorB >> borderColorA + >> outlineColorR >> outlineColorG >> outlineColorB >> outlineColorA; + + menu.foregroundColor = QColor(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA); + menu.backgroundColor = QColor(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA); + menu.borderColor = QColor(borderColorR, borderColorG, borderColorB, borderColorA); + menu.outlineColor = QColor(outlineColorR, outlineColorG, outlineColorB, outlineColorA); + + *aZoneFileStream >> menu.materialPtr >> menu.fontPtr >> menu.fullScreen >> menu.itemCount + >> menu.fontIndex >> menu.cursorItem >> menu.fadeCycle >> menu.fadeClamp + >> menu.fadeAmount >> menu.fadeInAmount >> menu.blurRadius >> menu.onOpenPtr + >> menu.onFocusPtr >> menu.onClosePtr >> menu.onESCPtr >> menu.onKeyPtr + >> menu.visibleExpCount >> menu.expEntryPtr >> menu.allowedBindingPtr + >> menu.soundNamePtr >> menu.imageTrack; + + float focusColorR, focusColorG, focusColorB, focusColorA, + disabledColorR, disabledColorG, disabledColorB, disabledColorA; + *aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA + >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA; + menu.focusColor = QColor(focusColorR, focusColorG, focusColorB, focusColorA); + menu.disabledColor = QColor(disabledColorR, disabledColorG, disabledColorB, disabledColorA); + + *aZoneFileStream >> menu.rectXExpCount >> menu.rectXExpPtr >> menu.rectYExpCount >> menu.rectYExpPtr; + + aZoneFileStream->skipRawData(4); // Separator + + char menuDefNameChar; + int menuDefNameLen = 0; + *aZoneFileStream >> menuDefNameChar; + while (menuDefNameChar != 0 && menuDefNameLen < 30) { + menuDefNameLen++; + menu.name += menuDefNameChar; + *aZoneFileStream >> menuDefNameChar; + } + + char defStringChar; + int defStringLen = 0; + *aZoneFileStream >> defStringChar; + while (defStringChar != 0 && defStringLen < 30) { + defStringLen++; + menu.definition += defStringChar; + *aZoneFileStream >> defStringChar; + } + aZoneFileStream->skipRawData(4 * 10); + + *aZoneFileStream >> menu.itemWindowDefNamePtr; + + float itemRectX, itemRectY, itemRectWidth, itemRectHeight; + *aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight; + menu.itemRect = QRectF(itemRectX, itemRectY, itemRectWidth, itemRectHeight); + + *aZoneFileStream >> menu.itemHAlignment >> menu.itemVAlignment >> menu.itemGroupPtr + >> menu.itemWindowStyle >> menu.itemWindowBorder >> menu.itemOwnerDraw + >> menu.itemOwnerDrawFlags >> menu.itemBorderSize >> menu.itemStaticFlags + >> menu.itemDynamicFlags >> menu.itemNextTime; + + float itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA, + itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA, + itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA, + itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA; + *aZoneFileStream >> itemForegroundColorR >> itemForegroundColorG >> itemForegroundColorB >> itemForegroundColorA + >> itemBackgroundColorR >> itemBackgroundColorG >> itemBackgroundColorB >> itemBackgroundColorA + >> itemBorderColorR >> itemBorderColorG >> itemBorderColorB >> itemBorderColorA + >> itemOutlineColorR >> itemOutlineColorG >> itemOutlineColorB >> itemOutlineColorA; + + menu.itemForegroundColor = QColor(itemForegroundColorR, itemForegroundColorG, itemForegroundColorB, itemForegroundColorA); + menu.itemBackgroundColor = QColor(itemBackgroundColorR, itemBackgroundColorG, itemBackgroundColorB, itemBackgroundColorA); + menu.itemBorderColor = QColor(itemBorderColorR, itemBorderColorG, itemBorderColorB, itemBorderColorA); + menu.itemOutlineColor = QColor(itemOutlineColorR, itemOutlineColorG, itemOutlineColorB, itemOutlineColorA); + + *aZoneFileStream >> menu.itemMaterialPtr; + + float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight; + *aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight; + menu.itemTextRect = QRectF(itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight); + + quint32 hItemTextAlignInt, vItemTextAlignInt, itemType, fontTypeInt, textStyleInt; + *aZoneFileStream >> hItemTextAlignInt >> vItemTextAlignInt >> itemType >> menu.dataType + >> menu.alignment >> fontTypeInt >> menu.textAlignMode >> menu.textalignx >> menu.textaligny + >> menu.textscale >> textStyleInt >> menu.gameMsgWindowIndex >> menu.gameMsgWindowMode + >> menu.testPtr >> menu.textSavegameInfo >> menu.parentPtr; + menu.itemText_hAlign = (MENU_H_ALIGNMENT)hItemTextAlignInt; + menu.itemText_vAlign = (MENU_V_ALIGNMENT)vItemTextAlignInt; + menu.itemType = (MENU_ITEM_TYPE)itemType; + menu.fontEnum = (MENU_FONT_TYPE)fontTypeInt; + menu.textStyle = (MENU_ITEM_TEXTSTYLE)textStyleInt; + + *aZoneFileStream >> menu.mouseEnterText >> menu.mouseExitText >> menu.mouseEnter >> menu.mouseExit + >> menu.action >> menu.onAccept >> menu.onFocus >> menu.leaveFocus >> menu.dvar >> menu.dvarTest + >> menu.keyHandlerPtr >> menu.enableDvarPtr >> menu.dvarFlags >> menu.focusSoundPtr + >> menu.special >> menu.cursorPos; + + // itemDefData_t typeData; + + // listBoxDef_s *listBox; + + *aZoneFileStream >> menu.startPos >> menu.endPos >> menu.drawPadding; + + *aZoneFileStream >> menu.elementWidth >> menu.elementHeight; + + *aZoneFileStream >> menu.elementStyle >> menu.numColumns; + + //columnInfo_s columnInfo[16]; + + *aZoneFileStream >> menu.doubleClickPtr; + + + *aZoneFileStream >> menu.notselectable >> menu.noScrollBars >> menu.usePaging; + + float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA, + itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA, + itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA; + *aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA + >> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA + >> itemFocusColorR >> itemFocusColorG >> itemFocusColorB >> itemFocusColorA; + menu.itemSelectBorderColor = QColor(itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA); + menu.itemDisableColor = QColor(itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA); + menu.itemFocusColor = QColor(itemFocusColorR, itemFocusColorG, itemFocusColorB, itemFocusColorA); + + *aZoneFileStream >> menu.selectIconPtr >> menu.backgroundItemListboxPtr >> menu.highlightTexturePtr; + + // editFieldDef_s *editField; + + *aZoneFileStream >> menu.minVal >> menu.maxVal >> menu.defVal >> menu.range >> menu.maxChars + >> menu.maxCharsGotoNext >> menu.maxPaintChars >> menu.paintOffset; + + // multiDef_s *multi; + + for (int i = 0; i < 32; i++) { + quint32 dvarList; + *aZoneFileStream >> dvarList; + menu.dvarListPtrs.push_back(dvarList); + } + + for (int i = 0; i < 32; i++) { + quint32 dvarStr; + *aZoneFileStream >> dvarStr; + menu.dvarStrPtrs.push_back(dvarStr); + } + + for (int i = 0; i < 32; i++) { + float dvarValue; + *aZoneFileStream >> dvarValue; + menu.dvarValues.push_back(dvarValue); + } + + *aZoneFileStream >> menu.count >> menu.strDef >> menu.enumDvarNamePtr; + aZoneFileStream->skipRawData(4); + //>> menu.dataPtr + *aZoneFileStream >> menu.itemImageTrack; + + qDebug() << aZoneFileStream->device()->pos(); + + //statement_s visibleExp; + //statement_s textExp; + //statement_s materialExp; + //statement_s rectXExp; + //statement_s rectYExp; + //statement_s rectWExp; + //statement_s rectHExp; + //statement_s foreColorAExp; + result.menuDefs << menu; + } + return result; +} + +void ZoneFile_COD9_WiiU::pParseAsset_Weapon(QDataStream *aZoneFileStream) { + //WEAPON_FILE + Q_UNUSED(aZoneFileStream); +} + +void ZoneFile_COD9_WiiU::pParseAsset_D3DBSP(QDataStream *aZoneFileStream) { + //D3DBSP_DUMP + Q_UNUSED(aZoneFileStream); +} + +StringTable ZoneFile_COD9_WiiU::pParseAsset_StringTable(QDataStream *aZoneFileStream) { + StringTable result; + + aZoneFileStream->skipRawData(4); + + *aZoneFileStream + >> result.columnCount + >> result.rowCount; + + // Todo fix this + result.columnCount = 0; + result.rowCount = 0; + + aZoneFileStream->skipRawData(4); + + QString stringTableName; + char stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + while (stringTableNameChar != 0) { + result.name += stringTableNameChar; + *aZoneFileStream >> stringTableNameChar; + } + + for (quint32 i = 0; i < result.rowCount; i++) { + QByteArray pointerData(4, Qt::Uninitialized); + aZoneFileStream->readRawData(pointerData.data(), 4); + result.tablePointers.push_back(pointerData.toHex()); + + aZoneFileStream->skipRawData(4); + } + + for (const QString &pointerAddr : result.tablePointers) { + QString leadingContent = ""; + if (pointerAddr == "FFFFFFFF") { + char leadingContentChar; + *aZoneFileStream >> leadingContentChar; + while (leadingContentChar != 0) { + leadingContent += leadingContentChar; + *aZoneFileStream >> leadingContentChar; + } + } else { + leadingContent = pointerAddr; + } + + QString content; + char contentChar; + *aZoneFileStream >> contentChar; + while (contentChar != 0) { + content += contentChar; + *aZoneFileStream >> contentChar; + } + result.content[leadingContent] = content; + } + return result; +} + +AssetType ZoneFile_COD9_WiiU::AssetStrToEnum(const QString aAssetType) { + const QString cleanedType = aAssetType.toUpper(); + if (cleanedType == "17000000") { // localized string PARTIALLY VERIFIED + return ASSET_LOCAL_STRING; + } else if (cleanedType == "20000000") { // raw_file PARTIALLY VERIFIED + return ASSET_RAW_FILE; + } else if (cleanedType == "1A000000") { // fx PARTIALLY VERIFIED + return ASSET_EFFECT; + } else if (cleanedType == "09000000") { // loaded_sound PARTIALLY VERIFIED + return ASSET_SOUND; + } else if (cleanedType == "04000000") { // x_anim PARTIALLY VERIFIED + return ASSET_ANIMATION; + } else if (cleanedType == "0C000000") { // collision_map PARTIALLY VERIFIED + return ASSET_COLLISION_MAP; + } else if (cleanedType == "21000000") { // string_table PARTIALLY VERIFIED + return ASSET_STRING_TABLE; + } else if (cleanedType == "15000000") { // menu_file PARTIALLY VERIFIED + return ASSET_MENU; + } else if (cleanedType == "07000000") { // tech set PARTIALLY VERIFIED + return ASSET_TECH_SET; + } else if (cleanedType == "18000000") { // weapon PARTIALLY VERIFIED + return ASSET_WEAPON; + } else if (cleanedType == "11000000") { // gfx map PARTIALLY VERIFIED + return ASSET_GFX_MAP; + } else if (cleanedType == "12000000") { // light_def PARTIALLY VERIFIED + return ASSET_LIGHT_DEF; + } else if (cleanedType == "14000000") { // font PARTIALLY VERIFIED + return ASSET_FONT; + } else if (cleanedType == "05000000") { // xmodel PARTIALLY VERIFIED + return ASSET_MODEL; + } else if (cleanedType == "0D000000") { // d3dbsp PARTIALLY VERIFIED + return ASSET_D3DBSP; + } else if (cleanedType == "06000000") { // image PARTIALLY VERIFIED + return ASSET_IMAGE; + } else if (cleanedType == "0E000000") { // game map sp PARTIALLY VERIFIED + return ASSET_GAME_MAP_SP; + } else if (cleanedType == "0B000000") { // col map sp PARTIALLY VERIFIED + return ASSET_COL_MAP_SP; + } + return ASSET_NONE; +} + +QByteArray ZoneFile_COD9_WiiU::GetBinaryData() { + QByteArray result; + + return result; +} diff --git a/libs/zonefile/zonefile_cod9.h b/libs/zonefile/WiiU/zonefile_cod9_wiiu.h similarity index 88% rename from libs/zonefile/zonefile_cod9.h rename to libs/zonefile/WiiU/zonefile_cod9_wiiu.h index a77aa9a..a69625b 100644 --- a/libs/zonefile/zonefile_cod9.h +++ b/libs/zonefile/WiiU/zonefile_cod9_wiiu.h @@ -3,19 +3,19 @@ #include "zonefile.h" -class ZoneFile_COD9 : public ZoneFile +class ZoneFile_COD9_WiiU : public ZoneFile { public: - ZoneFile_COD9(); - ~ZoneFile_COD9(); + ZoneFile_COD9_WiiU(); + ~ZoneFile_COD9_WiiU(); - bool Load(const QByteArray aFileData, FF_PLATFORM aPlatform) override; - QString AssetTypeToString(const QString aAssetType); + bool Load(const QByteArray aFileData) override; + AssetType AssetStrToEnum(const QString aAssetType) override; QByteArray GetBinaryData() override; protected: - void pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) override; + void pParseZoneHeader(QDataStream *aZoneFileStream) override; quint32 pParseZoneSize(QDataStream *aZoneFileStream) override; void pParseZoneUnknownsA(QDataStream *aZoneFileStream) override; quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) override; diff --git a/libs/zonefile/asset_structs.h b/libs/zonefile/asset_structs.h index 1ed6c16..26214fe 100644 --- a/libs/zonefile/asset_structs.h +++ b/libs/zonefile/asset_structs.h @@ -8,17 +8,113 @@ #include #include -struct LocalString { +enum AssetType { + ASSET_NONE = 0x00, + ASSET_RAW_FILE = 0x01, + ASSET_SCRIPT_PARSE_TREE = 0x02, + ASSET_EFFECT = 0x03, + ASSET_SOUND = 0x04, + ASSET_ANIMATION = 0x05, + ASSET_COLLISION_MAP = 0x06, + ASSET_STRING_TABLE = 0x07, + ASSET_MENU = 0x08, + ASSET_TECH_SET = 0x09, + ASSET_WEAPON = 0x10, + ASSET_GFX_MAP = 0x11, + ASSET_LIGHT_DEF = 0x12, + ASSET_FONT = 0x13, + ASSET_MODEL = 0x14, + ASSET_D3DBSP = 0x15, + ASSET_IMAGE = 0x16, + ASSET_GAME_MAP_SP = 0x17, + ASSET_COL_MAP_SP = 0x18, + ASSET_PHYS_PRESET = 0x19, + ASSET_DESTRUCTIBLE = 0x20, + ASSET_LOCAL_STRING = 0x21, + ASSET_SHADER = 0x22, + ASSET_MP_MAP = 0x23, + ASSET_SP_MAP = 0x24, + ASSET_UI_MAP = 0x25, + ASSET_SND_DRIVER_GLOBALS = 0x26, + ASSET_AI_TYPE = 0x27, + ASSET_MATERIAL = 0x28, + ASSET_COMPUTE_SHADER_SET = 0x29, + ASSET_LIGHT_DESCRIPTION = 0x30, + ASSET_BIT_FIELD = 0x31, + ASSET_STRUCTURED_TABLE = 0x32, + ASSET_LEADERBOARD_DEF = 0x33, + ASSET_DDL = 0x34, + ASSET_KEY_VALUE_PAIRS = 0x35, + ASSET_SCRIPT_BUNDLE = 0x36, + ASSET_SCRIPT_BUNDLE_LIST = 0x37, + ASSET_MAP_TABLE = 0x38, + ASSET_MAP_TABLE_LOADING_IMAGES = 0x39, + ASSET_SURFACE_SOUND_DEF = 0x40, + ASSET_SURFACE_FX_TABLE = 0x41, + ASSET_RUMBLE = 0x42, + ASSET_AIM_TABLE = 0x43, + ASSET_MEDAL = 0x44, + ASSET_MEDAL_TABLE = 0x45, + ASSET_OBJECTIVE = 0x46, + ASSET_OBJECTIVE_LIST = 0x47, + ASSET_LASER = 0x48, + ASSET_BEAM = 0x49, + ASSET_STREAMER_HINT = 0x50, + ASSET_ANIM_SELECTOR_TABLE = 0x51, + ASSET_ANIM_MAPPING_TABLE = 0x52, + ASSET_ANIM_STATE_MACHINE = 0x53, + ASSET_BEHAVIOR_TREE = 0x54, + ASSET_BEHAVIOR_STATE_MACHINE = 0x55, + ASSET_FOOTSTEP_TABLE = 0x56, + ASSET_ENTITY_FX_IMPACTS = 0x57, + ASSET_ENTITY_SOUND_IMPACTS = 0x58, + ASSET_VEHICLE_FX_DEF = 0x59, + ASSET_VEHICLE_SOUND_DEF = 0x60, + ASSET_VEHICLE = 0x61, + ASSET_VEHICLE_TRACER = 0x62, + ASSET_PLAYER_SOUNDS_TABLE = 0x63, + ASSET_PLAYER_FX_TABLE = 0x64, + ASSET_SHARED_WEAPON_SOUNDS = 0x65, + ASSET_ATTACHMENT = 0x66, + ASSET_ATTACHMENT_UNIQUE = 0x67, + ASSET_WEAPON_CAMO = 0x68, + ASSET_CUSTOMIZATION_TABLE = 0x69, + ASSET_CUSTOMIZATION_TABLE_FEIMAGES = 0x70, + ASSET_CUSTOMIZATION_TABLE_COLOR = 0x71, + ASSET_PHYS_CONSTRAINTS = 0x72, + ASSET_DESTRUCTIBLE_DEF = 0x73, + ASSET_MODEL_MESH = 0x74, + ASSET_S_ANIM = 0x75, + ASSET_FONT_ICON = 0x76, + ASSET_CG_MEDIA_TABLE = 0x77, + ASSET_SHOCK_FILE = 0x78, + ASSET_ZONE_FILE = 0x79, + ASSET_FAST_FILE = 0x80, + ASSET_SOUND_DRIVER_GLOBALS = 0x81 +}; + +struct Asset { + quint32 startPos; + quint32 endPos; +}; + +struct LocalString : Asset { QString string; QString alias; }; -struct RawFile { +struct RawFile : Asset { quint32 length; QString path; QString contents; }; +struct GscFile { + quint64 length; + QString path; + QString contents; +}; + struct TechSet { QString name; bool hasShaders = false; @@ -96,6 +192,8 @@ struct Model { quint32 physGeomsPtr; QString modelName; + + QVector unknowns; }; struct Animation { @@ -150,9 +248,21 @@ struct StringTable { struct Image { QString name; QString materialName; + IMAGE_COMPRESSION compression; + quint32 size1; quint32 size2; - IMAGE_COMPRESSION compression; + + quint32 unknown1; + quint32 unknown2; + quint32 unknown3; + quint32 unknown4; + quint32 unknown5; + quint32 unknown6; + quint32 unknown7; + quint32 unknown8; + quint32 unknown9; + quint32 unknowna; quint32 unknownb; quint32 unknownc; @@ -166,23 +276,17 @@ struct Image { quint32 unknownk; quint32 unknownl; quint32 unknownm; - quint32 unknown1; - quint32 unknown2; - quint32 unknown3; - quint32 unknown4; - quint32 unknown5; - quint32 unknown6; - quint32 unknown7; - quint32 unknown8; - quint32 unknown9; + + int chunkCount; + QVector unknowns; }; struct Material { - quint32 namePtr; + qint32 namePtr; QString name; quint32 refNamePtr; QString refName; - quint8 unknownA[12]; + QVector pointers; quint32 stateBits[2]; quint16 textureCount; quint16 constCount; @@ -353,6 +457,7 @@ struct SoundAsset { struct AssetMap { QVector localStrings; QVector rawFiles; + QVector gscFiles; //QVector phyPresets; QVector models; QVector materials; diff --git a/libs/zonefile/zonefile.cpp b/libs/zonefile/zonefile.cpp index ac9aae8..ded7694 100644 --- a/libs/zonefile/zonefile.cpp +++ b/libs/zonefile/zonefile.cpp @@ -44,50 +44,342 @@ ZoneFile &ZoneFile::operator=(const ZoneFile &other) { return *this; } -QIcon ZoneFile::AssetStrToIcon(const QString aAssetStr) { - const QString cleanedType = aAssetStr.toUpper(); - if (cleanedType == "LOCAL STRING") { // localized string PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_StringFile.png"); - } else if (cleanedType == "RAW FILE") { // raw_file PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_RawFile.png"); - } else if (cleanedType == "GSC FILE") { // raw_file PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_GSCFile.png"); - } else if (cleanedType == "EFFECT") { // fx PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Effect.png"); - } else if (cleanedType == "SOUND") { // loaded_sound PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Sound.png"); - } else if (cleanedType == "ANIMATION") { // x_anim PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Animation.png"); - } else if (cleanedType == "COLLISION MAP") { // collision_map PARTIALLY VERIFIED - //return "COLLISION MAP"; - } else if (cleanedType == "STRING TABLE") { // string_table PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_StringTable.png"); - } else if (cleanedType == "MENU") { // menu_file PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_MenuFile.png"); - } else if (cleanedType == "TECH SET") { // tech set PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_TechSetFile.png"); - } else if (cleanedType == "WEAPON") { // weapon PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Weapon.png"); - } else if (cleanedType == "GFX MAP") { // gfx map PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_FXMap.png"); - } else if (cleanedType == "LIGHT DEF") { // light_def PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_LightDef.png"); - } else if (cleanedType == "FONT") { // font PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Font.png"); - } else if (cleanedType == "MODEL") { // xmodel PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Model.png"); - } else if (cleanedType == "D3DBSP") { // d3dbsp PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_BSP.png"); - } else if (cleanedType == "IMAGE") { // image PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Image.png"); - } else if (cleanedType == "GAME MAP SP") { // game map sp PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_GameMapSp.png"); - } else if (cleanedType == "COL MAP SP") { // col map sp PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_ColMapSp.png"); - } else if (cleanedType == "PHYS PRESET") { // col map sp PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_PhysPreset.png"); - } else if (cleanedType == "DESTRUCTIBLE") { // col map sp PARTIALLY VERIFIED - return QIcon(":/icons/icons/Icon_Destructible.png"); +QString ZoneFile::AssetEnumToStr(const AssetType aAssetType) +{ + if (aAssetType == ASSET_LOCAL_STRING) { + return "LOCAL_STRING"; + } else if (aAssetType == ASSET_RAW_FILE) { + return "RAW_FILE"; + } else if (aAssetType == ASSET_SCRIPT_PARSE_TREE) { + return "GSC_FILE"; + } else if (aAssetType == ASSET_EFFECT) { + return "EFFECT"; + } else if (aAssetType == ASSET_SOUND) { + return "SOUND"; + } else if (aAssetType == ASSET_ANIMATION) { + return "ANIMATION"; + } else if (aAssetType == ASSET_COLLISION_MAP) { + return "COLLISION_MAP"; + } else if (aAssetType == ASSET_STRING_TABLE) { + return "STRING_TABLE"; + } else if (aAssetType == ASSET_MENU) { + return "MENU"; + } else if (aAssetType == ASSET_TECH_SET) { + return "TECH_SET"; + } else if (aAssetType == ASSET_WEAPON) { + return "WEAPON"; + } else if (aAssetType == ASSET_GFX_MAP) { + return "GFX_MAP"; + } else if (aAssetType == ASSET_LIGHT_DEF) { + return "LIGHT_DEF"; + } else if (aAssetType == ASSET_FONT) { + return "FONT"; + } else if (aAssetType == ASSET_MODEL) { + return "MODEL"; + } else if (aAssetType == ASSET_D3DBSP) { + return "D3DBSP"; + } else if (aAssetType == ASSET_IMAGE) { + return "IMAGE"; + } else if (aAssetType == ASSET_GAME_MAP_SP) { + return "GAME_MAP_SP"; + } else if (aAssetType == ASSET_COL_MAP_SP) { + return "COL_MAP_SP"; + } else if (aAssetType == ASSET_COL_MAP_SP) { + return "COL_MAP_SP"; + } else if (aAssetType == ASSET_UI_MAP) { + return "UI_MAP"; + } else if (aAssetType == ASSET_DESTRUCTIBLE) { + return "DESTRUCTIBLE"; + } else if (aAssetType == ASSET_MATERIAL) { + return "MATERIAL"; + } else if (aAssetType == ASSET_PHYS_PRESET) { + return "PHYS_PRESET"; + } else if (aAssetType == ASSET_COMPUTE_SHADER_SET) { + return "COMPUTE_SHADER_SET"; + } else if (aAssetType == ASSET_STRUCTURED_TABLE) { + return "STRUCTURED_TABLE"; + } else if (aAssetType == ASSET_LEADERBOARD_DEF) { + return "LEADERBOARD_DEF"; + } else if (aAssetType == ASSET_DDL) { + return "DDL"; + } else if (aAssetType == ASSET_SCRIPT_PARSE_TREE) { + return "SCRIPT_PARSE_TREE"; + } else if (aAssetType == ASSET_KEY_VALUE_PAIRS) { + return "KEY_VALUE_PAIRS"; + } else if (aAssetType == ASSET_SCRIPT_BUNDLE) { + return "SCRIPT_BUNDLE"; + } else if (aAssetType == ASSET_SCRIPT_BUNDLE_LIST) { + return "SCRIPT_BUNDLE_LIST"; + } else if (aAssetType == ASSET_LIGHT_DEF) { + return "LIGHT_DEF"; + } else if (aAssetType == ASSET_BIT_FIELD) { + return "BIT_FIELD"; + } else if (aAssetType == ASSET_MAP_TABLE) { + return "MAP_TABLE"; + } else if (aAssetType == ASSET_MAP_TABLE_LOADING_IMAGES) { + return "MAP_TABLE_LOADING_IMAGES"; + } else if (aAssetType == ASSET_SURFACE_SOUND_DEF) { + return "SURFACE_SOUND_DEF"; + } else if (aAssetType == ASSET_SURFACE_FX_TABLE) { + return "SURFACE_FX_TABLE"; + } else if (aAssetType == ASSET_RUMBLE) { + return "RUMBLE"; + } else if (aAssetType == ASSET_AIM_TABLE) { + return "AIM_TABLE"; + } else if (aAssetType == ASSET_MEDAL) { + return "MEDAL"; + } else if (aAssetType == ASSET_MEDAL_TABLE) { + return "MEDAL_TABLE"; + } else if (aAssetType == ASSET_OBJECTIVE) { + return "OBJECTIVE"; + } else if (aAssetType == ASSET_OBJECTIVE_LIST) { + return "OBJECTIVE_LIST"; + } else if (aAssetType == ASSET_LASER) { + return "LASER"; + } else if (aAssetType == ASSET_BEAM) { + return "BEAM"; + } else if (aAssetType == ASSET_STREAMER_HINT) { + return "STREAMER_HINT"; + } else if (aAssetType == ASSET_ANIM_SELECTOR_TABLE) { + return "ANIM_SELECTOR_TABLE"; + } else if (aAssetType == ASSET_ANIM_MAPPING_TABLE) { + return "ANIM_MAPPING_TABLE"; + } else if (aAssetType == ASSET_ANIM_STATE_MACHINE) { + return "ANIM_STATE_MACHINE"; + } else if (aAssetType == ASSET_BEHAVIOR_TREE) { + return "BEHAVIOR_TREE"; + } else if (aAssetType == ASSET_BEHAVIOR_STATE_MACHINE) { + return "BEHAVIOR_STATE_MACHINE"; + } else if (aAssetType == ASSET_FOOTSTEP_TABLE) { + return "FOOTSTEP_TABLE"; + } else if (aAssetType == ASSET_ENTITY_FX_IMPACTS) { + return "ENTITY_FX_IMPACTS"; + } else if (aAssetType == ASSET_ENTITY_SOUND_IMPACTS) { + return "ENTITY_SOUND_IMPACTS"; + } else if (aAssetType == ASSET_VEHICLE_FX_DEF) { + return "VEHICLE_FX_DEF"; + } else if (aAssetType == ASSET_VEHICLE_SOUND_DEF) { + return "VEHICLE_SOUND_DEF"; + } else if (aAssetType == ASSET_VEHICLE) { + return "VEHICLE"; + } else if (aAssetType == ASSET_VEHICLE_TRACER) { + return "VEHICLE_TRACER"; + } else if (aAssetType == ASSET_PLAYER_SOUNDS_TABLE) { + return "PLAYER_SOUNDS_TABLE"; + } else if (aAssetType == ASSET_PLAYER_FX_TABLE) { + return "PLAYER_FX_TABLE"; + } else if (aAssetType == ASSET_SHARED_WEAPON_SOUNDS) { + return "SHARED_WEAPON_SOUNDS"; + } else if (aAssetType == ASSET_ATTACHMENT) { + return "ATTACHMENT"; + } else if (aAssetType == ASSET_ATTACHMENT_UNIQUE) { + return "ATTACHMENT_UNIQUE"; + } else if (aAssetType == ASSET_WEAPON_CAMO) { + return "WEAPON_CAMO"; + } else if (aAssetType == ASSET_CUSTOMIZATION_TABLE) { + return "CUSTOMIZATION_TABLE"; + } else if (aAssetType == ASSET_CUSTOMIZATION_TABLE_FEIMAGES) { + return "CUSTOMIZATION_TABLE_FEIMAGES"; + } else if (aAssetType == ASSET_CUSTOMIZATION_TABLE_COLOR) { + return "CUSTOMIZATION_TABLE_COLOR"; + } else if (aAssetType == ASSET_PHYS_CONSTRAINTS) { + return "PHYS_CONSTRAINTS"; + } else if (aAssetType == ASSET_DESTRUCTIBLE_DEF) { + return "DESTRUCTIBLE_DEF"; + } else if (aAssetType == ASSET_MODEL_MESH) { + return "MODEL_MESH"; + } else if (aAssetType == ASSET_S_ANIM) { + return "S_ANIM"; + } else if (aAssetType == ASSET_SOUND) { + return "SOUND"; + } else if (aAssetType == ASSET_FONT_ICON) { + return "FONT_ICON"; + } else if (aAssetType == ASSET_SHOCK_FILE) { + return "SHOCK_FILE"; + } else if (aAssetType == ASSET_FAST_FILE) { + return "FAST_FILE"; + } else if (aAssetType == ASSET_ZONE_FILE) { + return "ZONE_FILE"; + } else if (aAssetType == ASSET_SOUND_DRIVER_GLOBALS) { + return "SOUND_DRIVER_GLOBALS"; + } + return "UNKNOWN"; +} +QIcon ZoneFile::AssetTypeToIcon(const AssetType aAssetType) { + QString assetCode; + const QStringList parts = AssetEnumToStr(aAssetType).split('_'); + foreach (const QString part, parts) { + assetCode.append(part[0]); + } + if (parts.size() == 1) { + assetCode.append(parts[0][1]); + } + return Utils::CreateAssetIcon(assetCode); + + if (aAssetType == ASSET_NONE) { + return Utils::CreateAssetIcon("NO"); + } else if (aAssetType == ASSET_RAW_FILE) { + return Utils::CreateAssetIcon("RAW"); + } else if (aAssetType == ASSET_SCRIPT_PARSE_TREE) { + return Utils::CreateAssetIcon("PT"); + } else if (aAssetType == ASSET_EFFECT) { + return Utils::CreateAssetIcon("EF"); + } else if (aAssetType == ASSET_SOUND) { + return Utils::CreateAssetIcon("SN"); + } else if (aAssetType == ASSET_ANIMATION) { + return Utils::CreateAssetIcon("AN"); + } else if (aAssetType == ASSET_COLLISION_MAP) { + return Utils::CreateAssetIcon("CM"); + } else if (aAssetType == ASSET_STRING_TABLE) { + return Utils::CreateAssetIcon("ST"); + } else if (aAssetType == ASSET_MENU) { + return Utils::CreateAssetIcon("MN"); + } else if (aAssetType == ASSET_TECH_SET) { + return Utils::CreateAssetIcon("TS"); + } else if (aAssetType == ASSET_WEAPON) { + return Utils::CreateAssetIcon("WP"); + } else if (aAssetType == ASSET_GFX_MAP) { + return Utils::CreateAssetIcon("GFM"); + } else if (aAssetType == ASSET_LIGHT_DEF) { + return Utils::CreateAssetIcon("LDF"); + } else if (aAssetType == ASSET_FONT) { + return Utils::CreateAssetIcon("FN"); + } else if (aAssetType == ASSET_MODEL) { + return Utils::CreateAssetIcon("MD"); + } else if (aAssetType == ASSET_D3DBSP) { + return Utils::CreateAssetIcon("BSP"); + } else if (aAssetType == ASSET_IMAGE) { + return Utils::CreateAssetIcon("IM"); + } else if (aAssetType == ASSET_GAME_MAP_SP) { + return Utils::CreateAssetIcon("GMS"); + } else if (aAssetType == ASSET_COL_MAP_SP) { + return Utils::CreateAssetIcon("CMS"); + } else if (aAssetType == ASSET_PHYS_PRESET) { + return Utils::CreateAssetIcon("PP"); + } else if (aAssetType == ASSET_DESTRUCTIBLE) { + return Utils::CreateAssetIcon("DE"); + } else if (aAssetType == ASSET_LOCAL_STRING) { + return Utils::CreateAssetIcon("LS"); + } else if (aAssetType == ASSET_SHADER) { + return Utils::CreateAssetIcon("SH"); + } else if (aAssetType == ASSET_MP_MAP) { + return Utils::CreateAssetIcon("MM"); + } else if (aAssetType == ASSET_SP_MAP) { + return Utils::CreateAssetIcon("SM"); + } else if (aAssetType == ASSET_UI_MAP) { + return Utils::CreateAssetIcon("UM"); + } else if (aAssetType == ASSET_SND_DRIVER_GLOBALS) { + return Utils::CreateAssetIcon("DG"); + } else if (aAssetType == ASSET_AI_TYPE) { + return Utils::CreateAssetIcon("AT"); + } else if (aAssetType == ASSET_MATERIAL) { + return Utils::CreateAssetIcon("MT"); + } else if (aAssetType == ASSET_COMPUTE_SHADER_SET) { + return Utils::CreateAssetIcon("CSH"); + } else if (aAssetType == ASSET_LIGHT_DESCRIPTION) { + return Utils::CreateAssetIcon("LDS"); + } else if (aAssetType == ASSET_BIT_FIELD) { + return Utils::CreateAssetIcon("BF"); + } else if (aAssetType == ASSET_STRUCTURED_TABLE) { + return Utils::CreateAssetIcon("SDT"); + } else if (aAssetType == ASSET_LEADERBOARD_DEF) { + return Utils::CreateAssetIcon("LBD"); + } else if (aAssetType == ASSET_DDL) { + return Utils::CreateAssetIcon("DDL"); + } else if (aAssetType == ASSET_KEY_VALUE_PAIRS) { + return Utils::CreateAssetIcon("KV"); + } else if (aAssetType == ASSET_SCRIPT_BUNDLE) { + return Utils::CreateAssetIcon("SB"); + } else if (aAssetType == ASSET_SCRIPT_BUNDLE_LIST) { + return Utils::CreateAssetIcon("SBL"); + } else if (aAssetType == ASSET_MAP_TABLE) { + return Utils::CreateAssetIcon("MT"); + } else if (aAssetType == ASSET_MAP_TABLE_LOADING_IMAGES) { + return Utils::CreateAssetIcon("LI"); + } else if (aAssetType == ASSET_SURFACE_SOUND_DEF) { + return Utils::CreateAssetIcon("SSD"); + } else if (aAssetType == ASSET_SURFACE_FX_TABLE) { + return Utils::CreateAssetIcon("FT"); + } else if (aAssetType == ASSET_RUMBLE) { + return Utils::CreateAssetIcon("RM"); + } else if (aAssetType == ASSET_AIM_TABLE) { + return Utils::CreateAssetIcon("AMT"); + } else if (aAssetType == ASSET_MEDAL) { + return Utils::CreateAssetIcon("ME"); + } else if (aAssetType == ASSET_MEDAL_TABLE) { + return Utils::CreateAssetIcon("MET"); + } else if (aAssetType == ASSET_OBJECTIVE) { + return Utils::CreateAssetIcon("OB"); + } else if (aAssetType == ASSET_OBJECTIVE_LIST) { + return Utils::CreateAssetIcon("OBL"); + } else if (aAssetType == ASSET_LASER) { + return Utils::CreateAssetIcon("LS"); + } else if (aAssetType == ASSET_BEAM) { + return Utils::CreateAssetIcon("BM"); + } else if (aAssetType == ASSET_STREAMER_HINT) { + return Utils::CreateAssetIcon("SH"); + } else if (aAssetType == ASSET_ANIM_SELECTOR_TABLE) { + return Utils::CreateAssetIcon("AST"); + } else if (aAssetType == ASSET_ANIM_MAPPING_TABLE) { + return Utils::CreateAssetIcon("AMP"); + } else if (aAssetType == ASSET_ANIM_STATE_MACHINE) { + return Utils::CreateAssetIcon("ASM"); + } else if (aAssetType == ASSET_BEHAVIOR_TREE) { + return Utils::CreateAssetIcon("BT"); + } else if (aAssetType == ASSET_BEHAVIOR_STATE_MACHINE) { + return Utils::CreateAssetIcon("BSM"); + } else if (aAssetType == ASSET_FOOTSTEP_TABLE) { + return Utils::CreateAssetIcon("FT"); + } else if (aAssetType == ASSET_ENTITY_FX_IMPACTS) { + return Utils::CreateAssetIcon("FI"); + } else if (aAssetType == ASSET_ENTITY_SOUND_IMPACTS) { + return Utils::CreateAssetIcon("SI"); + } else if (aAssetType == ASSET_VEHICLE_FX_DEF) { + return Utils::CreateAssetIcon("FD"); + } else if (aAssetType == ASSET_VEHICLE_SOUND_DEF) { + return Utils::CreateAssetIcon("SDD"); + } else if (aAssetType == ASSET_VEHICLE) { + return Utils::CreateAssetIcon("VE"); + } else if (aAssetType == ASSET_VEHICLE_TRACER) { + return Utils::CreateAssetIcon("VT"); + } else if (aAssetType == ASSET_PLAYER_SOUNDS_TABLE) { + return Utils::CreateAssetIcon("SDT"); + } else if (aAssetType == ASSET_PLAYER_FX_TABLE) { + return Utils::CreateAssetIcon("FXT"); + } else if (aAssetType == ASSET_SHARED_WEAPON_SOUNDS) { + return Utils::CreateAssetIcon("SWS"); + } else if (aAssetType == ASSET_ATTACHMENT) { + return Utils::CreateAssetIcon("AT"); + } else if (aAssetType == ASSET_ATTACHMENT_UNIQUE) { + return Utils::CreateAssetIcon("AU"); + } else if (aAssetType == ASSET_WEAPON_CAMO) { + return Utils::CreateAssetIcon("WPC"); + } else if (aAssetType == ASSET_CUSTOMIZATION_TABLE) { + return Utils::CreateAssetIcon("CT"); + } else if (aAssetType == ASSET_CUSTOMIZATION_TABLE_FEIMAGES) { + return Utils::CreateAssetIcon("CI"); + } else if (aAssetType == ASSET_CUSTOMIZATION_TABLE_COLOR) { + return Utils::CreateAssetIcon("CC"); + } else if (aAssetType == ASSET_PHYS_CONSTRAINTS) { + return Utils::CreateAssetIcon("PC"); + } else if (aAssetType == ASSET_DESTRUCTIBLE_DEF) { + return Utils::CreateAssetIcon("DD"); + } else if (aAssetType == ASSET_MODEL_MESH) { + return Utils::CreateAssetIcon("MM"); + } else if (aAssetType == ASSET_S_ANIM) { + return Utils::CreateAssetIcon("SA"); + } else if (aAssetType == ASSET_FONT_ICON) { + return Utils::CreateAssetIcon("FI"); + } else if (aAssetType == ASSET_CG_MEDIA_TABLE) { + return Utils::CreateAssetIcon("MT"); + } else if (aAssetType == ASSET_SHOCK_FILE) { + return Utils::CreateAssetIcon("SF"); + } else if (aAssetType == ASSET_FAST_FILE) { + return Utils::CreateAssetIcon("FF"); + } else if (aAssetType == ASSET_ZONE_FILE) { + return Utils::CreateAssetIcon("ZF"); + } else if (aAssetType == ASSET_SOUND_DRIVER_GLOBALS) { + return Utils::CreateAssetIcon("SDG"); } return QIcon(); } @@ -107,6 +399,10 @@ QString ZoneFile::GetStem() { return mStem; } +QString ZoneFile::GetBaseStem() { + return mStem.split('.').first(); +} + quint32 ZoneFile::GetSize() { return mSize; } diff --git a/libs/zonefile/zonefile.h b/libs/zonefile/zonefile.h index 1e08020..9d6ac53 100644 --- a/libs/zonefile/zonefile.h +++ b/libs/zonefile/zonefile.h @@ -14,15 +14,16 @@ public: ZoneFile(const ZoneFile &aZoneFile); ZoneFile &operator=(const ZoneFile &other); - virtual bool Load(const QByteArray aFileData, FF_PLATFORM platform = FF_PLATFORM_NONE) = 0; - virtual QString AssetTypeToString(const QString aAssetType) = 0; - - QIcon AssetStrToIcon(const QString aAssetStr); + virtual bool Load(const QByteArray aFileData) = 0; + virtual AssetType AssetStrToEnum(const QString aAssetType) = 0; + static QString AssetEnumToStr(const AssetType aAssetType); + static QIcon AssetTypeToIcon(const AssetType aAssetType); virtual QByteArray GetBinaryData() = 0; virtual bool SaveZoneFile(const QString aZoneFilePath); QString GetStem(); + QString GetBaseStem(); quint32 GetSize(); quint32 GetTagCount(); QStringList GetTags(); @@ -39,7 +40,7 @@ public: void SetAssetMap(const AssetMap aAssetMap); private slots: - virtual void pParseZoneHeader(QDataStream *aZoneFileStream, FF_PLATFORM aPlatform) = 0; + virtual void pParseZoneHeader(QDataStream *aZoneFileStream) = 0; virtual quint32 pParseZoneSize(QDataStream *aZoneFileStream) = 0; virtual void pParseZoneUnknownsA(QDataStream *aZoneFileStream) = 0; virtual quint32 pParseZoneTagCount(QDataStream *aZoneFileStream) = 0; diff --git a/libs/zonefile/zonefile.pro b/libs/zonefile/zonefile.pro index ec85195..b296b04 100644 --- a/libs/zonefile/zonefile.pro +++ b/libs/zonefile/zonefile.pro @@ -3,25 +3,94 @@ TEMPLATE = lib CONFIG += staticlib c++17 SOURCES += \ + # Base class zonefile.cpp \ - zonefile_cod2.cpp \ - zonefile_cod5.cpp \ - zonefile_cod7.cpp \ - zonefile_cod9.cpp + # 360 classes + 360/zonefile_cod2_360.cpp \ + 360/zonefile_cod4_360.cpp \ + 360/zonefile_cod5_360.cpp \ + 360/zonefile_cod6_360.cpp \ + 360/zonefile_cod7_360.cpp \ + 360/zonefile_cod8_360.cpp \ + 360/zonefile_cod9_360.cpp \ + 360/zonefile_cod10_360.cpp \ + 360/zonefile_cod11_360.cpp \ + 360/zonefile_cod12_360.cpp \ + # PS3 classes + PS3/zonefile_cod4_ps3.cpp \ + PS3/zonefile_cod5_ps3.cpp \ + PS3/zonefile_cod6_ps3.cpp \ + PS3/zonefile_cod7_ps3.cpp \ + PS3/zonefile_cod8_ps3.cpp \ + PS3/zonefile_cod9_ps3.cpp \ + PS3/zonefile_cod10_ps3.cpp \ + PS3/zonefile_cod11_ps3.cpp \ + PS3/zonefile_cod12_ps3.cpp \ + # PC classes + PC/zonefile_cod4_pc.cpp \ + PC/zonefile_cod5_pc.cpp \ + PC/zonefile_cod6_pc.cpp \ + PC/zonefile_cod7_pc.cpp \ + PC/zonefile_cod8_pc.cpp \ + PC/zonefile_cod9_pc.cpp \ + PC/zonefile_cod10_pc.cpp \ + PC/zonefile_cod11_pc.cpp \ + PC/zonefile_cod12_pc.cpp \ + # Wii classes + Wii/zonefile_cod4_wii.cpp \ + Wii/zonefile_cod7_wii.cpp \ + Wii/zonefile_cod8_wii.cpp \ + # WiiU classes + WiiU/zonefile_cod9_wiiu.cpp \ + WiiU/zonefile_cod10_wiiu.cpp HEADERS += \ - asset_structs.h \ + # Base class zonefile.h \ - zonefile_cod2.h \ - zonefile_cod5.h \ - zonefile_cod7.h \ - zonefile_cod9.h + # 360 classes + 360/zonefile_cod2_360.h \ + 360/zonefile_cod4_360.h \ + 360/zonefile_cod5_360.h \ + 360/zonefile_cod6_360.h \ + 360/zonefile_cod7_360.h \ + 360/zonefile_cod8_360.h \ + 360/zonefile_cod9_360.h \ + 360/zonefile_cod10_360.h \ + 360/zonefile_cod11_360.h \ + 360/zonefile_cod12_360.h \ + # PS3 classes + PS3/zonefile_cod4_ps3.h \ + PS3/zonefile_cod5_ps3.h \ + PS3/zonefile_cod6_ps3.h \ + PS3/zonefile_cod7_ps3.h \ + PS3/zonefile_cod8_ps3.h \ + PS3/zonefile_cod9_ps3.h \ + PS3/zonefile_cod10_ps3.h \ + PS3/zonefile_cod11_ps3.h \ + PS3/zonefile_cod12_ps3.h \ + # PC classes + PC/zonefile_cod4_pc.h \ + PC/zonefile_cod5_pc.h \ + PC/zonefile_cod6_pc.h \ + PC/zonefile_cod7_pc.h \ + PC/zonefile_cod8_pc.h \ + PC/zonefile_cod9_pc.h \ + PC/zonefile_cod10_pc.h \ + PC/zonefile_cod11_pc.h \ + PC/zonefile_cod12_pc.h \ + # Wii classes + Wii/zonefile_cod4_wii.h \ + Wii/zonefile_cod7_wii.h \ + Wii/zonefile_cod8_wii.h \ + # WiiU classes + WiiU/zonefile_cod9_wiiu.h \ + WiiU/zonefile_cod10_wiiu.h LIBS += \ -L$$OUT_PWD/../libs/core -lcore INCLUDEPATH += \ - $$PWD/../core + $$PWD/../core \ DEPENDPATH += \ $$PWD/../core diff --git a/localize.h b/localize.h deleted file mode 100644 index cd58c4a..0000000 --- a/localize.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef LOCALIZE_H -#define LOCALIZE_H - -#include -#include - -struct Localize { - quint32 valuePtr; - quint32 namePtr; - QString referenceStr; - QString localizedStr; -}; - -inline QDataStream &operator<<(QDataStream &out, const Localize &localize) { - out << localize.valuePtr << localize.namePtr; - - // Parse gsc contents - QByteArray localizedStrData(localize.localizedStr.toUtf8()); - out.writeRawData(localizedStrData.data(), localizedStrData.size()); - - // Parse rawfile path - QByteArray refStrData(localize.referenceStr.toUtf8()); - out.writeRawData(refStrData.data(), refStrData.size()); - - return out; -} - -inline QDataStream &operator>>(QDataStream &in, Localize &localize) { - // Parse value and name pointers - in >> localize.valuePtr >> localize.namePtr; - - // Parse localized string - QString localizedStr; - char localizedStrChar; - in >> localizedStrChar; - while (localizedStrChar != 0) { - localizedStr += localizedStrChar; - in >> localizedStrChar; - } - localize.localizedStr = localizedStr; - - // Parse localized reference name - QString refStr; - char refStrChar; - in >> refStrChar; - while (refStrChar != 0) { - refStr += refStrChar; - in >> refStrChar; - } - localize.referenceStr = refStr; - - return in; -} - -#endif // LOCALIZE_H diff --git a/rawfile.h b/rawfile.h deleted file mode 100644 index 23bed60..0000000 --- a/rawfile.h +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef RAWFILE_H -#define RAWFILE_H - -#include -#include -#include - -struct RawFile { - quint32 gscNamePtr; - quint32 gscLength; - quint32 rawFilePathPtr; - QString rawFilePath; - QString rawFileContents; -}; - -inline QDataStream &operator<<(QDataStream &out, const RawFile &rawFile) { - out << rawFile.gscNamePtr; - out << rawFile.gscLength; - out << rawFile.rawFilePathPtr; - - // Parse rawfile path - QByteArray rawFilePathData(rawFile.rawFilePath.toUtf8()); - out.writeRawData(rawFilePathData.data(), rawFilePathData.size()); - - // Parse gsc contents - QByteArray rawFileContentsData(rawFile.rawFileContents.toUtf8()); - out.writeRawData(rawFileContentsData.data(), rawFileContentsData.size()); - - return out; -} - -inline QDataStream &operator>>(QDataStream &in, RawFile &rawFile) { - in >> rawFile.gscNamePtr; - in >> rawFile.gscLength; - in >> rawFile.rawFilePathPtr; - - // Parse rawfile path - QString rawFilePath; - char scriptPathChar; - in >> scriptPathChar; - while (scriptPathChar != 0) { - rawFilePath += scriptPathChar; - in >> scriptPathChar; - } - rawFile.rawFilePath = rawFilePath; - - // Parse gsc contents - QString rawFileContents; - char rawFileContentsChar; - in >> rawFileContentsChar; - while (rawFileContentsChar != 0 && rawFileContentsChar != -1) { - rawFileContents += rawFileContentsChar; - in >> rawFileContentsChar; - } - rawFile.rawFileContents = rawFileContents; - - return in; -} - - -#endif // RAWFILE_H diff --git a/tests/360/autotest_cod10_360.cpp b/tests/360/autotest_cod10_360.cpp index 5bebf11..7da3e78 100644 --- a/tests/360/autotest_cod10_360.cpp +++ b/tests/360/autotest_cod10_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD10_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,24 +31,18 @@ void AutoTest_COD10_360::initTestCase() { } void AutoTest_COD10_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod10_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD10_360::testDecompression() { - QFETCH(QString, fastFilePath_cod10_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod10_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod10_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod10_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -58,10 +56,10 @@ void AutoTest_COD10_360::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod10_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod10_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -72,24 +70,18 @@ void AutoTest_COD10_360::testDecompression() { } void AutoTest_COD10_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod10_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD10_360::testCompression() { - QFETCH(QString, zoneFilePath_cod10_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod10_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod10_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod10_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -119,6 +111,36 @@ void AutoTest_COD10_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD10_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD10_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD10"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD10_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod11_360.cpp b/tests/360/autotest_cod11_360.cpp index 9b2a37f..74fe896 100644 --- a/tests/360/autotest_cod11_360.cpp +++ b/tests/360/autotest_cod11_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD11_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,24 +31,18 @@ void AutoTest_COD11_360::initTestCase() { } void AutoTest_COD11_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod11_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD11_360::testDecompression() { - QFETCH(QString, fastFilePath_cod11_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod11_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod11_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod11_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -58,10 +56,10 @@ void AutoTest_COD11_360::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod11_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod11_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -72,24 +70,18 @@ void AutoTest_COD11_360::testDecompression() { } void AutoTest_COD11_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod11_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD11_360::testCompression() { - QFETCH(QString, zoneFilePath_cod11_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod11_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod11_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod11_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -119,6 +111,36 @@ void AutoTest_COD11_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD11_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD11_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD11"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD11_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod12_360.cpp b/tests/360/autotest_cod12_360.cpp index dd7a1d0..f5f10bf 100644 --- a/tests/360/autotest_cod12_360.cpp +++ b/tests/360/autotest_cod12_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD12_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,34 +31,133 @@ void AutoTest_COD12_360::initTestCase() { } void AutoTest_COD12_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod12_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD12_360::testDecompression() { - QFETCH(QString, fastFilePath_cod12_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod12_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod12_360); + QFile testFastFile(fastFilePath); bool fastFileOpened = testFastFile.open(QIODevice::ReadOnly); if (!fastFileOpened) { recordResult(testName, false); } QVERIFY2(fastFileOpened, - qPrintable("Failed to open test fastfile: " + fastFilePath_cod12_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); - // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. - const QByteArray compressedData = testFFData.mid(12); - const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + // Assume the first 12 bytes are a header; + QDataStream fastFileStream(testFFData); + + QByteArray magic(8, Qt::Uninitialized); + fastFileStream.readRawData(magic.data(), 8); + bool properMagic = magic == "TAff0000"; + if (!properMagic) { + recordResult(testName, false); + } + QVERIFY2(properMagic, + qPrintable("Invalid fastfile magic: " + magic)); + + quint32 version; + fastFileStream >> version; + bool properVersion = version == 606; + if (!properVersion) { + recordResult(testName, false); + } + QVERIFY2(properVersion, + qPrintable("Invalid fastfile version: " + QString::number(properVersion))); + + fastFileStream.skipRawData(1); + + quint8 compressionFlag, platformFlag, encryptionFlag; + fastFileStream >> compressionFlag >> platformFlag >> encryptionFlag; + + bool properCompression = compressionFlag == 1; + if (!properCompression) + { + recordResult(testName, false); + } + QVERIFY2(properCompression, + qPrintable("Invalid Fast File Compression: " + QString::number(properVersion) + " Only LZX Fast Files are supported.")); + + bool properPlatform = platformFlag == 4; + if (!properPlatform) + { + recordResult(testName, false); + } + QVERIFY2(properPlatform, + qPrintable("Invalid Fast File Platform: " + QString::number(properVersion) + " Only 360 Fast Files are supported.")); + + bool properEncryption = encryptionFlag == 0; + if (!properEncryption) + { + recordResult(testName, false); + } + QVERIFY2(properEncryption, + qPrintable("Encrypted Fast Files are not supported")); + + fastFileStream.device()->seek(144); + + quint64 size; + fastFileStream >> size; + + fastFileStream.device()->seek(584); + + QByteArray testZoneData; + quint64 consumed = 0; + + while (consumed < size) { + /* block header ------------------------------------------------ */ + quint32 compressedSize, decompressedSize, blockSize, blockPosition; + fastFileStream >> compressedSize // DWORD 0 + >> decompressedSize // DWORD 1 + >> blockSize // copy of compressedSize + >> blockPosition; // DWORD 3 + + if (blockPosition != fastFileStream.device()->pos() - 16) { + qWarning("Block position mismatch"); break; + } + + /* padding block ? --------------------------------------------- */ + if (decompressedSize == 0) { + fastFileStream.skipRawData( + ((fastFileStream.device()->pos() + 0x7FFFFF) & ~0x7FFFFF) - + fastFileStream.device()->pos()); + continue; + } + + /* read LZO slice ---------------------------------------------- */ + fastFileStream.device()->seek(blockPosition + 16); + qDebug() << "Reading block at pos" << blockPosition + 16 << ", compressed:" << compressedSize; + + QByteArray compressedData(compressedSize, Qt::Uninitialized); + fastFileStream.readRawData(compressedData.data(), compressedSize); + + qDebug() << "Compressed data:" << compressedData.toHex(); + + if (compressedData.at(0) == 'c') { + return; + } + + QByteArray decompressed = Compression::DecompressXMem(compressedData); + if (decompressed.isEmpty()) { + qWarning() << "Empty decompression output, skipping"; + continue; + } + if (!decompressed.left(4).contains('\0')) { + qDebug() << "Block starts with" << decompressed.left(16).toHex(); + } + + testZoneData.append(decompressed); + consumed += decompressed.size(); + + /* advance to next header (blocks are file-aligned) ------------- */ + fastFileStream.device()->seek(blockPosition + 16 + blockSize); + } // Verify the decompressed data via its embedded zone size. QDataStream zoneStream(testZoneData); @@ -65,11 +168,11 @@ void AutoTest_COD12_360::testDecompression() { if (!sizeMatches) { recordResult(testName, false); } - QVERIFY2(sizeMatches, - qPrintable("Decompression validation failed for: " + fastFilePath_cod12_360)); + //QVERIFY2(sizeMatches, + // qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod12_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -84,24 +187,18 @@ void AutoTest_COD12_360::testDecompression() { } void AutoTest_COD12_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod12_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD12_360::testCompression() { - QFETCH(QString, zoneFilePath_cod12_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod12_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod12_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod12_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -131,6 +228,37 @@ void AutoTest_COD12_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD12_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD12_360::testFactory() { + QFETCH(QString, fastFilePath); + return; + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD12"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD12_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod2_360.cpp b/tests/360/autotest_cod2_360.cpp index cd82e76..11a8cc2 100644 --- a/tests/360/autotest_cod2_360.cpp +++ b/tests/360/autotest_cod2_360.cpp @@ -4,6 +4,7 @@ #include "autotest_cod.h" #include "compression.h" +#include "fastfile_factory.h" class AutoTest_COD2_360 : public AutoTest_COD { Q_OBJECT @@ -12,12 +13,16 @@ class AutoTest_COD2_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,28 +32,22 @@ void AutoTest_COD2_360::initTestCase() { } void AutoTest_COD2_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod2_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD2_360::testDecompression() { - QFETCH(QString, fastFilePath_cod2_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod2_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod2_360); + QFile testFastFile(fastFilePath); bool fastFileOpened = testFastFile.open(QIODevice::ReadOnly); if (!fastFileOpened) { recordResult(testName, false); } QVERIFY2(fastFileOpened - , qPrintable("Failed to open test fastfile: " + fastFilePath_cod2_360)); + , qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -63,10 +62,10 @@ void AutoTest_COD2_360::testDecompression() { zoneStream >> zoneSize; // TODO: Find new way to verify as cod2 doesn't store size in zone file //QVERIFY2(zoneSize + 44 == testZoneData.size(), - // qPrintable("Decompression validation failed for: " + fastFilePath_cod2_360)); + // qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod2_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -83,30 +82,24 @@ void AutoTest_COD2_360::testDecompression() { } void AutoTest_COD2_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod2_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD2_360::testCompression() { - QFETCH(QString, zoneFilePath_cod2_360); + QFETCH(QString, zoneFilePath); - const QString testName = "Compress: " + zoneFilePath_cod2_360; + const QString testName = "Compress: " + zoneFilePath; - QFile zoneFile(zoneFilePath_cod2_360); + QFile zoneFile(zoneFilePath); bool zoneFileOpened = zoneFile.open(QIODevice::ReadOnly); if (!zoneFileOpened) { recordResult(testName, false); } - QVERIFY2(zoneFileOpened, qPrintable("Failed to open zone file: " + zoneFilePath_cod2_360)); + QVERIFY2(zoneFileOpened, qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod2_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -120,10 +113,7 @@ void AutoTest_COD2_360::testCompression() { QByteArray header = originalFFData.left(20); - QByteArray newCompressedData;// = Compressor::CompressZLIB(decompressedData, Z_BEST_COMPRESSION); - newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_COMPRESSION, MAX_WBITS, 8, Z_DEFAULT_STRATEGY, {}); - - QByteArray recompressedData = header + newCompressedData; + QByteArray recompressedData = header + Compression::CompressZLIB(decompressedData); QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff"); QFile recompressedFile(recompressedFilePath); @@ -144,6 +134,36 @@ void AutoTest_COD2_360::testCompression() { recordResult(testName, true); } +void AutoTest_COD2_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD2_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD2"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD2_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod4_360.cpp b/tests/360/autotest_cod4_360.cpp index 9446a47..a27f2da 100644 --- a/tests/360/autotest_cod4_360.cpp +++ b/tests/360/autotest_cod4_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD4_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,24 +31,18 @@ void AutoTest_COD4_360::initTestCase() { } void AutoTest_COD4_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod4_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD4_360::testDecompression() { - QFETCH(QString, fastFilePath_cod4_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod4_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod4_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod4_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -66,10 +64,10 @@ void AutoTest_COD4_360::testDecompression() { qDebug() << "Test zone Size: " << testZoneData.size(); } QVERIFY2(abs(zoneSize - testZoneData.size()) == 36, - qPrintable("Decompression validation failed for: " + fastFilePath_cod4_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod4_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -80,24 +78,18 @@ void AutoTest_COD4_360::testDecompression() { } void AutoTest_COD4_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod4_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD4_360::testCompression() { - QFETCH(QString, zoneFilePath_cod4_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod4_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod4_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod4_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -121,6 +113,36 @@ void AutoTest_COD4_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD4_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD4_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD4"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD4_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod5_360.cpp b/tests/360/autotest_cod5_360.cpp index f9dff03..039c8a5 100644 --- a/tests/360/autotest_cod5_360.cpp +++ b/tests/360/autotest_cod5_360.cpp @@ -2,6 +2,7 @@ #include #include +#include "fastfile_factory.h" #include "autotest_cod.h" #include "compression.h" @@ -12,12 +13,16 @@ class AutoTest_COD5_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,25 +32,18 @@ void AutoTest_COD5_360::initTestCase() { } void AutoTest_COD5_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod5_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD5_360::testDecompression() { - QFETCH(QString, fastFilePath_cod5_360); - return; + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod5_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod5_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod5_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -64,10 +62,10 @@ void AutoTest_COD5_360::testDecompression() { qDebug() << "Difference: " << abs(zoneSize - testZoneData.size()); } QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod5_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod5_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -78,24 +76,18 @@ void AutoTest_COD5_360::testDecompression() { } void AutoTest_COD5_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod5_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD5_360::testCompression() { - QFETCH(QString, zoneFilePath_cod5_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod5_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod5_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod5_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -125,6 +117,36 @@ void AutoTest_COD5_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD5_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD5_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD5"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD5_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod6_360.cpp b/tests/360/autotest_cod6_360.cpp index 7d550eb..259b10b 100644 --- a/tests/360/autotest_cod6_360.cpp +++ b/tests/360/autotest_cod6_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD6_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,24 +31,18 @@ void AutoTest_COD6_360::initTestCase() { } void AutoTest_COD6_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod6_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD6_360::testDecompression() { - QFETCH(QString, fastFilePath_cod6_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod6_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod6_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod6_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -58,6 +56,7 @@ void AutoTest_COD6_360::testDecompression() { pattern.append(static_cast(0xEC)); int index = testFFData.indexOf(pattern); + qDebug() << "Zlib Index: " << index; QByteArray compressedData = testFFData.mid(index); QByteArray testZoneData = Compression::DecompressZLIB(compressedData); @@ -82,10 +81,10 @@ void AutoTest_COD6_360::testDecompression() { qDebug() << "Difference: " << abs(zoneSize - testZoneData.size()); } QVERIFY2(zoneSize + 32 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod6_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod6_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -96,24 +95,18 @@ void AutoTest_COD6_360::testDecompression() { } void AutoTest_COD6_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod6_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD6_360::testCompression() { - QFETCH(QString, zoneFilePath_cod6_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod6_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod6_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod6_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -144,6 +137,36 @@ void AutoTest_COD6_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD6_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD6_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD6"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD6_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod7_360.cpp b/tests/360/autotest_cod7_360.cpp index ebdd0dc..2b32e58 100644 --- a/tests/360/autotest_cod7_360.cpp +++ b/tests/360/autotest_cod7_360.cpp @@ -13,12 +13,16 @@ class AutoTest_COD7_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -28,24 +32,18 @@ void AutoTest_COD7_360::initTestCase() { } void AutoTest_COD7_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod7_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD7_360::testDecompression() { - QFETCH(QString, fastFilePath_cod7_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod7_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod7_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod7_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -120,10 +118,10 @@ void AutoTest_COD7_360::testDecompression() { qDebug() << "Difference: " << abs(zoneSize - testZoneData.size()); } QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod7_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod7_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -134,51 +132,115 @@ void AutoTest_COD7_360::testDecompression() { } void AutoTest_COD7_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod7_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD7_360::testCompression() { - QFETCH(QString, zoneFilePath_cod7_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod7_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod7_360)); - QByteArray decompressedData = zoneFile.readAll(); + const QString testName = "Compress: " + zoneFilePath; + + // Open the original .zone file (decompressed zone data). + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), + qPrintable("Failed to open zone file: " + zoneFilePath)); + const QByteArray zoneData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod7_360); - QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); + QByteArray compressedData; + QByteArray key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d"); - QFile originalFile(originalFFPath); - QVERIFY2(originalFile.open(QIODevice::ReadOnly), qPrintable("Failed to open original .ff file: " + originalFFPath)); - QByteArray originalFFData = originalFile.readAll(); - originalFile.close(); + // Read the original fastfile header to recover metadata (filename, IV table, etc.) + QString ffPath = zoneFilePath; + ffPath.replace(".zone", ".ff"); + QFile originalFF(ffPath); + QVERIFY2(originalFF.open(QIODevice::ReadOnly), + qPrintable("Failed to open original fastfile: " + ffPath)); + QByteArray header = originalFF.read(0x13C); // Everything up to section data + originalFF.seek(24); // IV Table starts at 24 (after magic + skip + filename) + QByteArray fileName(32, Qt::Uninitialized); + originalFF.read(fileName.data(), 32); + originalFF.close(); - QByteArray header = originalFFData.left(12); + QByteArray ivTable = Encryption::InitIVTable(fileName); - QByteArray newCompressedData;// = Compressor::CompressZLIB(decompressedData, Z_BEST_COMPRESSION); - newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_COMPRESSION, MAX_WBITS, 8, Z_DEFAULT_STRATEGY, {}); + // Rebuild sections from zone data + QDataStream zoneStream(zoneData); + zoneStream.setByteOrder(QDataStream::BigEndian); + quint32 zoneSize; + zoneStream >> zoneSize; - int remainder = (newCompressedData.size() + 12) % 32; - if (remainder != 0) { - int paddingNeeded = 32 - remainder; - newCompressedData.append(QByteArray(paddingNeeded, '\0')); + QByteArray remainingData = zoneData.mid(4); // exclude size field + const int chunkSize = 0x40000; // 256KB max section size + + QDataStream fastFileStreamOut(&compressedData, QIODevice::WriteOnly); + fastFileStreamOut.setByteOrder(QDataStream::BigEndian); + + int sectionIndex = 0; + int offset = 0; + while (offset < remainingData.size()) { + int sectionLen = qMin(chunkSize, remainingData.size() - offset); + QByteArray chunk = remainingData.mid(offset, sectionLen); + + QByteArray deflated = Compression::CompressDeflate(chunk); + + QByteArray iv = Encryption::GetIV(ivTable, sectionIndex); + QByteArray encrypted = Encryption::salsa20DecryptSection(deflated, key, iv); + QByteArray sha1 = QCryptographicHash::hash(chunk, QCryptographicHash::Sha1); + Encryption::UpdateIVTable(ivTable, sectionIndex, sha1); + + fastFileStreamOut << static_cast(encrypted.size()); + fastFileStreamOut.writeRawData(encrypted.constData(), encrypted.size()); + + offset += sectionLen; + sectionIndex++; } - QByteArray recompressedData = header + newCompressedData; + // Write 0 section size terminator + fastFileStreamOut << static_cast(0); - QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff"); - QFile recompressedFile(recompressedFilePath); - QVERIFY2(recompressedFile.open(QIODevice::WriteOnly), qPrintable("Failed to write recompressed file.")); - recompressedFile.write(recompressedData); - recompressedFile.close(); + // Combine with header + QByteArray fullFastFile = header + compressedData; - QCOMPARE(recompressedData, originalFFData); + // Save re-encoded fastfile + QFileInfo fi(zoneFilePath); + QString outputFileName = fi.completeBaseName() + "_recompressed.ff"; + QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); + QFile outputFile(outputFilePath); + QVERIFY2(outputFile.open(QIODevice::WriteOnly), + qPrintable("Failed to open output file for writing: " + outputFilePath)); + outputFile.write(fullFastFile); + outputFile.close(); +} + +void AutoTest_COD7_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD7_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD7"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); } void AutoTest_COD7_360::cleanupTestCase() { diff --git a/tests/360/autotest_cod8_360.cpp b/tests/360/autotest_cod8_360.cpp index 954d95d..18bc90b 100644 --- a/tests/360/autotest_cod8_360.cpp +++ b/tests/360/autotest_cod8_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD8_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,32 +31,21 @@ void AutoTest_COD8_360::initTestCase() { } void AutoTest_COD8_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod8_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - break; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD8_360::testDecompression() { - QFETCH(QString, fastFilePath_cod8_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod8_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod8_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod8_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); - //const QByteArray testData = Compression::CompressXMem("Hello World!"); - //const QByteArray testOutData = Compression::DecompressXMem(testData); - //qDebug() << "Input: Hello World! - Output: " << testData.toHex() << " - New: " << testOutData; - QByteArray pattern; pattern.append(static_cast(0xFF)); @@ -82,10 +75,10 @@ void AutoTest_COD8_360::testDecompression() { qDebug() << "Difference: " << abs(zoneSize - testZoneData.size()); } //QVERIFY2(zoneSize + 44 == testZoneData.size(), - // qPrintable("Decompression validation failed for: " + fastFilePath_cod8_360)); + // qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod8_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -96,25 +89,18 @@ void AutoTest_COD8_360::testDecompression() { } void AutoTest_COD8_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod8_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - break; - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD8_360::testCompression() { - QFETCH(QString, zoneFilePath_cod8_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod8_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod8_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod8_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -144,6 +130,36 @@ void AutoTest_COD8_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD8_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD8_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD8"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD8_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/360/autotest_cod9_360.cpp b/tests/360/autotest_cod9_360.cpp index 6807fa0..6df0cbc 100644 --- a/tests/360/autotest_cod9_360.cpp +++ b/tests/360/autotest_cod9_360.cpp @@ -12,12 +12,16 @@ class AutoTest_COD9_360 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,24 +31,18 @@ void AutoTest_COD9_360::initTestCase() { } void AutoTest_COD9_360::testDecompression_data() { - QTest::addColumn("fastFilePath_cod9_360"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD9_360::testDecompression() { - QFETCH(QString, fastFilePath_cod9_360); + QFETCH(QString, fastFilePath); - const QString testName = "Decompress: " + fastFilePath_cod9_360; + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod9_360); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod9_360)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -58,10 +56,10 @@ void AutoTest_COD9_360::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod9_360)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod9_360); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -72,24 +70,18 @@ void AutoTest_COD9_360::testDecompression() { } void AutoTest_COD9_360::testCompression_data() { - QTest::addColumn("zoneFilePath_cod9_360"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD9_360::testCompression() { - QFETCH(QString, zoneFilePath_cod9_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod9_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod9_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod9_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -119,6 +111,36 @@ void AutoTest_COD9_360::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD9_360::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD9_360::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD9"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "360"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD9_360::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod10_pc.cpp b/tests/PC/autotest_cod10_pc.cpp index ad2a304..ab58eef 100644 --- a/tests/PC/autotest_cod10_pc.cpp +++ b/tests/PC/autotest_cod10_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD10_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,23 +31,16 @@ void AutoTest_COD10_PC::initTestCase() { } void AutoTest_COD10_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod10_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } - void AutoTest_COD10_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod10_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod10_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod10_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -57,10 +54,10 @@ void AutoTest_COD10_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod10_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod10_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -71,24 +68,18 @@ void AutoTest_COD10_PC::testDecompression() { } void AutoTest_COD10_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod10_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD10_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod10_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod10_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod10_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod10_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -116,6 +107,36 @@ void AutoTest_COD10_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD10_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD10_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD10"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD10_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod11_pc.cpp b/tests/PC/autotest_cod11_pc.cpp index 999a038..9874b66 100644 --- a/tests/PC/autotest_cod11_pc.cpp +++ b/tests/PC/autotest_cod11_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD11_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,23 +31,16 @@ void AutoTest_COD11_PC::initTestCase() { } void AutoTest_COD11_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod11_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } - void AutoTest_COD11_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod11_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod11_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod11_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -57,10 +54,10 @@ void AutoTest_COD11_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod11_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod11_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -71,24 +68,18 @@ void AutoTest_COD11_PC::testDecompression() { } void AutoTest_COD11_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod11_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD11_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod11_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod11_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod11_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod11_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -116,6 +107,36 @@ void AutoTest_COD11_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD11_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD11_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD11"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD11_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod12_pc.cpp b/tests/PC/autotest_cod12_pc.cpp index ef8b276..0f05a55 100644 --- a/tests/PC/autotest_cod12_pc.cpp +++ b/tests/PC/autotest_cod12_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD12_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,68 +31,148 @@ void AutoTest_COD12_PC::initTestCase() { } void AutoTest_COD12_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod12_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } - void AutoTest_COD12_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod12_pc); + QFETCH(QString, fastFilePath); + + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod12_pc); - QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod12_pc)); + QFile testFastFile(fastFilePath); + bool fastFileOpened = testFastFile.open(QIODevice::ReadOnly); + if (!fastFileOpened) { + recordResult(testName, false); + } + QVERIFY2(fastFileOpened, + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. - const QByteArray compressedData = testFFData.mid(12); - const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + QDataStream fastFileStream(testFFData); + fastFileStream.setByteOrder(QDataStream::LittleEndian); + + QByteArray magic(8, Qt::Uninitialized); + fastFileStream.readRawData(magic.data(), 8); + bool properMagic = magic == "TAff0000"; + if (!properMagic) { + recordResult(testName, false); + } + QVERIFY2(properMagic, + qPrintable("Invalid fastfile magic: " + magic)); + + quint32 version; + fastFileStream >> version; + bool properVersion = version == 593; + if (!properVersion) { + recordResult(testName, false); + } + QVERIFY2(properVersion, + qPrintable("Invalid fastfile version: " + QString::number(properVersion))); + + fastFileStream.skipRawData(1); + + quint8 compressionFlag, platformFlag, encryptionFlag; + fastFileStream >> compressionFlag >> platformFlag >> encryptionFlag; + + bool properCompression = compressionFlag == 1; + if (!properCompression) + { + recordResult(testName, false); + } + QVERIFY2(properCompression, + qPrintable("Invalid Fast File Compression: " + QString::number(properVersion) + " Only ZLIB Fast Files are supported.")); + + bool properPlatform = platformFlag == 0; + if (!properPlatform) + { + recordResult(testName, false); + } + QVERIFY2(properPlatform, + qPrintable("Invalid Fast File Platform: " + QString::number(properVersion) + " Only PC Fast Files are supported.")); + + bool properEncryption = encryptionFlag == 0; + if (!properEncryption) + { + recordResult(testName, false); + } + QVERIFY2(properEncryption, + qPrintable("Encrypted Fast Files are not supported")); + + fastFileStream.device()->seek(144); + + quint64 size; + fastFileStream >> size; + + fastFileStream.device()->seek(584); + + QByteArray testZoneData; + int consumed = 0; + while (consumed < size) { + quint32 compressedSize, decompressedSize, blockSize, blockPosition; + fastFileStream >> compressedSize >> decompressedSize >> blockSize >> blockPosition; + + if (blockPosition != fastFileStream.device()->pos() - 16) { + qDebug() << "Block position does not match stream position!"; + break; + } + + if (decompressedSize == 0) { + fastFileStream.skipRawData((((fastFileStream.device()->pos()) + ((0x800000) - 1)) & ~((0x800000) - 1)) - fastFileStream.device()->pos()); + continue; + } + + fastFileStream.skipRawData(2); + QByteArray compressedData(compressedSize - 2, Qt::Uninitialized); + fastFileStream.readRawData(compressedData.data(), compressedSize - 2); + testZoneData.append(Compression::DecompressDeflate(compressedData)); + + consumed += decompressedSize; + fastFileStream.device()->seek(blockPosition + 16 + blockSize); + } // Verify the decompressed data via its embedded zone size. QDataStream zoneStream(testZoneData); zoneStream.setByteOrder(QDataStream::LittleEndian); quint32 zoneSize; zoneStream >> zoneSize; - QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod12_pc)); + bool sizeMatches = zoneSize + 44 == testZoneData.size(); + if (!sizeMatches) { + recordResult(testName, false); + } + //QVERIFY2(sizeMatches, + // qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod12_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); - QVERIFY2(outputFile.open(QIODevice::WriteOnly), - qPrintable("Failed to open output file for writing: " + outputFilePath)); + bool zoneFileOpened = outputFile.open(QIODevice::WriteOnly); + if (!zoneFileOpened) { + recordResult(testName, false); + } + QVERIFY2(zoneFileOpened, + qPrintable("Failed to open output zone file for writing: " + outputFilePath)); outputFile.write(testZoneData); outputFile.close(); } void AutoTest_COD12_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod12_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD12_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod12_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod12_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod12_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod12_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -116,6 +200,36 @@ void AutoTest_COD12_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD12_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD12_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD12"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD12_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod4_pc.cpp b/tests/PC/autotest_cod4_pc.cpp index b89ae4f..ab3cc1f 100644 --- a/tests/PC/autotest_cod4_pc.cpp +++ b/tests/PC/autotest_cod4_pc.cpp @@ -13,12 +13,16 @@ class AutoTest_COD4_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -28,22 +32,16 @@ void AutoTest_COD4_PC::initTestCase() { } void AutoTest_COD4_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod4_pc"); - - QStringList fastFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : fastFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD4_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod4_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod4_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod4_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -57,10 +55,10 @@ void AutoTest_COD4_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod4_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod4_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -71,24 +69,18 @@ void AutoTest_COD4_PC::testDecompression() { } void AutoTest_COD4_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod4_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD4_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod4_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod4_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod4_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod4_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -112,6 +104,36 @@ void AutoTest_COD4_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD4_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD4_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD4"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD4_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod5_pc.cpp b/tests/PC/autotest_cod5_pc.cpp index 4a1608e..6a8e3c4 100644 --- a/tests/PC/autotest_cod5_pc.cpp +++ b/tests/PC/autotest_cod5_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD5_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD5_PC::initTestCase() { } void AutoTest_COD5_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod5_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD5_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod5_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod5_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod5_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD5_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod5_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod5_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD5_PC::testDecompression() { } void AutoTest_COD5_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod5_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD5_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod5_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod5_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod5_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod5_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -116,6 +108,36 @@ void AutoTest_COD5_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD5_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD5_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath, true); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD5"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD5_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod6_pc.cpp b/tests/PC/autotest_cod6_pc.cpp index 33d0f48..4d0b75f 100644 --- a/tests/PC/autotest_cod6_pc.cpp +++ b/tests/PC/autotest_cod6_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD6_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD6_PC::initTestCase() { } void AutoTest_COD6_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod6_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD6_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod6_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod6_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod6_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD6_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 40 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod6_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod6_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD6_PC::testDecompression() { } void AutoTest_COD6_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod6_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD6_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod6_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod6_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod6_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod6_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -108,6 +100,36 @@ void AutoTest_COD6_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD6_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD6_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD6"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD6_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod7_pc.cpp b/tests/PC/autotest_cod7_pc.cpp index 3d26478..465d053 100644 --- a/tests/PC/autotest_cod7_pc.cpp +++ b/tests/PC/autotest_cod7_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD7_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD7_PC::initTestCase() { } void AutoTest_COD7_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod7_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD7_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod7_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod7_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod7_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD7_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod7_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod7_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD7_PC::testDecompression() { } void AutoTest_COD7_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod7_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD7_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod7_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod7_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod7_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod7_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -115,6 +107,36 @@ void AutoTest_COD7_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD7_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD7_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD7"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD7_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod8_pc.cpp b/tests/PC/autotest_cod8_pc.cpp index decf3b3..e4df99c 100644 --- a/tests/PC/autotest_cod8_pc.cpp +++ b/tests/PC/autotest_cod8_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD8_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,23 +31,16 @@ void AutoTest_COD8_PC::initTestCase() { } void AutoTest_COD8_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod8_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } - void AutoTest_COD8_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod8_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod8_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod8_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -57,10 +54,10 @@ void AutoTest_COD8_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod8_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod8_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -71,24 +68,18 @@ void AutoTest_COD8_PC::testDecompression() { } void AutoTest_COD8_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod8_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD8_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod8_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod8_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod8_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod8_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -116,6 +107,36 @@ void AutoTest_COD8_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD8_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD8_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD8"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD8_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PC/autotest_cod9_pc.cpp b/tests/PC/autotest_cod9_pc.cpp index f8a1e64..2d578e4 100644 --- a/tests/PC/autotest_cod9_pc.cpp +++ b/tests/PC/autotest_cod9_pc.cpp @@ -12,12 +12,16 @@ class AutoTest_COD9_PC : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,23 +31,16 @@ void AutoTest_COD9_PC::initTestCase() { } void AutoTest_COD9_PC::testDecompression_data() { - QTest::addColumn("fastFilePath_cod9_pc"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } - void AutoTest_COD9_PC::testDecompression() { - QFETCH(QString, fastFilePath_cod9_pc); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod9_pc); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod9_pc)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -57,10 +54,10 @@ void AutoTest_COD9_PC::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod9_pc)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod9_pc); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -71,24 +68,18 @@ void AutoTest_COD9_PC::testDecompression() { } void AutoTest_COD9_PC::testCompression_data() { - QTest::addColumn("zoneFilePath_cod9_pc"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD9_PC::testCompression() { - QFETCH(QString, zoneFilePath_cod9_pc); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod9_pc); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod9_pc)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod9_pc); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -116,6 +107,36 @@ void AutoTest_COD9_PC::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD9_PC::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD9_PC::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD9"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PC"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD9_PC::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod10_ps3.cpp b/tests/PS3/autotest_cod10_ps3.cpp index 6432d3b..204417d 100644 --- a/tests/PS3/autotest_cod10_ps3.cpp +++ b/tests/PS3/autotest_cod10_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD10_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD10_PS3::initTestCase() { } void AutoTest_COD10_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod10_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD10_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod10_ps3); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod10_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod10_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD10_PS3::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod10_ps3)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod10_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD10_PS3::testDecompression() { } void AutoTest_COD10_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod10_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD10_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod10_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod10_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod10_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod10_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD10_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD10_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD10_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD10"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD10_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod11_ps3.cpp b/tests/PS3/autotest_cod11_ps3.cpp index e20a48b..06d5af0 100644 --- a/tests/PS3/autotest_cod11_ps3.cpp +++ b/tests/PS3/autotest_cod11_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD11_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD11_PS3::initTestCase() { } void AutoTest_COD11_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod11_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD11_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod11_ps3); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod11_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod11_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD11_PS3::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod11_ps3)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod11_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD11_PS3::testDecompression() { } void AutoTest_COD11_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod11_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD11_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod11_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod11_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod11_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod11_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD11_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD11_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD11_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD11"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD11_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod12_ps3.cpp b/tests/PS3/autotest_cod12_ps3.cpp index 8a23cd2..6dda192 100644 --- a/tests/PS3/autotest_cod12_ps3.cpp +++ b/tests/PS3/autotest_cod12_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD12_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,67 +31,148 @@ void AutoTest_COD12_PS3::initTestCase() { } void AutoTest_COD12_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod12_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD12_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod12_ps3); + QFETCH(QString, fastFilePath); + + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod12_ps3); - QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod12_ps3)); + QFile testFastFile(fastFilePath); + bool fastFileOpened = testFastFile.open(QIODevice::ReadOnly); + if (!fastFileOpened) { + recordResult(testName, false); + } + QVERIFY2(fastFileOpened, + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. - const QByteArray compressedData = testFFData.mid(12); - const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + QDataStream fastFileStream(testFFData); + fastFileStream.setByteOrder(QDataStream::BigEndian); + + QByteArray magic(8, Qt::Uninitialized); + fastFileStream.readRawData(magic.data(), 8); + bool properMagic = magic == "TAff00PS"; + if (!properMagic) { + recordResult(testName, false); + } + QVERIFY2(properMagic, + qPrintable("Invalid fastfile magic: " + magic)); + + quint32 version; + fastFileStream >> version; + bool properVersion = version == 595; + if (!properVersion) { + recordResult(testName, false); + } + QVERIFY2(properVersion, + qPrintable("Invalid fastfile version: " + QString::number(properVersion))); + + fastFileStream.skipRawData(1); + + quint8 compressionFlag, platformFlag, encryptionFlag; + fastFileStream >> compressionFlag >> platformFlag >> encryptionFlag; + + bool properCompression = compressionFlag == 1; + if (!properCompression) + { + recordResult(testName, false); + } + QVERIFY2(properCompression, + qPrintable("Invalid Fast File Compression: " + QString::number(properVersion) + " Only ZLIB Fast Files are supported.")); + + bool properPlatform = platformFlag == 3; + if (!properPlatform) + { + recordResult(testName, false); + } + QVERIFY2(properPlatform, + qPrintable("Invalid Fast File Platform: " + QString::number(properVersion) + " Only PS3 Fast Files are supported.")); + + bool properEncryption = encryptionFlag == 0; + if (!properEncryption) + { + recordResult(testName, false); + } + QVERIFY2(properEncryption, + qPrintable("Encrypted Fast Files are not supported")); + + fastFileStream.device()->seek(144); + + quint64 size; + fastFileStream >> size; + + fastFileStream.device()->seek(584); + + QByteArray testZoneData; + int consumed = 0; + while (consumed < size) { + quint32 compressedSize, decompressedSize, blockSize, blockPosition; + fastFileStream >> compressedSize >> decompressedSize >> blockSize >> blockPosition; + + if (blockPosition != fastFileStream.device()->pos() - 16) { + qDebug() << "Block position does not match stream position!"; + break; + } + + if (decompressedSize == 0) { + fastFileStream.skipRawData((((fastFileStream.device()->pos()) + ((0x800000) - 1)) & ~((0x800000) - 1)) - fastFileStream.device()->pos()); + continue; + } + + fastFileStream.skipRawData(2); + QByteArray compressedData(compressedSize - 2, Qt::Uninitialized); + fastFileStream.readRawData(compressedData.data(), compressedSize - 2); + testZoneData.append(Compression::DecompressDeflate(compressedData)); + + consumed += decompressedSize; + fastFileStream.device()->seek(blockPosition + 16 + blockSize); + } // Verify the decompressed data via its embedded zone size. QDataStream zoneStream(testZoneData); zoneStream.setByteOrder(QDataStream::LittleEndian); quint32 zoneSize; zoneStream >> zoneSize; - QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod12_ps3)); + bool sizeMatches = zoneSize + 44 == testZoneData.size(); + if (!sizeMatches) { + recordResult(testName, false); + } + //QVERIFY2(sizeMatches, + // qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod12_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); - QVERIFY2(outputFile.open(QIODevice::WriteOnly), - qPrintable("Failed to open output file for writing: " + outputFilePath)); + bool zoneFileOpened = outputFile.open(QIODevice::WriteOnly); + if (!zoneFileOpened) { + recordResult(testName, false); + } + QVERIFY2(zoneFileOpened, + qPrintable("Failed to open output zone file for writing: " + outputFilePath)); outputFile.write(testZoneData); outputFile.close(); } void AutoTest_COD12_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod12_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD12_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod12_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod12_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod12_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod12_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +202,36 @@ void AutoTest_COD12_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD12_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD12_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD12"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD12_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod4_ps3.cpp b/tests/PS3/autotest_cod4_ps3.cpp index 8ca2dc2..8b1ae15 100644 --- a/tests/PS3/autotest_cod4_ps3.cpp +++ b/tests/PS3/autotest_cod4_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD4_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,67 +31,80 @@ void AutoTest_COD4_PS3::initTestCase() { } void AutoTest_COD4_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod4_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD4_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod4_ps3); + QFETCH(QString, fastFilePath); - // Open the original .ff file. - QFile testFastFile(fastFilePath_cod4_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod4_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); - // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. - const QByteArray compressedData = testFFData.mid(12); - const QByteArray testZoneData = Compression::DecompressDeflate(compressedData); + // Validate header + QVERIFY2(testFFData.size() > 12, "FastFile too small to contain header"); + QByteArray header = testFFData.left(8); + QVERIFY2(header == "IWffu100", "Invalid FastFile header!"); - // Verify the decompressed data via its embedded zone size. - QDataStream zoneStream(testZoneData); - zoneStream.setByteOrder(QDataStream::LittleEndian); - quint32 zoneSize; - zoneStream >> zoneSize; - //QVERIFY2(zoneSize + 44 == testZoneData.size(), - // qPrintable("Decompression validation failed for: " + fastFilePath_cod4_ps3)); + QDataStream headerStream(testFFData.mid(8, 6)); + headerStream.setByteOrder(QDataStream::BigEndian); + qint32 version; + qint16 identifier; + headerStream >> version >> identifier; + QVERIFY2(version == 1, "Unsupported game version"); - // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod4_ps3); + QByteArray decompressed; + int pos = 12; + + // Loop until EOF or invalid chunk + while (pos <= testFFData.size()) { + // Read 2-byte BIG-ENDIAN chunk size + quint16 chunkSize; + QDataStream chunkStream(testFFData.mid(pos, 2)); + chunkStream.setByteOrder(QDataStream::BigEndian); + chunkStream >> chunkSize; + + pos += 2; + + if (chunkSize == 0 || pos + chunkSize > testFFData.size()) { + qWarning() << "Invalid or incomplete chunk detected, stopping."; + break; + } + + const QByteArray compressedChunk = testFFData.mid(pos, chunkSize); + + decompressed.append(Compression::DecompressDeflate(compressedChunk)); + + pos += chunkSize; + } + + // Write decompressed .zone file + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); QVERIFY2(outputFile.open(QIODevice::WriteOnly), qPrintable("Failed to open output file for writing: " + outputFilePath)); - outputFile.write(testZoneData); + outputFile.write(decompressed); outputFile.close(); } -void AutoTest_COD4_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod4_ps3"); - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } +void AutoTest_COD4_PS3::testCompression_data() { + AutoTest_COD::testCompression_data(); } void AutoTest_COD4_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod4_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod4_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod4_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod4_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -96,26 +113,71 @@ void AutoTest_COD4_PS3::testCompression() { originalFile.close(); QByteArray header = originalFFData.left(12); + QByteArray recompressedData = header; - QByteArray newCompressedData = Compression::CompressDeflateWithSettings(decompressedData, Z_BEST_COMPRESSION); + // Split decompressed data into chunks (optional: same size as original or fixed 0x4000) + const int chunkSize = 0x4000; + int offset = 0; - int remainder = (newCompressedData.size() + 12) % 32; - if (remainder != 0) { - int paddingNeeded = 32 - remainder; - newCompressedData.append(QByteArray(paddingNeeded, '\0')); + while (offset < decompressedData.size()) { + QByteArray chunk = decompressedData.mid(offset, chunkSize); + offset += chunk.size(); + + QByteArray compressedChunk = Compression::CompressDeflate(chunk); + quint16 length = static_cast(compressedChunk.size()); + + // Write 2-byte big-endian chunk size + recompressedData.append(static_cast((length >> 8) & 0xFF)); + recompressedData.append(static_cast(length & 0xFF)); + + // Write compressed chunk + recompressedData.append(compressedChunk); } - QByteArray recompressedData = header + newCompressedData; + // No terminator chunk needed if original didn't have one + // Save new file QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff"); QFile recompressedFile(recompressedFilePath); QVERIFY2(recompressedFile.open(QIODevice::WriteOnly), qPrintable("Failed to write recompressed file.")); recompressedFile.write(recompressedData); recompressedFile.close(); + // Validate byte-for-byte match QCOMPARE(recompressedData, originalFFData); } + +void AutoTest_COD4_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD4_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD4"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD4_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod5_ps3.cpp b/tests/PS3/autotest_cod5_ps3.cpp index 7b1ed14..df8e22a 100644 --- a/tests/PS3/autotest_cod5_ps3.cpp +++ b/tests/PS3/autotest_cod5_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD5_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,72 +31,79 @@ void AutoTest_COD5_PS3::initTestCase() { } void AutoTest_COD5_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod5_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD5_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod5_ps3); + QFETCH(QString, fastFilePath); - // Open the original .ff file. - QFile testFastFile(fastFilePath_cod5_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod5_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); - // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. - const QByteArray compressedData = testFFData.mid(12); - const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + // Validate header + QVERIFY2(testFFData.size() > 12, "FastFile too small to contain header"); + QByteArray header = testFFData.left(8); + QVERIFY2(header == "IWffu100", "Invalid FastFile header!"); - // Verify the decompressed data via its embedded zone size. - QDataStream zoneStream(testZoneData); - zoneStream.setByteOrder(QDataStream::LittleEndian); - quint32 zoneSize; - zoneStream >> zoneSize; - if (abs(zoneSize - testZoneData.size()) != 36) { - qDebug() << "Zone Size: " << zoneSize; - qDebug() << "Test zone Size: " << testZoneData.size(); - qDebug() << "Difference: " << abs(zoneSize - testZoneData.size()); + QDataStream headerStream(testFFData.mid(8, 6)); + headerStream.setByteOrder(QDataStream::BigEndian); + qint32 version; + qint16 identifier; + headerStream >> version >> identifier; + QVERIFY2(version == 387, "Unsupported game version"); + + QByteArray decompressed; + int pos = 12; + + // Loop until EOF or invalid chunk + while (pos <= testFFData.size()) { + // Read 2-byte BIG-ENDIAN chunk size + quint16 chunkSize; + QDataStream chunkStream(testFFData.mid(pos, 2)); + chunkStream.setByteOrder(QDataStream::BigEndian); + chunkStream >> chunkSize; + + pos += 2; + + if (chunkSize == 0 || pos + chunkSize > testFFData.size()) { + qWarning() << "Invalid or incomplete chunk detected, stopping."; + break; + } + + const QByteArray compressedChunk = testFFData.mid(pos, chunkSize); + + decompressed.append(Compression::DecompressDeflate(compressedChunk)); + + pos += chunkSize; } - QVERIFY2(zoneSize + 36 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod5_ps3)); - // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod5_ps3); + // Write decompressed .zone file + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); QVERIFY2(outputFile.open(QIODevice::WriteOnly), qPrintable("Failed to open output file for writing: " + outputFilePath)); - outputFile.write(testZoneData); + outputFile.write(decompressed); outputFile.close(); } void AutoTest_COD5_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod5_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD5_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod5_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod5_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod5_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod5_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -101,27 +112,70 @@ void AutoTest_COD5_PS3::testCompression() { originalFile.close(); QByteArray header = originalFFData.left(12); + QByteArray recompressedData = header; - QByteArray newCompressedData;// = Compressor::CompressZLIB(decompressedData, Z_BEST_COMPRESSION); - newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_COMPRESSION, MAX_WBITS, 8, Z_DEFAULT_STRATEGY, {}); + // Split decompressed data into chunks (optional: same size as original or fixed 0x4000) + const int chunkSize = 0x4000; + int offset = 0; - int remainder = (newCompressedData.size() + 12) % 32; - if (remainder != 0) { - int paddingNeeded = 32 - remainder; - newCompressedData.append(QByteArray(paddingNeeded, '\0')); + while (offset < decompressedData.size()) { + QByteArray chunk = decompressedData.mid(offset, chunkSize); + offset += chunk.size(); + + QByteArray compressedChunk = Compression::CompressDeflate(chunk); + quint16 length = static_cast(compressedChunk.size()); + + // Write 2-byte big-endian chunk size + recompressedData.append(static_cast((length >> 8) & 0xFF)); + recompressedData.append(static_cast(length & 0xFF)); + + // Write compressed chunk + recompressedData.append(compressedChunk); } - QByteArray recompressedData = header + newCompressedData; + // No terminator chunk needed if original didn't have one + // Save new file QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff"); QFile recompressedFile(recompressedFilePath); QVERIFY2(recompressedFile.open(QIODevice::WriteOnly), qPrintable("Failed to write recompressed file.")); recompressedFile.write(recompressedData); recompressedFile.close(); + // Validate byte-for-byte match QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD5_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD5_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD5"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD5_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod6_ps3.cpp b/tests/PS3/autotest_cod6_ps3.cpp index b5b5234..42fbcac 100644 --- a/tests/PS3/autotest_cod6_ps3.cpp +++ b/tests/PS3/autotest_cod6_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD6_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD6_PS3::initTestCase() { } void AutoTest_COD6_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod6_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD6_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod6_ps3); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod6_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod6_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD6_PS3::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod6_ps3)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod6_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD6_PS3::testDecompression() { } void AutoTest_COD6_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod6_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD6_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod6_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod6_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod6_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod6_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD6_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD6_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD6_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD6"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD6_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod7_ps3.cpp b/tests/PS3/autotest_cod7_ps3.cpp index a49fa55..488c30b 100644 --- a/tests/PS3/autotest_cod7_ps3.cpp +++ b/tests/PS3/autotest_cod7_ps3.cpp @@ -4,6 +4,7 @@ #include "autotest_cod.h" #include "compression.h" +#include "encryption.h" class AutoTest_COD7_PS3 : public AutoTest_COD { Q_OBJECT @@ -12,12 +13,16 @@ class AutoTest_COD7_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,39 +32,95 @@ void AutoTest_COD7_PS3::initTestCase() { } void AutoTest_COD7_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod7_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD7_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod7_ps3); + QFETCH(QString, fastFilePath); + + const QString testName = "Decompress: " + fastFilePath; // Open the original .ff file. - QFile testFastFile(fastFilePath_cod7_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod7_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); - // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. - const QByteArray compressedData = testFFData.mid(12); - const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + QByteArray decompressedData; + QByteArray key = QByteArray::fromHex("46D3F997F29C9ACE175B0DAE3AB8C0C1B8E423E2E3BF7E3C311EA35245BF193A"); + + // Create a QDataStream on the input data. + QDataStream fastFileStream(testFFData); + fastFileStream.setByteOrder(QDataStream::BigEndian); + fastFileStream.skipRawData(16); + + // Read the 8-byte magic. + QByteArray fileMagic(8, Qt::Uninitialized); + fastFileStream.readRawData(fileMagic.data(), 8); + QVERIFY2(fileMagic == "PHEEBs71", + qPrintable("Invalid fast file magic: " + fileMagic)); + fastFileStream.skipRawData(4); + + // Read IV table name (32 bytes). + QByteArray fileName(32, Qt::Uninitialized); + fastFileStream.readRawData(fileName.data(), 32); + + // 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; + 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. + decompressedData.append(Compression::DecompressDeflate(decData)); + + sectionIndex++; + } + + const QByteArray testZoneData = decompressedData; // Verify the decompressed data via its embedded zone size. QDataStream zoneStream(testZoneData); - zoneStream.setByteOrder(QDataStream::LittleEndian); + zoneStream.setByteOrder(QDataStream::BigEndian); quint32 zoneSize; zoneStream >> zoneSize; - QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod7_ps3)); + if (abs(zoneSize - testZoneData.size()) != 36) { + qDebug() << "Zone Size: " << zoneSize; + qDebug() << "Test zone Size: " << testZoneData.size(); + qDebug() << "Difference: " << abs(zoneSize - testZoneData.size()); + } + QVERIFY2(zoneSize + 36 == testZoneData.size(), + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod7_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +131,18 @@ void AutoTest_COD7_PS3::testDecompression() { } void AutoTest_COD7_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod7_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD7_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod7_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod7_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod7_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod7_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +172,36 @@ void AutoTest_COD7_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD7_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD7_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD7"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD7_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod8_ps3.cpp b/tests/PS3/autotest_cod8_ps3.cpp index fdae339..99d1bff 100644 --- a/tests/PS3/autotest_cod8_ps3.cpp +++ b/tests/PS3/autotest_cod8_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD8_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD8_PS3::initTestCase() { } void AutoTest_COD8_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod8_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD8_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod8_ps3); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod8_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod8_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD8_PS3::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod8_ps3)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod8_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD8_PS3::testDecompression() { } void AutoTest_COD8_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod8_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD8_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod8_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod8_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod8_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod8_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD8_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD8_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD8_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD8"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD8_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/PS3/autotest_cod9_ps3.cpp b/tests/PS3/autotest_cod9_ps3.cpp index 660f16b..c3b3f78 100644 --- a/tests/PS3/autotest_cod9_ps3.cpp +++ b/tests/PS3/autotest_cod9_ps3.cpp @@ -12,12 +12,16 @@ class AutoTest_COD9_PS3 : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD9_PS3::initTestCase() { } void AutoTest_COD9_PS3::testDecompression_data() { - QTest::addColumn("fastFilePath_cod9_ps3"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD9_PS3::testDecompression() { - QFETCH(QString, fastFilePath_cod9_ps3); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod9_ps3); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod9_ps3)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD9_PS3::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod9_ps3)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod9_ps3); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD9_PS3::testDecompression() { } void AutoTest_COD9_PS3::testCompression_data() { - QTest::addColumn("zoneFilePath_cod9_ps3"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD9_PS3::testCompression() { - QFETCH(QString, zoneFilePath_cod9_ps3); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod9_ps3); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod9_ps3)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod9_ps3); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD9_PS3::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD9_PS3::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD9_PS3::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD9"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "PS3"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD9_PS3::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/Wii/autotest_cod4_wii.cpp b/tests/Wii/autotest_cod4_wii.cpp new file mode 100644 index 0000000..14dbe3f --- /dev/null +++ b/tests/Wii/autotest_cod4_wii.cpp @@ -0,0 +1,146 @@ +#include +#include +#include + +#include "autotest_cod.h" +#include "compression.h" + +class AutoTest_COD4_Wii : public AutoTest_COD { + Q_OBJECT + + const QString EXPORT_DIR = "./exports/cod4/Wii"; + +private slots: + void initTestCase(); + + void testDecompression_data(); + void testDecompression(); + + void testCompression_data(); + void testCompression(); + + void testFactory_data(); + void testFactory(); + + void cleanupTestCase(); +}; + +void AutoTest_COD4_Wii::initTestCase() { + // Ensure the exports directory exists. + createDirectory(EXPORT_DIR); +} + +void AutoTest_COD4_Wii::testDecompression_data() { + AutoTest_COD::testDecompression_data(); +} + +void AutoTest_COD4_Wii::testDecompression() { + QFETCH(QString, fastFilePath); + + // Open the original .ff file. + QFile testFastFile(fastFilePath); + QVERIFY2(testFastFile.open(QIODevice::ReadOnly), + qPrintable("Failed to open test fastfile: " + fastFilePath)); + const QByteArray testFFData = testFastFile.readAll(); + testFastFile.close(); + + // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. + const QByteArray compressedData = testFFData.mid(12); + const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + + // Verify the decompressed data via its embedded zone size. + QDataStream zoneStream(testZoneData); + zoneStream.setByteOrder(QDataStream::BigEndian); + quint32 zoneSize; + zoneStream >> zoneSize; + QVERIFY2(zoneSize + 40 == testZoneData.size(), + qPrintable(QString("Decompression validation failed, got [%1] expected [%2]").arg(zoneSize + 40).arg(testZoneData.size()))); + + // Write the decompressed zone data to the exports folder with a .zone extension. + QFileInfo fi(fastFilePath); + QString outputFileName = fi.completeBaseName() + ".zone"; + QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); + QFile outputFile(outputFilePath); + QVERIFY2(outputFile.open(QIODevice::WriteOnly), + qPrintable("Failed to open output file for writing: " + outputFilePath)); + outputFile.write(testZoneData); + outputFile.close(); +} + +void AutoTest_COD4_Wii::testCompression_data() { + AutoTest_COD::testCompression_data(); +} + +void AutoTest_COD4_Wii::testCompression() { + QFETCH(QString, zoneFilePath); + + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); + QByteArray decompressedData = zoneFile.readAll(); + zoneFile.close(); + + QFileInfo fi(zoneFilePath); + QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); + + QFile originalFile(originalFFPath); + QVERIFY2(originalFile.open(QIODevice::ReadOnly), qPrintable("Failed to open original .ff file: " + originalFFPath)); + QByteArray originalFFData = originalFile.readAll(); + originalFile.close(); + + QByteArray header = originalFFData.left(12); + + QByteArray newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_SPEED); + + int remainder = (newCompressedData.size() + 12) % 32; + if (remainder != 0) { + int paddingNeeded = 32 - remainder; + newCompressedData.append(QByteArray(paddingNeeded, '\0')); + } + + QByteArray recompressedData = header + newCompressedData; + + QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff"); + QFile recompressedFile(recompressedFilePath); + QVERIFY2(recompressedFile.open(QIODevice::WriteOnly), qPrintable("Failed to write recompressed file.")); + recompressedFile.write(recompressedData); + recompressedFile.close(); + + QCOMPARE(recompressedData, originalFFData); +} + +void AutoTest_COD4_Wii::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD4_Wii::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD4"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "Wii"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + +void AutoTest_COD4_Wii::cleanupTestCase() { + // Any cleanup if necessary. +} + +// Don't generate a main() function +#include "autotest_cod4_wii.moc" diff --git a/tests/Wii/autotest_cod7_wii.cpp b/tests/Wii/autotest_cod7_wii.cpp index 69948a5..8a986b5 100644 --- a/tests/Wii/autotest_cod7_wii.cpp +++ b/tests/Wii/autotest_cod7_wii.cpp @@ -12,12 +12,16 @@ class AutoTest_COD7_Wii : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD7_Wii::initTestCase() { } void AutoTest_COD7_Wii::testDecompression_data() { - QTest::addColumn("fastFilePath_cod7_wii"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD7_Wii::testDecompression() { - QFETCH(QString, fastFilePath_cod7_wii); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod7_wii); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod7_wii)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -52,14 +50,14 @@ void AutoTest_COD7_Wii::testDecompression() { // Verify the decompressed data via its embedded zone size. QDataStream zoneStream(testZoneData); - zoneStream.setByteOrder(QDataStream::LittleEndian); + zoneStream.setByteOrder(QDataStream::BigEndian); quint32 zoneSize; zoneStream >> zoneSize; - QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod7_wii)); + QVERIFY2(zoneSize + 40 == testZoneData.size(), + qPrintable(QString("Decompression validation failed, got [%1] expected [%2]").arg(zoneSize + 40).arg(testZoneData.size()))); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod7_wii); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD7_Wii::testDecompression() { } void AutoTest_COD7_Wii::testCompression_data() { - QTest::addColumn("zoneFilePath_cod7_wii"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD7_Wii::testCompression() { - QFETCH(QString, zoneFilePath_cod2_360); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod2_360); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod2_360)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod2_360); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -97,8 +89,7 @@ void AutoTest_COD7_Wii::testCompression() { QByteArray header = originalFFData.left(12); - QByteArray newCompressedData;// = Compressor::CompressZLIB(decompressedData, Z_BEST_COMPRESSION); - newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_COMPRESSION, MAX_WBITS, 8, Z_DEFAULT_STRATEGY, {}); + QByteArray newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_SPEED); int remainder = (newCompressedData.size() + 12) % 32; if (remainder != 0) { @@ -117,6 +108,36 @@ void AutoTest_COD7_Wii::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD7_Wii::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD7_Wii::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD7"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "Wii"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD7_Wii::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/Wii/autotest_cod8_wii.cpp b/tests/Wii/autotest_cod8_wii.cpp new file mode 100644 index 0000000..1ab4a00 --- /dev/null +++ b/tests/Wii/autotest_cod8_wii.cpp @@ -0,0 +1,138 @@ +#include +#include +#include + +#include "autotest_cod.h" +#include "compression.h" + +class AutoTest_COD8_Wii : public AutoTest_COD { + Q_OBJECT + + const QString EXPORT_DIR = "./exports/cod8/Wii"; + +private slots: + void initTestCase(); + + void testDecompression_data(); + void testDecompression(); + + void testCompression_data(); + void testCompression(); + + void testFactory_data(); + void testFactory(); + + void cleanupTestCase(); +}; + +void AutoTest_COD8_Wii::initTestCase() { + // Ensure the exports directory exists. + createDirectory(EXPORT_DIR); +} + +void AutoTest_COD8_Wii::testDecompression_data() { + AutoTest_COD::testDecompression_data(); +} + +void AutoTest_COD8_Wii::testDecompression() { + QFETCH(QString, fastFilePath); + + // Open the original .ff file. + QFile testFastFile(fastFilePath); + QVERIFY2(testFastFile.open(QIODevice::ReadOnly), + qPrintable("Failed to open test fastfile: " + fastFilePath)); + const QByteArray testFFData = testFastFile.readAll(); + testFastFile.close(); + + // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. + const QByteArray compressedData = testFFData.mid(25); + const QByteArray testZoneData = Compression::DecompressZLIB(compressedData); + + // Verify the decompressed data via its embedded zone size. + QDataStream zoneStream(testZoneData); + zoneStream.setByteOrder(QDataStream::BigEndian); + quint32 zoneSize; + zoneStream >> zoneSize; + QVERIFY2(zoneSize + 32 == testZoneData.size(), + qPrintable(QString("Decompression validation failed, got [%1] expected [%2]").arg(zoneSize + 32).arg(testZoneData.size()))); + + // Write the decompressed zone data to the exports folder with a .zone extension. + QFileInfo fi(fastFilePath); + QString outputFileName = fi.completeBaseName() + ".zone"; + QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); + QFile outputFile(outputFilePath); + QVERIFY2(outputFile.open(QIODevice::WriteOnly), + qPrintable("Failed to open output file for writing: " + outputFilePath)); + outputFile.write(testZoneData); + outputFile.close(); +} + +void AutoTest_COD8_Wii::testCompression_data() { + AutoTest_COD::testCompression_data(); +} + +void AutoTest_COD8_Wii::testCompression() { + QFETCH(QString, zoneFilePath); + + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); + QByteArray decompressedData = zoneFile.readAll(); + zoneFile.close(); + + QFileInfo fi(zoneFilePath); + QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); + + QFile originalFile(originalFFPath); + QVERIFY2(originalFile.open(QIODevice::ReadOnly), qPrintable("Failed to open original .ff file: " + originalFFPath)); + QByteArray originalFFData = originalFile.readAll(); + originalFile.close(); + + QByteArray header = originalFFData.left(25); + QByteArray newCompressedData = Compression::CompressZLIBWithSettings(decompressedData, Z_BEST_SPEED); + QByteArray recompressedData = header + newCompressedData; + + QString recompressedFilePath = QDir(EXPORT_DIR).filePath(fi.completeBaseName() + ".ff"); + QFile recompressedFile(recompressedFilePath); + QVERIFY2(recompressedFile.open(QIODevice::WriteOnly), qPrintable("Failed to write recompressed file.")); + recompressedFile.write(recompressedData); + recompressedFile.close(); + + QCOMPARE(recompressedData, originalFFData); +} + +void AutoTest_COD8_Wii::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD8_Wii::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD8"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "Wii"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + +void AutoTest_COD8_Wii::cleanupTestCase() { + // Any cleanup if necessary. +} + +// Don't generate a main() function +#include "autotest_cod8_wii.moc" diff --git a/tests/WiiU/autotest_cod10_wiiu.cpp b/tests/WiiU/autotest_cod10_wiiu.cpp index ec487f4..2eb61b0 100644 --- a/tests/WiiU/autotest_cod10_wiiu.cpp +++ b/tests/WiiU/autotest_cod10_wiiu.cpp @@ -12,12 +12,16 @@ class AutoTest_COD10_WiiU : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD10_WiiU::initTestCase() { } void AutoTest_COD10_WiiU::testDecompression_data() { - QTest::addColumn("fastFilePath_cod10_wiiu"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD10_WiiU::testDecompression() { - QFETCH(QString, fastFilePath_cod10_wiiu); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod10_wiiu); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod10_wiiu)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD10_WiiU::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod10_wiiu)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod10_wiiu); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD10_WiiU::testDecompression() { } void AutoTest_COD10_WiiU::testCompression_data() { - QTest::addColumn("zoneFilePath_cod10_wiiu"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD10_WiiU::testCompression() { - QFETCH(QString, zoneFilePath_cod10_wiiu); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod10_wiiu); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod10_wiiu)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod10_wiiu); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD10_WiiU::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD10_WiiU::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD10_WiiU::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD10"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "WiiU"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD10_WiiU::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/WiiU/autotest_cod9_wiiu.cpp b/tests/WiiU/autotest_cod9_wiiu.cpp index 819f170..8025fc6 100644 --- a/tests/WiiU/autotest_cod9_wiiu.cpp +++ b/tests/WiiU/autotest_cod9_wiiu.cpp @@ -12,12 +12,16 @@ class AutoTest_COD9_WiiU : public AutoTest_COD { private slots: void initTestCase(); - // Data-driven test for decompression + void testDecompression_data(); void testDecompression(); - // Data-driven test for recompression (compression) + void testCompression_data(); void testCompression(); + + void testFactory_data(); + void testFactory(); + void cleanupTestCase(); }; @@ -27,22 +31,16 @@ void AutoTest_COD9_WiiU::initTestCase() { } void AutoTest_COD9_WiiU::testDecompression_data() { - QTest::addColumn("fastFilePath_cod9_wiiu"); - - QStringList ffFiles = findFastFiles(getFastFileDirectory()); - for (const QString &filePath : ffFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testDecompression_data(); } void AutoTest_COD9_WiiU::testDecompression() { - QFETCH(QString, fastFilePath_cod9_wiiu); + QFETCH(QString, fastFilePath); // Open the original .ff file. - QFile testFastFile(fastFilePath_cod9_wiiu); + QFile testFastFile(fastFilePath); QVERIFY2(testFastFile.open(QIODevice::ReadOnly), - qPrintable("Failed to open test fastfile: " + fastFilePath_cod9_wiiu)); + qPrintable("Failed to open test fastfile: " + fastFilePath)); const QByteArray testFFData = testFastFile.readAll(); testFastFile.close(); @@ -56,10 +54,10 @@ void AutoTest_COD9_WiiU::testDecompression() { quint32 zoneSize; zoneStream >> zoneSize; QVERIFY2(zoneSize + 44 == testZoneData.size(), - qPrintable("Decompression validation failed for: " + fastFilePath_cod9_wiiu)); + qPrintable("Decompression validation failed for: " + fastFilePath)); // Write the decompressed zone data to the exports folder with a .zone extension. - QFileInfo fi(fastFilePath_cod9_wiiu); + QFileInfo fi(fastFilePath); QString outputFileName = fi.completeBaseName() + ".zone"; QString outputFilePath = QDir(EXPORT_DIR).filePath(outputFileName); QFile outputFile(outputFilePath); @@ -70,24 +68,18 @@ void AutoTest_COD9_WiiU::testDecompression() { } void AutoTest_COD9_WiiU::testCompression_data() { - QTest::addColumn("zoneFilePath_cod9_wiiu"); - - QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); - for (const QString &filePath : zoneFiles) { - QString fileName = QFileInfo(filePath).fileName(); - QTest::newRow(qPrintable(fileName)) << filePath; - } + AutoTest_COD::testCompression_data(); } void AutoTest_COD9_WiiU::testCompression() { - QFETCH(QString, zoneFilePath_cod9_wiiu); + QFETCH(QString, zoneFilePath); - QFile zoneFile(zoneFilePath_cod9_wiiu); - QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath_cod9_wiiu)); + QFile zoneFile(zoneFilePath); + QVERIFY2(zoneFile.open(QIODevice::ReadOnly), qPrintable("Failed to open zone file: " + zoneFilePath)); QByteArray decompressedData = zoneFile.readAll(); zoneFile.close(); - QFileInfo fi(zoneFilePath_cod9_wiiu); + QFileInfo fi(zoneFilePath); QString originalFFPath = QDir(getFastFileDirectory()).filePath(fi.completeBaseName() + ".ff"); QFile originalFile(originalFFPath); @@ -117,6 +109,36 @@ void AutoTest_COD9_WiiU::testCompression() { QCOMPARE(recompressedData, originalFFData); } +void AutoTest_COD9_WiiU::testFactory_data() { + AutoTest_COD::testFactory_data(); +} + +void AutoTest_COD9_WiiU::testFactory() { + QFETCH(QString, fastFilePath); + + const QString testName = "Factory ingest: " + fastFilePath; + + std::shared_ptr fastFile = FastFileFactory::Create(fastFilePath); + + const QString game = fastFile->GetGame(); + bool correctGame = game == "COD9"; + if (!correctGame) { + recordResult(testName, false); + } + QVERIFY2(correctGame + , qPrintable("Factory parsed wrong game [" + game + "] for fastfile: " + fastFilePath)); + + const QString platform = fastFile->GetPlatform(); + bool correctPlatform = platform == "WiiU"; + if (!correctPlatform) { + recordResult(testName, false); + } + QVERIFY2(correctPlatform + , qPrintable("Factory parsed wrong platform [" + platform + "] for fastfile: " + fastFilePath)); + + recordResult(testName, true); +} + void AutoTest_COD9_WiiU::cleanupTestCase() { // Any cleanup if necessary. } diff --git a/tests/autotest_cod.h b/tests/autotest_cod.h index aa45d15..ab62fc1 100644 --- a/tests/autotest_cod.h +++ b/tests/autotest_cod.h @@ -3,6 +3,10 @@ #include +#include "fastfile_factory.h" + +#define FILE_MAX 3 + class AutoTest_COD : public QObject { Q_OBJECT @@ -34,41 +38,93 @@ public: QDir newDir("."); newDir.mkpath(aDir); } - QStringList findFastFiles(const QString &aBaseDir, int aMaxIter = MAX_ITER) { - QStringList fastFiles; - - QDirIterator it(aBaseDir, QStringList() << "*.ff", QDir::Files, QDirIterator::Subdirectories); - - int i = 0; - while (it.hasNext() && i < aMaxIter) { - fastFiles << it.next(); - ++i; - } - - return fastFiles; - } - QStringList findZoneFiles(const QString &aBaseDir, int aMaxIter = MAX_ITER) { - QStringList zoneFiles; + QStringList findZoneFiles(const QString &aBaseDir, int aMaxIter = FILE_MAX) { + QList> fileList; QDirIterator it(aBaseDir, QStringList() << "*.zone", QDir::Files, QDirIterator::Subdirectories); - int i = 0; while (it.hasNext() && i < aMaxIter) { - zoneFiles << it.next(); + QString path = it.next(); + QFileInfo fi(path); + fileList.append(qMakePair(fi.size(), path)); ++i; } - return zoneFiles; + std::sort(fileList.begin(), fileList.end(), + [](const QPair &a, const QPair &b) { + return a.first < b.first; // sort by size + }); + + QStringList sorted; + for (const auto &pair : fileList) + sorted << pair.second; + + return sorted; } + + QStringList findFastFiles(const QString &aBaseDir, int aMaxIter = FILE_MAX) { + QList> fileList; + + QDirIterator it(aBaseDir, QStringList() << "*.ff", QDir::Files, QDirIterator::Subdirectories); + int i = 0; + while (it.hasNext() && i < aMaxIter) { + QString path = it.next(); + QFileInfo fi(path); + fileList.append(qMakePair(fi.size(), path)); + ++i; + } + + std::sort(fileList.begin(), fileList.end(), + [](const QPair &a, const QPair &b) { + return a.first < b.first; // sort by size + }); + + QStringList sorted; + for (const auto &pair : fileList) + sorted << pair.second; + + return sorted; + } + virtual void initTestCase() = 0; - virtual void testDecompression_data() = 0; + + void testDecompression_data() { + QTest::addColumn("fastFilePath"); + + QStringList ffFiles = findFastFiles(getFastFileDirectory()); + for (const QString &filePath : ffFiles) { + QString fileName = QFileInfo(filePath).fileName(); + QTest::newRow(qPrintable(fileName)) << filePath; + } + } virtual void testDecompression() = 0; - virtual void testCompression_data() = 0; + + void testCompression_data() { + QTest::addColumn("zoneFilePath"); + + QStringList zoneFiles = findZoneFiles(getZoneFileDirectory()); + for (const QString &filePath : zoneFiles) { + QString fileName = QFileInfo(filePath).fileName(); + QTest::newRow(qPrintable(fileName)) << filePath; + break; + } + } virtual void testCompression() = 0; + + void testFactory_data() { + QTest::addColumn("fastFilePath"); + + QStringList ffFiles = findFastFiles(getFastFileDirectory()); + for (const QString &filePath : ffFiles) { + QString fileName = QFileInfo(filePath).fileName(); + QTest::newRow(qPrintable(fileName)) << filePath; + } + } + virtual void testFactory() = 0; + virtual void cleanupTestCase() = 0; private: - static const int MAX_ITER = 10000; QString mFastFileDirectory; QString mZoneFileDirectory; }; diff --git a/tests/test_main.cpp b/tests/test_main.cpp index 9860a28..b45f9db 100644 --- a/tests/test_main.cpp +++ b/tests/test_main.cpp @@ -32,7 +32,9 @@ #include "PS3/autotest_cod11_ps3.cpp" #include "PS3/autotest_cod12_ps3.cpp" +#include "Wii/autotest_cod4_wii.cpp" #include "Wii/autotest_cod7_wii.cpp" +#include "Wii/autotest_cod8_wii.cpp" #include "WiiU/autotest_cod9_wiiu.cpp" #include "WiiU/autotest_cod10_wiiu.cpp" @@ -50,11 +52,11 @@ #define TEST_COD5 0 #define TEST_COD6 0 #define TEST_COD7 0 -#define TEST_COD8 1 +#define TEST_COD8 0 #define TEST_COD9 0 #define TEST_COD10 0 #define TEST_COD11 0 -#define TEST_COD12 0 +#define TEST_COD12 1 // individual platforms #define TEST_360 0 @@ -185,7 +187,7 @@ int main(int argc, char *argv[]) { AutoTest_COD8_PC *test_cod8_pc = new AutoTest_COD8_PC(); test_cod8_pc->setFastFileDirectory("G:/Fast Files/PC/COD8"); test_cod8_pc->setZoneFileDirectory("./exports/cod8/PC"); - //cod8Tests << test_cod8_pc; + cod8Tests << test_cod8_pc; pcTests << test_cod8_pc; AutoTest_COD9_PC *test_cod9_pc = new AutoTest_COD9_PC(); @@ -209,7 +211,7 @@ int main(int argc, char *argv[]) { AutoTest_COD12_PC *test_cod12_pc = new AutoTest_COD12_PC(); test_cod12_pc->setFastFileDirectory("G:/Fast Files/PC/COD12"); test_cod12_pc->setZoneFileDirectory("./exports/cod12/PC"); - cod12Tests << test_cod12_pc; + //cod12Tests << test_cod12_pc; pcTests << test_cod12_pc; /**********************************/ @@ -225,7 +227,7 @@ int main(int argc, char *argv[]) { AutoTest_COD5_PS3 *test_cod5_ps3 = new AutoTest_COD5_PS3(); test_cod5_ps3->setFastFileDirectory("G:/Fast Files/PS3/COD5"); test_cod5_ps3->setZoneFileDirectory("./exports/cod5/PS3"); - //cod5Tests << test_cod5_ps3; + cod5Tests << test_cod5_ps3; ps3Tests << test_cod5_ps3; AutoTest_COD6_PS3 *test_cod6_ps3 = new AutoTest_COD6_PS3(); @@ -243,7 +245,7 @@ int main(int argc, char *argv[]) { AutoTest_COD8_PS3 *test_cod8_ps3 = new AutoTest_COD8_PS3(); test_cod8_ps3->setFastFileDirectory("G:/Fast Files/PS3/COD8"); test_cod8_ps3->setZoneFileDirectory("./exports/cod8/PS3"); - //cod8Tests << test_cod8_ps3; + cod8Tests << test_cod8_ps3; ps3Tests << test_cod8_ps3; AutoTest_COD9_PS3 *test_cod9_ps3 = new AutoTest_COD9_PS3(); @@ -267,19 +269,31 @@ int main(int argc, char *argv[]) { AutoTest_COD12_PS3 *test_cod12_ps3 = new AutoTest_COD12_PS3(); test_cod12_ps3->setFastFileDirectory("G:/Fast Files/PS3/COD12"); test_cod12_ps3->setZoneFileDirectory("./exports/cod12/PS3"); - cod12Tests << test_cod12_ps3; + //cod12Tests << test_cod12_ps3; ps3Tests << test_cod12_ps3; /**********************************/ /********* Wii COD TESTS *********/ /**********************************/ + AutoTest_COD4_Wii *test_cod4_wii = new AutoTest_COD4_Wii(); + test_cod4_wii->setFastFileDirectory("G:/Fast Files/Wii/COD4"); + test_cod4_wii->setZoneFileDirectory("./exports/cod4/Wii"); + cod4Tests << test_cod4_wii; + wiiTests << test_cod4_wii; + AutoTest_COD7_Wii *test_cod7_wii = new AutoTest_COD7_Wii(); test_cod7_wii->setFastFileDirectory("G:/Fast Files/Wii/COD7"); test_cod7_wii->setZoneFileDirectory("./exports/cod7/Wii"); cod7Tests << test_cod7_wii; wiiTests << test_cod7_wii; + AutoTest_COD8_Wii *test_cod8_wii = new AutoTest_COD8_Wii(); + test_cod8_wii->setFastFileDirectory("G:/Fast Files/Wii/COD8"); + test_cod8_wii->setZoneFileDirectory("./exports/cod8/Wii"); + cod8Tests << test_cod8_wii; + wiiTests << test_cod8_wii; + /**********************************/ /********* WiiU COD TESTS *********/ /**********************************/ @@ -309,54 +323,63 @@ int main(int argc, char *argv[]) { qDebug() << "-- RUNNING TEST_COD4 --"; foreach (auto test, cod4Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD5) { qDebug() << "-- RUNNING TEST_COD5 --"; foreach (auto test, cod5Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD6) { qDebug() << "-- RUNNING TEST_COD6 --"; foreach (auto test, cod6Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD7) { qDebug() << "-- RUNNING TEST_COD7 --"; foreach (auto test, cod7Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD8) { qDebug() << "-- RUNNING TEST_COD8 --"; foreach (auto test, cod8Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD9) { qDebug() << "-- RUNNING TEST_COD9 --"; foreach (auto test, cod9Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD10) { qDebug() << "-- RUNNING TEST_COD10 --"; foreach (auto test, cod10Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD11) { qDebug() << "-- RUNNING TEST_COD11 --"; foreach (auto test, cod11Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_COD_GAMES || TEST_COD12) { qDebug() << "-- RUNNING TEST_COD12 --"; foreach (auto test, cod12Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } @@ -364,30 +387,35 @@ int main(int argc, char *argv[]) { qDebug() << "-- RUNNING TEST_360 --"; foreach (auto test, xbox360Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_PLATFORMS || TEST_PC) { qDebug() << "-- RUNNING TEST_PC --"; foreach (auto test, pcTests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_PLATFORMS || TEST_PS3) { qDebug() << "-- RUNNING TEST_PS3 --"; foreach (auto test, ps3Tests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_PLATFORMS || TEST_WII) { qDebug() << "-- RUNNING TEST_WII --"; foreach (auto test, wiiTests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } if (TEST_EVERYTHING || TEST_ALL_PLATFORMS || TEST_WIIU) { qDebug() << "-- RUNNING TEST_WIIU --"; foreach (auto test, wiiUTests) { QTest::qExec(test, argc, argv); + allResults.append({ test->metaObject()->className(), test->getCollectedTestResults() }); } } diff --git a/tests/tests.pro b/tests/tests.pro index 798cf98..c0bbfc6 100644 --- a/tests/tests.pro +++ b/tests/tests.pro @@ -43,7 +43,9 @@ SOURCES += \ PS3/autotest_cod11_ps3.cpp \ PS3/autotest_cod12_ps3.cpp \ # Wii autotests + Wii/autotest_cod4_wii.cpp \ Wii/autotest_cod7_wii.cpp \ + Wii/autotest_cod8_wii.cpp \ # WiiU autotests WiiU/autotest_cod9_wiiu.cpp \ WiiU/autotest_cod10_wiiu.cpp \ @@ -63,14 +65,8 @@ HEADERS += \ # SOURCES -= autotest_cod5.cpp # } -app.depends += \ - libs/core \ - libs/compression \ - libs/encryption \ - libs/fastfile - LIBS += \ - -L$$OUT_PWD/../libs/ -lcore -lencryption -lcompression -lfastfile \ + -L$$OUT_PWD/../libs/ -lcore -lencryption -lcompression -lfastfile -lzonefile \ -L$$PWD/../third_party/xbox_sdk/lib -lxcompress64 INCLUDEPATH += \ @@ -78,16 +74,16 @@ INCLUDEPATH += \ $$PWD/../libs/core \ $$PWD/../libs/encryption \ $$PWD/../libs/compression \ - $$PWD/../libs/fastfile + $$PWD/../libs/fastfile \ + $$PWD/../libs/zonefile DEPENDPATH += \ $$PWD/../third_party/xbox_sdk/include \ $$PWD/../libs/core \ $$PWD/../libs/encryption \ $$PWD/../libs/compression \ - $$PWD/../libs/fastfile - -RESOURCES += + $$PWD/../libs/fastfile \ + $$PWD/../libs/zonefile # Copy DLLs to Debug & Release folder QMAKE_POST_LINK += xcopy /Y /E /I \"$$PWD/../third_party/xbox_sdk/lib\\*.dll\" \"$$OUT_PWD/debug/\" $$escape_expand(\\n\\t) diff --git a/third_party/xbox_sdk/include/xcompress.h b/third_party/xbox_sdk/include/xcompress.h index 56dc05d..e8929ba 100644 --- a/third_party/xbox_sdk/include/xcompress.h +++ b/third_party/xbox_sdk/include/xcompress.h @@ -185,6 +185,19 @@ XMemDecompressStream( __inout SIZE_T* pSrcSize ); +XBOXAPI +HRESULT +WINAPI +XMemDecompressSegmentTD( + __in XMEMDECOMPRESSION_CONTEXT Context, + __out_bcount( *pDestSize ) VOID* pDestination, + __inout SIZE_T* pDestSize, + __in_bcount( *pSrcSize ) CONST VOID* pSource, + __inout SIZE_T SrcSize, + __inout SIZE_T DestSize, + __inout SIZE_T Offset + ); + /* * LZX codec for lossless compression */ diff --git a/tools/compro/compro.pro b/tools/compro/compro.pro new file mode 100644 index 0000000..5c437c8 --- /dev/null +++ b/tools/compro/compro.pro @@ -0,0 +1,28 @@ +QT += core widgets gui multimedia + +SUBDIRS += compro + +CONFIG += c++17 + +SOURCES += \ + compromain.cpp \ + mainwindow.cpp + +HEADERS += \ + mainwindow.h + +LIBS += \ + -L$$OUT_PWD/../../libs/ -lcompression \ + -L$$PWD/../../third_party/xbox_sdk/lib -lxcompress64 + +INCLUDEPATH += \ + $$PWD/../../libs/compression \ + $$PWD/../../third_party/xbox_sdk/include + +DEPENDPATH += \ + $$PWD/../../libs/compression \ + $$PWD/../../third_party/xbox_sdk/include + +FORMS += \ + mainwindow.ui + diff --git a/tools/compro/compromain.cpp b/tools/compro/compromain.cpp new file mode 100644 index 0000000..fd3e533 --- /dev/null +++ b/tools/compro/compromain.cpp @@ -0,0 +1,11 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/tools/compro/mainwindow.cpp b/tools/compro/mainwindow.cpp new file mode 100644 index 0000000..8907cb0 --- /dev/null +++ b/tools/compro/mainwindow.cpp @@ -0,0 +1,66 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +#include "compression.h" + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + + connect(ui->plainTextEdit_Input, &QPlainTextEdit::textChanged, this, &MainWindow::InputChanged); +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +void MainWindow::InputChanged() +{ + QString input = ui->plainTextEdit_Input->toPlainText(); + if (input.isEmpty()) { + qDebug() << "Input data was empty!"; + return; + } + + QByteArray inputData = QByteArray::fromHex(input.remove(' ').toUtf8()); + if (inputData.isEmpty()) { + qDebug() << "Failed to parse valid HEX data!"; + return; + } + + bool flagOk; + int flag = QString("0x%1").arg(ui->spinBox_Flags->value()).toInt(&flagOk, 16); + if (!flagOk) + { + qDebug() << "Failed to parse flag!"; + return; + } + + bool windowSizeOk; + int windowSize = QString("0x%1").arg(ui->spinBox_WindowSize->value()).toInt(&windowSizeOk, 16); + if (!windowSizeOk) + { + qDebug() << "Failed to parse window size!"; + return; + } + + bool partSizeOk; + int partitionSize = QString("0x%1").arg(ui->spinBox_PartitionSize->value()).toInt(&partSizeOk, 16); + if (!partSizeOk) + { + qDebug() << "Failed to parse partition size!"; + return; + } + + try { + QByteArray output = Compression::DecompressXMem(inputData, flag, windowSize, partitionSize); + ui->plainTextEdit_Output->setPlainText(output.toHex(' ').toUpper()); + } catch (const std::exception &e) { + ui->plainTextEdit_Output->setPlainText(QString("Decompression failed: %1").arg(e.what())); + } catch (...) { + ui->plainTextEdit_Output->setPlainText("Decompression failed: Unknown error"); + } +} diff --git a/tools/compro/mainwindow.h b/tools/compro/mainwindow.h new file mode 100644 index 0000000..84d720d --- /dev/null +++ b/tools/compro/mainwindow.h @@ -0,0 +1,25 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private slots: + void InputChanged(); + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/tools/compro/mainwindow.ui b/tools/compro/mainwindow.ui new file mode 100644 index 0000000..bbcb887 --- /dev/null +++ b/tools/compro/mainwindow.ui @@ -0,0 +1,153 @@ + + + MainWindow + + + + 0 + 0 + 1006 + 600 + + + + MainWindow + + + + + + + 0 + + + + LZX + + + + + + + + Input + + + + + + Input HEX Data (Ex: 63 60 C0 04...) + + + + + + + + + + Qt::Orientation::Vertical + + + + + + + Parameters + + + + + + Flags: + + + + + + + Window Size: + + + + + + + Compression Partition Size: + + + + + + + 0x + + + + + + + 0x + + + 100000 + + + 20000 + + + + + + + 0x + + + 100000 + + + 80000 + + + + + + + + + + + + Qt::Orientation::Horizontal + + + + + + + Output + + + + + + true + + + Output HEX Data + + + + + + + + + + + + + + + + diff --git a/tools/tools.pro b/tools/tools.pro index 8bb493d..ae6dd69 100644 --- a/tools/tools.pro +++ b/tools/tools.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs -SUBDIRS += zentry +SUBDIRS += zentry \ + compro diff --git a/tools/zentry/zentry.pro b/tools/zentry/zentry.pro index 06c4b31..68b8e1e 100644 --- a/tools/zentry/zentry.pro +++ b/tools/zentry/zentry.pro @@ -13,11 +13,6 @@ SOURCES += \ HEADERS += \ zentrywindow.h -FORMS += - -app.depends += \ - libs/compression - LIBS += \ -L$$OUT_PWD/../../libs/ -lcompression \ -L$$PWD/../../third_party/xbox_sdk/lib -lxcompress64 diff --git a/zone.h b/zone.h deleted file mode 100644 index fb860c4..0000000 --- a/zone.h +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef ZONE_H -#define ZONE_H - -#include "enums.h" -#include "qtypes.h" -#include -#include - -struct Zone { - quint32 zoneFileSize; - quint32 unknown1; - quint32 unknown2; - quint32 unknown3; - quint32 unknown4; - quint32 unknown5; - quint32 unknown6; - quint32 unknown7; - quint32 unknown8; - quint32 tagCount; - quint32 unknown9; - quint32 recordCount; - quint32 unknown10; - quint32 unknown11; - QVector tagPtrs; - QStringList tags; - - QVector assetTypes; -}; - -inline QDataStream &operator<<(QDataStream &out, const Zone &zone) { - // Write adjusted fastfile size - out << zone.zoneFileSize - 36; - // Write unknowns 1-8 - out << zone.unknown1; - out << zone.unknown2; - out << zone.unknown3; - out << zone.unknown4; - out << zone.unknown5; - out << zone.unknown6; - out << zone.unknown7; - out << zone.unknown8; - // Write tag count - out << zone.tagCount; - // Write unknown 9 - out << zone.unknown9; - // Write record count - out << zone.recordCount; - // Write unknowns 10-11 - out << zone.unknown10; - out << zone.unknown11; - // Write tag pointers - foreach (quint32 tagPtr, zone.tagPtrs) { - out << tagPtr; - } - // Write tags - foreach (QString tag, zone.tags) { - out << tag.toLocal8Bit(); - } - - return out; -} - -inline QDataStream &operator>>(QDataStream &in, Zone &zone) { - // Parse file size - in >> zone.zoneFileSize; - zone.zoneFileSize += 36; - // Parse unknowns 1-8 - in >> zone.unknown1; - in >> zone.unknown2; - in >> zone.unknown3; - in >> zone.unknown4; - in >> zone.unknown5; - in >> zone.unknown6; - in >> zone.unknown7; - in >> zone.unknown8; - // Parse tag count - in >> zone.tagCount; - // Parse unknown 9 - in >> zone.unknown9; - // Parse record count - in >> zone.recordCount; - - in >> zone.unknown10; - if (zone.tagCount) { - // Parse unknowns 10-11 - in >> zone.unknown11; - - // Parse tag ptrs - for (quint32 i = 0; i < zone.tagCount - 1; i++) { - quint32 tagPtr; - in >> tagPtr; - - zone.tagPtrs.push_back(tagPtr); - } - - // Parse tags/strings before index - QString zoneTag; - char zoneTagChar; - for (quint32 i = 0; i < zone.tagCount - 1; i++) { - in >> zoneTagChar; - while (zoneTagChar != 0) { - zoneTag += zoneTagChar; - in >> zoneTagChar; - } - zone.tags.push_back(zoneTag); - zoneTag.clear(); - } - } - - // Parse index - for (quint32 i = 0; i < zone.recordCount; i++) { - // Parse asset type - quint32 assetType; - in >> assetType; - // Add asset type to vector - zone.assetTypes << (ASSET_TYPE)assetType; - // Skip separator - in.skipRawData(4); - } - - return in; -} - -#endif // ZONE_H