Uplifted tf out of the ui. Minecraft nbt style
12
Data.qrc
@ -21,4 +21,16 @@
|
||||
<file>data/d3dbsp/asset_viewer.d3dbsp</file>
|
||||
<file>data/d3dbsp/barebones.d3dbsp</file>
|
||||
</qresource>
|
||||
<qresource prefix="/images">
|
||||
<file>data/images/XPlor.png</file>
|
||||
<file>data/images/copy.svg</file>
|
||||
<file>data/images/cut.svg</file>
|
||||
<file>data/images/new_file.svg</file>
|
||||
<file>data/images/open_file.svg</file>
|
||||
<file>data/images/open_folder.svg</file>
|
||||
<file>data/images/paste.svg</file>
|
||||
<file>data/images/refresh.svg</file>
|
||||
<file>data/images/save.svg</file>
|
||||
<file>data/images/multiple.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
QT += core gui 3dcore 3drender 3dinput 3dextras
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
RC_ICONS = XPlor.ico
|
||||
|
||||
CONFIG += c++17
|
||||
|
||||
@ -13,16 +14,24 @@ CONFIG += c++17
|
||||
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||
|
||||
SOURCES += \
|
||||
aboutdialog.cpp \
|
||||
main.cpp \
|
||||
mainwindow.cpp
|
||||
mainwindow.cpp \
|
||||
modelviewer.cpp
|
||||
|
||||
HEADERS += \
|
||||
aboutdialog.h \
|
||||
compression.h \
|
||||
enums.h \
|
||||
ffparser.h \
|
||||
mainwindow.h \
|
||||
modelviewer.h \
|
||||
structs.h \
|
||||
utils.h
|
||||
utils.h \
|
||||
zfparser.h
|
||||
|
||||
FORMS += \
|
||||
aboutdialog.ui \
|
||||
mainwindow.ui
|
||||
|
||||
# Default rules for deployment.
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 15.0.0, 2025-01-08T01:31:51. -->
|
||||
<!-- Written by QtCreator 15.0.0, 2025-01-12T21:27:06. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
@ -244,10 +244,10 @@
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph "dwarf,4096" -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">FastFile_WaW2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/Users/njohnson/Projects/FastFile_WaW/FastFile_WaW.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">C:/Users/njohnson/Projects/XPlor/FastFile_WaW.pro</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
|
||||
14
aboutdialog.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "aboutdialog.h"
|
||||
#include "ui_aboutdialog.h"
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent)
|
||||
: QDialog(parent)
|
||||
, ui(new Ui::AboutDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
AboutDialog::~AboutDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
22
aboutdialog.h
Normal file
@ -0,0 +1,22 @@
|
||||
#ifndef ABOUTDIALOG_H
|
||||
#define ABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class AboutDialog;
|
||||
}
|
||||
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AboutDialog(QWidget *parent = nullptr);
|
||||
~AboutDialog();
|
||||
|
||||
private:
|
||||
Ui::AboutDialog *ui;
|
||||
};
|
||||
|
||||
#endif // ABOUTDIALOG_H
|
||||
241
aboutdialog.ui
Normal file
@ -0,0 +1,241 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutDialog</class>
|
||||
<widget class="QDialog" name="AboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>350</width>
|
||||
<height>200</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>350</width>
|
||||
<height>200</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About XPlor</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>80</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="Data.qrc">:/images/data/images/XPlor.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
<pointsize>16</pointsize>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>XPlor v1.5</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Copyright © 2024 RedLine Solutions LLC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>For more, check out redline.llc</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>With Help From:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_9">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>- Paging Red</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_8">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>- ISOCheated</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Roboto</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>- SureShotIan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="Data.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
34
compression.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef COMPRESSION_H
|
||||
#define COMPRESSION_H
|
||||
|
||||
#include "utils.h"
|
||||
#include "QtZlib/zlib.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QDebug>
|
||||
|
||||
class Compressor {
|
||||
public:
|
||||
static QByteArray DecompressZLIB(QByteArray compressedData) {
|
||||
QByteArray decompressedData;
|
||||
uLongf decompressedSize = compressedData.size() * 4;
|
||||
decompressedData.resize(static_cast<int>(decompressedSize));
|
||||
|
||||
Bytef *destination = reinterpret_cast<Bytef*>(decompressedData.data());
|
||||
uLongf *destLen = &decompressedSize;
|
||||
const Bytef *source = reinterpret_cast<const Bytef*>(compressedData.data());
|
||||
uLong sourceLen = compressedData.size();
|
||||
|
||||
int result = uncompress(destination, destLen, source, sourceLen);
|
||||
|
||||
if (result == Z_OK) {
|
||||
decompressedData.resize(static_cast<int>(decompressedSize));
|
||||
} else {
|
||||
decompressedData.clear();
|
||||
qDebug() << QString("In DecompressZLIB: %1").arg(Utils::ZLibErrorToString(result)).toLatin1();
|
||||
}
|
||||
return decompressedData;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // COMPRESSION_H
|
||||
BIN
data/images/XPlor.png
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
1
data/images/copy.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M15 11a3 3 0 0 1-3-3V4H8a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-8zm-2-3a2 2 0 0 0 2 2h3.59L13 4.41zM8 3h5l7 7v9a3 3 0 0 1-3 3H8a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3m0 21a5 5 0 0 1-5-5V7h1v12a4 4 0 0 0 4 4h8v1z"/></svg>
|
||||
|
After Width: | Height: | Size: 332 B |
1
data/images/cut.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M9 6.5c0 .79-.26 1.5-.7 2.1L20 20.29V21h-.71l-7.79-7.79l-3.2 3.19c.44.6.7 1.31.7 2.1A3.5 3.5 0 0 1 5.5 22A3.5 3.5 0 0 1 2 18.5A3.5 3.5 0 0 1 5.5 15c.79 0 1.5.26 2.1.7l3.19-3.2L7.6 9.3c-.6.44-1.31.7-2.1.7A3.5 3.5 0 0 1 2 6.5A3.5 3.5 0 0 1 5.5 3A3.5 3.5 0 0 1 9 6.5m-1 0A2.5 2.5 0 0 0 5.5 4A2.5 2.5 0 0 0 3 6.5A2.5 2.5 0 0 0 5.5 9A2.5 2.5 0 0 0 8 6.5M19.29 4H20v.71l-7.15 7.14l-.7-.7zM5.5 16A2.5 2.5 0 0 0 3 18.5A2.5 2.5 0 0 0 5.5 21A2.5 2.5 0 0 0 8 18.5A2.5 2.5 0 0 0 5.5 16"/></svg>
|
||||
|
After Width: | Height: | Size: 594 B |
BIN
data/images/multiple.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
1
data/images/new_file.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M14 11a3 3 0 0 1-3-3V4H7a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-8zm-2-3a2 2 0 0 0 2 2h3.59L12 4.41zM7 3h5l7 7v9a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3m2 16v-2H7v-1h2v-2h1v2h2v1h-2v2z"/></svg>
|
||||
|
After Width: | Height: | Size: 319 B |
1
data/images/open_file.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M14 11a3 3 0 0 1-3-3V4H7a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h9a2 2 0 0 0 2-2v-8zm-2-3a2 2 0 0 0 2 2h3.59L12 4.41zM7 3h5l7 7v9a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3"/></svg>
|
||||
|
After Width: | Height: | Size: 287 B |
1
data/images/open_folder.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M5 5h4l3 3h6a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5a3 3 0 0 1-3-3V8a3 3 0 0 1 3-3m0 1a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h13a2 2 0 0 0 2-2v-6a2 2 0 0 0-2-2h-6.41l-3-3z"/></svg>
|
||||
|
After Width: | Height: | Size: 275 B |
1
data/images/paste.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M11.5 1a2.5 2.5 0 0 1 2.45 2H17a3 3 0 0 1 3 3v13a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V6a3 3 0 0 1 3-3h3.05a2.5 2.5 0 0 1 2.45-2m1.41 2a1.495 1.495 0 0 0-2.82 0zM6 4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2h-1v3H7V4zm2 0v2h7V4z"/></svg>
|
||||
|
After Width: | Height: | Size: 363 B |
1
data/images/refresh.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M5 5h5v5H9V6.5c-2.35.97-4 3.29-4 6c0 3.58 2.91 6.5 6.5 6.5a6.5 6.5 0 0 0 6.5-6.5c0-3.08-2.14-5.66-5-6.33V5.14c3.42.7 6 3.72 6 7.36c0 4.13-3.36 7.5-7.5 7.5A7.5 7.5 0 0 1 4 12.5C4 9.72 5.5 7.3 7.74 6H5z"/></svg>
|
||||
|
After Width: | Height: | Size: 321 B |
1
data/images/save.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="96" height="96" viewBox="0 0 24 24"><path fill="currentColor" d="M6 4h10.59L20 7.41V18a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3m0 1a2 2 0 0 0-2 2v11a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7.91L16.09 5H15v5H6zm1 0v4h7V5zm5 7a3 3 0 0 1 3 3a3 3 0 0 1-3 3a3 3 0 0 1-3-3a3 3 0 0 1 3-3m0 1a2 2 0 0 0-2 2a2 2 0 0 0 2 2a2 2 0 0 0 2-2a2 2 0 0 0-2-2"/></svg>
|
||||
|
After Width: | Height: | Size: 392 B |
19
enums.h
@ -98,4 +98,23 @@ enum BSPVERSION_TYPE
|
||||
BSPVERSION_COD_BO = 45
|
||||
};
|
||||
|
||||
enum FF_COMPANY {
|
||||
COMPANY_NONE = 0x00,
|
||||
COMPANY_INFINITY_WARD = 0x01,
|
||||
COMPANY_TREYARCH = 0x02,
|
||||
COMPANY_SLEDGEHAMMER = 0x03,
|
||||
COMPANY_NEVERSOFT = 0x04
|
||||
};
|
||||
|
||||
enum FF_FILETYPE {
|
||||
FILETYPE_NONE = 0x00,
|
||||
FILETYPE_FAST_FILE = 0x01
|
||||
};
|
||||
|
||||
enum FF_SIGNAGE {
|
||||
SIGNAGE_NONE = 0x00,
|
||||
SIGNAGE_SIGNED = 0x01,
|
||||
SIGNAGE_UNSIGNED = 0x02
|
||||
};
|
||||
|
||||
#endif // ENUMS_H
|
||||
|
||||
103
ffparser.h
Normal file
@ -0,0 +1,103 @@
|
||||
#ifndef FFPARSER_H
|
||||
#define FFPARSER_H
|
||||
|
||||
#include "enums.h"
|
||||
#include "structs.h"
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDebug>
|
||||
|
||||
class FastFileParser {
|
||||
public:
|
||||
static FF_COMPANY ParseFFCompany(QDataStream *afastFileStream) {
|
||||
// Check for null datastream ptr
|
||||
if (!afastFileStream) { return COMPANY_NONE; }
|
||||
// Parse company
|
||||
QByteArray companyData(2, Qt::Uninitialized);
|
||||
afastFileStream->readRawData(companyData.data(), 2);
|
||||
if (companyData == "IW") {
|
||||
qDebug() << "Company found: 'INFINITY_WARD'";
|
||||
return COMPANY_INFINITY_WARD;
|
||||
} else if (companyData == "TA") {
|
||||
qDebug() << "Company found: 'TREYARCH'";
|
||||
return COMPANY_TREYARCH;
|
||||
} else if (companyData == "Sl") {
|
||||
qDebug() << "Company found: 'SLEDGEHAMMER'";
|
||||
return COMPANY_SLEDGEHAMMER;
|
||||
} else if (companyData == "NX") {
|
||||
qDebug() << "Company found: 'NEVERSOFT'";
|
||||
return COMPANY_NEVERSOFT;
|
||||
} else {
|
||||
qDebug() << QString("Failed to find company, found '%1'!").arg(companyData);
|
||||
}
|
||||
return COMPANY_NONE;
|
||||
}
|
||||
|
||||
static FF_FILETYPE ParseFFFileType(QDataStream *afastFileStream) {
|
||||
// Parse filetype
|
||||
QByteArray fileTypeData(2, Qt::Uninitialized);
|
||||
afastFileStream->readRawData(fileTypeData.data(), 2);
|
||||
if (fileTypeData == "ff") {
|
||||
qDebug() << "File type found: 'FAST_FILE'";
|
||||
return FILETYPE_FAST_FILE;
|
||||
} else {
|
||||
qDebug() << "Failed to find file type!";
|
||||
}
|
||||
return FILETYPE_NONE;
|
||||
}
|
||||
|
||||
static FF_SIGNAGE ParseFFSignage(QDataStream *afastFileStream) {
|
||||
// Parse filetype
|
||||
QByteArray signedData(1, Qt::Uninitialized);
|
||||
afastFileStream->readRawData(signedData.data(), 1);
|
||||
if (signedData == "u") {
|
||||
qDebug() << "Found valid signage: Unsigned";
|
||||
return SIGNAGE_UNSIGNED;
|
||||
} else if (signedData == "0") {
|
||||
qDebug() << "Found valid signage: Signed";
|
||||
return SIGNAGE_SIGNED;
|
||||
} else {
|
||||
qDebug() << "Failed to determine signage of fastfile!";
|
||||
}
|
||||
return SIGNAGE_NONE;
|
||||
}
|
||||
|
||||
static QString ParseFFMagic(QDataStream *afastFileStream) {
|
||||
// Parse magic
|
||||
QByteArray magicData(3, Qt::Uninitialized);
|
||||
afastFileStream->readRawData(magicData.data(), 3);
|
||||
if (magicData == "100") {
|
||||
qDebug() << QString("Found valid magic: '%1'").arg(magicData);
|
||||
return magicData;
|
||||
} else {
|
||||
qDebug() << "Magic invalid!";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static quint32 ParseFFVersion(QDataStream *afastFileStream) {
|
||||
// Parse version
|
||||
quint32 version;
|
||||
*afastFileStream >> version;
|
||||
qDebug() << "Version:" << version;
|
||||
if (version == 387) {
|
||||
qDebug() << QString("Found valid version: '%1'").arg(version);
|
||||
return 387;
|
||||
} else {
|
||||
qDebug() << "Version invalid!";
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static FastFile ParseFFHeader(QDataStream *afastFileStream) {
|
||||
FastFile fastFile;
|
||||
fastFile.company = ParseFFCompany(afastFileStream);
|
||||
fastFile.fileType = ParseFFFileType(afastFileStream);
|
||||
fastFile.signage = ParseFFSignage(afastFileStream);
|
||||
fastFile.magic = ParseFFMagic(afastFileStream);
|
||||
fastFile.version = ParseFFVersion(afastFileStream);
|
||||
return fastFile;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // FFPARSER_H
|
||||
1265
mainwindow.cpp
111
mainwindow.h
@ -4,6 +4,11 @@
|
||||
#include "enums.h"
|
||||
#include "structs.h"
|
||||
#include "utils.h"
|
||||
#include "aboutdialog.h"
|
||||
#include "compression.h"
|
||||
#include "ffparser.h"
|
||||
#include "zfparser.h"
|
||||
#include "modelviewer.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QFileDialog>
|
||||
@ -12,52 +17,8 @@
|
||||
#include <QDebug>
|
||||
#include <QTableWidgetItem>
|
||||
#include <QTreeWidgetItem>
|
||||
|
||||
#include <Qt3DCore/QEntity>
|
||||
#include <Qt3DRender/QCamera>
|
||||
#include <Qt3DRender/QCameraLens>
|
||||
#include <Qt3DCore/QTransform>
|
||||
#include <Qt3DCore/QAspectEngine>
|
||||
|
||||
#include <Qt3DInput/QInputAspect>
|
||||
|
||||
#include <Qt3DRender/QRenderAspect>
|
||||
#include <Qt3DRender/QGeometryRenderer>
|
||||
#include <Qt3DExtras/QForwardRenderer>
|
||||
#include <Qt3DExtras/QPhongMaterial>
|
||||
#include <Qt3DExtras/QSphereMesh>
|
||||
#include <Qt3DExtras/QTorusMesh>
|
||||
#include <Qt3DRender/qcamera.h>
|
||||
#include <Qt3DCore/qentity.h>
|
||||
#include <Qt3DRender/qcameralens.h>
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QCheckBox>
|
||||
#include <QtWidgets/QCommandLinkButton>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
#include <Qt3DRender/qmesh.h>
|
||||
#include <Qt3DRender/qtechnique.h>
|
||||
#include <Qt3DRender/qmaterial.h>
|
||||
#include <Qt3DRender/qeffect.h>
|
||||
#include <Qt3DRender/qtexture.h>
|
||||
#include <Qt3DRender/qrenderpass.h>
|
||||
#include <Qt3DRender/qsceneloader.h>
|
||||
#include <Qt3DRender/qpointlight.h>
|
||||
|
||||
#include <Qt3DCore/qtransform.h>
|
||||
#include <Qt3DCore/qaspectengine.h>
|
||||
|
||||
#include <Qt3DRender/qrenderaspect.h>
|
||||
#include <Qt3DExtras/qforwardrenderer.h>
|
||||
|
||||
#include <Qt3DExtras/qt3dwindow.h>
|
||||
#include <Qt3DExtras/qfirstpersoncameracontroller.h>
|
||||
|
||||
#include <Qt3DExtras/QNormalDiffuseMapMaterial>
|
||||
|
||||
#include <QDockWidget>
|
||||
#include <QPlainTextEdit>
|
||||
#include <windows.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@ -75,60 +36,15 @@ public:
|
||||
~MainWindow();
|
||||
void Reset();
|
||||
|
||||
QByteArray DecompressZLIB(QByteArray compressedData);
|
||||
|
||||
private slots:
|
||||
void on_pushButton_FastFile_clicked();
|
||||
void on_pushButton_FastFile_2_clicked();
|
||||
bool OpenFastFile(const QString aFastFilePath);
|
||||
bool OpenFastFile();
|
||||
|
||||
QFile *OpenFastFile();
|
||||
QFile *OpenZoneFile();
|
||||
void ParseFFHeader(QFile *aFastFilePtr);
|
||||
void ParseFFCompany(QDataStream *aFastFileStream);
|
||||
void ParseFFFileType(QDataStream *afastFileStream);
|
||||
void ParseFFSignage(QDataStream *afastFileStream);
|
||||
void ParseFFMagic(QDataStream *afastFileStream);
|
||||
void ParseFFVersion(QDataStream *afastFileStream);
|
||||
|
||||
void ParseZoneHeader(QDataStream *aZoneFileStream);
|
||||
void ParseZoneSize(QDataStream *aZoneFileStream);
|
||||
|
||||
void ParseZoneUnknownsA(QDataStream *aZoneFileStream);
|
||||
void ParseZoneUnknownsB(QDataStream *aZoneFileStream);
|
||||
void ParseZoneUnknownsC(QDataStream *aZoneFileStream);
|
||||
void ParseZoneTagCount(QDataStream *aZoneFileStream);
|
||||
void ParseZoneRecordCount(QDataStream *aZoneFileStream);
|
||||
void ParseZoneTags(QDataStream *aZoneFileStream);
|
||||
void ParseZoneIndex(QDataStream *aZoneFileStream);
|
||||
|
||||
void ParseAsset_LocalString(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_RawFile(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_PhysPreset(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_XModel(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_Material(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_PixelShader(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_TechSet(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_Image(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_LoadedSound(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_ColMapMP(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_GameMapSP(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_GameMapMP(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_LightDef(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_UIMap(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_AIType(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_FX(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_XAnim(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_StringTable(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_MenuFile(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_Weapon(QDataStream *aZoneFileStream);
|
||||
void ParseAsset_D3DBSP(QDataStream *aZoneFileStream);
|
||||
bool OpenZoneFile(const QString aZoneFilePath);
|
||||
bool OpenZoneFile();
|
||||
|
||||
int LoadFile_D3DBSP(const QString aFilePath);
|
||||
|
||||
void ScriptSelected();
|
||||
void StrTableSelected(QString aStrTableName);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
QMap<QString, int> mTypeMap;
|
||||
@ -139,6 +55,11 @@ private:
|
||||
QMap<QString, QTreeWidgetItem*> mTreeMap;
|
||||
QMap<QString, QVector<QPair<QString, QString>>> mStrTableMap;
|
||||
|
||||
QTreeWidget *mTreeWidget;
|
||||
QTreeWidgetItem *mRootItem;
|
||||
QPlainTextEdit *mScriptEditor;
|
||||
ModelViewer *mModelViewer;
|
||||
|
||||
quint32 mBSPVersion;
|
||||
quint32 mDiskLumpCount;
|
||||
QVector<quint32> mDiskLumpOrder;
|
||||
|
||||
1369
mainwindow.ui
73
modelviewer.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
#include "modelviewer.h"
|
||||
|
||||
ModelViewer::ModelViewer(QWidget *parent)
|
||||
: QWidget{parent} {
|
||||
Qt3DExtras::Qt3DWindow *view = new Qt3DExtras::Qt3DWindow();
|
||||
view->defaultFrameGraph()->setClearColor(QColor(QRgb(0x4d4d4f)));
|
||||
|
||||
QWidget *container = QWidget::createWindowContainer(view);
|
||||
QSize screenSize = view->screen()->size();
|
||||
container->setMinimumSize(QSize(200, 100));
|
||||
container->setMaximumSize(screenSize);
|
||||
|
||||
QHBoxLayout *hLayout = new QHBoxLayout(this);
|
||||
QVBoxLayout *vLayout = new QVBoxLayout();
|
||||
vLayout->setAlignment(Qt::AlignTop);
|
||||
hLayout->addWidget(container, 1);
|
||||
hLayout->addLayout(vLayout);
|
||||
|
||||
// Root entity
|
||||
Qt3DCore::QEntity *rootEntity = new Qt3DCore::QEntity();
|
||||
|
||||
// Camera
|
||||
Qt3DRender::QCamera *cameraEntity = view->camera();
|
||||
|
||||
cameraEntity->lens()->setPerspectiveProjection(45.0f, 16.0f/9.0f, 0.1f, 1000.0f);
|
||||
cameraEntity->setPosition(QVector3D(0, 0, 50.0f)); // Move farther along Z-axis
|
||||
cameraEntity->setUpVector(QVector3D(0, 1, 0));
|
||||
cameraEntity->setViewCenter(QVector3D(0, 0, 0));
|
||||
|
||||
Qt3DCore::QEntity *lightEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
Qt3DRender::QPointLight *light = new Qt3DRender::QPointLight(lightEntity);
|
||||
light->setColor("white");
|
||||
light->setIntensity(1);
|
||||
lightEntity->addComponent(light);
|
||||
|
||||
Qt3DCore::QTransform *lightTransform = new Qt3DCore::QTransform(lightEntity);
|
||||
lightTransform->setTranslation(cameraEntity->position());
|
||||
lightEntity->addComponent(lightTransform);
|
||||
|
||||
// For camera controls
|
||||
Qt3DExtras::QFirstPersonCameraController *camController = new Qt3DExtras::QFirstPersonCameraController(rootEntity);
|
||||
camController->setCamera(cameraEntity);
|
||||
|
||||
// Set root object of the scene
|
||||
view->setRootEntity(rootEntity);
|
||||
|
||||
// Load custom 3D model
|
||||
Qt3DRender::QMesh *customMesh = new Qt3DRender::QMesh();
|
||||
customMesh->setSource(QUrl::fromLocalFile(":/obj/data/obj/defaultactor_LOD0.obj"));
|
||||
|
||||
// Adjust the model transformation
|
||||
Qt3DCore::QTransform *customTransform = new Qt3DCore::QTransform();
|
||||
customTransform->setRotationX(-90);
|
||||
customTransform->setRotationY(-90);
|
||||
|
||||
// Keep translation if necessary
|
||||
customTransform->setTranslation(QVector3D(0.0f, -100.0f, -200.0f));
|
||||
|
||||
Qt3DExtras::QNormalDiffuseMapMaterial *customMaterial = new Qt3DExtras::QNormalDiffuseMapMaterial();
|
||||
|
||||
Qt3DRender::QTextureLoader *normalMap = new Qt3DRender::QTextureLoader();
|
||||
normalMap->setSource(QUrl::fromLocalFile(":/obj/data/obj/normalmap.png"));
|
||||
customMaterial->setNormal(normalMap);
|
||||
|
||||
Qt3DRender::QTextureLoader *diffuseMap = new Qt3DRender::QTextureLoader();
|
||||
diffuseMap->setSource(QUrl::fromLocalFile(":/obj/data/obj/diffusemap.png"));
|
||||
customMaterial->setDiffuse(diffuseMap);
|
||||
|
||||
Qt3DCore::QEntity *m_torusEntity = new Qt3DCore::QEntity(rootEntity);
|
||||
m_torusEntity->addComponent(customMesh);
|
||||
m_torusEntity->addComponent(customMaterial);
|
||||
m_torusEntity->addComponent(customTransform);
|
||||
}
|
||||
53
modelviewer.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef MODELVIEWER_H
|
||||
#define MODELVIEWER_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <QWidget>
|
||||
#include <QHBoxLayout>
|
||||
#include <QCheckBox>
|
||||
#include <QCommandLinkButton>
|
||||
#include <QScreen>
|
||||
#include <QHBoxLayout>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
// Qt3DCore includes
|
||||
#include <QEntity>
|
||||
#include <QTransform>
|
||||
#include <QAspectEngine>
|
||||
#include <qtransform.h>
|
||||
#include <qaspectengine.h>
|
||||
#include <qentity.h>
|
||||
// Qt3DInput includes
|
||||
#include <QInputAspect>
|
||||
// Qt3DRender includes
|
||||
#include <QRenderAspect>
|
||||
#include <QGeometryRenderer>
|
||||
#include <QCamera>
|
||||
#include <QCameraLens>
|
||||
#include <QMesh>
|
||||
#include <QTechnique>
|
||||
#include <QMaterial>
|
||||
#include <QEffect>
|
||||
#include <QTexture>
|
||||
#include <QRenderPass>
|
||||
#include <QSceneLoader>
|
||||
#include <QPointLight>
|
||||
// Qt3DExtras includes
|
||||
#include <Qt3DWindow>
|
||||
#include <QFirstPersonCameraController>
|
||||
#include <QNormalDiffuseMapMaterial>
|
||||
#include <QForwardRenderer>
|
||||
#include <QPhongMaterial>
|
||||
#include <QSphereMesh>
|
||||
#include <QTorusMesh>
|
||||
|
||||
class ModelViewer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ModelViewer(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
};
|
||||
|
||||
#endif // MODELVIEWER_H
|
||||
110
structs.h
@ -1,7 +1,12 @@
|
||||
#ifndef STRUCTS_H
|
||||
#define STRUCTS_H
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
|
||||
// Define Lump Structure
|
||||
struct Lump {
|
||||
@ -16,4 +21,109 @@ struct LumpIndexEntry {
|
||||
quint32 length;
|
||||
};
|
||||
|
||||
struct LocalString {
|
||||
QString string;
|
||||
QString alias;
|
||||
};
|
||||
|
||||
struct RawFile {
|
||||
quint32 length;
|
||||
QString path;
|
||||
QString contents;
|
||||
};
|
||||
|
||||
struct TechSet {
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct Animation {
|
||||
quint16 dataByteCount;
|
||||
quint16 dataShortCount;
|
||||
quint16 dataIntCount;
|
||||
quint16 randomDataByteCount;
|
||||
quint16 randomDataIntCount;
|
||||
quint16 numframes;
|
||||
bool isLooped;
|
||||
bool isDelta;
|
||||
quint8 noneRotatedBoneCount;
|
||||
quint8 twoDRotatedBoneCount;
|
||||
quint8 normalRotatedBoneCount;
|
||||
quint8 twoDStaticRotatedBoneCount;
|
||||
quint8 normalStaticRotatedBoneCount;
|
||||
quint8 normalTranslatedBoneCount;
|
||||
quint8 preciseTranslatedBoneCount;
|
||||
quint8 staticTranslatedBoneCount;
|
||||
quint8 noneTranslatedBoneCount;
|
||||
quint8 totalBoneCount;
|
||||
quint8 otherBoneCount1;
|
||||
quint8 otherBoneCount2;
|
||||
quint8 notifyCount;
|
||||
quint8 assetType;
|
||||
bool pad;
|
||||
unsigned int randomDataShortCount;
|
||||
unsigned int indexCount;
|
||||
float frameRate;
|
||||
float frequency;
|
||||
quint32 boneIDsPtr;
|
||||
quint32 dataBytePtr;
|
||||
quint32 dataShortPtr;
|
||||
quint32 dataIntPtr;
|
||||
quint32 randomDataShortPtr;
|
||||
quint32 randomDataBytePtr;
|
||||
quint32 randomDataIntPtr;
|
||||
quint32 longIndiciesPtr;
|
||||
quint32 notificationsPtr;
|
||||
quint32 deltaPartsPtr;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct StringTable {
|
||||
quint32 columnCount;
|
||||
quint32 rowCount;
|
||||
QString name;
|
||||
};
|
||||
|
||||
struct AssetMap {
|
||||
QVector<LocalString> localStrings;
|
||||
QVector<RawFile> rawFiles;
|
||||
//QVector<PhysPreset> phyPresets;
|
||||
//QVector<Model> models;
|
||||
//QVector<Material> rawFiles;
|
||||
//QVector<Shader> shaders;
|
||||
QVector<TechSet> techSets;
|
||||
//QVector<Image> images;
|
||||
//QVector<Sound> sounds;
|
||||
//QVector<CollisionMap> collMaps;
|
||||
//QVector<LightDefinition> lightDefs;
|
||||
//QVector<UiMap> uiMaps;
|
||||
//QVector<DriverGlobal> driverGlobals;
|
||||
//QVector<AiType> aiType;
|
||||
//QVector<Effect> effects;
|
||||
QVector<Animation> animations;
|
||||
QVector<StringTable> stringTables;
|
||||
//QVector<Menu> menus;
|
||||
//QVector<Weapon> weapons;
|
||||
//QVector<D3DBSP> d3dbspDumps;
|
||||
//QVector<SingleplayerMap> spMaps;
|
||||
};
|
||||
|
||||
struct ZoneFile {
|
||||
quint32 size;
|
||||
quint32 tagCount;
|
||||
QStringList tags;
|
||||
quint32 recordCount;
|
||||
QStringList records;
|
||||
AssetMap assetMap;
|
||||
};
|
||||
|
||||
struct FastFile {
|
||||
FF_COMPANY company;
|
||||
FF_FILETYPE fileType;
|
||||
FF_SIGNAGE signage;
|
||||
QString magic;
|
||||
quint32 version;
|
||||
|
||||
ZoneFile zoneFile;
|
||||
};
|
||||
|
||||
#endif // STRUCTS_H
|
||||
|
||||
65
utils.h
@ -5,6 +5,8 @@
|
||||
|
||||
#include <QString>
|
||||
#include <QtZlib/zlib.h>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
class Utils {
|
||||
public:
|
||||
@ -164,6 +166,69 @@ public:
|
||||
static quint32 PaddingSize(quint32 size) {
|
||||
return PadInt4(size) - size;
|
||||
}
|
||||
|
||||
static QString GetOpenFastFileName(QWidget *parent = nullptr) {
|
||||
// Open file dialog to steam apps
|
||||
const QString steamPath = "C:/Program Files (x86)/Steam/steamapps/common/Call of Duty World at War/zone/english/";
|
||||
const QString fastFilePath = QFileDialog::getOpenFileName(parent, "Open Fast File", steamPath, "Fast File (*.ff);;All Files (*.*)");
|
||||
if (fastFilePath.isNull()) {
|
||||
// User pressed cancel
|
||||
return "";
|
||||
} else if (!QFile::exists(fastFilePath)) {
|
||||
QMessageBox::warning(parent, "Warning!", QString("%1 does not exist!.").arg(fastFilePath));
|
||||
return "";
|
||||
}
|
||||
return fastFilePath;
|
||||
}
|
||||
|
||||
static QString GetOpenZoneFileName(QWidget *parent = nullptr) {
|
||||
// Open file dialog to steam apps
|
||||
const QString steamPath = "C:/Program Files (x86)/Steam/steamapps/common/Call of Duty World at War/zone/english/";
|
||||
const QString zoneFilePath = QFileDialog::getOpenFileName(parent, "Open Zone File", steamPath, "Zone File (*.zone);;All Files (*.*)");
|
||||
if (zoneFilePath.isNull()) {
|
||||
// User pressed cancel
|
||||
return "";
|
||||
} else if (!QFile::exists(zoneFilePath)) {
|
||||
QMessageBox::warning(parent, "Warning!", QString("%1 does not exist!.").arg(zoneFilePath));
|
||||
return nullptr;
|
||||
}
|
||||
return zoneFilePath;
|
||||
}
|
||||
|
||||
static QString CompanyEnumToStr(FF_COMPANY aCompany) {
|
||||
switch (aCompany) {
|
||||
case COMPANY_NONE:
|
||||
return "None";
|
||||
case COMPANY_INFINITY_WARD:
|
||||
return "Infinity Ward";
|
||||
case COMPANY_TREYARCH:
|
||||
return "Treyarch";
|
||||
case COMPANY_SLEDGEHAMMER:
|
||||
return "Sledgehammer";
|
||||
case COMPANY_NEVERSOFT:
|
||||
return "Neversoft";
|
||||
}
|
||||
}
|
||||
|
||||
static QString FileTypeEnumToStr(FF_FILETYPE aFileType) {
|
||||
switch (aFileType) {
|
||||
case FILETYPE_NONE:
|
||||
return "None";
|
||||
case FILETYPE_FAST_FILE:
|
||||
return "Fast File";
|
||||
}
|
||||
}
|
||||
|
||||
static QString SignageEnumToStr(FF_SIGNAGE aSignage) {
|
||||
switch (aSignage) {
|
||||
case SIGNAGE_NONE:
|
||||
return "None";
|
||||
case SIGNAGE_SIGNED:
|
||||
return "Signed";
|
||||
case SIGNAGE_UNSIGNED:
|
||||
return "Unsigned";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // UTILS_H
|
||||
|
||||
523
zfparser.h
Normal file
@ -0,0 +1,523 @@
|
||||
#ifndef ZFPARSER_H
|
||||
#define ZFPARSER_H
|
||||
|
||||
#include "qtypes.h"
|
||||
#include "utils.h"
|
||||
#include "structs.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
#include <QDataStream>
|
||||
|
||||
class ZoneFileParser {
|
||||
public:
|
||||
static ZoneFile ParseZoneHeader(QDataStream *aZoneFileStream) {
|
||||
ZoneFile result;
|
||||
|
||||
result.size = ParseZoneSize(aZoneFileStream);
|
||||
ParseZoneUnknownsA(aZoneFileStream);
|
||||
|
||||
result.tagCount = ParseZoneTagCount(aZoneFileStream);
|
||||
ParseZoneUnknownsB(aZoneFileStream);
|
||||
|
||||
result.recordCount = ParseZoneRecordCount(aZoneFileStream);
|
||||
|
||||
if (result.tagCount) {
|
||||
ParseZoneUnknownsC(aZoneFileStream);
|
||||
result.tags = ParseZoneTags(aZoneFileStream, result.tagCount);
|
||||
} else {
|
||||
aZoneFileStream->skipRawData(4);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static quint32 ParseZoneSize(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
|
||||
*/
|
||||
static void ParseZoneUnknownsA(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
|
||||
*/
|
||||
static quint32 ParseZoneTagCount(QDataStream *aZoneFileStream) {
|
||||
quint32 tagCount;
|
||||
*aZoneFileStream >> tagCount;
|
||||
return tagCount;
|
||||
}
|
||||
|
||||
/*
|
||||
ParseZoneRecordCount()
|
||||
|
||||
Parses the number of records in the zone index
|
||||
*/
|
||||
static quint32 ParseZoneRecordCount(QDataStream *aZoneFileStream) {
|
||||
quint32 recordCount;
|
||||
*aZoneFileStream >> recordCount;
|
||||
return recordCount;
|
||||
}
|
||||
|
||||
/*
|
||||
ParseZoneUnknownsB()
|
||||
|
||||
Parses the 2nd section of unknowns as hex vals and uint32s
|
||||
*/
|
||||
static void ParseZoneUnknownsB(QDataStream *aZoneFileStream) {
|
||||
// Byte 44-47: Unknown/empty?
|
||||
QByteArray unknown9(4, Qt::Uninitialized);
|
||||
aZoneFileStream->readRawData(unknown9.data(), 4);
|
||||
}
|
||||
|
||||
/*
|
||||
ParseZoneUnknownsC()
|
||||
|
||||
Parses the 3rd section of unknowns as hex vals and uint32s
|
||||
*/
|
||||
static void ParseZoneUnknownsC(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
|
||||
*/
|
||||
static QStringList ParseZoneTags(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;
|
||||
}
|
||||
tags << zoneTag;
|
||||
zoneTag.clear();
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
/*
|
||||
ParseZoneIndex()
|
||||
|
||||
Parse the binary zone index data and populate table
|
||||
*/
|
||||
static QStringList ParseZoneIndex(QDataStream *aZoneFileStream, quint32 recordCount) {
|
||||
QStringList result;
|
||||
|
||||
// Don't parse if no records
|
||||
if (!recordCount) { return result; }
|
||||
|
||||
// Track past assets and counts
|
||||
QString lastAssetType = "";
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
static AssetMap ParseAssets(QDataStream *aZoneFileStream, QStringList assetOrder) {
|
||||
AssetMap result;
|
||||
|
||||
for (int i = 0; i < assetOrder.size(); i++) {
|
||||
const QString typeHex = assetOrder[i];
|
||||
const QString typeStr = Utils::AssetTypeToString(typeHex);
|
||||
|
||||
if (typeStr == "LOCAL STRING") { // localized string asset
|
||||
result.localStrings << ParseAsset_LocalString(aZoneFileStream);
|
||||
} else if (typeStr == "RAW FILE") { // gsc
|
||||
result.rawFiles << ParseAsset_RawFile(aZoneFileStream);
|
||||
} else if (typeStr == "PHYS PRESET") { // physpreset
|
||||
ParseAsset_PhysPreset(aZoneFileStream);
|
||||
} else if (typeStr == "MODEL") { // xmodel
|
||||
ParseAsset_Model(aZoneFileStream);
|
||||
} else if (typeStr == "MATERIAL") { // material
|
||||
ParseAsset_Material(aZoneFileStream);
|
||||
} else if (typeStr == "SHADER") { // pixelshader
|
||||
ParseAsset_PixelShader(aZoneFileStream);
|
||||
} else if (typeStr == "TECH SET") { // techset include
|
||||
result.techSets << ParseAsset_TechSet(aZoneFileStream);
|
||||
} else if (typeStr == "IMAGE") { // image
|
||||
ParseAsset_Image(aZoneFileStream);
|
||||
} else if (typeStr == "SOUND") { // loaded_sound
|
||||
ParseAsset_LoadedSound(aZoneFileStream);
|
||||
} else if (typeStr == "COLLISION MAP") { // col_map_mp
|
||||
ParseAsset_ColMapMP(aZoneFileStream);
|
||||
} else if (typeStr == "MP MAP") { // game_map_sp
|
||||
ParseAsset_GameMapSP(aZoneFileStream);
|
||||
} else if (typeStr == "SP MAP") { // game_map_mp
|
||||
ParseAsset_GameMapMP(aZoneFileStream);
|
||||
} else if (typeStr == "LIGHT DEF") { // lightdef
|
||||
ParseAsset_LightDef(aZoneFileStream);
|
||||
} else if (typeStr == "UI MAP") { // ui_map
|
||||
ParseAsset_UIMap(aZoneFileStream);
|
||||
} else if (typeStr == "SND DRIVER GLOBALS") { // snddriverglobals
|
||||
ParseAsset_SNDDriverGlobals(aZoneFileStream);
|
||||
} else if (typeStr == "AI TYPE") { // aitype
|
||||
ParseAsset_AIType(aZoneFileStream);
|
||||
} else if (typeStr == "EFFECT") { // aitype
|
||||
ParseAsset_FX(aZoneFileStream);
|
||||
} else if (typeStr == "ANIMATION") { // aitype
|
||||
result.animations << ParseAsset_Animation(aZoneFileStream);
|
||||
} else if (typeStr == "STRING TABLE") { // string_table
|
||||
result.stringTables << ParseAsset_StringTable(aZoneFileStream);
|
||||
} else if (typeStr == "MENU") { // string_table
|
||||
ParseAsset_MenuFile(aZoneFileStream);
|
||||
} else if (typeStr == "WEAPON") { // string_table
|
||||
ParseAsset_Weapon(aZoneFileStream);
|
||||
} else if (typeStr == "D3DBSP DUMP") { // string_table
|
||||
ParseAsset_D3DBSP(aZoneFileStream);
|
||||
} else if (typeStr != "UNKNOWN") {
|
||||
qDebug() << "Found bad asset type!" << typeStr;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static LocalString ParseAsset_LocalString(QDataStream *aZoneFileStream) {
|
||||
LocalString result;
|
||||
|
||||
// Skip separator
|
||||
aZoneFileStream->skipRawData(8);
|
||||
|
||||
// Parse local string asset contents
|
||||
QString localStr;
|
||||
char localStrChar;
|
||||
*aZoneFileStream >> localStrChar;
|
||||
while (localStrChar != 0) {
|
||||
result.string += localStrChar;
|
||||
*aZoneFileStream >> localStrChar;
|
||||
}
|
||||
|
||||
// Parse rawfile name
|
||||
QString aliasName;
|
||||
char aliasNameChar;
|
||||
*aZoneFileStream >> aliasNameChar;
|
||||
while (aliasNameChar != 0) {
|
||||
result.alias += aliasNameChar;
|
||||
*aZoneFileStream >> aliasNameChar;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static RawFile ParseAsset_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;
|
||||
}
|
||||
|
||||
static void ParseAsset_PhysPreset(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_Model(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_Material(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_PixelShader(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static TechSet ParseAsset_TechSet(QDataStream *aZoneFileStream) {
|
||||
TechSet result;
|
||||
|
||||
aZoneFileStream->skipRawData(4);
|
||||
// Parse techset name
|
||||
char techSetNameChar;
|
||||
*aZoneFileStream >> techSetNameChar;
|
||||
while (techSetNameChar == 0) {
|
||||
*aZoneFileStream >> techSetNameChar;
|
||||
}
|
||||
while (techSetNameChar != 0) {
|
||||
result.name += techSetNameChar;
|
||||
*aZoneFileStream >> techSetNameChar;
|
||||
}
|
||||
result.name.replace(",", "");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void ParseAsset_Image(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_LoadedSound(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_ColMapMP(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_GameMapSP(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_GameMapMP(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_LightDef(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_UIMap(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_SNDDriverGlobals(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_AIType(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_FX(QDataStream *aZoneFileStream) {
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static Animation ParseAsset_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.twoDStaticRotatedBoneCount
|
||||
>> result.normalStaticRotatedBoneCount
|
||||
>> 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<quint8> 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;
|
||||
}
|
||||
|
||||
static void ParseAsset_MenuFile(QDataStream *aZoneFileStream) {
|
||||
//MENU_FILE
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_Weapon(QDataStream *aZoneFileStream) {
|
||||
//WEAPON_FILE
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static void ParseAsset_D3DBSP(QDataStream *aZoneFileStream) {
|
||||
//D3DBSP_DUMP
|
||||
Q_UNUSED(aZoneFileStream);
|
||||
}
|
||||
|
||||
static StringTable ParseAsset_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;
|
||||
}
|
||||
|
||||
QVector<QString> tablePointers = QVector<QString>();
|
||||
for (quint32 i = 0; i < result.rowCount; i++) {
|
||||
QByteArray pointerData(4, Qt::Uninitialized);
|
||||
aZoneFileStream->readRawData(pointerData.data(), 4);
|
||||
tablePointers.push_back(pointerData.toHex());
|
||||
|
||||
aZoneFileStream->skipRawData(4);
|
||||
}
|
||||
|
||||
for (const QString &pointerAddr : 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;
|
||||
}
|
||||
QPair<QString, QString> tableEntry = QPair<QString, QString>();
|
||||
tableEntry.first = leadingContent;
|
||||
tableEntry.second = content;
|
||||
//if (!mStrTableMap.contains(stringTableName)) {
|
||||
// mStrTableMap[stringTableName] = QVector<QPair<QString, QString>>();
|
||||
//}
|
||||
//mStrTableMap[stringTableName].push_back(tableEntry);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // ZFPARSER_H
|
||||