Treat bik file as a raw file, check file types.

This commit is contained in:
= 2025-01-12 20:12:41 -05:00
parent c649ee2b40
commit 80f7a73573
5 changed files with 239 additions and 81 deletions

View File

@ -1,6 +1,7 @@
#ifndef ENUMS_H #ifndef ENUMS_H
#define ENUMS_H #define ENUMS_H
#include "qtypes.h"
enum LUMP_TYPE enum LUMP_TYPE
{ {
LUMP_MATERIALS = 0x0, LUMP_MATERIALS = 0x0,
@ -98,4 +99,7 @@ enum BSPVERSION_TYPE
BSPVERSION_COD_BO = 45 BSPVERSION_COD_BO = 45
}; };
// Bink constants
const quint32 BINK_SURFACE32RGBA = 6;
#endif // ENUMS_H #endif // ENUMS_H

View File

@ -646,93 +646,124 @@ void MainWindow::ParseZoneIndex(QDataStream *aZoneFileStream) {
void MainWindow::ParseAsset_LocalString(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_LocalString(QDataStream *aZoneFileStream) {
// Skip separator // Skip separator
aZoneFileStream->skipRawData(8); qint32 langStrPtr, referenceStrPtr;
*aZoneFileStream >> langStrPtr >> referenceStrPtr;
// Parse local string asset contents // Parse language-specific string if present
QString localStr; QString langStr;
char localStrChar; if (langStrPtr == -1) {
*aZoneFileStream >> localStrChar; char langStrChar;
while (localStrChar != 0) { *aZoneFileStream >> langStrChar;
localStr += localStrChar; while (langStrChar != 0) {
*aZoneFileStream >> localStrChar; langStr += langStrChar;
*aZoneFileStream >> langStrChar;
}
} else {
langStr = "MEMORY_REFERENCE";
} }
// Parse rawfile name // Parse reference str ig present
QString aliasName; QString referenceStr;
char aliasNameChar; if (referenceStrPtr == -1) {
*aZoneFileStream >> aliasNameChar; char referenceStrChar;
while (aliasNameChar != 0) { *aZoneFileStream >> referenceStrChar;
aliasName += aliasNameChar; while (referenceStrChar != 0) {
*aZoneFileStream >> aliasNameChar; referenceStr += referenceStrChar;
*aZoneFileStream >> referenceStrChar;
}
} else {
referenceStr = "MEMORY_REFERENCE";
} }
// qDebug() << QString("%1 = %2").arg(aliasName).arg(localStr);
ui->listWidget_LocalString->addItem(QString("%1 = %2").arg(aliasName).arg(localStr)); const int localStrIndex = ui->listWidget_LocalString->count() + 1;
ui->listWidget_LocalString->addItem(QString("[%1] %2 = %3").arg(localStrIndex).arg(referenceStr).arg(langStr));
} }
void MainWindow::ParseAsset_RawFile(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_RawFile(QDataStream *aZoneFileStream) {
// Skip start separator FF FF FF FF (pointer?) // Skip start separator FF FF FF FF (pointer?)
aZoneFileStream->skipRawData(4); aZoneFileStream->skipRawData(4);
quint32 gscLength; quint32 rawFileLength;
*aZoneFileStream >> gscLength; *aZoneFileStream >> rawFileLength;
// Skip unknown 4 byte data // Skip unknown 4 byte data
aZoneFileStream->skipRawData(4); aZoneFileStream->skipRawData(4);
bool isBik = false;
// Parse rawfile path // Parse rawfile path
QString rawFilePath; QString rawFilePath;
char scriptPathChar; char rawFilePathChar;
*aZoneFileStream >> scriptPathChar; *aZoneFileStream >> rawFilePathChar;
while (scriptPathChar != 0) { while (rawFilePathChar != 0) {
rawFilePath += scriptPathChar; rawFilePath += rawFilePathChar;
*aZoneFileStream >> scriptPathChar; *aZoneFileStream >> rawFilePathChar;
} }
rawFilePath.replace(",", ""); rawFilePath.replace(",", "");
const QStringList pathParts = rawFilePath.split('/'); if (rawFilePath.contains(".bik")) {
if (pathParts.size() == 0) { isBik = true;
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 { } else {
const QString path = pathParts[0]; const QStringList pathParts = rawFilePath.split('/');
QTreeWidgetItem *newRootItem; if (pathParts.size() == 0) {
if (mTreeMap.contains(path)) { qDebug() << "Failed to parse ff path! " << rawFilePath;
newRootItem = mTreeMap[path]; exit(-1);
} else { } else if (pathParts.size() == 1) {
newRootItem = new QTreeWidgetItem(ui->treeWidget_Scripts); const QString path = pathParts[0];
QTreeWidgetItem *newRootItem = new QTreeWidgetItem(ui->treeWidget_Scripts);
newRootItem->setText(0, path); newRootItem->setText(0, path);
mTreeMap[path] = newRootItem; } else {
} const QString path = pathParts[0];
QTreeWidgetItem *newRootItem;
QTreeWidgetItem *parentItem = newRootItem;
for (int i = 1; i < pathParts.size(); i++) {
const QString path = pathParts[i];
QTreeWidgetItem *newChildItem;
if (mTreeMap.contains(path)) { if (mTreeMap.contains(path)) {
newChildItem = mTreeMap[path]; newRootItem = mTreeMap[path];
} else { } else {
newChildItem = new QTreeWidgetItem(); newRootItem = new QTreeWidgetItem(ui->treeWidget_Scripts);
newChildItem->setText(0, path); newRootItem->setText(0, path);
mTreeMap[path] = newChildItem; 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;
} }
parentItem->addChild(newChildItem);
parentItem = newChildItem;
} }
} }
// Parse gsc contents if (false && isBik) {
QString rawFileContents; qDebug() << "rawFileLength: " << rawFileLength;
char rawFileContentsChar; QByteArray bikData(rawFileLength, Qt::Uninitialized);
*aZoneFileStream >> rawFileContentsChar; aZoneFileStream->readRawData(bikData.data(), rawFileLength);
while (rawFileContentsChar != 0 && rawFileContentsChar != -1) {
rawFileContents += rawFileContentsChar; //QFile bikFile(QDir::currentPath() + "/" + rawFilePath.split('/').last());
//qDebug() << bikFile.fileName();
//if (!bikFile.open(QIODevice::WriteOnly)) {
// qWarning() << "Failed to open .bik file for writing!";
// return;
//}
//qDebug() << QString("%1: %2").arg(rawFilePath).arg(bikFile.fileName());
//bikFile.write(bikData);
} else {
// Parse gsc contents
QString rawFileContents;
char rawFileContentsChar;
*aZoneFileStream >> rawFileContentsChar; *aZoneFileStream >> rawFileContentsChar;
while (rawFileContentsChar != 0 && rawFileContentsChar != -1) {
rawFileContents += rawFileContentsChar;
*aZoneFileStream >> rawFileContentsChar;
}
mRawFileMap[rawFilePath] = (rawFileContents.isEmpty()) ? ("EMPTY") : (rawFileContents);
qDebug() << QString("%1: %2").arg(rawFilePath).arg(rawFileContents);
} }
mRawFileMap[rawFilePath] = (rawFileContents.isEmpty()) ? ("EMPTY") : (rawFileContents);
// qDebug() << QString("%1: %2").arg(rawFilePath).arg(rawFileContents);
} }
void MainWindow::ParseAsset_PhysPreset(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_PhysPreset(QDataStream *aZoneFileStream) {
@ -744,29 +775,99 @@ void MainWindow::ParseAsset_XModel(QDataStream *aZoneFileStream) {
} }
void MainWindow::ParseAsset_Material(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_Material(QDataStream *aZoneFileStream) {
aZoneFileStream->skipRawData(27 * 4);
qint32 materialNamePtr;
*aZoneFileStream >> materialNamePtr;
qDebug() << "materialNamePtr: " << materialNamePtr;
if (materialNamePtr == -1) {
QString materialName;
char materialNameChar;
*aZoneFileStream >> materialNameChar;
while (materialNameChar != 0) {
materialName += materialNameChar;
*aZoneFileStream >> materialNameChar;
}
qDebug() << "Parsing Material: " << materialName;
}
aZoneFileStream->skipRawData(3 * 4);
qint32 compressionPtr, compression, unknownSectionPtr;
*aZoneFileStream >> compressionPtr;
qDebug() << "compressionPtr: " << compressionPtr;
if (compressionPtr == -1) {
*aZoneFileStream >> compression;
qDebug() << QString("Found material with DXT%1 compression!").arg(compression);
*aZoneFileStream >> unknownSectionPtr;
qDebug() << "unknownSectionPtr: " << unknownSectionPtr;
if (unknownSectionPtr == -2) {
aZoneFileStream->skipRawData(6 * 4);
}
}
qint32 imageNamePtr;
*aZoneFileStream >> imageNamePtr;
qDebug() << "imageNamePtr: " << imageNamePtr;
if (imageNamePtr == -1) {
QString imageName;
char imageNameChar;
*aZoneFileStream >> imageNameChar;
while (imageNameChar != 0) {
imageName += imageNameChar;
*aZoneFileStream >> imageNameChar;
}
qDebug() << "- Embeded image: " << imageName;
}
QByteArray compressionData(4, Qt::Uninitialized);
QString compressionStr;
if (compressionPtr == -1) {
aZoneFileStream->skipRawData(2 * 4);
aZoneFileStream->readRawData(compressionData.data(), 4);
aZoneFileStream->skipRawData(4);
compressionStr = QString::fromUtf8(compressionData);
aZoneFileStream->skipRawData(4);
}
aZoneFileStream->skipRawData(4);
} }
void MainWindow::ParseAsset_PixelShader(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_PixelShader(QDataStream *aZoneFileStream) {
} }
void MainWindow::ParseAsset_TechSet(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_BikFile(QDataStream *aZoneFileStream) {
aZoneFileStream->skipRawData(4); QByteArray testData(32, Qt::Uninitialized);
// Parse techset name aZoneFileStream->readRawData(testData.data(), 32);
QString techSetName; qDebug() << "Test Data: " << testData;
char techSetNameChar;
*aZoneFileStream >> techSetNameChar; //aZoneFileStream->skipRawData(4);
while (techSetNameChar == 0) {
*aZoneFileStream >> techSetNameChar; quint32 fileSize;
} //*aZoneFileStream >> fileSize;
while (techSetNameChar != 0) { //qDebug() << ".bik file size:" << fileSize;
techSetName += techSetNameChar;
*aZoneFileStream >> techSetNameChar; // // Parse rawfile path
} // QString filePath;
techSetName.replace(",", ""); // char filePathChar;
ui->listWidget_TechSets->addItem(techSetName); // *aZoneFileStream >> filePathChar;
//qDebug() << "Tech Set: " << techSetName; // while (filePathChar != 0) {
// filePath += filePathChar;
// *aZoneFileStream >> filePathChar;
// }
// QByteArray bikData(fileSize, Qt::Uninitialized);
// aZoneFileStream->readRawData(bikData.data(), fileSize);
// qDebug() << filePath;
// QFile bikFile(QDir::currentPath() + "/" + filePath.split('/').last());
// qDebug() << bikFile.fileName();
// if (!bikFile.open(QIODevice::WriteOnly)) {
// qWarning() << "Failed to open .bik file for writing!";
// return;
// }
// bikFile.write(bikData);
} }
void MainWindow::ParseAsset_Image(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_Image(QDataStream *aZoneFileStream) {
@ -899,6 +1000,25 @@ void MainWindow::ParseAsset_D3DBSP(QDataStream *aZoneFileStream) {
//D3DBSP_DUMP //D3DBSP_DUMP
} }
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_StringTable(QDataStream *aZoneFileStream) { void MainWindow::ParseAsset_StringTable(QDataStream *aZoneFileStream) {
aZoneFileStream->skipRawData(4); aZoneFileStream->skipRawData(4);
@ -1029,8 +1149,8 @@ void MainWindow::on_pushButton_FastFile_clicked() {
ParseAsset_Material(&zoneFileStream); ParseAsset_Material(&zoneFileStream);
} else if (typeStr == "SHADER") { // pixelshader } else if (typeStr == "SHADER") { // pixelshader
ParseAsset_PixelShader(&zoneFileStream); ParseAsset_PixelShader(&zoneFileStream);
} else if (typeStr == "TECH SET") { // techset include } else if (typeStr == "BIK FILE") { // bik file?
ParseAsset_TechSet(&zoneFileStream); ParseAsset_BikFile(&zoneFileStream);
} else if (typeStr == "IMAGE") { // image } else if (typeStr == "IMAGE") { // image
ParseAsset_Image(&zoneFileStream); ParseAsset_Image(&zoneFileStream);
} else if (typeStr == "SOUND") { // loaded_sound } else if (typeStr == "SOUND") { // loaded_sound
@ -1061,6 +1181,8 @@ void MainWindow::on_pushButton_FastFile_clicked() {
ParseAsset_Weapon(&zoneFileStream); ParseAsset_Weapon(&zoneFileStream);
} else if (typeStr == "D3DBSP DUMP") { // string_table } else if (typeStr == "D3DBSP DUMP") { // string_table
ParseAsset_D3DBSP(&zoneFileStream); ParseAsset_D3DBSP(&zoneFileStream);
} else if (typeStr == "TECH SET") { // string_table
ParseAsset_TechSet(&zoneFileStream);
} else if (typeStr != "UNKNOWN") { } else if (typeStr != "UNKNOWN") {
qDebug() << "Found bad asset type!" << typeStr; qDebug() << "Found bad asset type!" << typeStr;
} }
@ -1126,8 +1248,8 @@ void MainWindow::on_pushButton_FastFile_2_clicked() {
ParseAsset_Material(&zoneFileStream); ParseAsset_Material(&zoneFileStream);
} else if (typeStr == "SHADER") { // pixelshader } else if (typeStr == "SHADER") { // pixelshader
ParseAsset_PixelShader(&zoneFileStream); ParseAsset_PixelShader(&zoneFileStream);
} else if (typeStr == "TECH SET") { // techset include } else if (typeStr == "BIK FILE") { // .bik file
ParseAsset_TechSet(&zoneFileStream); ParseAsset_BikFile(&zoneFileStream);
} else if (typeStr == "IMAGE") { // image } else if (typeStr == "IMAGE") { // image
ParseAsset_Image(&zoneFileStream); ParseAsset_Image(&zoneFileStream);
} else if (typeStr == "SOUND") { // loaded_sound } else if (typeStr == "SOUND") { // loaded_sound
@ -1158,7 +1280,9 @@ void MainWindow::on_pushButton_FastFile_2_clicked() {
ParseAsset_Weapon(&zoneFileStream); ParseAsset_Weapon(&zoneFileStream);
} else if (typeStr == "D3DBSP DUMP") { // string_table } else if (typeStr == "D3DBSP DUMP") { // string_table
ParseAsset_D3DBSP(&zoneFileStream); ParseAsset_D3DBSP(&zoneFileStream);
} else if (typeStr != "UNKNOWN") { } else if (typeStr == "TECH SET") { // string_table
ParseAsset_TechSet(&zoneFileStream);
} else {
qDebug() << "Found bad asset type!" << typeStr; qDebug() << "Found bad asset type!" << typeStr;
} }
} }

View File

@ -59,6 +59,10 @@
#include <Qt3DExtras/QNormalDiffuseMapMaterial> #include <Qt3DExtras/QNormalDiffuseMapMaterial>
#include <windows.h> #include <windows.h>
#include <stdexcept>
#include <iostream>
#include <memory>
#include <cstring>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { namespace Ui {
@ -107,7 +111,7 @@ private slots:
void ParseAsset_XModel(QDataStream *aZoneFileStream); void ParseAsset_XModel(QDataStream *aZoneFileStream);
void ParseAsset_Material(QDataStream *aZoneFileStream); void ParseAsset_Material(QDataStream *aZoneFileStream);
void ParseAsset_PixelShader(QDataStream *aZoneFileStream); void ParseAsset_PixelShader(QDataStream *aZoneFileStream);
void ParseAsset_TechSet(QDataStream *aZoneFileStream); void ParseAsset_BikFile(QDataStream *aZoneFileStream);
void ParseAsset_Image(QDataStream *aZoneFileStream); void ParseAsset_Image(QDataStream *aZoneFileStream);
void ParseAsset_LoadedSound(QDataStream *aZoneFileStream); void ParseAsset_LoadedSound(QDataStream *aZoneFileStream);
void ParseAsset_ColMapMP(QDataStream *aZoneFileStream); void ParseAsset_ColMapMP(QDataStream *aZoneFileStream);
@ -123,6 +127,7 @@ private slots:
void ParseAsset_MenuFile(QDataStream *aZoneFileStream); void ParseAsset_MenuFile(QDataStream *aZoneFileStream);
void ParseAsset_Weapon(QDataStream *aZoneFileStream); void ParseAsset_Weapon(QDataStream *aZoneFileStream);
void ParseAsset_D3DBSP(QDataStream *aZoneFileStream); void ParseAsset_D3DBSP(QDataStream *aZoneFileStream);
void ParseAsset_TechSet(QDataStream *aZoneFileStream);
int LoadFile_D3DBSP(const QString aFilePath); int LoadFile_D3DBSP(const QString aFilePath);

View File

@ -16,4 +16,26 @@ struct LumpIndexEntry {
quint32 length; quint32 length;
}; };
// Bink structure definitions
struct BINKRECT {
int Left;
int Top;
int Width;
int Height;
};
struct BINK {
int Width;
int Height;
uint32_t Frames;
uint32_t FrameNum;
uint32_t FrameRate;
uint32_t FrameRateDiv;
uint32_t ReadError;
uint32_t OpenFlags;
BINKRECT FrameRects;
uint32_t NumRects;
uint32_t FrameChangePercent;
};
#endif // STRUCTS_H #endif // STRUCTS_H

View File

@ -2,6 +2,7 @@
#define UTILS_H #define UTILS_H
#include "enums.h" #include "enums.h"
#include "qdir.h"
#include <QString> #include <QString>
#include <QtZlib/zlib.h> #include <QtZlib/zlib.h>
@ -45,6 +46,8 @@ public:
return "MODEL"; return "MODEL";
} else if (cleanedType == "0D000000") { // shader PARTIALLY VERIFIED } else if (cleanedType == "0D000000") { // shader PARTIALLY VERIFIED
return "SHADER"; return "SHADER";
} else if (cleanedType == "06000000") { // material PARTIALLY VERIFIED
return "MATERIAL";
} }
return "UNKNOWN"; return "UNKNOWN";
} }