XPlor/mainwindow.cpp

1403 lines
54 KiB
C++
Raw Normal View History

2025-01-09 17:54:44 -05:00
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow) {
ui->setupUi(this);
mTypeMap = QMap<ASSET_TYPE, int>();
2025-01-09 17:54:44 -05:00
mTypeOrder = QStringList();
mRawFileMap = QMap<QString, QString>();
mTreeMap = QMap<QString, QTreeWidgetItem*>();
mStrTableMap = QMap<QString, QVector<QPair<QString, QString>>>();
mBSPVersion = 0;
mDiskLumpCount = 0;
mDiskLumpOrder = QVector<quint32>();
mLumps = QMap<quint32, Lump>();
2025-01-10 04:35:03 -05:00
mRecentFiles = QQueue<QString>();
mSettingsValid = false;
mRecentFileActions = QVector<QAction*>();
const QString appSettingsPath = QDir::currentPath() + "/appSettings.ini";
QSettings appSettings(appSettingsPath, QSettings::IniFormat);
if (appSettings.contains("mRecentFiles")) {
mSettingsValid = true;
QStringList recentFiles = appSettings.value("mRecentFiles").toStringList();
foreach (QString recentFile, recentFiles) {
mRecentFiles.enqueue(recentFile);
}
}
2025-01-09 17:54:44 -05:00
connect(ui->treeWidget_Scripts, &QTreeWidget::itemSelectionChanged, this, &MainWindow::ScriptSelected);
connect(ui->comboBox_StringTable, &QComboBox::currentTextChanged, this, &MainWindow::StrTableSelected);
// Initialize Asset Index Table
ui->tableWidget_Index->setColumnCount(3);
ui->tableWidget_Index->setHorizontalHeaderLabels({"Asset Type", "Asset Name", "Asset Count"});
ui->tableWidget_Index->verticalHeader()->setVisible(false);
ui->tableWidget_Index->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget_Index->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget_Index->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget_Index->setShowGrid(false);
ui->tableWidget_Index->setStyleSheet("QTableView {selection-background-color: red;}");
// Initialize Asset Order Table
ui->tableWidget_Order->setColumnCount(3);
ui->tableWidget_Order->setHorizontalHeaderLabels({"Asset Type", "Asset Name", "Asset Count"});
ui->tableWidget_Order->verticalHeader()->setVisible(false);
ui->tableWidget_Order->setEditTriggers(QAbstractItemView::NoEditTriggers);
ui->tableWidget_Order->setSelectionBehavior(QAbstractItemView::SelectRows);
ui->tableWidget_Order->setSelectionMode(QAbstractItemView::SingleSelection);
ui->tableWidget_Order->setShowGrid(false);
ui->tableWidget_Order->setStyleSheet("QTableView {selection-background-color: red;}");
2025-01-10 04:35:45 -05:00
ui->treeWidget_Menus->setHeaderLabels({"Components", "Description"});
ui->treeWidget_Menus->setColumnWidth(0, width() / 4 * 3); // Name column
2025-01-09 17:54:44 -05:00
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(ui->frame_Scene);
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);
LoadFile_D3DBSP(":/d3dbsp/data/d3dbsp/barebones.d3dbsp");
Reset();
}
MainWindow::~MainWindow() {
2025-01-10 04:35:03 -05:00
const QString appSettingsPath = QDir::currentPath() + "/appSettings.ini";
QSettings appSettings(appSettingsPath, QSettings::IniFormat);
appSettings.setValue("mRecentFiles", mRecentFiles.toList());
2025-01-09 17:54:44 -05:00
delete ui;
}
void MainWindow::Reset() {
// Reset tabwidget to 'General' tab
ui->tabWidget->setCurrentIndex(0);
// Reset 'General' tab fields
ui->lineEdit_FastFile->clear();
ui->comboBox_Company->setCurrentIndex(0);
ui->comboBox_FileType->setCurrentIndex(0);
ui->checkBox_Signed->setChecked(false);
ui->lineEdit_Magic->clear();
ui->spinBox_Magic->clear();
ui->spinBox_TagCount->clear();
ui->spinBox_FileSize->clear();
ui->spinBox_RecordCount->clear();
// Reset 'Unknowns' tab fields
ui->lineEdit_U1->clear();
ui->spinBox_U1->clear();
ui->lineEdit_U2->clear();
ui->spinBox_U2->clear();
ui->lineEdit_U3->clear();
ui->spinBox_U3->clear();
ui->lineEdit_U4->clear();
ui->spinBox_U4->clear();
ui->lineEdit_U5->clear();
ui->spinBox_U5->clear();
ui->lineEdit_U6->clear();
ui->spinBox_U6->clear();
ui->lineEdit_U7->clear();
ui->spinBox_U7->clear();
ui->lineEdit_U8->clear();
ui->spinBox_U8->clear();
ui->lineEdit_U9->clear();
ui->spinBox_U9->clear();
ui->lineEdit_U10->clear();
ui->spinBox_U10->clear();
ui->lineEdit_U11->clear();
ui->spinBox_U11->clear();
// Reset 'Tags' tab fields
ui->listWidget_Tags->clear();
// Reset 'Localized Strings' tab fields
ui->listWidget_LocalString->clear();
// Reset 'Asset Index/Order' tab fields
ui->tableWidget_Index->clear();
ui->tableWidget_Order->clear();
// Reset 'Raw Files' tab fields
ui->treeWidget_Scripts->clear();
ui->plainTextEdit_Scripts->clear();
// Reset 'Tech Sets' tab fields
ui->listWidget_TechSets->clear();
// Reset 'Zone Dump' tab fields
ui->spinBox_DumpIndex->clear();
ui->comboBox_DumpAsset->setCurrentIndex(0);
ui->plainTextEdit_ZoneDump->clear();
// Reset 'String Tables' tab fields
ui->comboBox_StringTable->setCurrentIndex(0);
ui->tableWidget_StringTable->clear();
// Reset '3D Scene' tab fields
ui->treeWidget_Models->clear();
// Reset class vars
mTypeMap.clear();
mTypeOrder.clear();
mTagCount = 0;
mRecordCount = 0;
mRawFileMap.clear();
mTreeMap.clear();
mStrTableMap.clear();
2025-01-10 04:35:03 -05:00
// Refresh recent files
RefreshRecentFileMenu();
2025-01-09 17:54:44 -05:00
}
void MainWindow::StrTableSelected(QString aStrTableName) {
ui->tableWidget_StringTable->clear();
ui->tableWidget_StringTable->setColumnCount(2);
int entryIndex = 0;
for (auto strTableEntry : mStrTableMap[aStrTableName]) {
ui->tableWidget_StringTable->insertRow(ui->tableWidget_StringTable->rowCount() + 1);
ui->tableWidget_StringTable->setItem(entryIndex, 0, new QTableWidgetItem(strTableEntry.first));
ui->tableWidget_StringTable->setItem(entryIndex, 1, new QTableWidgetItem(strTableEntry.second));
2025-01-09 17:54:44 -05:00
entryIndex++;
}
}
void MainWindow::ScriptSelected() {
QTreeWidgetItem *selectedItem = ui->treeWidget_Scripts->selectedItems()[0];
if (!selectedItem) {
qDebug() << "Attempted to load invalid tree item!";
return;
}
const QString itemName = selectedItem->text(0);
const QStringList scriptExts = {"gsc", "csc", "atr", "shock", "vision", "rmb"};
if (!scriptExts.contains(itemName.split('.').last())) {
qDebug() << QString("Attempted to parse invalid raw file: %1!").arg(itemName);
return;
}
ui->plainTextEdit_Scripts->clear();
for (auto [scriptName, scriptContents] : mRawFileMap.asKeyValueRange()) {
if (scriptName.contains(itemName)) {
ui->plainTextEdit_Scripts->setPlainText(scriptContents);
return;
}
}
}
QByteArray MainWindow::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;
}
/*
GetFastFilePath()
2025-01-09 17:54:44 -05:00
Opens a file dialog in the steam folder,
and opens the selected file.
*/
QString MainWindow::GetFastFilePath() {
2025-01-09 17:54:44 -05:00
// Reset dialog before opening new file
Reset();
// 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(this, "Open FastFile", steamPath, "FastFile (*.ff);;All Files (*.*)");
if (!QFile::exists(fastFilePath)) {
QMessageBox::warning(this, "Warning!", QString("%1 does not exist!.").arg(fastFilePath));
return nullptr;
}
ui->lineEdit_FastFile->setText(fastFilePath);
const QString fastFileStem = fastFilePath.split('/').last();
setWindowTitle(QString("FastFile Wizard - %1").arg(fastFileStem));
return fastFilePath;
2025-01-09 17:54:44 -05:00
}
/*
GetZoneFilePath()
2025-01-09 17:54:44 -05:00
Opens a file dialog in the steam folder,
and opens the selected file.
*/
QString MainWindow::GetZoneFilePath() {
2025-01-09 17:54:44 -05:00
// Reset dialog before opening new file
Reset();
// 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(this, "Open ZoneFile", steamPath, "ZoneFile (*.zone);;All Files (*.*)");
if (!QFile::exists(zoneFilePath)) {
QMessageBox::warning(this, "Warning!", QString("%1 does not exist!.").arg(zoneFilePath));
return nullptr;
}
ui->lineEdit_ZoneFile->setText(zoneFilePath);
const QString zoneFileStem = zoneFilePath.split('/').last();
setWindowTitle(QString("FastFile Wizard - %1").arg(zoneFileStem));
return zoneFilePath;
}
QByteArray MainWindow::OpenFastFile(QString aFastFilePath)
{
Reset();
2025-01-09 17:54:44 -05:00
// Check fastfile can be read
QFile *fastFile = new QFile(aFastFilePath);
qDebug() << aFastFilePath;
if (!fastFile->open(QIODevice::ReadOnly)) {
QMessageBox::warning(this, "Warning!", QString("FastFile '%1' could not be read!.").arg(fastFile->fileName()));
return QByteArray();
}
LogOpenedFile(fastFile->fileName());
ui->lineEdit_FastFile->setText(fastFile->fileName());
// Decompress fastfile and close
const QByteArray fastFileData = fastFile->readAll();
// Parse data from fast file header
ParseFFHeader(fastFileData.mid(0, 12));
fastFile->close();
// Decompress fastfile and close
const QByteArray decompressedData = DecompressZLIB(fastFileData.mid(12));
// ui->plainTextEdit_ZoneDump->setPlainText(decompressedData.toHex());
const QString zoneFilePath = aFastFilePath.replace(".ff", ".zone");
ui->lineEdit_ZoneFile->setText(zoneFilePath);
// Open zone file
OpenZoneFile(zoneFilePath);
// Clean up & return
delete fastFile;
return fastFileData;
}
QByteArray MainWindow::OpenZoneFile(QString aZoneFilePath)
{
Reset();
// Check zone file is writeable
QFile *zoneFile = new QFile(aZoneFilePath);
2025-01-09 17:54:44 -05:00
if (!zoneFile->open(QIODevice::ReadOnly)) {
QMessageBox::warning(this, "Warning!", QString("ZoneFile '%1' could not be read!.").arg(zoneFile->fileName()));
return QByteArray();
2025-01-09 17:54:44 -05:00
}
LogOpenedFile(zoneFile->fileName());
ui->lineEdit_ZoneFile->setText(zoneFile->fileName());
// Parse & close zone file
QByteArray zoneFileData = zoneFile->readAll();
ParseZoneFile(zoneFileData);
zoneFile->close();
// Check if corresponding zone file exists
const QString fastFilePath = zoneFile->fileName().replace(".zone", ".ff");
if (QFile::exists(fastFilePath)) {
ui->lineEdit_FastFile->setText(fastFilePath);
LogOpenedFile(fastFilePath);
}
// Clean up & return
delete zoneFile;
return zoneFileData;
2025-01-09 17:54:44 -05:00
}
void MainWindow::ParseFFCompany(QDataStream *afastFileStream) {
// Check for null datastream ptr
if (!afastFileStream) { return; }
// Parse company
QByteArray companyData(2, Qt::Uninitialized);
afastFileStream->readRawData(companyData.data(), 2);
if (companyData == "IW") {
qDebug() << "Company found: 'INFINITY_WARD'";
ui->comboBox_Company->setCurrentIndex(1);
} else if (companyData == "TA") {
qDebug() << "Company found: 'TREYARCH'";
ui->comboBox_Company->setCurrentIndex(2);
} else if (companyData == "Sl") {
qDebug() << "Company found: 'SLEDGEHAMMER'";
ui->comboBox_Company->setCurrentIndex(3);
} else if (companyData == "NX") {
qDebug() << "Company found: 'NEVERSOFT'";
ui->comboBox_Company->setCurrentIndex(4);
} else {
qDebug() << QString("Failed to find company, found '%1'!").arg(companyData);
return;
}
}
void MainWindow::ParseFFFileType(QDataStream *afastFileStream) {
// Parse filetype
QByteArray fileTypeData(2, Qt::Uninitialized);
afastFileStream->readRawData(fileTypeData.data(), 2);
if (fileTypeData == "ff") {
qDebug() << "File type found: 'FAST_FILE'";
ui->comboBox_FileType->setCurrentIndex(1);
} else {
qDebug() << "Failed to find file type!";
return;
}
}
void MainWindow::ParseFFSignage(QDataStream *afastFileStream) {
// Parse filetype
QByteArray signedData(1, Qt::Uninitialized);
afastFileStream->readRawData(signedData.data(), 1);
if (signedData == "u") {
qDebug() << "Found valid signage: Unsigned";
ui->checkBox_Signed->setChecked(false);
} else if (signedData == "0") {
qDebug() << "Found valid signage: Signed";
ui->checkBox_Signed->setChecked(true);
} else {
qDebug() << "Failed to determine signage of fastfile!";
return;
}
}
void MainWindow::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);
ui->lineEdit_Magic->setText(magicData.toHex());
ui->spinBox_Magic->setValue(magicData.toInt());
} else {
qDebug() << "Magic invalid!";
return;
}
}
void MainWindow::ParseFFVersion(QDataStream *afastFileStream) {
// Parse version
quint32 version;
*afastFileStream >> version;
qDebug() << "Version:" << version;
if (version == 387) {
qDebug() << QString("Found valid version: '%1'").arg(version);
ui->spinBox_Version->setValue(version);
} else {
qDebug() << "Version invalid!";
return;
}
}
void MainWindow::ParseFFHeader(QByteArray aFastFileData) {
2025-01-09 17:54:44 -05:00
// Open stream to fastfile
QDataStream afastFileStream(aFastFileData);
2025-01-09 17:54:44 -05:00
afastFileStream.setByteOrder(QDataStream::LittleEndian);
ParseFFCompany(&afastFileStream);
ParseFFFileType(&afastFileStream);
ParseFFSignage(&afastFileStream);
ParseFFMagic(&afastFileStream);
ParseFFVersion(&afastFileStream);
}
void MainWindow::ParseAsset_Localize(QDataStream *aZoneFileStream) {
Localize localize;
*aZoneFileStream >> localize;
2025-01-09 17:54:44 -05:00
ui->listWidget_LocalString->addItem(QString("%1 = %2").arg(localize.referenceStr).arg(localize.localizedStr));
2025-01-09 17:54:44 -05:00
}
void MainWindow::ParseAsset_RawFile(QDataStream *aZoneFileStream) {
RawFile rawFile;
*aZoneFileStream >> rawFile;
2025-01-09 17:54:44 -05:00
QString rawFilePath = rawFile.rawFilePath;
2025-01-09 17:54:44 -05:00
rawFilePath.replace(",", "");
const QStringList pathParts = rawFilePath.split('/');
if (pathParts.size() == 0) {
qDebug() << "Failed to parse ff path! " << rawFilePath;
exit(-1);
} else if (pathParts.size() == 1) {
const QString path = pathParts[0];
QTreeWidgetItem *newRootItem = new QTreeWidgetItem(ui->treeWidget_Scripts);
newRootItem->setText(0, path);
} else {
const QString path = pathParts[0];
QTreeWidgetItem *newRootItem;
if (mTreeMap.contains(path)) {
newRootItem = mTreeMap[path];
} else {
newRootItem = new QTreeWidgetItem(ui->treeWidget_Scripts);
newRootItem->setText(0, path);
mTreeMap[path] = newRootItem;
}
QTreeWidgetItem *parentItem = newRootItem;
for (int i = 1; i < pathParts.size(); i++) {
const QString path = pathParts[i];
QTreeWidgetItem *newChildItem;
if (mTreeMap.contains(path)) {
newChildItem = mTreeMap[path];
} else {
newChildItem = new QTreeWidgetItem();
newChildItem->setText(0, path);
mTreeMap[path] = newChildItem;
}
parentItem->addChild(newChildItem);
parentItem = newChildItem;
}
}
mRawFileMap[rawFilePath] = (rawFile.rawFileContents.isEmpty()) ? ("EMPTY") : (rawFile.rawFileContents);
2025-01-09 17:54:44 -05:00
}
void MainWindow::ParseAsset_XModel(QDataStream *aZoneFileStream) {
}
void MainWindow::ParseAsset_Material(QDataStream *aZoneFileStream) {
}
void MainWindow::ParseAsset_PixelShader(QDataStream *aZoneFileStream) {
}
void MainWindow::ParseAsset_TechSet(QDataStream *aZoneFileStream) {
aZoneFileStream->skipRawData(4);
// Parse techset name
QString techSetName;
char techSetNameChar;
*aZoneFileStream >> techSetNameChar;
while (techSetNameChar == 0) {
*aZoneFileStream >> techSetNameChar;
}
while (techSetNameChar != 0) {
techSetName += techSetNameChar;
*aZoneFileStream >> techSetNameChar;
}
techSetName.replace(",", "");
ui->listWidget_TechSets->addItem(techSetName);
//qDebug() << "Tech Set: " << techSetName;
}
void MainWindow::ParseAsset_LoadedSound(QDataStream *aZoneFileStream) {
}
void MainWindow::ParseAsset_ColMapMP(QDataStream *aZoneFileStream) {
}
void MainWindow::ParseAsset_FX(QDataStream *aZoneFileStream) {
2025-01-09 17:54:44 -05:00
}
void MainWindow::ParseAsset_Font(QDataStream *aZoneFileStream) {
2025-01-09 17:54:44 -05:00
}
void MainWindow::ParseAsset_XAnim(QDataStream *aZoneFileStream) {
// Read in pointer to x_anim name
QByteArray namePtr(4, Qt::Uninitialized);
aZoneFileStream->readRawData(namePtr.data(), 4);
// Read in counts
quint16 dataByteCount, dataShortCount,
dataIntCount, randomDataByteCount,
randomDataIntCount, numframes;
*aZoneFileStream >> dataByteCount >> dataShortCount >>
dataIntCount >> randomDataByteCount >>
randomDataIntCount >> numframes;
// Read bool flags
bool isLooped, isDelta;
*aZoneFileStream >> isLooped >> isDelta;
// Read in more counts
quint8 noneRotatedBoneCount,
twoDRotatedBoneCount, normalRotatedBoneCount,
twoDStaticRotatedBoneCount, normalStaticRotatedBoneCount,
normalTranslatedBoneCount, preciseTranslatedBoneCount,
staticTranslatedBoneCount, noneTranslatedBoneCount,
totalBoneCount, otherBoneCount1, otherBoneCount2;
*aZoneFileStream >> noneRotatedBoneCount >>
twoDRotatedBoneCount >> normalRotatedBoneCount >>
twoDStaticRotatedBoneCount >> normalStaticRotatedBoneCount >>
normalTranslatedBoneCount >> preciseTranslatedBoneCount >>
staticTranslatedBoneCount >> noneTranslatedBoneCount >>
totalBoneCount >> otherBoneCount1 >> otherBoneCount2;
// Yet more counts
quint8 notifyCount, assetType;
*aZoneFileStream >> notifyCount >> assetType;
// Read more bool flags
bool pad;
*aZoneFileStream >> pad;
// Yet more more counts
unsigned int randomDataShortCount, indexCount;
*aZoneFileStream >> randomDataShortCount >> indexCount;
// Read in floats
float frameRate, frequency;
*aZoneFileStream >> frameRate >> frequency;
// Read in pointers
quint32 boneIDsPtr, dataBytePtr, dataShortPtr, dataIntPtr,
randomDataShortPtr, randomDataBytePtr, randomDataIntPtr,
longIndiciesPtr, notificationsPtr, deltaPartsPtr;
*aZoneFileStream >> boneIDsPtr >> dataBytePtr >> dataShortPtr
>> dataIntPtr >> randomDataShortPtr >> randomDataBytePtr
>> randomDataIntPtr >> longIndiciesPtr >> notificationsPtr
>> deltaPartsPtr;
// Read in x_anim file name
QString xAnimName;
char xAnimNameChar;
*aZoneFileStream >> xAnimNameChar;
while (xAnimNameChar != 0) {
xAnimName += xAnimNameChar;
*aZoneFileStream >> xAnimNameChar;
}
// Parse x_anim index header
QVector<quint8> sectionLengths;
for (int i = 0; i < numframes; i++) {
quint8 sectionlength;
*aZoneFileStream >> sectionlength;
sectionLengths.push_back(sectionlength);
// Skip padding
aZoneFileStream->skipRawData(1);
}
// Skip unknown section
aZoneFileStream->skipRawData(2 * 8);
}
void MainWindow::ParseAsset_MenuFile(QDataStream *aZoneFileStream) {
//MENU_FILE
2025-01-10 04:35:45 -05:00
aZoneFileStream->skipRawData(4); // Separator
// Parse menu def count
quint32 menuDefCount;
*aZoneFileStream >> menuDefCount;
if (menuDefCount > 1000) { return; }
for (int i = 0; i < menuDefCount; i++) {
aZoneFileStream->skipRawData(4); // Separator
// Read in x_anim file name
QString menuFilepath;
char menuFilepathChar;
*aZoneFileStream >> menuFilepathChar;
while (menuFilepathChar != 0) {
menuFilepath += menuFilepathChar;
*aZoneFileStream >> menuFilepathChar;
}
qDebug() << "Parsing " << menuFilepath;
QTreeWidgetItem *menuFilePathNode = new QTreeWidgetItem(ui->treeWidget_Menus);
aZoneFileStream->skipRawData(4); // Separator
QByteArray menuNamePtr(4, Qt::Uninitialized);
aZoneFileStream->readRawData(menuNamePtr.data(), 4);
QTreeWidgetItem *menuNamePtrNode = new QTreeWidgetItem(menuFilePathNode);
menuNamePtrNode->setText(0, QString("Menu name ptr: %1").arg(menuNamePtr.toHex().toUpper()));
QTreeWidgetItem *menuRectNode = new QTreeWidgetItem(menuFilePathNode);
menuRectNode->setText(0, "Menu Rect");
float menuRectX, menuRectY, menuRectWidth, menuRectHeight;
*aZoneFileStream >> menuRectX >> menuRectY >> menuRectWidth >> menuRectHeight;
QTreeWidgetItem *menuRectXNode = new QTreeWidgetItem(menuRectNode);
menuRectXNode->setText(0, QString("X: %1").arg(menuRectX));
QTreeWidgetItem *menuRectYNode = new QTreeWidgetItem(menuRectNode);
menuRectYNode->setText(0, QString("Y: %1").arg(menuRectY));
QTreeWidgetItem *menuRectWidthNode = new QTreeWidgetItem(menuRectNode);
menuRectWidthNode->setText(0, QString("Width: %1").arg(menuRectWidth));
QTreeWidgetItem *menuRectHeightNode = new QTreeWidgetItem(menuRectNode);
menuRectHeightNode->setText(0, QString("Height: %1").arg(menuRectHeight));
MENU_H_ALIGNMENT hAlign;
*aZoneFileStream >> hAlign;
QTreeWidgetItem *hAlignNode = new QTreeWidgetItem(menuRectNode);
QString hAlignStr = Utils::MenuHAlignToStr(hAlign);
hAlignNode->setText(0, QString("Horiz. Align: %1").arg(hAlignStr));
MENU_V_ALIGNMENT vAlign;
*aZoneFileStream >> vAlign;
QTreeWidgetItem *vAlignNode = new QTreeWidgetItem(menuRectNode);
QString vAlignStr = Utils::MenuVAlignToStr(vAlign);
vAlignNode->setText(0, QString("Vert. Align: %1").arg(vAlignStr));
float rectClientX, rectClientY, rectClientWidth, rectClientHeight;
*aZoneFileStream >> rectClientX >> rectClientY >> rectClientWidth >> rectClientHeight;
QTreeWidgetItem *menuRectClientNode = new QTreeWidgetItem(menuFilePathNode);
menuRectClientNode->setText(0, "Menu Client Rect");
QTreeWidgetItem *menuRectClientXNode = new QTreeWidgetItem(menuRectClientNode);
menuRectClientXNode->setText(0, QString("X: %1").arg(rectClientX));
QTreeWidgetItem *menuRectClientYNode = new QTreeWidgetItem(menuRectClientNode);
menuRectClientYNode->setText(0, QString("Y: %1").arg(rectClientY));
QTreeWidgetItem *menuRectClientWidthNode = new QTreeWidgetItem(menuRectClientNode);
menuRectClientWidthNode->setText(0, QString("Width: %1").arg(rectClientWidth));
QTreeWidgetItem *menuRectClientHeightNode = new QTreeWidgetItem(menuRectClientNode);
menuRectClientHeightNode->setText(0, QString("Height: %1").arg(rectClientHeight));
// Client horizontal alignment
MENU_H_ALIGNMENT hClientAlign;
*aZoneFileStream >> hClientAlign;
QTreeWidgetItem *hClientAlignNode = new QTreeWidgetItem(menuRectClientNode);
QString hClientAlignStr = Utils::MenuHAlignToStr(hAlign);
hClientAlignNode->setText(0, QString("Horiz. Align: %1").arg(hClientAlignStr));
// Client vertical alignment
MENU_V_ALIGNMENT vClientAlign;
*aZoneFileStream >> vClientAlign;
QTreeWidgetItem *vClientAlignNode = new QTreeWidgetItem(menuRectClientNode);
QString vClientAlignStr = Utils::MenuVAlignToStr(vAlign);
vClientAlignNode->setText(0, QString("Vert. Align: %1").arg(vClientAlignStr));
quint32 groupPtr; // Should be const char *
*aZoneFileStream >> groupPtr;
MENU_WINDOW_STYLE style;
*aZoneFileStream >> style;
MENU_WINDOW_BORDER border;
*aZoneFileStream >> border;
quint32 ownerDraw, ownerDrawFlags;
*aZoneFileStream >> ownerDraw >> ownerDrawFlags;
float borderSize;
*aZoneFileStream >> borderSize;
int staticFlags, dynamicFlags, nextTime;
*aZoneFileStream >> staticFlags >> dynamicFlags >> nextTime;
QTreeWidgetItem *colorsNode = new QTreeWidgetItem(menuFilePathNode);
colorsNode->setText(0, "Menu Colors");
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;
QTreeWidgetItem *foregroundColorNode = new QTreeWidgetItem(colorsNode);
foregroundColorNode->setText(0, QString("Foreground Color: RGBA(%1, %2, %3, %4)")
.arg(foregroundColorR).arg(foregroundColorG).arg(foregroundColorB).arg(foregroundColorA));
foregroundColorNode->setBackground(1, Utils::ColorFromNormalized(foregroundColorR, foregroundColorG, foregroundColorB, foregroundColorA));
QTreeWidgetItem *backgroundColorNode = new QTreeWidgetItem(colorsNode);
backgroundColorNode->setText(0, QString("Background Color: RGBA(%1, %2, %3, %4)")
.arg(backgroundColorR).arg(backgroundColorG).arg(backgroundColorB).arg(backgroundColorA));
backgroundColorNode->setBackground(1, Utils::ColorFromNormalized(backgroundColorR, backgroundColorG, backgroundColorB, backgroundColorA));
QTreeWidgetItem *borderColorNode = new QTreeWidgetItem(colorsNode);
borderColorNode->setText(0, QString("Borer Color: RGBA(%1, %2, %3, %4)")
.arg(borderColorR).arg(borderColorG).arg(borderColorB).arg(borderColorA));
borderColorNode->setBackground(1, Utils::ColorFromNormalized(borderColorR, borderColorG, borderColorB, borderColorA));
QTreeWidgetItem *outlineColorNode = new QTreeWidgetItem(colorsNode);
outlineColorNode->setText(0, QString("Outline Color: RGBA(%1, %2, %3, %4)")
.arg(outlineColorR).arg(outlineColorG).arg(outlineColorB).arg(outlineColorA));
outlineColorNode->setBackground(1, Utils::ColorFromNormalized(outlineColorR, outlineColorG, outlineColorB, outlineColorA));
quint32 materialPtr; // Should be Material *
*aZoneFileStream >> materialPtr;
quint32 fontPtr, fullScreen, itemCount, fontIndex;
*aZoneFileStream >> fontPtr >> fullScreen >> itemCount >> fontIndex;
quint32 cursorItem, fadeCycle;
*aZoneFileStream >> cursorItem >> fadeCycle;
float fadeClamp, fadeAmount, fadeInAmount, blurRadius;
*aZoneFileStream >> fadeClamp >> fadeAmount >> fadeInAmount >> blurRadius;
quint32 onOpenPtr, onFocusPtr, onClosePtr, onESCPtr; // Should be const char *
*aZoneFileStream >> onOpenPtr >> onFocusPtr >> onClosePtr >> onESCPtr;
quint32 onKeyPtr; // Should be ItemKeyHandler *
*aZoneFileStream >> onKeyPtr;
quint32 visibleExpCount, expEntryPtr; // components of statement_s
*aZoneFileStream >> visibleExpCount >> expEntryPtr;
quint32 allowedBindingPtr, soundNamePtr; // Should be const char *
*aZoneFileStream >> allowedBindingPtr >> soundNamePtr;
quint32 imageTrack;
*aZoneFileStream >> imageTrack;
float focusColorR, focusColorG, focusColorB, focusColorA;
*aZoneFileStream >> focusColorR >> focusColorG >> focusColorB >> focusColorA;
QTreeWidgetItem *focusColorNode = new QTreeWidgetItem(colorsNode);
focusColorNode->setText(0, QString("Focus Color: RGBA(%1, %2, %3, %4)")
.arg(focusColorR).arg(focusColorG).arg(focusColorB).arg(focusColorA));
focusColorNode->setBackground(1, Utils::ColorFromNormalized(focusColorR, focusColorG, focusColorB, focusColorA));
//QTreeWidgetItem *menuDefChildNode = new QTreeWidgetItem(menuDefNode);
//menuDefChildNode->setText(0, menuDefName);
float disabledColorR, disabledColorG, disabledColorB, disabledColorA;
*aZoneFileStream >> disabledColorR >> disabledColorG >> disabledColorB >> disabledColorA;
QTreeWidgetItem *disabledColorNode = new QTreeWidgetItem(colorsNode);
disabledColorNode->setText(0, QString("Disabled Color: RGBA(%1, %2, %3, %4)")
.arg(disabledColorR).arg(disabledColorG).arg(disabledColorB).arg(disabledColorA));
disabledColorNode->setBackground(1, Utils::ColorFromNormalized(disabledColorR, disabledColorG, disabledColorB, disabledColorA));
quint32 rectXExpCount, rectXExpPtr; // components of statement_s
*aZoneFileStream >> rectXExpCount >> rectXExpPtr;
quint32 rectYExpCount, rectYExpPtr; // components of statement_s
*aZoneFileStream >> rectYExpCount >> rectYExpPtr;
aZoneFileStream->skipRawData(4); // Separator
QString menuDefName;
char menuDefNameChar;
int menuDefNameLen = 0;
*aZoneFileStream >> menuDefNameChar;
while (menuDefNameChar != 0 && menuDefNameLen < 30) {
menuDefNameLen++;
menuDefName += menuDefNameChar;
*aZoneFileStream >> menuDefNameChar;
}
menuFilePathNode->setText(0, QString("%1 - %2").arg(menuDefName).arg(menuFilepath));
QString defString;
char defStringChar;
int defStringLen = 0;
*aZoneFileStream >> defStringChar;
while (defStringChar != 0 && defStringLen < 30) {
defStringLen++;
defString += defStringChar;
*aZoneFileStream >> defStringChar;
}
aZoneFileStream->skipRawData(4 * 10);
QTreeWidgetItem *itemsNode = new QTreeWidgetItem(menuFilePathNode);
itemsNode->setText(0, "Item Definitions");
quint32 itemWindowDefNamePtr;
*aZoneFileStream >> itemWindowDefNamePtr;
QTreeWidgetItem *itemRectNode = new QTreeWidgetItem(itemsNode);
itemRectNode->setText(0, "Item Text Rect");
float itemRectX, itemRectY, itemRectWidth, itemRectHeight;
*aZoneFileStream >> itemRectX >> itemRectY >> itemRectWidth >> itemRectHeight;
QTreeWidgetItem *itemRectXNode = new QTreeWidgetItem(itemRectNode);
itemRectXNode->setText(0, QString("X: %1").arg(itemRectX));
QTreeWidgetItem *itemRectYNode = new QTreeWidgetItem(itemRectNode);
itemRectYNode->setText(0, QString("Y: %1").arg(itemRectY));
QTreeWidgetItem *itemRectWidthNode = new QTreeWidgetItem(itemRectNode);
itemRectWidthNode->setText(0, QString("Width: %1").arg(itemRectWidth));
QTreeWidgetItem *itemRectHeightNode = new QTreeWidgetItem(itemRectNode);
itemRectHeightNode->setText(0, QString("Height: %1").arg(itemRectHeight));
MENU_H_ALIGNMENT itemHAlignment;
*aZoneFileStream >> itemHAlignment;
QTreeWidgetItem *hTextAlignNode = new QTreeWidgetItem(itemRectNode);
QString hTextAlignStr = Utils::MenuHAlignToStr(itemHAlignment);
hTextAlignNode->setText(0, QString("Horiz. Align: %1").arg(hTextAlignStr));
MENU_V_ALIGNMENT itemVAlignment;
*aZoneFileStream >> itemVAlignment;
QTreeWidgetItem *vTextAlignNode = new QTreeWidgetItem(itemRectNode);
QString vTextAlignStr = Utils::MenuVAlignToStr(itemVAlignment);
vTextAlignNode->setText(0, QString("Vert. Align: %1").arg(vTextAlignStr));
quint32 itemGroupPtr; // Should be const char*
*aZoneFileStream >> itemGroupPtr;
MENU_WINDOW_STYLE itemWindowStyle;
*aZoneFileStream >> itemWindowStyle;
MENU_WINDOW_BORDER itemWindowBorder;
*aZoneFileStream >> itemWindowBorder;
quint32 itemOwnerDraw, itemOwnerDrawFlags;
*aZoneFileStream >> itemOwnerDraw >> itemOwnerDrawFlags;
float itemBorderSize;
*aZoneFileStream >> itemBorderSize;
int itemStaticFlags, itemDynamicFlags, itemNextTime;
*aZoneFileStream >> itemStaticFlags >> itemDynamicFlags >> 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;
quint32 itemMaterialPtr; // Should be Material *
*aZoneFileStream >> itemMaterialPtr;
QTreeWidgetItem *itemTextRectNode = new QTreeWidgetItem(itemsNode);
itemTextRectNode->setText(0, "Item Text Rect");
float itemTextRectX, itemTextRectY, itemTextRectWidth, itemTextRectHeight;
*aZoneFileStream >> itemTextRectX >> itemTextRectY >> itemTextRectWidth >> itemTextRectHeight;
QTreeWidgetItem *itemTextRectXNode = new QTreeWidgetItem(itemTextRectNode);
itemTextRectXNode->setText(0, QString("X: %1").arg(itemTextRectX));
QTreeWidgetItem *itemTextRectYNode = new QTreeWidgetItem(itemTextRectNode);
itemTextRectYNode->setText(0, QString("Y: %1").arg(itemTextRectY));
QTreeWidgetItem *itemTextRectWidthNode = new QTreeWidgetItem(itemTextRectNode);
itemTextRectWidthNode->setText(0, QString("Width: %1").arg(itemTextRectWidth));
QTreeWidgetItem *itemTextRectHeightNode = new QTreeWidgetItem(itemTextRectNode);
itemTextRectHeightNode->setText(0, QString("Height: %1").arg(itemTextRectHeight));
MENU_H_ALIGNMENT itemText_hAlign;
*aZoneFileStream >> itemText_hAlign;
QTreeWidgetItem *hItemTextAlignNode = new QTreeWidgetItem(itemTextRectNode);
QString hItemTextAlignStr = Utils::MenuHAlignToStr(itemText_hAlign);
hItemTextAlignNode->setText(0, QString("Horiz. Align: %1").arg(hItemTextAlignStr));
MENU_V_ALIGNMENT itemText_vAlign;
*aZoneFileStream >> itemText_vAlign;
QTreeWidgetItem *vItemTextAlignNode = new QTreeWidgetItem(itemTextRectNode);
QString vItemTextAlignStr = Utils::MenuVAlignToStr(itemText_vAlign);
vItemTextAlignNode->setText(0, QString("Vert. Align: %1").arg(vItemTextAlignStr));
MENU_ITEM_TYPE itemType;
*aZoneFileStream >> itemType;
quint32 dataType, alignment;
*aZoneFileStream >> dataType >> alignment;
MENU_FONT_TYPE fontEnum;
*aZoneFileStream >> fontEnum;
quint32 textAlignMode;
*aZoneFileStream >> textAlignMode;
float textalignx, textaligny, textscale;
*aZoneFileStream >> textalignx >> textaligny >> textscale;
MENU_ITEM_TEXTSTYLE textStyle;
*aZoneFileStream >> textStyle;
int gameMsgWindowIndex, gameMsgWindowMode;
*aZoneFileStream >> gameMsgWindowIndex >> gameMsgWindowMode;
quint32 testPtr; // const char *
*aZoneFileStream >> testPtr;
quint32 textSavegameInfo;
*aZoneFileStream >> textSavegameInfo;
quint32 parentPtr; // menuDef_t *
*aZoneFileStream >> parentPtr;
quint32 mouseEnterText, mouseExitText, mouseEnter, mouseExit,
action, onAccept, onFocus, leaveFocus, dvar, dvarTest; // const char *
*aZoneFileStream >> mouseEnterText >> mouseExitText >> mouseEnter >> mouseExit
>> action >> onAccept >> onFocus >> leaveFocus >> dvar >> dvarTest;
quint32 keyHandlerPtr; // ItemKeyHandler *
*aZoneFileStream >> keyHandlerPtr;
quint32 enableDvarPtr; // const char *
*aZoneFileStream >> enableDvarPtr;
quint32 dvarFlags;
*aZoneFileStream >> dvarFlags;
quint32 focusSoundPtr; // snd_alias_list_t *;
*aZoneFileStream >> focusSoundPtr;
float special;
*aZoneFileStream >> special;
quint32 cursorPos;
*aZoneFileStream >> cursorPos;
// itemDefData_t typeData;
// listBoxDef_s *listBox;
quint32 startPos, endPos, drawPadding;
*aZoneFileStream >> startPos >> endPos >> drawPadding;
float elementWidth, elementHeight;
*aZoneFileStream >> elementWidth >> elementHeight;
quint32 elementStyle, numColumns;
*aZoneFileStream >> elementStyle >> numColumns;
//columnInfo_s columnInfo[16];
quint32 doubleClickPtr; // const char *
*aZoneFileStream >> doubleClickPtr;
int notselectable, noScrollBars, usePaging;
*aZoneFileStream >> notselectable >> noScrollBars >> usePaging;
float itemSelectBorderColorR, itemSelectBorderColorG, itemSelectBorderColorB, itemSelectBorderColorA,
itemDisableColorR, itemDisableColorG, itemDisableColorB, itemDisableColorA,
itemFocusColor2R, itemFocusColor2G, itemFocusColor2B, itemFocusColor2A;
*aZoneFileStream >> itemSelectBorderColorR >> itemSelectBorderColorG >> itemSelectBorderColorB >> itemSelectBorderColorA
>> itemDisableColorR >> itemDisableColorG >> itemDisableColorB >> itemDisableColorA
>> itemFocusColor2R >> itemFocusColor2G >> itemFocusColor2B >> itemFocusColor2A;
quint32 selectIconPtr, backgroundItemListboxPtr, highlightTexturePtr; // Material *
*aZoneFileStream >> selectIconPtr >> backgroundItemListboxPtr >> highlightTexturePtr;
// editFieldDef_s *editField;
float minVal, maxVal, defVal, range;
*aZoneFileStream >> minVal >> maxVal >> defVal >> range;
int maxChars, maxCharsGotoNext, maxPaintChars, paintOffset;
*aZoneFileStream >> maxChars >> maxCharsGotoNext >> maxPaintChars >> paintOffset;
// multiDef_s *multi;
QVector<quint32> dvarListPtrs = QVector<quint32>(32);
for (int i = 0; i < 32; i++) {
quint32 dvarList;
*aZoneFileStream >> dvarList;
dvarListPtrs.push_back(dvarList);
}
QVector<quint32> dvarStrPtrs = QVector<quint32>(32);
for (int i = 0; i < 32; i++) {
quint32 dvarStr;
*aZoneFileStream >> dvarStr;
dvarStrPtrs.push_back(dvarStr);
}
QVector<float> dvarValues = QVector<float>(32);
for (int i = 0; i < 32; i++) {
float dvarValue;
*aZoneFileStream >> dvarValue;
dvarValues.push_back(dvarValue);
}
quint32 count, strDef;
*aZoneFileStream >> count >> strDef;
quint32 enumDvarNamePtr; // const char *
*aZoneFileStream >> enumDvarNamePtr;
quint32 dataPtr; // void *
*aZoneFileStream >> dataPtr;
quint32 itemImageTrack;
*aZoneFileStream >> itemImageTrack;
//statement_s visibleExp;
//statement_s textExp;
//statement_s materialExp;
//statement_s rectXExp;
//statement_s rectYExp;
//statement_s rectWExp;
//statement_s rectHExp;
//statement_s foreColorAExp;
}
2025-01-09 17:54:44 -05:00
}
void MainWindow::ParseAsset_Weapon(QDataStream *aZoneFileStream) {
//WEAPON_FILE
}
void MainWindow::ParseAsset_D3DBSP(QDataStream *aZoneFileStream) {
//D3DBSP_DUMP
}
void MainWindow::ParseAsset_StringTable(QDataStream *aZoneFileStream) {
aZoneFileStream->skipRawData(4);
quint32 columnCount, rowCount;
*aZoneFileStream >> columnCount >> rowCount;
columnCount = 0;
rowCount = 0;
aZoneFileStream->skipRawData(4);
QString stringTableName;
char stringTableNameChar;
*aZoneFileStream >> stringTableNameChar;
while (stringTableNameChar != 0) {
stringTableName += stringTableNameChar;
*aZoneFileStream >> stringTableNameChar;
}
ui->comboBox_StringTable->addItem(stringTableName);
QVector<QString> tablePointers = QVector<QString>();
for (quint32 i = 0; i < 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);
}
}
void MainWindow::on_pushButton_FastFile_clicked() {
// Open fast file
QString fastFilePath = GetFastFilePath();
OpenFastFile(fastFilePath);
}
2025-01-09 17:54:44 -05:00
void MainWindow::on_pushButton_ZoneFile_clicked() {
const QString zoneFilePath = GetZoneFilePath();
OpenZoneFile(zoneFilePath);
}
2025-01-09 17:54:44 -05:00
void MainWindow::LogOpenedFile(QString aFileName)
{
mRecentFiles.enqueue(aFileName);
mRecentFiles.removeDuplicates();
2025-01-09 17:54:44 -05:00
RefreshRecentFileMenu();
}
2025-01-09 17:54:44 -05:00
void MainWindow::RefreshRecentFileMenu()
{
foreach (QAction* action, mRecentFileActions) {
ui->menuRecent_Fast_Files->removeAction(action);
ui->menuRecent_Zone_Files->removeAction(action);
2025-01-09 17:54:44 -05:00
action->deleteLater();
2025-01-09 17:54:44 -05:00
}
mRecentFileActions.clear();
foreach (QString recentFileText, mRecentFiles) {
if (recentFileText.contains(".ff")) {
QAction *recentFastFileAction = new QAction(ui->menuRecent_Fast_Files);
recentFastFileAction->setText(recentFileText);
mRecentFileActions << recentFastFileAction;
ui->menuRecent_Fast_Files->addAction(recentFastFileAction);
connect(recentFastFileAction, &QAction::triggered, this, [&, this, recentFileText](bool checked = false) {
OpenFastFile(recentFileText);
});
} else if (recentFileText.contains(".zone")) {
QAction *recentZoneFileAction = new QAction(ui->menuRecent_Zone_Files);
recentZoneFileAction->setText(recentFileText);
mRecentFileActions << recentZoneFileAction;
ui->menuRecent_Zone_Files->addAction(recentZoneFileAction);
connect(recentZoneFileAction, &QAction::triggered, this, [&, this, recentFileText](bool checked = false) {
OpenZoneFile(recentFileText);
});
2025-01-09 17:54:44 -05:00
}
}
}
void MainWindow::ParseZoneFile(QByteArray aDecompressedData) {
2025-01-09 17:54:44 -05:00
// Open zone file as little endian stream
QDataStream zoneFileStream(aDecompressedData);
2025-01-09 17:54:44 -05:00
zoneFileStream.setByteOrder(QDataStream::LittleEndian);
zoneFileStream.setFloatingPointPrecision(QDataStream::SinglePrecision);
2025-01-09 17:54:44 -05:00
// Parse data from zone file header
Zone zone;
zoneFileStream >> zone;
// Add header data to ui
ui->spinBox_FileSize->setValue(zone.zoneFileSize);
ui->spinBox_TagCount->setValue(zone.tagCount);
ui->spinBox_RecordCount->setValue(zone.recordCount);
// Add unknowns to ui
ui->lineEdit_U1->setText(QString::number(zone.unknown1, 16).toUpper());
ui->spinBox_U1->setValue(zone.unknown1);
ui->lineEdit_U2->setText(QString::number(zone.unknown2, 16).toUpper());
ui->spinBox_U2->setValue(zone.unknown2);
ui->lineEdit_U3->setText(QString::number(zone.unknown3, 16).toUpper());
ui->spinBox_U3->setValue(zone.unknown3);
ui->lineEdit_U4->setText(QString::number(zone.unknown4, 16).toUpper());
ui->spinBox_U4->setValue(zone.unknown4);
ui->lineEdit_U5->setText(QString::number(zone.unknown5, 16).toUpper());
ui->spinBox_U5->setValue(zone.unknown5);
ui->lineEdit_U6->setText(QString::number(zone.unknown6, 16).toUpper());
ui->spinBox_U6->setValue(zone.unknown6);
ui->lineEdit_U7->setText(QString::number(zone.unknown7, 16).toUpper());
ui->spinBox_U7->setValue(zone.unknown7);
ui->lineEdit_U8->setText(QString::number(zone.unknown8, 16).toUpper());
ui->spinBox_U8->setValue(zone.unknown8);
ui->lineEdit_U9->setText(QString::number(zone.unknown9, 16).toUpper());
ui->spinBox_U9->setValue(zone.unknown9);
ui->lineEdit_U10->setText(QString::number(zone.unknown10, 16).toUpper());
ui->spinBox_U10->setValue(zone.unknown10);
ui->lineEdit_U11->setText(QString::number(zone.unknown11, 16).toUpper());
ui->spinBox_U11->setValue(zone.unknown11);
// Add tags to ui list
foreach (const QString tag, zone.tags) {
ui->listWidget_Tags->addItem(tag);
}
2025-01-09 17:54:44 -05:00
// Track past assets and counts
int consecutiveIndex = 0;
int consecutiveCount = 0;
ASSET_TYPE lastAssetType = ASSET_UNKNOWN;
foreach (ASSET_TYPE assetType, zone.assetTypes) {
const QString typeStr = Utils::AssetTypeToString(assetType);
2025-01-09 17:54:44 -05:00
if (!mTypeMap.contains(assetType)) {
mTypeMap[assetType] = 0;
}
mTypeMap[assetType]++;
2025-01-09 17:54:44 -05:00
// Set lastAsset as current if first run
if (lastAssetType == ASSET_UNKNOWN) {
lastAssetType = assetType;
}
2025-01-09 17:54:44 -05:00
// Track counts or populate asset order table
if (lastAssetType == assetType) {
// Count consecutive assets
consecutiveCount++;
} else {
// Insert row and populate for the previous asset type
ui->tableWidget_Order->insertRow(consecutiveIndex);
ui->tableWidget_Order->setItem(consecutiveIndex, 0, new QTableWidgetItem(Utils::AssetTypeToString(lastAssetType)));
ui->tableWidget_Order->setItem(consecutiveIndex, 1, new QTableWidgetItem(QString::number(consecutiveCount)));
2025-01-09 17:54:44 -05:00
// Update counts and asset type
consecutiveCount = 1;
consecutiveIndex++;
lastAssetType = assetType;
}
2025-01-09 17:54:44 -05:00
// qDebug() << "Parsing Asset of Type: " << typeHex;
if (typeStr == "ANIMATION") { // aitype
ParseAsset_XAnim(&zoneFileStream);
2025-01-09 17:54:44 -05:00
} else if (typeStr == "MODEL") { // xmodel
ParseAsset_XModel(&zoneFileStream);
} else if (typeStr == "MATERIAL") { // material
ParseAsset_Material(&zoneFileStream);
} else if (typeStr == "TECH SET") { // techset include
ParseAsset_TechSet(&zoneFileStream);
} else if (typeStr == "SOUND") { // loaded_sound
ParseAsset_LoadedSound(&zoneFileStream);
} else if (typeStr == "COLLISION MAP") { // col_map_mp
ParseAsset_ColMapMP(&zoneFileStream);
} else if (typeStr == "SHADER") { // pixelshader
ParseAsset_PixelShader(&zoneFileStream);
} else if (typeStr == "D3DBSP DUMP") { // string_table
ParseAsset_D3DBSP(&zoneFileStream);
} else if (typeStr == "FONT") { // font
ParseAsset_Font(&zoneFileStream);
2025-01-09 17:54:44 -05:00
} else if (typeStr == "MENU") { // string_table
ParseAsset_MenuFile(&zoneFileStream);
} else if (typeStr == "LOCAL STRING") { // localized string asset
ParseAsset_Localize(&zoneFileStream);
2025-01-09 17:54:44 -05:00
} else if (typeStr == "WEAPON") { // string_table
ParseAsset_Weapon(&zoneFileStream);
} else if (typeStr == "EFFECT") { // aitype
ParseAsset_FX(&zoneFileStream);
} else if (typeStr == "RAW FILE") { // gsc
// ParseAsset_RawFile(&zoneFileStream);
RawFile rawFile = RawFile();
zoneFileStream >> rawFile;
mRawFilesVec >> rawFile;
} else if (typeStr == "STRING TABLE") { // string_table
ParseAsset_StringTable(&zoneFileStream);
} else {
2025-01-09 17:54:44 -05:00
qDebug() << "Found bad asset type!" << typeStr;
}
}
// Track current and consecutive assets
int assetIndex = 0;
// Iterate asset types found in index
for (auto [assetType, assetCount] : mTypeMap.asKeyValueRange()) {
const QString typeStr = Utils::AssetTypeToString(assetType);
// Insert row and populate
ui->tableWidget_Index->insertRow(assetIndex);
ui->tableWidget_Index->setItem(assetIndex, 0, new QTableWidgetItem(typeStr));
ui->tableWidget_Index->setItem(assetIndex, 1, new QTableWidgetItem(QString::number(assetCount)));
// Update count
assetIndex++;
}
2025-01-09 17:54:44 -05:00
}
int MainWindow::LoadFile_D3DBSP(const QString aFilePath) {
QFile file(aFilePath);
if (!file.open(QIODevice::ReadOnly)) {
qDebug() << "Error: Unable to open file" << aFilePath;
return 1; // ERR_FILE_NOT_FOUND
}
QDataStream stream(&file);
stream.setByteOrder(QDataStream::LittleEndian);
// Read Magic Value
quint32 magicValue;
stream >> magicValue;
if (magicValue != 'PSBI') {
qDebug() << "Error: Not a valid D3DBSP file";
return 2; // ERR_NOT_A_D3DBSP_FILE
}
// Read BSP Version and Lump Count
stream >> mBSPVersion;
stream >> mDiskLumpCount;
// Assign diskLumpOrderSize
mDiskLumpOrder.resize(mDiskLumpCount);
qDebug() << "BSP Version:" << mBSPVersion;
qDebug() << "Lump Count:" << mDiskLumpCount;
// Read Lump Index Entries
quint32 lumpOffset = sizeof(quint32) * 3 + sizeof(LumpIndexEntry) * mDiskLumpCount;
for (quint32 i = 0; i < mDiskLumpCount; i++) {
LumpIndexEntry indexEntry;
stream >> indexEntry.type >> indexEntry.length;
mDiskLumpOrder[i] = indexEntry.type;
Lump &lump = mLumps[indexEntry.type];
lump.size = indexEntry.length;
lump.content.resize(indexEntry.length);
lump.isEmpty = false;
qDebug() << "Lump Type:" << Utils::LumpTypeToString((LUMP_TYPE)indexEntry.type) << "Lump Size:" << indexEntry.length;
// Handle offsets and padding
qint64 currentPos = file.pos();
file.seek(lumpOffset);
file.read(lump.content.data(), lump.size);
file.seek(currentPos);
lumpOffset += Utils::PadInt4(indexEntry.length);
}
file.close();
return 0; // Success
}