From f6d32552b0dfb91aed0ae581047c5be4b5641b1b Mon Sep 17 00:00:00 2001 From: njohnson Date: Fri, 19 Dec 2025 23:06:03 -0500 Subject: [PATCH] Remove some libs, fix many assets, update some UIs. --- app/app.pro | 13 +- app/ddsviewer.cpp | 282 ++-- app/ddsviewer.h | 7 +- app/imagewidget.h | 4 +- app/iwiviewer.cpp | 138 +- app/iwiviewer.h | 6 +- app/localstringviewer.cpp | 2 +- app/mainwindow.cpp | 350 ++--- app/mainwindow.h | 2 - app/modelviewer.ui | 1232 +++++++++-------- app/preferenceeditor.cpp | 2 + app/preferenceeditor.h | 3 + app/preferenceeditor.ui | 23 +- app/techsetviewer.cpp | 18 +- app/techsetviewer.ui | 6 +- app/xtreewidget.cpp | 572 +++----- app/xtreewidget.h | 18 +- app/xtreewidgetitem.cpp | 46 +- app/xtreewidgetitem.h | 27 +- app/zonefileviewer.cpp | 18 +- app/zonefileviewer.h | 1 + libs/compression/compression.cpp | 74 +- libs/compression/compression.h | 19 +- libs/fastfile/360/fastfile_cod10_360.cpp | 3 +- libs/fastfile/360/fastfile_cod11_360.cpp | 3 +- libs/fastfile/360/fastfile_cod12_360.cpp | 3 +- libs/fastfile/360/fastfile_cod2_360.cpp | 3 +- libs/fastfile/360/fastfile_cod4_360.cpp | 3 +- libs/fastfile/360/fastfile_cod5_360.cpp | 3 +- libs/fastfile/360/fastfile_cod6_360.cpp | 3 +- libs/fastfile/360/fastfile_cod7_360.cpp | 3 +- libs/fastfile/360/fastfile_cod7_5_360.cpp | 3 +- libs/fastfile/360/fastfile_cod8_360.cpp | 3 +- libs/fastfile/360/fastfile_cod9_360.cpp | 3 +- libs/fastfile/PC/fastfile_cod10_pc.cpp | 7 +- libs/fastfile/PC/fastfile_cod11_pc.cpp | 3 +- libs/fastfile/PC/fastfile_cod12_pc.cpp | 2 - libs/fastfile/PC/fastfile_cod21_pc.cpp | 209 +++ libs/fastfile/PC/fastfile_cod21_pc.h | 20 + libs/fastfile/PC/fastfile_cod4_pc.cpp | 5 +- libs/fastfile/PC/fastfile_cod5_pc.cpp | 3 +- libs/fastfile/PC/fastfile_cod6_pc.cpp | 3 +- libs/fastfile/PC/fastfile_cod7_pc.cpp | 22 +- libs/fastfile/PC/fastfile_cod8_pc.cpp | 3 +- libs/fastfile/PC/fastfile_cod9_pc.cpp | 3 +- libs/fastfile/PS3/fastfile_cod10_ps3.cpp | 11 +- libs/fastfile/PS3/fastfile_cod11_ps3.cpp | 3 +- libs/fastfile/PS3/fastfile_cod12_ps3.cpp | 11 +- libs/fastfile/PS3/fastfile_cod4_ps3.cpp | 3 +- libs/fastfile/PS3/fastfile_cod5_ps3.cpp | 3 +- libs/fastfile/PS3/fastfile_cod6_ps3.cpp | 3 +- libs/fastfile/PS3/fastfile_cod7_ps3.cpp | 3 +- libs/fastfile/PS3/fastfile_cod8_ps3.cpp | 11 +- libs/fastfile/PS3/fastfile_cod9_ps3.cpp | 15 +- libs/fastfile/Wii/fastfile_cod4_wii.cpp | 3 +- libs/fastfile/Wii/fastfile_cod7_wii.cpp | 5 +- libs/fastfile/Wii/fastfile_cod8_wii.cpp | 3 +- libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp | 15 +- libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp | 15 +- libs/fastfile/fastfile.cpp | 72 +- libs/fastfile/fastfile.h | 20 +- libs/fastfile/fastfile_factory.h | 83 +- libs/iwifile/iwifile.cpp | 177 +-- libs/iwifile/iwifile.h | 3 - libs/xassets/xanimdeltapart.cpp | 6 +- libs/xassets/xanimdeltapartquat.cpp | 8 +- libs/xassets/xanimdeltapartquatdata.cpp | 6 +- libs/xassets/xanimdeltapartquatdataframes.cpp | 12 +- libs/xassets/xanimdynamicframes.cpp | 12 +- libs/xassets/xanimdynamicindices.cpp | 4 +- libs/xassets/xanimindices.cpp | 11 +- libs/xassets/xanimnotifyinfo.cpp | 10 +- libs/xassets/xanimparts.cpp | 153 +- libs/xassets/xanimparts.h | 2 +- libs/xassets/xanimparttrans.cpp | 10 +- libs/xassets/xanimparttransdata.cpp | 8 +- libs/xassets/xanimparttransframes.cpp | 22 +- libs/xassets/xasset.cpp | 52 +- libs/xassets/xasset.h | 23 +- libs/xassets/xassetlist.cpp | 7 +- libs/xassets/xassettype.h | 9 +- libs/xassets/xcardmemory.cpp | 9 +- libs/xassets/xcardmemory.h | 4 +- libs/xassets/xcollisionpartition.cpp | 12 +- libs/xassets/xcollisionpartition.h | 2 +- libs/xassets/xcommoninfo.cpp | 44 + libs/xassets/xcommoninfo.h | 26 + libs/xassets/xcomworld.cpp | 14 +- libs/xassets/xcstaticmodelwritable.cpp | 9 +- libs/xassets/xcstaticmodelwritable.h | 1 - libs/xassets/xd3dindexbuffer.cpp | 14 +- libs/xassets/xd3dresource.cpp | 41 +- libs/xassets/xdmaterial.cpp | 5 +- libs/xassets/xdmaterial.h | 4 +- libs/xassets/xdobjanimmat.cpp | 12 +- libs/xassets/xdynentityclient.cpp | 9 +- libs/xassets/xdynentityclient.h | 4 +- libs/xassets/xdynentitycoll.cpp | 14 +- libs/xassets/xdynentitydef.cpp | 9 +- libs/xassets/xdynentitydef.h | 4 +- libs/xassets/xdynentitypose.cpp | 2 +- libs/xassets/xeffectdef.cpp | 23 +- libs/xassets/xeffectdef.h | 14 +- libs/xassets/xeffectdefref.cpp | 13 +- libs/xassets/xentryinternaldata.cpp | 4 +- libs/xassets/xexpressionentry.cpp | 5 +- libs/xassets/xexpressionentry.h | 2 +- libs/xassets/xfile.cpp | 17 +- libs/xassets/xfont.cpp | 7 +- libs/xassets/xfxeffectdef.cpp | 2 +- libs/xassets/xfxelematlas.cpp | 10 +- libs/xassets/xfxelemdef.cpp | 20 +- libs/xassets/xfxelemdef.h | 4 +- libs/xassets/xfxelemvec3range.cpp | 21 +- libs/xassets/xfxelemvec3range.h | 1 - libs/xassets/xfxelemvelstateinframe.cpp | 5 - libs/xassets/xfxelemvelstateinframe.h | 1 - libs/xassets/xfxfloatrange.cpp | 10 +- libs/xassets/xfxfloatrange.h | 1 - libs/xassets/xfximpactentry.cpp | 31 +- libs/xassets/xfximpactentry.h | 5 +- libs/xassets/xfximpacttable.cpp | 30 +- libs/xassets/xfximpacttable.h | 6 +- libs/xassets/xfxintrange.cpp | 10 +- libs/xassets/xfxintrange.h | 5 +- libs/xassets/xfxspawndef.cpp | 6 +- libs/xassets/xfxspawndeflooping.cpp | 10 +- libs/xassets/xfxspawndeflooping.h | 1 - libs/xassets/xfxspawndefoneshot.cpp | 9 +- libs/xassets/xfxspawndefoneshot.h | 1 - libs/xassets/xfxtraildef.cpp | 34 +- libs/xassets/xfxtraildef.h | 11 +- libs/xassets/xfxtrailvertex.cpp | 15 +- libs/xassets/xfxtrailvertex.h | 1 - libs/xassets/xgame.h | 28 +- libs/xassets/xgfxcolor.cpp | 25 +- libs/xassets/xgfxdrawsurffields.cpp | 10 +- libs/xassets/xgfxdrawsurffields.h | 2 + libs/xassets/xgfximage.cpp | 41 +- libs/xassets/xgfximage.h | 6 +- libs/xassets/xgfximageloaddef.cpp | 11 +- libs/xassets/xgfxlightdef.cpp | 5 +- libs/xassets/xgfxlightdef.h | 2 +- libs/xassets/xgfxpackedvertex.cpp | 23 +- libs/xassets/xgfxpixelshaderloaddef.cpp | 81 +- libs/xassets/xgfxpixelshaderloaddef.h | 19 +- libs/xassets/xgfxplacement.cpp | 17 +- libs/xassets/xgfxvertexshaderloaddef.cpp | 89 +- libs/xassets/xgfxvertexshaderloaddef.h | 18 +- libs/xassets/xgfxworld.cpp | 2 +- libs/xassets/xitemdef.cpp | 301 +++- libs/xassets/xitemdef.h | 58 +- libs/xassets/xitemdefdata.cpp | 5 - libs/xassets/xitemdefdata.h | 2 +- libs/xassets/xitemkeyhandler.cpp | 37 +- libs/xassets/xitemkeyhandler.h | 2 +- libs/xassets/xlistboxdef.cpp | 71 +- libs/xassets/xlistboxdef.h | 28 +- libs/xassets/xlocalizeentry.cpp | 7 +- libs/xassets/xlocalizeentry.h | 6 +- libs/xassets/xmapents.cpp | 2 +- libs/xassets/xmaterial.cpp | 183 ++- libs/xassets/xmaterial.h | 28 +- libs/xassets/xmaterialargumentdef.cpp | 7 +- libs/xassets/xmaterialargumentdef.h | 2 +- libs/xassets/xmaterialconstantdef.cpp | 11 +- libs/xassets/xmaterialinfo.cpp | 196 ++- libs/xassets/xmaterialinfo.h | 42 +- libs/xassets/xmaterialpass.cpp | 59 +- libs/xassets/xmaterialpass.h | 10 +- libs/xassets/xmaterialpixelshader.cpp | 45 +- libs/xassets/xmaterialpixelshader.h | 11 +- libs/xassets/xmaterialpixelshaderprogram.cpp | 29 +- libs/xassets/xmaterialpixelshaderprogram.h | 5 +- libs/xassets/xmaterialshaderargument.cpp | 9 +- libs/xassets/xmaterialshaderargument.h | 4 +- libs/xassets/xmaterialstreamrouting.cpp | 13 +- libs/xassets/xmaterialstreamrouting.h | 2 +- libs/xassets/xmaterialtechnique.cpp | 90 +- libs/xassets/xmaterialtechnique.h | 13 +- libs/xassets/xmaterialtechniqueset.cpp | 178 ++- libs/xassets/xmaterialtechniqueset.h | 15 +- libs/xassets/xmaterialtexturedef.cpp | 17 +- libs/xassets/xmaterialtexturedef.h | 3 +- libs/xassets/xmaterialtexturedefinfo.cpp | 13 +- .../xassets/xmaterialtexturedefsamplerstate.h | 13 + libs/xassets/xmaterialvertexdeclaration.cpp | 26 +- libs/xassets/xmaterialvertexdeclaration.h | 3 +- libs/xassets/xmaterialvertexshader.cpp | 43 +- libs/xassets/xmaterialvertexshader.h | 8 +- libs/xassets/xmaterialvertexshaderprogram.cpp | 27 +- libs/xassets/xmaterialvertexshaderprogram.h | 8 +- libs/xassets/xmaterialvertexstreamrouting.cpp | 11 +- libs/xassets/xmenudef.cpp | 86 +- libs/xassets/xmenudef.h | 5 +- libs/xassets/xmenulist.cpp | 53 +- libs/xassets/xmenulist.h | 14 +- libs/xassets/xmodel.cpp | 18 +- libs/xassets/xmodel.h | 4 +- libs/xassets/xmodellodinfo.cpp | 58 +- libs/xassets/xmodellodinfo.h | 7 +- libs/xassets/xmodelpieces.cpp | 2 +- libs/xassets/xmodelquat.cpp | 31 + libs/xassets/xmodelquat.h | 21 + libs/xassets/xmultidef.cpp | 38 +- libs/xassets/xmultidef.h | 13 +- libs/xassets/xoperand.cpp | 5 +- libs/xassets/xoperandinternaldataunion.cpp | 20 +- libs/xassets/xoperandinternaldataunion.h | 5 +- libs/xassets/xpackedtexcoords.cpp | 8 +- libs/xassets/xpackedunitvec.cpp | 9 +- libs/xassets/xpackedunitvec.h | 2 +- libs/xassets/xphyspreset.cpp | 3 +- libs/xassets/xpicmip.cpp | 28 + libs/xassets/xpicmip.h | 21 + libs/xassets/xplatform.h | 12 +- libs/xassets/xrawfile.cpp | 36 +- libs/xassets/xrawfile.h | 9 +- libs/xassets/xrigidvertlist.cpp | 91 +- libs/xassets/xrigidvertlist.h | 14 +- libs/xassets/xscriptstringlist.cpp | 23 + libs/xassets/xscriptstringlist.h | 5 + libs/xassets/xsoundaliaslist.cpp | 5 - libs/xassets/xsoundaliaslist.h | 2 +- libs/xassets/xsoundcurve.cpp | 3 +- libs/xassets/xsounddriverglobals.cpp | 1 + libs/xassets/xstatement.cpp | 48 +- libs/xassets/xstatement.h | 9 + libs/xassets/xstreamfilenameraw.cpp | 2 +- libs/xassets/xstring.cpp | 40 +- libs/xassets/xstring.h | 2 +- libs/xassets/xstringtable.cpp | 7 +- libs/xassets/xstringtable.h | 6 +- libs/xassets/xsunflare.cpp | 57 +- libs/xassets/xsunflare.h | 12 +- libs/xassets/xsurface.cpp | 112 +- libs/xassets/xsurface.h | 15 +- libs/xassets/xsurfacecollisionaabb.cpp | 22 +- libs/xassets/xsurfacecollisionleaf.cpp | 2 +- libs/xassets/xsurfacecollisionnode.cpp | 5 +- libs/xassets/xsurfacecollisiontree.cpp | 47 +- libs/xassets/xsurfacetri.cpp | 21 + libs/xassets/xsurfacetri.h | 18 + libs/xassets/xsurfacevertexinfo.cpp | 57 +- libs/xassets/xweapondef.cpp | 2 + libs/xassets/xwindowdef.cpp | 189 ++- libs/xassets/xwindowdef.h | 37 +- libs/zonefile/360/zonefile_cod10_360.cpp | 2 +- libs/zonefile/360/zonefile_cod2_360.cpp | 2 +- libs/zonefile/360/zonefile_cod5_360.cpp | 2 +- libs/zonefile/360/zonefile_cod6_360.cpp | 2 +- libs/zonefile/360/zonefile_cod9_360.cpp | 2 +- libs/zonefile/PC/zonefile_cod10_pc.cpp | 2 +- libs/zonefile/PC/zonefile_cod11_pc.cpp | 2 +- libs/zonefile/PC/zonefile_cod21_pc.cpp | 81 ++ libs/zonefile/PC/zonefile_cod21_pc.h | 16 + libs/zonefile/PC/zonefile_cod4_pc.cpp | 49 +- libs/zonefile/PC/zonefile_cod5_pc.cpp | 6 +- libs/zonefile/PC/zonefile_cod6_pc.cpp | 2 +- libs/zonefile/PC/zonefile_cod7_pc.cpp | 6 - libs/zonefile/PC/zonefile_cod7_pc.h | 3 +- libs/zonefile/PC/zonefile_cod8_pc.cpp | 2 +- libs/zonefile/PC/zonefile_cod9_pc.cpp | 2 +- libs/zonefile/PS3/zonefile_cod10_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod11_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod12_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod5_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod6_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod7_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod8_ps3.cpp | 2 +- libs/zonefile/PS3/zonefile_cod9_ps3.cpp | 2 +- libs/zonefile/Wii/zonefile_cod4_wii.cpp | 2 +- libs/zonefile/Wii/zonefile_cod7_wii.cpp | 2 +- libs/zonefile/Wii/zonefile_cod8_wii.cpp | 2 +- libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp | 2 +- libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp | 2 +- libs/zonefile/zonefile.cpp | 140 +- libs/zonefile/zonefile.h | 20 +- third_party/oodle_lib/dll/oo2core_8_win64.dll | Bin 0 -> 972792 bytes tools/asset_assess/mainwindow.cpp | 3 +- 280 files changed, 4938 insertions(+), 3380 deletions(-) create mode 100644 libs/fastfile/PC/fastfile_cod21_pc.cpp create mode 100644 libs/fastfile/PC/fastfile_cod21_pc.h create mode 100644 libs/xassets/xcommoninfo.cpp create mode 100644 libs/xassets/xcommoninfo.h create mode 100644 libs/xassets/xmaterialtexturedefsamplerstate.h create mode 100644 libs/xassets/xmodelquat.cpp create mode 100644 libs/xassets/xmodelquat.h create mode 100644 libs/xassets/xpicmip.cpp create mode 100644 libs/xassets/xpicmip.h create mode 100644 libs/xassets/xsurfacetri.cpp create mode 100644 libs/xassets/xsurfacetri.h create mode 100644 libs/zonefile/PC/zonefile_cod21_pc.cpp create mode 100644 libs/zonefile/PC/zonefile_cod21_pc.h create mode 100644 third_party/oodle_lib/dll/oo2core_8_win64.dll diff --git a/app/app.pro b/app/app.pro index 1cbef80..433d696 100644 --- a/app/app.pro +++ b/app/app.pro @@ -10,7 +10,9 @@ SOURCES += $$files($$PWD/*.cpp) HEADERS += $$files($$PWD/*.h) FORMS += $$files($$PWD/*.ui) -RESOURCES += ../data/data.qrc +RESOURCES += ../data/data.qrc \ + ../data/Data.qrc \ + data/Data.qrc LIBS += \ -L$$PWD/../third_party/devil_sdk/lib/ -lDevIL -lILU -lILUT \ @@ -21,9 +23,6 @@ LIBS += \ -L$$OUT_PWD/../libs/ -lcompression \ -L$$OUT_PWD/../libs/ -lencryption \ -L$$OUT_PWD/../libs/ -lfastfile \ - -L$$OUT_PWD/../libs/ -lddsfile \ - -L$$OUT_PWD/../libs/ -lipakfile \ - -L$$OUT_PWD/../libs/ -liwifile \ -L$$OUT_PWD/../libs/ -lzonefile INCLUDEPATH += \ @@ -34,9 +33,6 @@ INCLUDEPATH += \ $$PWD/../libs/compression \ $$PWD/../libs/encryption \ $$PWD/../libs/fastfile \ - $$PWD/../libs/ddsfile \ - $$PWD/../libs/ipakfile \ - $$PWD/../libs/iwifile \ $$PWD/../libs/xassets \ $$PWD/../libs/zonefile @@ -48,9 +44,6 @@ DEPENDPATH += \ $$PWD/../libs/compression \ $$PWD/../libs/encryption \ $$PWD/../libs/fastfile \ - $$PWD/../libs/ddsfile \ - $$PWD/../libs/ipakfile \ - $$PWD/../libs/iwifile \ $$PWD/../libs/xassets \ $$PWD/../libs/zonefile diff --git a/app/ddsviewer.cpp b/app/ddsviewer.cpp index 6cdad15..0263e37 100644 --- a/app/ddsviewer.cpp +++ b/app/ddsviewer.cpp @@ -7,176 +7,176 @@ DDSViewer::DDSViewer(QWidget *parent) , ui(new Ui::DDSViewer) { ui->setupUi(this); - mDDSFile = nullptr; + //mDDSFile = nullptr; } DDSViewer::~DDSViewer() { delete ui; } -void DDSViewer::SetDDSFile(const DDSFile* aDDSFile) { - mDDSFile = aDDSFile; +// void DDSViewer::SetDDSFile(const DDSFile* aDDSFile) { +// mDDSFile = aDDSFile; - ui->label_Title->setText(mDDSFile->fileStem + ".dds"); +// ui->label_Title->setText(mDDSFile->fileStem + ".dds"); - char magicData[5]; - magicData[0] = static_cast(mDDSFile->header.magic & 0xFF); - magicData[1] = static_cast((mDDSFile->header.magic >> 8) & 0xFF); - magicData[2] = static_cast((mDDSFile->header.magic >> 16) & 0xFF); - magicData[3] = static_cast((mDDSFile->header.magic >> 24) & 0xFF); - magicData[4] = '\0'; +// char magicData[5]; +// magicData[0] = static_cast(mDDSFile->header.magic & 0xFF); +// magicData[1] = static_cast((mDDSFile->header.magic >> 8) & 0xFF); +// magicData[2] = static_cast((mDDSFile->header.magic >> 16) & 0xFF); +// magicData[3] = static_cast((mDDSFile->header.magic >> 24) & 0xFF); +// magicData[4] = '\0'; - // If you’re using Qt and want a QString: - QString magicStr = QString::fromLatin1(magicData); - ui->lineEdit_Magic->setText(magicStr); - ui->spinBox_Size->setValue(mDDSFile->header.size); +// // If you’re using Qt and want a QString: +// QString magicStr = QString::fromLatin1(magicData); +// ui->lineEdit_Magic->setText(magicStr); +// ui->spinBox_Size->setValue(mDDSFile->header.size); - ui->checkBox_CapsValid->setChecked((mDDSFile->header.flags & DDSD_CAPS) != 0); - ui->checkBox_HeightValid->setChecked((mDDSFile->header.flags & DDSD_HEIGHT) != 0); - ui->checkBox_WidthValid->setChecked((mDDSFile->header.flags & DDSD_WIDTH) != 0); - ui->checkBox_PitchValid->setChecked((mDDSFile->header.flags & DDSD_PITCH) != 0); - ui->checkBox_PFValid->setChecked((mDDSFile->header.flags & DDSD_PIXELFORMAT) != 0); - ui->checkBox_MipmapCountValid->setChecked((mDDSFile->header.flags & DDSD_MIPMAPCOUNT) != 0); - ui->checkBox_LinearSizeValid->setChecked((mDDSFile->header.flags & DDSD_LINEARSIZE) != 0); - ui->checkBox_DepthValid->setChecked((mDDSFile->header.flags & DDSD_DEPTH) != 0); +// ui->checkBox_CapsValid->setChecked((mDDSFile->header.flags & DDSD_CAPS) != 0); +// ui->checkBox_HeightValid->setChecked((mDDSFile->header.flags & DDSD_HEIGHT) != 0); +// ui->checkBox_WidthValid->setChecked((mDDSFile->header.flags & DDSD_WIDTH) != 0); +// ui->checkBox_PitchValid->setChecked((mDDSFile->header.flags & DDSD_PITCH) != 0); +// ui->checkBox_PFValid->setChecked((mDDSFile->header.flags & DDSD_PIXELFORMAT) != 0); +// ui->checkBox_MipmapCountValid->setChecked((mDDSFile->header.flags & DDSD_MIPMAPCOUNT) != 0); +// ui->checkBox_LinearSizeValid->setChecked((mDDSFile->header.flags & DDSD_LINEARSIZE) != 0); +// ui->checkBox_DepthValid->setChecked((mDDSFile->header.flags & DDSD_DEPTH) != 0); - ui->spinBox_PLSize->setValue(mDDSFile->header.pitchOrLinearSize); - ui->spinBox_Depth->setValue(mDDSFile->header.depth); - ui->spinBox_Width->setValue(mDDSFile->header.width); - ui->spinBox_Height->setValue(mDDSFile->header.height); - ui->spinBox_MipmapCount->setValue(mDDSFile->header.mipMapCount); +// ui->spinBox_PLSize->setValue(mDDSFile->header.pitchOrLinearSize); +// ui->spinBox_Depth->setValue(mDDSFile->header.depth); +// ui->spinBox_Width->setValue(mDDSFile->header.width); +// ui->spinBox_Height->setValue(mDDSFile->header.height); +// ui->spinBox_MipmapCount->setValue(mDDSFile->header.mipMapCount); - ui->spinBox_Res1->setValue(mDDSFile->header.reserved1[0]); - ui->spinBox_Res2->setValue(mDDSFile->header.reserved1[1]); - ui->spinBox_Res3->setValue(mDDSFile->header.reserved1[2]); - ui->spinBox_Res4->setValue(mDDSFile->header.reserved1[3]); - ui->spinBox_Res5->setValue(mDDSFile->header.reserved1[4]); - ui->spinBox_Res6->setValue(mDDSFile->header.reserved1[5]); - ui->spinBox_Res7->setValue(mDDSFile->header.reserved1[6]); - ui->spinBox_Res8->setValue(mDDSFile->header.reserved1[7]); - ui->spinBox_Res9->setValue(mDDSFile->header.reserved1[8]); - ui->spinBox_Res10->setValue(mDDSFile->header.reserved1[9]); - ui->spinBox_Res11->setValue(mDDSFile->header.reserved1[10]); +// ui->spinBox_Res1->setValue(mDDSFile->header.reserved1[0]); +// ui->spinBox_Res2->setValue(mDDSFile->header.reserved1[1]); +// ui->spinBox_Res3->setValue(mDDSFile->header.reserved1[2]); +// ui->spinBox_Res4->setValue(mDDSFile->header.reserved1[3]); +// ui->spinBox_Res5->setValue(mDDSFile->header.reserved1[4]); +// ui->spinBox_Res6->setValue(mDDSFile->header.reserved1[5]); +// ui->spinBox_Res7->setValue(mDDSFile->header.reserved1[6]); +// ui->spinBox_Res8->setValue(mDDSFile->header.reserved1[7]); +// ui->spinBox_Res9->setValue(mDDSFile->header.reserved1[8]); +// ui->spinBox_Res10->setValue(mDDSFile->header.reserved1[9]); +// ui->spinBox_Res11->setValue(mDDSFile->header.reserved1[10]); - ui->spinBox_Res12->setValue(mDDSFile->header.reserved2); +// ui->spinBox_Res12->setValue(mDDSFile->header.reserved2); - ui->spinBox_PF_Size->setValue(mDDSFile->header.pixelFormat.size); +// ui->spinBox_PF_Size->setValue(mDDSFile->header.pixelFormat.size); - ui->checkBox_PF_AlphaPxValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_ALPHAPIXELS) != 0); - ui->checkBox_PF_AlphaOnlyValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_ALPHA) != 0); - ui->checkBox_PF_FormatValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_FOURCC) != 0); - ui->checkBox_PF_RGBValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_RGB) != 0); - ui->checkBox_PF_YUVValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_YUV) != 0); - ui->checkBox_PF_LuminanceValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_LUMINANCE) != 0); +// ui->checkBox_PF_AlphaPxValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_ALPHAPIXELS) != 0); +// ui->checkBox_PF_AlphaOnlyValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_ALPHA) != 0); +// ui->checkBox_PF_FormatValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_FOURCC) != 0); +// ui->checkBox_PF_RGBValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_RGB) != 0); +// ui->checkBox_PF_YUVValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_YUV) != 0); +// ui->checkBox_PF_LuminanceValid->setChecked((mDDSFile->header.pixelFormat.flags & DDPF_LUMINANCE) != 0); - QString formatStr = QString::number(mDDSFile->header.pixelFormat.format); - switch (mDDSFile->header.pixelFormat.format) { - case IWI_FORMAT_ARGB32: - formatStr = "ARGB32"; - break; - case IWI_FORMAT_RGB24: - formatStr = "RGB24"; - break; - case IWI_FORMAT_GA16: - formatStr = "GA16"; - break; - case IWI_FORMAT_A8: - formatStr = "A8"; - break; - case IWI_FORMAT_DXT1: - formatStr = "DXT1"; - break; - case IWI_FORMAT_DXT3: - formatStr = "DXT3"; - break; - case IWI_FORMAT_DXT5: - formatStr = "DXT5"; - break; - } - ui->lineEdit_PF_Format->setText(formatStr); - ui->spinBox_PF_RGBBitCount->setValue(mDDSFile->header.pixelFormat.rgbBitCount); - ui->spinBox_RedBitCount->setValue(mDDSFile->header.pixelFormat.rBitMask); - ui->spinBox_GreenBitCount->setValue(mDDSFile->header.pixelFormat.gBitMask); - ui->spinBox_BlueBitCount->setValue(mDDSFile->header.pixelFormat.bBitMask); - ui->spinBox_AlphaBitMask->setValue(mDDSFile->header.pixelFormat.aBitMask); +// QString formatStr = QString::number(mDDSFile->header.pixelFormat.format); +// switch (mDDSFile->header.pixelFormat.format) { +// case IWI_FORMAT_ARGB32: +// formatStr = "ARGB32"; +// break; +// case IWI_FORMAT_RGB24: +// formatStr = "RGB24"; +// break; +// case IWI_FORMAT_GA16: +// formatStr = "GA16"; +// break; +// case IWI_FORMAT_A8: +// formatStr = "A8"; +// break; +// case IWI_FORMAT_DXT1: +// formatStr = "DXT1"; +// break; +// case IWI_FORMAT_DXT3: +// formatStr = "DXT3"; +// break; +// case IWI_FORMAT_DXT5: +// formatStr = "DXT5"; +// break; +// } +// ui->lineEdit_PF_Format->setText(formatStr); +// ui->spinBox_PF_RGBBitCount->setValue(mDDSFile->header.pixelFormat.rgbBitCount); +// ui->spinBox_RedBitCount->setValue(mDDSFile->header.pixelFormat.rBitMask); +// ui->spinBox_GreenBitCount->setValue(mDDSFile->header.pixelFormat.gBitMask); +// ui->spinBox_BlueBitCount->setValue(mDDSFile->header.pixelFormat.bBitMask); +// ui->spinBox_AlphaBitMask->setValue(mDDSFile->header.pixelFormat.aBitMask); - ui->checkBox_Caps1_TextureValid->setChecked((mDDSFile->header.caps.caps1 & DDSCAPS_TEXTURE) != 0); - ui->checkBox_Caps1_ComplexValid->setChecked((mDDSFile->header.caps.caps1 & DDSCAPS_COMPLEX) != 0); - ui->checkBox_Caps1_MipmapValid->setChecked((mDDSFile->header.caps.caps1 & DDSCAPS_MIPMAP) != 0); +// ui->checkBox_Caps1_TextureValid->setChecked((mDDSFile->header.caps.caps1 & DDSCAPS_TEXTURE) != 0); +// ui->checkBox_Caps1_ComplexValid->setChecked((mDDSFile->header.caps.caps1 & DDSCAPS_COMPLEX) != 0); +// ui->checkBox_Caps1_MipmapValid->setChecked((mDDSFile->header.caps.caps1 & DDSCAPS_MIPMAP) != 0); - ui->checkBox_Caps2_CubemapValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0); - ui->checkBox_Caps2_CMPXValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) != 0); - ui->checkBox_Caps2_CMNXValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) != 0); - ui->checkBox_Caps2_CMPYValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) != 0); - ui->checkBox_Caps2_CMNYValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) != 0); - ui->checkBox_Caps2_CMPZValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) != 0); - ui->checkBox_Caps2_CMNZValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) != 0); - ui->checkBox_Caps2_VolumeValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_VOLUME) != 0); +// ui->checkBox_Caps2_CubemapValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0); +// ui->checkBox_Caps2_CMPXValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) != 0); +// ui->checkBox_Caps2_CMNXValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) != 0); +// ui->checkBox_Caps2_CMPYValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) != 0); +// ui->checkBox_Caps2_CMNYValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) != 0); +// ui->checkBox_Caps2_CMPZValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) != 0); +// ui->checkBox_Caps2_CMNZValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) != 0); +// ui->checkBox_Caps2_VolumeValid->setChecked((mDDSFile->header.caps.caps2 & DDSCAPS2_VOLUME) != 0); - ui->spinBox_Caps_DDSX->setValue(mDDSFile->header.caps.dDSX); - ui->spinBox_Caps_Res->setValue(mDDSFile->header.caps.reserved); +// ui->spinBox_Caps_DDSX->setValue(mDDSFile->header.caps.dDSX); +// ui->spinBox_Caps_Res->setValue(mDDSFile->header.caps.reserved); - ui->comboBox_Mipmap->clear(); - for (auto mipmap : mDDSFile->mipmaps) { - ui->comboBox_Mipmap->addItem(QString("%1x%2").arg(mipmap.width).arg(mipmap.height)); - } +// ui->comboBox_Mipmap->clear(); +// for (auto mipmap : mDDSFile->mipmaps) { +// ui->comboBox_Mipmap->addItem(QString("%1x%2").arg(mipmap.width).arg(mipmap.height)); +// } - connect(ui->comboBox_Mipmap, &QComboBox::currentIndexChanged, this, &DDSViewer::MipmapIndexChanged); +// connect(ui->comboBox_Mipmap, &QComboBox::currentIndexChanged, this, &DDSViewer::MipmapIndexChanged); - if (!mDDSFile->mipmaps.empty()) { - MipmapIndexChanged(0); - } -} +// if (!mDDSFile->mipmaps.empty()) { +// MipmapIndexChanged(0); +// } +// } -void DDSViewer::MipmapIndexChanged(int aMipmapIndex) { - if (aMipmapIndex == -1) { return; } +// void DDSViewer::MipmapIndexChanged(int aMipmapIndex) { +// if (aMipmapIndex == -1) { return; } - auto mipmaps = mDDSFile->mipmaps; - auto mipmap = mipmaps[aMipmapIndex]; +// auto mipmaps = mDDSFile->mipmaps; +// auto mipmap = mipmaps[aMipmapIndex]; - ui->spinBox_MipmapSize->setValue(mipmap.size); - ui->spinBox_MipmapWidth->setValue(mipmap.width); - ui->spinBox_MipmapHeight->setValue(mipmap.height); +// ui->spinBox_MipmapSize->setValue(mipmap.size); +// ui->spinBox_MipmapWidth->setValue(mipmap.width); +// ui->spinBox_MipmapHeight->setValue(mipmap.height); - // Validate Data - if (mipmap.size <= 0) { - qDebug() << "Error: Mipmap data is empty!"; - return; - } - if (mipmap.width <= 0 || mipmap.height <= 0) { - qDebug() << "Error: Invalid mipmap dimensions!"; - return; - } +// // Validate Data +// if (mipmap.size <= 0) { +// qDebug() << "Error: Mipmap data is empty!"; +// return; +// } +// if (mipmap.width <= 0 || mipmap.height <= 0) { +// qDebug() << "Error: Invalid mipmap dimensions!"; +// return; +// } - // Ensure data size matches expected size - int bytesPerPixel = 4; // RGBA8888 - quint32 expectedSize = mipmap.width * mipmap.height * bytesPerPixel; - if (mipmap.size < expectedSize) { - qDebug() << "Error: Mipmap data size mismatch! Expected:" << expectedSize << ", Got:" << mipmap.size; - return; - } +// // Ensure data size matches expected size +// int bytesPerPixel = 4; // RGBA8888 +// quint32 expectedSize = mipmap.width * mipmap.height * bytesPerPixel; +// if (mipmap.size < expectedSize) { +// qDebug() << "Error: Mipmap data size mismatch! Expected:" << expectedSize << ", Got:" << mipmap.size; +// return; +// } - // Create QImage - const unsigned char* imageData = reinterpret_cast(mipmap.data.constData()); - QImage image(reinterpret_cast(imageData), - mipmap.width, mipmap.height, - mipmap.width * bytesPerPixel, // Stride - QImage::Format_RGBA8888); +// // Create QImage +// const unsigned char* imageData = reinterpret_cast(mipmap.data.constData()); +// QImage image(reinterpret_cast(imageData), +// mipmap.width, mipmap.height, +// mipmap.width * bytesPerPixel, // Stride +// QImage::Format_RGBA8888); - if (image.isNull()) { - qDebug() << "Error: QImage creation failed!"; - return; - } +// if (image.isNull()) { +// qDebug() << "Error: QImage creation failed!"; +// return; +// } - // Convert to QPixmap - QPixmap pixmap = QPixmap::fromImage(image); - if (pixmap.isNull()) { - qDebug() << "Error: QPixmap conversion failed!"; - return; - } +// // Convert to QPixmap +// QPixmap pixmap = QPixmap::fromImage(image); +// if (pixmap.isNull()) { +// qDebug() << "Error: QPixmap conversion failed!"; +// return; +// } - // Scale and display - pixmap = pixmap.scaled(ui->label_Image->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); - ui->label_Image->setPixmap(pixmap); -} +// // Scale and display +// pixmap = pixmap.scaled(ui->label_Image->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); +// ui->label_Image->setPixmap(pixmap); +// } diff --git a/app/ddsviewer.h b/app/ddsviewer.h index d5b8ce0..33ce1a4 100644 --- a/app/ddsviewer.h +++ b/app/ddsviewer.h @@ -1,7 +1,6 @@ #ifndef DDSVIEWER_H #define DDSVIEWER_H -#include "ddsfile.h" #include namespace Ui { @@ -16,14 +15,14 @@ public: explicit DDSViewer(QWidget *parent = nullptr); ~DDSViewer(); - void SetDDSFile(const DDSFile *aDDSFile); + //void SetDDSFile(const DDSFile *aDDSFile); private slots: - void MipmapIndexChanged(int aMipmapIndex); + //void MipmapIndexChanged(int aMipmapIndex); private: Ui::DDSViewer *ui; - const DDSFile* mDDSFile; + //const DDSFile* mDDSFile; }; #endif // DDSVIEWER_H diff --git a/app/imagewidget.h b/app/imagewidget.h index 22be24c..c65a64a 100644 --- a/app/imagewidget.h +++ b/app/imagewidget.h @@ -2,9 +2,9 @@ #define IMAGEWIDGET_H #include "enums.h" -#include "dds_structs.h" +//#include "dds_structs.h" #include "d3dbsp_structs.h" -#include "ipak_structs.h" +//#include "ipak_structs.h" #include diff --git a/app/iwiviewer.cpp b/app/iwiviewer.cpp index e4b9c3e..f80b3e0 100644 --- a/app/iwiviewer.cpp +++ b/app/iwiviewer.cpp @@ -14,85 +14,85 @@ IWIViewer::~IWIViewer() delete ui; } -void IWIViewer::SetIWIFile(const IWIFile* aIWIFile) { - mIWIFile = aIWIFile; +// void IWIViewer::SetIWIFile(const IWIFile* aIWIFile) { +// mIWIFile = aIWIFile; - ui->label_Title->setText(mIWIFile->fileStem + ".iwi"); +// ui->label_Title->setText(mIWIFile->fileStem + ".iwi"); - // If you’re using Qt and want a QString: - QString magicStr = QString::fromLatin1(mIWIFile->header.Magic, 3); - ui->lineEdit_Magic->setText(magicStr); +// // If you’re using Qt and want a QString: +// QString magicStr = QString::fromLatin1(mIWIFile->header.Magic, 3); +// ui->lineEdit_Magic->setText(magicStr); - ui->spinBox_Version->setValue(mIWIFile->header.Version); - ui->spinBox_Depth->setValue(mIWIFile->info.Depth); - QString formatStr = ""; - switch (mIWIFile->info.Format) { - case IWI_FORMAT_ARGB32: - formatStr = "ARGB32"; - break; - case IWI_FORMAT_RGB24: - formatStr = "RGB24"; - break; - case IWI_FORMAT_GA16: - formatStr = "GA16"; - break; - case IWI_FORMAT_A8: - formatStr = "A8"; - break; - case IWI_FORMAT_DXT1: - formatStr = "DXT1"; - break; - case IWI_FORMAT_DXT3: - formatStr = "DXT3"; - break; - case IWI_FORMAT_DXT5: - formatStr = "DXT5"; - break; - } - ui->lineEdit_Format->setText(formatStr); - ui->spinBox_Height->setValue(mIWIFile->info.Height); - ui->spinBox_Width->setValue(mIWIFile->info.Width); - ui->spinBox_Usage->setValue(mIWIFile->info.Usage); +// ui->spinBox_Version->setValue(mIWIFile->header.Version); +// ui->spinBox_Depth->setValue(mIWIFile->info.Depth); +// QString formatStr = ""; +// switch (mIWIFile->info.Format) { +// case IWI_FORMAT_ARGB32: +// formatStr = "ARGB32"; +// break; +// case IWI_FORMAT_RGB24: +// formatStr = "RGB24"; +// break; +// case IWI_FORMAT_GA16: +// formatStr = "GA16"; +// break; +// case IWI_FORMAT_A8: +// formatStr = "A8"; +// break; +// case IWI_FORMAT_DXT1: +// formatStr = "DXT1"; +// break; +// case IWI_FORMAT_DXT3: +// formatStr = "DXT3"; +// break; +// case IWI_FORMAT_DXT5: +// formatStr = "DXT5"; +// break; +// } +// ui->lineEdit_Format->setText(formatStr); +// ui->spinBox_Height->setValue(mIWIFile->info.Height); +// ui->spinBox_Width->setValue(mIWIFile->info.Width); +// ui->spinBox_Usage->setValue(mIWIFile->info.Usage); - ui->comboBox_Mipmap->clear(); - for (auto mipmap : mIWIFile->mipmaps) { - ui->comboBox_Mipmap->addItem(QString::number(mipmap.offset)); - } +// ui->comboBox_Mipmap->clear(); +// for (auto mipmap : mIWIFile->mipmaps) { +// ui->comboBox_Mipmap->addItem(QString::number(mipmap.offset)); +// } - connect(ui->comboBox_Mipmap, &QComboBox::currentIndexChanged, this, &IWIViewer::MipmapIndexChanged); +// connect(ui->comboBox_Mipmap, &QComboBox::currentIndexChanged, this, &IWIViewer::MipmapIndexChanged); - if (!mIWIFile->mipmaps.empty()) { - MipmapIndexChanged(0); - } -} +// if (!mIWIFile->mipmaps.empty()) { +// MipmapIndexChanged(0); +// } +// } -void IWIViewer::MipmapIndexChanged(int aMipmapIndex) { - auto mipmaps = mIWIFile->mipmaps; +// void IWIViewer::MipmapIndexChanged(int aMipmapIndex) { +// auto mipmaps = mIWIFile->mipmaps; - if (aMipmapIndex == -1) { return; } +// if (aMipmapIndex == -1) { return; } - auto mipmap = mipmaps[aMipmapIndex]; - ui->spinBox_MipmapSize->setValue(mipmap.size); - ui->spinBox_MipmapOffset->setValue(mipmap.offset); +// auto mipmap = mipmaps[aMipmapIndex]; +// ui->spinBox_MipmapSize->setValue(mipmap.size); +// ui->spinBox_MipmapOffset->setValue(mipmap.offset); - const unsigned char* imageData = reinterpret_cast(mipmap.data.constData()); - QImage image(reinterpret_cast(imageData), - mIWIFile->info.Width, mIWIFile->info.Height, - QImage::Format_RGBA8888); +// const unsigned char* imageData = reinterpret_cast(mipmap.data.constData()); +// QImage image(reinterpret_cast(imageData), +// mIWIFile->info.Width, mIWIFile->info.Height, +// QImage::Format_RGBA8888); - if (image.isNull()) { - qDebug() << "Error: QImage creation failed!"; - return; - } +// if (image.isNull()) { +// qDebug() << "Error: QImage creation failed!"; +// return; +// } - // Convert to QPixmap - QPixmap pixmap = QPixmap::fromImage(image); - if (pixmap.isNull()) { - qDebug() << "Error: QPixmap conversion failed!"; - return; - } +// // Convert to QPixmap +// QPixmap pixmap = QPixmap::fromImage(image); +// if (pixmap.isNull()) { +// qDebug() << "Error: QPixmap conversion failed!"; +// return; +// } - // Scale and display - pixmap = pixmap.scaled(ui->label_Image->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); - ui->label_Image->setPixmap(pixmap); -} +// // Scale and display +// pixmap = pixmap.scaled(ui->label_Image->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); +// ui->label_Image->setPixmap(pixmap); +// } diff --git a/app/iwiviewer.h b/app/iwiviewer.h index f83982f..1f7d814 100644 --- a/app/iwiviewer.h +++ b/app/iwiviewer.h @@ -1,7 +1,7 @@ #ifndef IWIVIEWER_H #define IWIVIEWER_H -#include "iwifile.h" +//#include "iwifile.h" #include namespace Ui { @@ -18,10 +18,10 @@ public: void MipmapIndexChanged(int aMipmapIndex); - void SetIWIFile(const IWIFile *aIWIFile); + //void SetIWIFile(const IWIFile *aIWIFile); private: Ui::IWIViewer *ui; - const IWIFile* mIWIFile; + //const IWIFile* mIWIFile; }; #endif // IWIVIEWER_H diff --git a/app/localstringviewer.cpp b/app/localstringviewer.cpp index 1563ed2..0202b0f 100644 --- a/app/localstringviewer.cpp +++ b/app/localstringviewer.cpp @@ -42,7 +42,7 @@ void LocalStringViewer::AddLocalString(XLocalizeEntry aLocalString) { ui->tableWidget_Strings->setRowCount(mLocalStrings.size()); ui->groupBox_LocalStrViewer->setTitle(QString("Entries (%1)").arg(mLocalStrings.size())); QTableWidgetItem *aliasItem = new QTableWidgetItem(aLocalString.GetValue()->GetString()); - QTableWidgetItem *stringItem = new QTableWidgetItem(aLocalString.GetName()->GetString()); + QTableWidgetItem *stringItem = new QTableWidgetItem(aLocalString.LocalizeEntryName()->GetString()); ui->tableWidget_Strings->setItem(mLocalStrings.size() - 1, 0, aliasItem); ui->tableWidget_Strings->setItem(mLocalStrings.size() - 1, 1, stringItem); } diff --git a/app/mainwindow.cpp b/app/mainwindow.cpp index c177e21..b9b91af 100644 --- a/app/mainwindow.cpp +++ b/app/mainwindow.cpp @@ -15,12 +15,8 @@ #include "stringtableviewer.h" #include "techsetviewer.h" #include "fastfile_factory.h" -#include "iwifile.h" -#include "ddsfile.h" #include "statusbarmanager.h" -#include "ddsviewer.h" #include "fastfileviewer.h" -#include "ipak_structs.h" #include "iwiviewer.h" #include "localstringviewer.h" #include "zonefileviewer.h" @@ -33,9 +29,9 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); - setAcceptDrops(true); + XAsset::SetDebug(false); - XAsset::SetDebug(true); + setAcceptDrops(true); mTypeMap = QMap(); mTypeOrder = QStringList(); @@ -82,6 +78,11 @@ MainWindow::MainWindow(QWidget *parent) Q_UNUSED(checked); PreferenceEditor *prefEditor = new PreferenceEditor(this); + + connect(prefEditor, &PreferenceEditor::DebugModeChanged, this, [](bool aEnable) { + XAsset::SetDebug(aEnable); + }); + prefEditor->exec(); }); @@ -168,13 +169,13 @@ MainWindow::MainWindow(QWidget *parent) scriptEditor->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); scriptEditor->setFont(QFont("Consolas")); - // if (rawFile->contents.isEmpty()) { - // scriptEditor->setPlainText("EMPTY"); - // } else { - // scriptEditor->setPlainText(rawFile->contents); - // } + if (rawFile->Buffer().isEmpty()) { + scriptEditor->setPlainText("EMPTY"); + } else { + scriptEditor->setPlainText(QString::fromUtf8(rawFile->Buffer())); + } - QString fileStem;// = rawFile->path.split('/').last(); + QString fileStem = rawFile->DisplayName().split('/').last(); for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { delete scriptEditor; @@ -265,48 +266,48 @@ MainWindow::MainWindow(QWidget *parent) // } // } - //ui->tabWidget->addTab(matViewer, fileStem); + ui->tabWidget->addTab(matViewer, aParentName); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, Utils::CreateAssetIcon(ASSET_TYPE_MATERIAL)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); - connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](const DDSFile* ddsFile, const QString aParentName) { - DDSViewer *ddsViewer = new DDSViewer(this); - ddsViewer->setAcceptDrops(false); - ddsViewer->SetDDSFile(ddsFile); - ddsViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); + //connect(mTreeWidget, &XTreeWidget::DDSFileSelected, this, [this](const DDSFile* ddsFile, const QString aParentName) { + // DDSViewer *ddsViewer = new DDSViewer(this); + // ddsViewer->setAcceptDrops(false); + // ddsViewer->SetDDSFile(ddsFile); + // ddsViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - QString fileStem = ddsFile->fileStem + ".dds"; - for (int i = 0; i < ui->tabWidget->count(); i++) { - if (ui->tabWidget->tabText(i) == fileStem) { - delete ddsViewer; - return; - } - } + // QString fileStem = ddsFile->fileStem + ".dds"; + // for (int i = 0; i < ui->tabWidget->count(); i++) { + // if (ui->tabWidget->tabText(i) == fileStem) { + // delete ddsViewer; + // return; + // } + // } - ui->tabWidget->addTab(ddsViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); - ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); - }); + // ui->tabWidget->addTab(ddsViewer, fileStem); + // ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); + // ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); + //}); - connect(mTreeWidget, &XTreeWidget::IWIFileSelected, this, [this](const IWIFile* iwiFile, const QString aParentName) { - IWIViewer *iwiViewer = new IWIViewer(this); - iwiViewer->setAcceptDrops(false); - iwiViewer->SetIWIFile(iwiFile); - iwiViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); + // connect(mTreeWidget, &XTreeWidget::IWIFileSelected, this, [this](const IWIFile* iwiFile, const QString aParentName) { + // IWIViewer *iwiViewer = new IWIViewer(this); + // iwiViewer->setAcceptDrops(false); + // iwiViewer->SetIWIFile(iwiFile); + // iwiViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - QString fileStem = iwiFile->fileStem + ".iwi"; - for (int i = 0; i < ui->tabWidget->count(); i++) { - if (ui->tabWidget->tabText(i) == fileStem) { - delete iwiViewer; - return; - } - } + // QString fileStem = iwiFile->fileStem + ".iwi"; + // for (int i = 0; i < ui->tabWidget->count(); i++) { + // if (ui->tabWidget->tabText(i) == fileStem) { + // delete iwiViewer; + // return; + // } + // } - ui->tabWidget->addTab(iwiViewer, fileStem); - ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); - ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); - }); + // ui->tabWidget->addTab(iwiViewer, fileStem); + // ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); + // ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); + // }); connect(mTreeWidget, &XTreeWidget::FastFileSelected, this, [this](const FastFile* aFastFile, const QString aParentName) { FastFileViewer *fastFileViewer = new FastFileViewer(this); @@ -383,7 +384,7 @@ MainWindow::MainWindow(QWidget *parent) techSetViewer->SetTechSet(aTechSet); techSetViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - QString fileStem = aTechSet->GetName(); + QString fileStem = aTechSet->TechniqueSetName().GetString(); for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { delete techSetViewer; @@ -391,7 +392,7 @@ MainWindow::MainWindow(QWidget *parent) } } - ui->tabWidget->addTab(techSetViewer, aTechSet->GetName()); + ui->tabWidget->addTab(techSetViewer, aTechSet->TechniqueSetName().GetString()); ui->tabWidget->setTabIcon(ui->tabWidget->count() - 1, Utils::CreateAssetIcon(ASSET_TYPE_TECHNIQUE_SET)); ui->tabWidget->setCurrentIndex(ui->tabWidget->count() - 1); }); @@ -402,7 +403,7 @@ MainWindow::MainWindow(QWidget *parent) strTableViewer->SetStringTable(aStrTable); strTableViewer->setProperty("PARENT_NAME", QVariant::fromValue(aParentName)); - QString fileStem = aStrTable->GetName()->GetString(); + QString fileStem = aStrTable->StringTableName()->GetString(); for (int i = 0; i < ui->tabWidget->count(); i++) { if (ui->tabWidget->tabText(i) == fileStem) { delete strTableViewer; @@ -482,7 +483,7 @@ MainWindow::MainWindow(QWidget *parent) QDockWidget *logDockWidget = new QDockWidget(this); logDockWidget->setWidget(mLogWidget); logDockWidget->setWindowTitle("Logs"); - addDockWidget(Qt::RightDockWidgetArea, logDockWidget); + addDockWidget(Qt::BottomDockWidgetArea, logDockWidget); ui->toolBar->addAction(ui->actionNew_Fast_File); ui->toolBar->addAction(ui->actionNew_Zone_File); @@ -673,21 +674,21 @@ quint32 DXT3 = 0x33545844; // 'DXT3' quint32 DXT5 = 0x35545844; // 'DXT5' int MainWindow::LoadFile_IWI(const QString aFilePath) { - mTreeWidget->AddIWIFile(new IWIFile(aFilePath)); + //mTreeWidget->AddIWIFile(new IWIFile(aFilePath)); return 0; } -int MainWindow::LoadFile_DDSFiles(const QStringList aFilePaths) { - for (const QString &filePath : aFilePaths) { - if (!filePath.endsWith(".dds", Qt::CaseInsensitive)) { - qDebug() << "Error: Invalid filename " << filePath; - return -1; - } - mTreeWidget->AddDDSFile(new DDSFile(filePath)); - } - return 0; -} +// int MainWindow::LoadFile_DDSFiles(const QStringList aFilePaths) { +// for (const QString &filePath : aFilePaths) { +// if (!filePath.endsWith(".dds", Qt::CaseInsensitive)) { +// qDebug() << "Error: Invalid filename " << filePath; +// return -1; +// } +// mTreeWidget->AddDDSFile(new DDSFile(filePath)); +// } +// return 0; +// } void MainWindow::HandleLogEntry(const QString &entry) { QString logContents = mLogWidget->toPlainText() + "\n" + entry; @@ -711,14 +712,14 @@ void MainWindow::HandleProgressUpdate(const QString &message, int progress, int statusBar()->showMessage(progressText); } -int MainWindow::LoadFile_DDS(const QString aFilePath) { - if (!aFilePath.endsWith(".dds", Qt::CaseInsensitive)) { - qDebug() << "Error: Invalid filename " << aFilePath; - return -1; - } - mTreeWidget->AddDDSFile(new DDSFile(aFilePath)); - return 0; -} +// int MainWindow::LoadFile_DDS(const QString aFilePath) { +// if (!aFilePath.endsWith(".dds", Qt::CaseInsensitive)) { +// qDebug() << "Error: Invalid filename " << aFilePath; +// return -1; +// } +// mTreeWidget->AddDDSFile(new DDSFile(aFilePath)); +// return 0; +// } int MainWindow::LoadFile_XSUB(const QString aFilePath) { QFile file(aFilePath); @@ -757,130 +758,130 @@ int MainWindow::LoadFile_IPAK(const QString aFilePath) { QDataStream stream(&file); stream.setByteOrder(QDataStream::BigEndian); - IPAKHeader header; - stream >> header; + // IPAKHeader header; + // stream >> header; - if (header.version == "50000") { - if (header.magic == "KAPI") { - stream.setByteOrder(QDataStream::LittleEndian); - } else if (header.magic == "IPAK") { - stream.setByteOrder(QDataStream::BigEndian); - } else { - qDebug() << "Invalid IPAK file!"; - return -1; - } - } else { - qDebug() << "Invalid IPAK file version!"; - return -1; - } + // if (header.version == "50000") { + // if (header.magic == "KAPI") { + // stream.setByteOrder(QDataStream::LittleEndian); + // } else if (header.magic == "IPAK") { + // stream.setByteOrder(QDataStream::BigEndian); + // } else { + // qDebug() << "Invalid IPAK file!"; + // return -1; + // } + // } else { + // qDebug() << "Invalid IPAK file version!"; + // return -1; + // } - qDebug() << "IPAK File " << "\n" - << "- Platform: " << header.platform << "\n" - << "- Magic: " << header.magic << "\n" - << "- Size: " << header.size << "\n" - << "- Version: " << header.version << "\n" - << "- Sections: " << header.sectionCount; + // qDebug() << "IPAK File " << "\n" + // << "- Platform: " << header.platform << "\n" + // << "- Magic: " << header.magic << "\n" + // << "- Size: " << header.size << "\n" + // << "- Version: " << header.version << "\n" + // << "- Sections: " << header.sectionCount; - QDir outputFolder = QDir(QDir::currentPath() + "/output"); - outputFolder.remove(QDir::currentPath() + "/output"); - outputFolder.mkdir(QDir::currentPath() + "/output"); + // QDir outputFolder = QDir(QDir::currentPath() + "/output"); + // outputFolder.remove(QDir::currentPath() + "/output"); + // outputFolder.mkdir(QDir::currentPath() + "/output"); - QVector metas = QVector(); + // QVector metas = QVector(); - QVector entries = QVector(); - QVector sections = QVector(header.sectionCount); - for (quint32 i = 0; i < header.sectionCount; i++) { - IPAKSection currentSection; - stream >> currentSection; - sections << currentSection; + // QVector entries = QVector(); + // QVector sections = QVector(header.sectionCount); + // for (quint32 i = 0; i < header.sectionCount; i++) { + // IPAKSection currentSection; + // stream >> currentSection; + // sections << currentSection; - qDebug() << " - IPAK Section " << i + 1 << "\n" - << " - Type: " << currentSection.type << " -> " << currentSection.typeInt << "\n" - << " - Offset: " << currentSection.offset << "\n" - << " - Item (IWI) Count: " << currentSection.itemCount << "\n" - << " - Size: " << currentSection.size; + // qDebug() << " - IPAK Section " << i + 1 << "\n" + // << " - Type: " << currentSection.type << " -> " << currentSection.typeInt << "\n" + // << " - Offset: " << currentSection.offset << "\n" + // << " - Item (IWI) Count: " << currentSection.itemCount << "\n" + // << " - Size: " << currentSection.size; - qint64 sectionPos = stream.device()->pos(); - stream.device()->seek(currentSection.offset); + // qint64 sectionPos = stream.device()->pos(); + // stream.device()->seek(currentSection.offset); - QString sectionType = currentSection.type; - if (sectionType == "Data") { - IPAKDataChunkHeader chunkHeader; - stream >> chunkHeader; - qDebug() << " - Chunk Header\n" - << " - Count: " << chunkHeader.count << "\n" - << " - Offset: " << chunkHeader.offset; + // QString sectionType = currentSection.type; + // if (sectionType == "Data") { + // IPAKDataChunkHeader chunkHeader; + // stream >> chunkHeader; + // qDebug() << " - Chunk Header\n" + // << " - Count: " << chunkHeader.count << "\n" + // << " - Offset: " << chunkHeader.offset; - for (quint32 j = 0; j < 31; j++) { - IPAKDataChunkCommand command; - stream >> command; - if (!command.size) { continue; } - chunkHeader.commands << command; - qDebug() << " - Command\n" - << " - Size: " << command.size << "\n" - << " - Compressed: " << command.compressed; + // for (quint32 j = 0; j < 31; j++) { + // IPAKDataChunkCommand command; + // stream >> command; + // if (!command.size) { continue; } + // chunkHeader.commands << command; + // qDebug() << " - Command\n" + // << " - Size: " << command.size << "\n" + // << " - Compressed: " << command.compressed; - } - for (quint32 j = 0; j < chunkHeader.count; j++) { - auto command = chunkHeader.commands[j]; + // } + // for (quint32 j = 0; j < chunkHeader.count; j++) { + // auto command = chunkHeader.commands[j]; - qDebug() << "Reading from " << stream.device()->pos(); - QByteArray data = stream.device()->read(command.size); - qDebug() << " to " << stream.device()->pos(); + // qDebug() << "Reading from " << stream.device()->pos(); + // QByteArray data = stream.device()->read(command.size); + // qDebug() << " to " << stream.device()->pos(); - QString outputFilePath = outputFolder.filePath(QString("%1.iwi").arg(j)); - if (command.compressed) { - //data = Compression::DecompressLZO(data); - } - QFile outputFile(outputFilePath); - if (!outputFile.open(QIODevice::WriteOnly)) { - qDebug() << "Failed to extract IPAK file."; - } - qDebug() << " - File Name: " << outputFile.fileName(); - outputFile.write(data); - outputFile.close(); - } + // QString outputFilePath = outputFolder.filePath(QString("%1.iwi").arg(j)); + // if (command.compressed) { + // //data = Compression::DecompressLZO(data); + // } + // QFile outputFile(outputFilePath); + // if (!outputFile.open(QIODevice::WriteOnly)) { + // qDebug() << "Failed to extract IPAK file."; + // } + // qDebug() << " - File Name: " << outputFile.fileName(); + // outputFile.write(data); + // outputFile.close(); + // } - qDebug() << stream.device()->pos(); - stream.skipRawData(sizeof(quint32) * (31 - chunkHeader.count)); - qDebug() << stream.device()->pos(); - } else if (sectionType == "Index") { - for (quint32 j = 0; j < currentSection.itemCount; j++) { - IPAKIndexEntry entry; - stream >> entry; + // qDebug() << stream.device()->pos(); + // stream.skipRawData(sizeof(quint32) * (31 - chunkHeader.count)); + // qDebug() << stream.device()->pos(); + // } else if (sectionType == "Index") { + // for (quint32 j = 0; j < currentSection.itemCount; j++) { + // IPAKIndexEntry entry; + // stream >> entry; - if (entry.size == 0) { continue; } + // if (entry.size == 0) { continue; } - entries << entry; + // entries << entry; - quint64 entryPos = stream.device()->pos(); - qDebug() << " - Index Entry " << j + 1 << "\n" - << " - Name Hash: " << entry.nameHash << "\n" - << " - Data Hash: " << entry.dataHash << "\n" - << " - Offset: " << entry.offset << "\n" - << " - Size: " << entry.size; + // quint64 entryPos = stream.device()->pos(); + // qDebug() << " - Index Entry " << j + 1 << "\n" + // << " - Name Hash: " << entry.nameHash << "\n" + // << " - Data Hash: " << entry.dataHash << "\n" + // << " - Offset: " << entry.offset << "\n" + // << " - Size: " << entry.size; - stream.device()->seek(entry.offset); + // stream.device()->seek(entry.offset); - QByteArray sectionData(entry.size, Qt::Uninitialized); - stream.readRawData(sectionData.data(), entry.size); + // QByteArray sectionData(entry.size, Qt::Uninitialized); + // stream.readRawData(sectionData.data(), entry.size); - const QString entryKey = QString::number(entry.nameHash); - QFile outputFile(outputFolder.filePath(QString("%1.dds").arg(entryKey))); - if (!outputFile.open(QIODevice::WriteOnly)) { - qDebug() << "Failed to extract IPAK file."; - } - qDebug() << " - File Name: " << outputFile.fileName(); - outputFile.write(sectionData); - outputFile.close(); + // const QString entryKey = QString::number(entry.nameHash); + // QFile outputFile(outputFolder.filePath(QString("%1.dds").arg(entryKey))); + // if (!outputFile.open(QIODevice::WriteOnly)) { + // qDebug() << "Failed to extract IPAK file."; + // } + // qDebug() << " - File Name: " << outputFile.fileName(); + // outputFile.write(sectionData); + // outputFile.close(); - stream.device()->seek(entryPos); - } - } - stream.device()->seek(sectionPos); - qDebug() << stream.device()->pos(); - } + // stream.device()->seek(entryPos); + // } + // } + // stream.device()->seek(sectionPos); + // qDebug() << stream.device()->pos(); + // } return 0; // Success } @@ -891,6 +892,7 @@ void MainWindow::dragEnterEvent(QDragEnterEvent *event) { if (mimeData->hasUrls()) { foreach (const QUrl url, mimeData->urls()) { if (!url.toString().contains(".ff") && + !url.toString().contains(".fp") && !url.toString().contains(".zone") && !url.toString().contains(".ipak") && !url.toString().contains(".d3dbsp") && @@ -925,7 +927,7 @@ void MainWindow::dropEvent(QDropEvent *event) { const QString urlStr = url.toLocalFile(); if (urlStr.contains(".zone")) { qDebug() << "OpenZoneFile Returned: " << OpenZoneFile(urlStr); - } else if (urlStr.contains(".ff")) { + } else if (urlStr.contains(".ff") || urlStr.contains(".fp")) { qDebug() << "OpenFastFile Returned: " << OpenFastFile(urlStr); } else if (urlStr.contains(".ipak")) { qDebug() << "LoadFile_IPAK Returned: " << LoadFile_IPAK(urlStr); @@ -935,7 +937,7 @@ void MainWindow::dropEvent(QDropEvent *event) { qDebug() << "LoadFile_IWI Returned: " << LoadFile_IWI(urlStr); } else if (urlStr.contains(".dds")) { if (mimeData->urls().size() == 1) { - qDebug() << "LoadFile_DDS Returned: " << LoadFile_DDS(urlStr); + //qDebug() << "LoadFile_DDS Returned: " << LoadFile_DDS(urlStr); } else { ddsPaths << urlStr; } @@ -969,7 +971,7 @@ void MainWindow::dropEvent(QDropEvent *event) { } } if (ddsPaths.size() > 1) { - qDebug() << "LoadFile_DDSFiles Returned: " << LoadFile_DDSFiles(ddsPaths); + //qDebug() << "LoadFile_DDSFiles Returned: " << LoadFile_DDSFiles(ddsPaths); } } else { ui->statusBar->showMessage("Can't display dropped data!"); diff --git a/app/mainwindow.h b/app/mainwindow.h index 7b2c3c8..037c32a 100644 --- a/app/mainwindow.h +++ b/app/mainwindow.h @@ -43,8 +43,6 @@ private slots: int LoadFile_IPAK(const QString aFilePath); int LoadFile_XSUB(const QString aFilePath); int LoadFile_IWI(const QString aFilePath); - int LoadFile_DDS(const QString aFilePath); - int LoadFile_DDSFiles(const QStringList aFilePaths); void HandleLogEntry(const QString &entry); void HandleStatusUpdate(const QString &message, int timeout); diff --git a/app/modelviewer.ui b/app/modelviewer.ui index 0a09b3a..b17a424 100644 --- a/app/modelviewer.ui +++ b/app/modelviewer.ui @@ -6,8 +6,8 @@ 0 0 - 1001 - 897 + 780 + 644 @@ -15,606 +15,636 @@ - - - Properties - - - - - - - - Name Pointer: - - - - - - - 1000000000 - - - - - - - Model Name: - - - - - - - - - - Tag Count: - - - - - - - tags - - - 1000000000 - - - - - - - Root Tag Count: - - - - - - - root tags - - - 1000000000 - - - - - - - Surface Count: - - - - - - - surfaces - - - 1000000000 - - - - - - - Unknown A: - - - - - - - 1000000000 - - - - - - - Bone Name Pointer: - - - - - - - 1000000000 - - - - - - - Parent List Pointer: - - - - - - - 1000000000 - - - - - - - Quats Pointer: - - - - - - - 1000000000 - - - - - - - Transformation Pointer: - - - - - - - 1000000000 - - - - - - - Classification Pointer: - - - - - - - 1000000000 - - - - - - - Base Material Pointer: - - - - - - - 1000000000 - - - - - - - Surfaces Pointer; - - - - - - - 1000000000 - - - - - - - Material Handlers Pointer: - - - - - - - 1000000000 - - - - - - - Coll Surf Pointer: - - - - - - - 1000000000 - - - - - - - Coll Surface Count: - - - - - - - 1000000000 - - - - - - - Contents: - - - - - - - 1000000000 - - - - - - - Bone Info Pointer: - - - - - - - 1000000000 - - - - - - - Radius: - - - - - - - - - - Min X: - - - - - - - - - - Min Y: - - - - - - - - - - Min Z: - - - - - - - - - - Max X: - - - - - - - - - - Max Y: - - - - - - - - - - Max Z: - - - - - - - - - - Lod Count: - - - - - - - 1000000000 - - - - - - - Coll Lod: - - - - - - - 1000000000 - - - - - - - Stream Info Pointer: - - - - - - - 1000000000 - - - - - - - Memory Usage: - - - - - - - 1000000000 - - - - - - - Flags: - - - - - - - 1000000000 - - - - - - - Phys Preset Pointer: - - - - - - - 1000000000 - - - - - - - Phys Geometry Pointer: - - - - - - - 1000000000 - - - - - - - - - - - Lod Info - - - - - - Lod Info Index: - - - - - - - - - - Qt::Orientation::Horizontal - - - - - - - Distance: - - - - - - - - - - Surface Count: - - - - - - - 1000000000 - - - - - - - Surface Index: - - - - - - - 1000000000 - - - - - - - Part Bit 1: - - - - - - - 1000000000 - - - - - - - Part Bit 2: - - - - - - - 1000000000 - - - - - - - Part Bit 3: - - - - - - - 1000000000 - - - - - - - Part Bit 4: - - - - - - - 1000000000 - - - - - - - Part Bit 5: - - - - - - - 1000000000 - - - - - - - - - - Qt::Orientation::Vertical - - - - 20 - 40 - - - - - - - - - - - - - Qt::Orientation::Vertical - - - - - - - 3D Window + + + 0 + + + + 0 + 0 + 762 + 566 + + + + Model Data + + + + + + + + Name Pointer: + + + + + + + 1000000000 + + + + + + + Model Name: + + + + + + + + + + Tag Count: + + + + + + + tags + + + 1000000000 + + + + + + + Root Tag Count: + + + + + + + root tags + + + 1000000000 + + + + + + + Surface Count: + + + + + + + surfaces + + + 1000000000 + + + + + + + Unknown A: + + + + + + + 1000000000 + + + + + + + Bone Name Pointer: + + + + + + + 1000000000 + + + + + + + Parent List Pointer: + + + + + + + 1000000000 + + + + + + + Quats Pointer: + + + + + + + 1000000000 + + + + + + + Transformation Pointer: + + + + + + + 1000000000 + + + + + + + Classification Pointer: + + + + + + + 1000000000 + + + + + + + Base Material Pointer: + + + + + + + 1000000000 + + + + + + + Surfaces Pointer; + + + + + + + 1000000000 + + + + + + + Material Handlers Pointer: + + + + + + + 1000000000 + + + + + + + Coll Surf Pointer: + + + + + + + 1000000000 + + + + + + + Coll Surface Count: + + + + + + + 1000000000 + + + + + + + + + Qt::Orientation::Vertical + + + + + + + + + Contents: + + + + + + + 1000000000 + + + + + + + Bone Info Pointer: + + + + + + + 1000000000 + + + + + + + Radius: + + + + + + + + + + Min X: + + + + + + + + + + Min Y: + + + + + + + + + + Min Z: + + + + + + + + + + Max X: + + + + + + + + + + Max Y: + + + + + + + + + + Max Z: + + + + + + + + + + Lod Count: + + + + + + + 1000000000 + + + + + + + Coll Lod: + + + + + + + 1000000000 + + + + + + + Stream Info Pointer: + + + + + + + 1000000000 + + + + + + + Memory Usage: + + + + + + + 1000000000 + + + + + + + Flags: + + + + + + + 1000000000 + + + + + + + Phys Preset Pointer: + + + + + + + 1000000000 + + + + + + + Phys Geometry Pointer: + + + + + + + 1000000000 + + + + + + + + + Qt::Orientation::Vertical + + + + + + + + + Lod Info + + + + + + Lod Info Index: + + + + + + + + + + Qt::Orientation::Horizontal + + + + + + + Distance: + + + + + + + + + + Surface Count: + + + + + + + 1000000000 + + + + + + + Surface Index: + + + + + + + 1000000000 + + + + + + + Part Bit 1: + + + + + + + 1000000000 + + + + + + + Part Bit 2: + + + + + + + 1000000000 + + + + + + + Part Bit 3: + + + + + + + 1000000000 + + + + + + + Part Bit 4: + + + + + + + 1000000000 + + + + + + + Part Bit 5: + + + + + + + 1000000000 + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + + + + + 0 + 0 + 762 + 566 + + + + 3D View + + diff --git a/app/preferenceeditor.cpp b/app/preferenceeditor.cpp index 03b3237..14dcb3f 100644 --- a/app/preferenceeditor.cpp +++ b/app/preferenceeditor.cpp @@ -27,6 +27,8 @@ PreferenceEditor::PreferenceEditor(QWidget *parent) ui->frame_FileEditors->show(); } }); + + connect(ui->checkBox_DebugMode, &QCheckBox::clicked, this, &PreferenceEditor::DebugModeChanged); } PreferenceEditor::~PreferenceEditor() diff --git a/app/preferenceeditor.h b/app/preferenceeditor.h index ac09083..33e0bef 100644 --- a/app/preferenceeditor.h +++ b/app/preferenceeditor.h @@ -15,6 +15,9 @@ public: explicit PreferenceEditor(QWidget *parent = nullptr); ~PreferenceEditor(); +signals: + void DebugModeChanged(bool aEnable); + private: Ui::PreferenceEditor *ui; }; diff --git a/app/preferenceeditor.ui b/app/preferenceeditor.ui index fc50978..8e09ab0 100644 --- a/app/preferenceeditor.ui +++ b/app/preferenceeditor.ui @@ -73,14 +73,14 @@ - 0 + -1 View - + :/icons/icons/Icon_Views.png:/icons/icons/Icon_Views.png @@ -89,7 +89,7 @@ Tree Widget - + :/icons/icons/Icon_Tree.png:/icons/icons/Icon_Tree.png @@ -98,12 +98,19 @@ File Editors - + :/icons/icons/Icon_Editor.png:/icons/icons/Icon_Editor.png + + + + Enable Debug Mode + + + @@ -135,7 +142,7 @@ - :/icons/icons/Icon_Views.png + :/icons/icons/Icon_Views.png true @@ -292,7 +299,7 @@ - :/icons/icons/Icon_Tree.png + :/icons/icons/Icon_Tree.png true @@ -370,7 +377,7 @@ - :/icons/icons/Icon_Editor.png + :/icons/icons/Icon_Editor.png true @@ -489,7 +496,7 @@ - + diff --git a/app/techsetviewer.cpp b/app/techsetviewer.cpp index 03ba4f7..d7fc588 100644 --- a/app/techsetviewer.cpp +++ b/app/techsetviewer.cpp @@ -16,10 +16,18 @@ TechSetViewer::~TechSetViewer() void TechSetViewer::SetTechSet(const XMaterialTechniqueSet* aTechSet) { //ui->listWidget_Ptrs->clear(); ui->label_Title->setText(aTechSet->GetName()); + ui->lineEdit_TechniqueName->setText(aTechSet->DisplayName()); + ui->spinBox_WorldVertFormat->setValue(aTechSet->WorldVertFormat()); - // int ptrIndex = 1; - //for (auto ptr : aTechSet->pointers) { - // ui->listWidget_Ptrs->addItem(QString("Pointer %1: %2").arg(ptrIndex).arg(ptr)); - // ptrIndex++; - //} + for (const XMaterialTechnique &technique : aTechSet->Techniques()) + { + ui->listWidget_Techniques->addItem(technique.DisplayName()); + } + + connect(ui->listWidget_Techniques, &QListWidget::currentRowChanged, this, [&](int aRow) { + const XMaterialTechnique &technique = aTechSet->Techniques()[aRow]; + ui->lineEdit_TechniqueName->setText(technique.DisplayName()); + ui->spinBox_Flags->setValue(technique.Flags()); + ui->spinBox_PassCount->setValue(technique.PassCount()); + }); } diff --git a/app/techsetviewer.ui b/app/techsetviewer.ui index 4bc7283..dd00c50 100644 --- a/app/techsetviewer.ui +++ b/app/techsetviewer.ui @@ -81,9 +81,9 @@ - + - + Name: @@ -92,7 +92,7 @@ - Technique set name + Technique name diff --git a/app/xtreewidget.cpp b/app/xtreewidget.cpp index d142819..be35bb8 100644 --- a/app/xtreewidget.cpp +++ b/app/xtreewidget.cpp @@ -7,8 +7,9 @@ XTreeWidget::XTreeWidget(QWidget *parent) : QTreeWidget(parent) { mFastFiles = QMap(); mZoneFiles = QMap(); - mDDSFiles = QMap(); - mIWIFiles = QMap(); + //mDDSFiles = QMap(); + //mIWIFiles = QMap(); + mRootItemMap = QMap>(); setContextMenuPolicy(Qt::CustomContextMenu); setSelectionMode(QTreeWidget::SingleSelection); @@ -41,36 +42,36 @@ void XTreeWidget::AddFastFile(FastFile* aFastFile) { XTreeWidgetItem *fastFileItem = new XTreeWidgetItem(this); fastFileItem->setText(0, aFastFile->GetStem()); fastFileItem->setIcon(0, Utils::CreateAssetIcon("FF")); - if (aFastFile->GetPlatform() == "PC") { + if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("PC")); - } else if (aFastFile->GetPlatform() == "360") { + } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("360")); - } else if (aFastFile->GetPlatform() == "PS3") { + } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_PS3) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("PS3")); - } else if (aFastFile->GetPlatform() == "Wii") { + } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_WII) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("WII")); - } else if (aFastFile->GetPlatform() == "WiiU") { + } else if (aFastFile->GetCommonInfo().GetPlatform() == PLATFORM_WIIU) { fastFileItem->setIcon(1, Utils::CreateAssetIcon("WU")); } - if (aFastFile->GetGame() == "COD2") { + if (aFastFile->GetCommonInfo().GetGame() == GAME_COD2) { fastFileItem->setIcon(2, Utils::CreateGameIcon(2)); - } if (aFastFile->GetGame() == "COD4") { + } if (aFastFile->GetCommonInfo().GetGame() == GAME_COD4) { fastFileItem->setIcon(2, Utils::CreateGameIcon(4)); - } else if (aFastFile->GetGame() == "COD5") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD5) { fastFileItem->setIcon(2, Utils::CreateGameIcon(5)); - } else if (aFastFile->GetGame() == "COD6") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD6) { fastFileItem->setIcon(2, Utils::CreateGameIcon(6)); - } else if (aFastFile->GetGame() == "COD7") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD7) { fastFileItem->setIcon(2, Utils::CreateGameIcon(7)); - } else if (aFastFile->GetGame() == "COD8") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD8) { fastFileItem->setIcon(2, Utils::CreateGameIcon(8)); - } else if (aFastFile->GetGame() == "COD9") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD9) { fastFileItem->setIcon(2, Utils::CreateGameIcon(9)); - } else if (aFastFile->GetGame() == "COD10") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD10) { fastFileItem->setIcon(2, Utils::CreateGameIcon(10)); - } else if (aFastFile->GetGame() == "COD11") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD11) { fastFileItem->setIcon(2, Utils::CreateGameIcon(11)); - } else if (aFastFile->GetGame() == "COD12") { + } else if (aFastFile->GetCommonInfo().GetGame() == GAME_COD12) { fastFileItem->setIcon(2, Utils::CreateGameIcon(12)); } @@ -83,6 +84,47 @@ void XTreeWidget::AddFastFile(FastFile* aFastFile) { sortByColumn(0, Qt::AscendingOrder); } +void XTreeWidget::AddAsset(XAsset* aAsset, const QString& aZoneFileName, XTreeWidgetItem* aRootItem) +{ + const XAssetType assetType = aAsset->GetType(); + QIcon assetIcon = Utils::CreateAssetIcon(assetType); + + QTreeWidgetItem *groupItem = nullptr; + for (int i = 0; i < aRootItem->childCount(); i++) + { + QTreeWidgetItem *testItem = aRootItem->child(i); + if (testItem && (testItem->text(0) == aAsset->GetName() || (testItem->text(0) + "s") == aAsset->GetName())) + { + groupItem = testItem; + break; + } + } + if (!groupItem) + { + QString newName = aAsset->GetName(); + if (*(newName.end() - 1) != 's') + { + newName += 's'; + } + + groupItem = new XTreeWidgetItem(aRootItem); + groupItem->setText(0, newName); + groupItem->setIcon(0, assetIcon); + } + + XTreeWidgetItem *newItem = new XTreeWidgetItem(groupItem); + newItem->SetAssetType(assetType); + newItem->SetAssetPtr(aAsset); + newItem->setText(0, aAsset->DisplayName()); + newItem->setIcon(0, assetIcon); + + for (XAsset *subAsset : aAsset->SubAssets()) + { + AddAsset(subAsset, aZoneFileName, newItem); + } + update(); +} + void XTreeWidget::AddZoneFile(const ZoneFile* aZoneFile, XTreeWidgetItem *aParentItem) { XTreeWidgetItem *zoneItem; if (aParentItem != nullptr) { @@ -90,183 +132,16 @@ void XTreeWidget::AddZoneFile(const ZoneFile* aZoneFile, XTreeWidgetItem *aParen } else { zoneItem = new XTreeWidgetItem(this); } + const QString zoneFileName = aZoneFile->GetBaseStem() + ".zone"; + zoneItem->setText(0, zoneFileName); zoneItem->setIcon(0, Utils::CreateAssetIcon("ZF")); - zoneItem->setText(0, aZoneFile->GetBaseStem() + ".zone"); XAssetList assetList = aZoneFile->GetAssetList(); - QVector localizeEntries; for (int i = 0; i < assetList.Size(); i++) { - XAsset *currentAsset = assetList.GetAsset(i); - if (currentAsset->GetType() == ASSET_TYPE_LOCALIZE_ENTRY) - { - localizeEntries.append(currentAsset); - } else if (currentAsset->GetType() == ASSET_TYPE_LOCALIZE_ENTRY) - { - localizeEntries.append(currentAsset); - } + AddAsset(assetList.GetAsset(i), zoneFileName, zoneItem); } - - // if (!assetMap.localizeEntries.isEmpty()) { - // QIcon localStrIcon = Utils::CreateAssetIcon(ASSET_TYPE_LOCALIZE_ENTRY); - - // XTreeWidgetItem *localStrRoot = new XTreeWidgetItem(zoneItem); - // localStrRoot->setText(0, "String Files"); - // localStrRoot->setIcon(0, localStrIcon); - // localStrRoot->SetCategory(CATEGORY_TYPE); - - // XTreeWidgetItem *localStrItem = new XTreeWidgetItem(localStrRoot); - // localStrItem->setText(0, aZoneFile->GetStem().section('.', 0, 0) + ".str"); - // localStrItem->setIcon(0, localStrIcon); - // } - - // if (!assetMap.techSets.isEmpty()) { - // QIcon techSetIcon = Utils::CreateAssetIcon(ASSET_TYPE_TECHNIQUE_SET); - - // XTreeWidgetItem *techSetRoot = new XTreeWidgetItem(zoneItem); - // techSetRoot->setText(0, "Tech Sets"); - // techSetRoot->setIcon(0, techSetIcon); - // techSetRoot->SetCategory(CATEGORY_TYPE); - - // for (auto techSet : assetMap.techSets) { - // XTreeWidgetItem *techSetItem = new XTreeWidgetItem(techSetRoot); - // techSetItem->setText(0, techSet.name); - // techSetItem->setIcon(0, techSetIcon); - // } - // } - - // if (!assetMap.rawFiles.isEmpty()) { - // QIcon rawFileIcon = Utils::CreateAssetIcon(ASSET_TYPE_RAWFILE); - - // XTreeWidgetItem *rawFileRoot = new XTreeWidgetItem(zoneItem); - // rawFileRoot->setText(0, "Raw Files"); - // rawFileRoot->setIcon(0, rawFileIcon); - // rawFileRoot->SetCategory(CATEGORY_TYPE); - // for (auto rawFile : assetMap.rawFiles) { - // if (!rawFile.length) { continue; } - - // XTreeWidgetItem *tempItem = rawFileRoot; - // // const QStringList pathParts = rawFile->path.split('/'); - // // for (const QString &pathPart : pathParts) { - // // bool childFound = false; - // // for (int i = 0; i < tempItem->childCount(); i++) { - // // QTreeWidgetItem *rawChildItem = tempItem->child(i); - // // XTreeWidgetItem *childItem = dynamic_cast(rawChildItem); - // // if (childItem->text(0) == pathPart) { - // // tempItem = childItem; - - // // childFound = true; - // // break; - // // } - // // } - - // // const QString rawFileStr = pathPart;// = QString("%1 [%2-%3]").arg(pathPart).arg(rawFile.startPos).arg(rawFile.endPos); - // // if (pathPart == pathParts.last()) { - // // XTreeWidgetItem *rawFileItem = new XTreeWidgetItem(tempItem); - // // rawFileItem->setText(0, rawFileStr); - - // // tempItem = rawFileItem; - // // } else if (!childFound) { - // // tempItem = new XTreeWidgetItem(tempItem); - // // tempItem->setText(0, rawFileStr); - // // } - - // // } - // tempItem->setIcon(0, rawFileIcon); - // } - // } - - // if (!assetMap.menuDefinitions.isEmpty()) { - // // QIcon MenuDefIcon = Utils::CreateAssetIcon(ASSET_TYPE_MENU); - - // // XTreeWidgetItem *menuRoot = new XTreeWidgetItem(zoneItem); - // // menuRoot->setText(0, "Menu Files"); - // // menuRoot->setIcon(0, MenuDefIcon); - // // menuRoot->SetCategory(CATEGORY_TYPE); - - // // int menuIndex = 1; - // // for (MenuDef menuDef : assetMap.menuDefinitions) { - // // XTreeWidgetItem *MenuDefRoot = new XTreeWidgetItem(menuRoot); - // // MenuDefRoot->setText(0, QString("Menu %1").arg(menuIndex)); - // // for (Menu menu : menuDef.men) { - // // XTreeWidgetItem *menuItem = new XTreeWidgetItem(MenuDefRoot); - // // menuItem->setText(0, menu.filePath); - // // menuItem->setIcon(0, MenuDefIcon); - // // } - // // menuIndex++; - // // } - // } - - // if (!assetMap.images.isEmpty()) { - // // QIcon imageIcon = Utils::CreateAssetIcon(ASSET_TYPE_IMAGE); - - // // XTreeWidgetItem *imageRoot = new XTreeWidgetItem(zoneItem); - // // imageRoot->setText(0, "Images"); - // // imageRoot->setIcon(0, imageIcon); - // // imageRoot->SetCategory(CATEGORY_TYPE); - - // // for (Image image : assetMap.images) { - // // XTreeWidgetItem *imageItem = new XTreeWidgetItem(imageRoot); - // // imageItem->setText(0, image.materialName); - // // imageItem->setIcon(0, imageIcon); - // // } - // } - - // if (!assetMap.models.isEmpty()) { - // QIcon modelIcon = Utils::CreateAssetIcon(ASSET_TYPE_XMODEL); - - // XTreeWidgetItem *modelsRoot = new XTreeWidgetItem(zoneItem); - // modelsRoot->setText(0, "Models"); - // modelsRoot->setIcon(0, modelIcon); - // modelsRoot->SetCategory(CATEGORY_TYPE); - - // for (auto model: assetMap.models) { - // XTreeWidgetItem *modelItem = new XTreeWidgetItem(modelsRoot); - // modelItem->setText(0, model.name); - // modelItem->setIcon(0, modelIcon); - // } - // } - - // if (!assetMap.materials.isEmpty()) { - // QIcon materialIcon = Utils::CreateAssetIcon(ASSET_TYPE_MATERIAL); - - // XTreeWidgetItem *materialsRoot = new XTreeWidgetItem(zoneItem); - // materialsRoot->setText(0, "Materials"); - // materialsRoot->setIcon(0, materialIcon); - // materialsRoot->SetCategory(CATEGORY_TYPE); - - // for (auto material: assetMap.materials) { - // XTreeWidgetItem *materialItem = new XTreeWidgetItem(materialsRoot); - // //materialItem->setText(0, material.name); - // materialItem->setIcon(0, materialIcon); - // } - // } - - // if (!assetMap.stringTables.isEmpty()) { - // QIcon stringTableIcon = Utils::CreateAssetIcon(ASSET_TYPE_STRINGTABLE); - - // XTreeWidgetItem *strTableRoot = new XTreeWidgetItem(zoneItem); - // strTableRoot->setText(0, "String Tables"); - // strTableRoot->setIcon(0, stringTableIcon); - // strTableRoot->SetCategory(CATEGORY_TYPE); - - // for (auto strTable: assetMap.stringTables) { - // XTreeWidgetItem *modelItem = new XTreeWidgetItem(strTableRoot); - // modelItem->setText(0, strTable.name); - // modelItem->setIcon(0, stringTableIcon); - // } - // } - - // if (!assetMap.sounds.isEmpty()) { - // QIcon soundIcon = Utils::CreateAssetIcon(ASSET_TYPE_SOUND); - - // XTreeWidgetItem *soundsRoot = new XTreeWidgetItem(zoneItem); - // soundsRoot->setText(0, "Sounds"); - // soundsRoot->setIcon(0, soundIcon); - // soundsRoot->SetCategory(CATEGORY_TYPE); - // } - mZoneFiles[aZoneFile->GetBaseStem() + ".zone"] = aZoneFile; } @@ -284,93 +159,93 @@ void XTreeWidget::PrepareContextMenu(const QPoint &pos) { QMenu *contextMenu = new QMenu(this); if (activeText.contains(".dds")) { - const QString fileStem = activeText.replace(".dds", ""); - if (!mDDSFiles.contains(fileStem)) { - qDebug() << "Error: Could not find " << fileStem << " in DDS map!"; - return; - } + // const QString fileStem = activeText.replace(".dds", ""); + // if (!mDDSFiles.contains(fileStem)) { + // qDebug() << "Error: Could not find " << fileStem << " in DDS map!"; + // return; + // } - QAction *closeAction = new QAction("Close File"); - contextMenu->addAction(closeAction); - connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) { - Q_UNUSED(checked); + // QAction *closeAction = new QAction("Close File"); + // contextMenu->addAction(closeAction); + // connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) { + // Q_UNUSED(checked); - mDDSFiles.remove(fileStem); - invisibleRootItem()->removeChild(activeItem); - }); + // mDDSFiles.remove(fileStem); + // invisibleRootItem()->removeChild(activeItem); + // }); - QMenu *exportSubmenu = new QMenu("Export...", this); - contextMenu->addMenu(exportSubmenu); + // QMenu *exportSubmenu = new QMenu("Export...", this); + // contextMenu->addMenu(exportSubmenu); - const DDSFile* ddsFile = mDDSFiles[fileStem]; + // const DDSFile* ddsFile = mDDSFiles[fileStem]; - QAction *exportIWIAction = new QAction("Export as IWI"); - exportSubmenu->addAction(exportIWIAction); - connect(exportIWIAction, &QAction::triggered, this, [ddsFile](bool checked) { - Q_UNUSED(checked); + // QAction *exportIWIAction = new QAction("Export as IWI"); + // exportSubmenu->addAction(exportIWIAction); + // connect(exportIWIAction, &QAction::triggered, this, [ddsFile](bool checked) { + // Q_UNUSED(checked); - ddsFile->SaveIWI(); - }); + // ddsFile->SaveIWI(); + // }); - QAction *exportPNGAction = new QAction("Export as PNG"); - exportSubmenu->addAction(exportPNGAction); - connect(exportPNGAction, &QAction::triggered, this, [ddsFile](bool checked) { - Q_UNUSED(checked); + // QAction *exportPNGAction = new QAction("Export as PNG"); + // exportSubmenu->addAction(exportPNGAction); + // connect(exportPNGAction, &QAction::triggered, this, [ddsFile](bool checked) { + // Q_UNUSED(checked); - ddsFile->SavePNG(); - }); + // ddsFile->SavePNG(); + // }); - QAction *exportJPGAction = new QAction("Export as JPG"); - exportSubmenu->addAction(exportJPGAction); - connect(exportJPGAction, &QAction::triggered, this, [ddsFile](bool checked) { - Q_UNUSED(checked); + // QAction *exportJPGAction = new QAction("Export as JPG"); + // exportSubmenu->addAction(exportJPGAction); + // connect(exportJPGAction, &QAction::triggered, this, [ddsFile](bool checked) { + // Q_UNUSED(checked); - ddsFile->SaveJPG(); - }); + // ddsFile->SaveJPG(); + // }); } else if (activeText.contains(".iwi")) { - const QString fileStem = activeText.replace(".iwi", ""); - if (!mIWIFiles.contains(fileStem)) { - qDebug() << "Error: Could not find " << fileStem << " in IWI map!"; - return; - } + // const QString fileStem = activeText.replace(".iwi", ""); + // if (!mIWIFiles.contains(fileStem)) { + // qDebug() << "Error: Could not find " << fileStem << " in IWI map!"; + // return; + // } - QAction *closeAction = new QAction("Close File"); - contextMenu->addAction(closeAction); - connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) { - Q_UNUSED(checked); + // QAction *closeAction = new QAction("Close File"); + // contextMenu->addAction(closeAction); + // connect(closeAction, &QAction::triggered, this, [this, &fileStem, &activeItem](bool checked) { + // Q_UNUSED(checked); - mIWIFiles.remove(fileStem); - invisibleRootItem()->removeChild(activeItem); - }); + // mIWIFiles.remove(fileStem); + // invisibleRootItem()->removeChild(activeItem); + // }); - QMenu *exportSubmenu = new QMenu("Export...", this); - contextMenu->addMenu(exportSubmenu); + // QMenu *exportSubmenu = new QMenu("Export...", this); + // contextMenu->addMenu(exportSubmenu); - const IWIFile* iwiFile = mIWIFiles[fileStem]; + // const IWIFile* iwiFile = mIWIFiles[fileStem]; - QAction *exportDDSAction = new QAction("Export as DDS"); - exportSubmenu->addAction(exportDDSAction); - connect(exportDDSAction, &QAction::triggered, this, [iwiFile](bool checked) { - Q_UNUSED(checked); + // QAction *exportDDSAction = new QAction("Export as DDS"); + // exportSubmenu->addAction(exportDDSAction); + // connect(exportDDSAction, &QAction::triggered, this, [iwiFile](bool checked) { + // Q_UNUSED(checked); - iwiFile->SaveDDS(); - }); + // iwiFile->SaveDDS(); + // }); - QAction *exportPNGAction = new QAction("Export as PNG"); - exportSubmenu->addAction(exportPNGAction); - connect(exportPNGAction, &QAction::triggered, this, [iwiFile](bool checked) { - Q_UNUSED(checked); + // QAction *exportPNGAction = new QAction("Export as PNG"); + // exportSubmenu->addAction(exportPNGAction); + // connect(exportPNGAction, &QAction::triggered, this, [iwiFile](bool checked) { + // Q_UNUSED(checked); - iwiFile->SavePNG(); - }); + // iwiFile->SavePNG(); + // }); - QAction *exportJPGAction = new QAction("Export as JPG"); - exportSubmenu->addAction(exportJPGAction); - connect(exportJPGAction, &QAction::triggered, this, [iwiFile](bool checked) { - Q_UNUSED(checked); + // QAction *exportJPGAction = new QAction("Export as JPG"); + // exportSubmenu->addAction(exportJPGAction); + // connect(exportJPGAction, &QAction::triggered, this, [iwiFile](bool checked) { + // Q_UNUSED(checked); - iwiFile->SaveJPG(); - }); + // iwiFile->SaveJPG(); + // }); } else if (activeText.contains(".ff")) { const QString fileStem = activeText; @@ -629,122 +504,35 @@ void XTreeWidget::ItemSelectionChanged() { QString selectedText = selectedItem->text(0); emit ItemSelected(selectedText); - XTreeWidgetItem *parentItem = dynamic_cast(selectedItem->parent()); - - /*if (selectedText.contains(".dds")) { - if (!mDDSFiles.contains(selectedText)) { - LogManager::instance().addError("Could not find " + selectedText + " in DDS map!"); - return; - } - emit DDSFileSelected(mDDSFiles[selectedText], selectedText); - } else if (selectedText.contains(".iwi")) { - if (!mIWIFiles.contains(selectedText)) { - LogManager::instance().addError("Could not find " + selectedText + " in IWI map!"); - return; - } - emit IWIFileSelected(mIWIFiles[selectedText], selectedText); - } else */if (selectedText.contains(".ff")) { - if (!mFastFiles.contains(selectedText)) { - LogManager::instance().addError("Could not find " + selectedText + " in Fast File map!"); - return; - } - emit FastFileSelected(mFastFiles[selectedText], selectedText); - } else if (selectedText.contains(".zone")) { - if (!mZoneFiles.contains(selectedText)) { - LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!"); - return; - } - emit ZoneFileSelected(mZoneFiles[selectedText], selectedText); - } else if (selectedText.contains(".str")) { - if (!mZoneFiles.contains(selectedText.replace(".str", ".zone"))) { - LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!"); - return; - } - emit LocalStringSelected(mZoneFiles[selectedText], selectedText); - } else if (parentItem && (parentItem->text(0) == "Images")) { - XTreeWidgetItem *grandpaItem = dynamic_cast(parentItem->parent()); - if (grandpaItem && grandpaItem->text(0).contains(".zone")) { - const QString fileStem = grandpaItem->text(0).section('.', 0, 0); - // QVector images = mZoneFiles[fileStem]->GetAssetMap().images; - // for (Image image : images) { - // if (image.materialName == selectedText) { - // emit ImageSelected(std::make_shared(image), fileStem); - // break; - // } - // } - } - } /*else if (parentItem && (parentItem->text(0) == "Tech Sets")) { - XTreeWidgetItem *grandpaItem = dynamic_cast(parentItem->parent()); - if (grandpaItem && grandpaItem->text(0).contains(".zone")) { - const QString fileStem = grandpaItem->text(0).section('.', 0, 0); - auto techsets = mZoneFiles[fileStem]->GetAssetList().techSets; - for (auto techset : techsets) { - if (techset.name == selectedText) { - emit TechSetSelected(new MaterialTechSet(techset), fileStem); - break; - } + switch (selectedItem->AssetType()) + { + case ASSET_TYPE_NONE: + if (selectedText.contains(".ff")) { + if (!mFastFiles.contains(selectedText)) { + LogManager::instance().addError("Could not find " + selectedText + " in Fast File map!"); + return; } - } - } else if (parentItem && (parentItem->text(0) == "Materials")) { - XTreeWidgetItem *grandpaItem = dynamic_cast(parentItem->parent()); - if (grandpaItem && grandpaItem->text(0).contains(".zone")) { - const QString fileStem = grandpaItem->text(0).section('.', 0, 0); - auto materials = mZoneFiles[fileStem]->GetAssetMap().materials; - for (auto material : materials) { - // if (material.name == selectedText) { - // emit MaterialSelected(std::make_shared(material), fileStem); - // break; - // } + emit FastFileSelected(mFastFiles[selectedText], selectedText); + } else if (selectedText.contains(".zone")) { + if (!mZoneFiles.contains(selectedText)) { + LogManager::instance().addError("Could not find " + selectedText + " in Zone File map!"); + return; } + emit ZoneFileSelected(mZoneFiles[selectedText], selectedText); } - } else if (parentItem && selectedText.contains(".wav")) { - XTreeWidgetItem *grandpaItem = dynamic_cast(parentItem->parent()); - while (grandpaItem && !grandpaItem->text(0).contains(".zone")) { - grandpaItem = dynamic_cast(grandpaItem->parent()); - - if (grandpaItem == invisibleRootItem()) { - break; - } - } - if (grandpaItem && grandpaItem != invisibleRootItem() && grandpaItem->text(0).contains(".zone")) { - const QString fileStem = grandpaItem->text(0).section('.', 0, 0); - // QVector LoadedSounds = mZoneFiles[fileStem]->GetAssetMap().sounds; - // for (LoadedSound LoadedSound : LoadedSounds) { - // for (Sound sound : LoadedSound.sounds) { - // if (sound.path.contains(selectedText)) { - // emit SoundSelected(std::make_shared(sound), fileStem); - // break; - // } - // } - // } - } - } else if (selectedItem->GetCategory() != CATEGORY_TYPE) { - XTreeWidgetItem *zoneRoot = selectedItem; - - bool zoneChild = false; - while (zoneRoot) { - zoneRoot = dynamic_cast(zoneRoot->parent()); - if (zoneRoot->text(0).contains("Raw Files")) { - zoneChild = true; - break; - } - } - if (!zoneChild) { return; } - const QString fileStem = zoneRoot->parent()->text(0); - - if (!mZoneFiles.contains(fileStem)) { - LogManager::instance().addError("Could not find " + fileStem + " in Zone File map!"); - return; - } - - auto rawFiles = mZoneFiles[fileStem]->GetAssetMap().rawFiles; - for (auto rawFile : rawFiles) { - //if (rawFile->path.split('/').last() == selectedText) { - // emit RawFileSelected(std::make_shared(rawFile), fileStem); - // return; - //} - } - }*/ + break; + case ASSET_TYPE_TECHNIQUE_SET: + emit TechSetSelected(dynamic_cast(selectedItem->AssetPtr()), selectedText); + break; + case ASSET_TYPE_MATERIAL: + emit MaterialSelected(dynamic_cast(selectedItem->AssetPtr()), selectedText); + break; + case ASSET_TYPE_RAWFILE: + emit RawFileSelected(dynamic_cast(selectedItem->AssetPtr()), selectedText); + break; + default: + break; + }; } const ZoneFile* XTreeWidget::FindZoneFile(const QString aStem) { @@ -773,34 +561,34 @@ bool XTreeWidget::HasFastFile(const QString aStem) { return FindFastFile(aStem) != nullptr; } -void XTreeWidget::AddIWIFile(IWIFile* aIWIFile) { - const QString iwiFileName = QString(aIWIFile->fileStem + ".iwi"); +// void XTreeWidget::AddIWIFile(IWIFile* aIWIFile) { +// const QString iwiFileName = QString(aIWIFile->fileStem + ".iwi"); - for (int i = 0; i < invisibleRootItem()->childCount(); i++) { - auto iwiFileItem = invisibleRootItem()->child(i); - if (iwiFileItem->text(0) == iwiFileName) { - delete iwiFileItem; - } - } +// for (int i = 0; i < invisibleRootItem()->childCount(); i++) { +// auto iwiFileItem = invisibleRootItem()->child(i); +// if (iwiFileItem->text(0) == iwiFileName) { +// delete iwiFileItem; +// } +// } - XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this); - iwiItem->setIcon(0, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); - iwiItem->setText(0, iwiFileName); - mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile; -} +// XTreeWidgetItem *iwiItem = new XTreeWidgetItem(this); +// iwiItem->setIcon(0, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); +// iwiItem->setText(0, iwiFileName); +// mIWIFiles[aIWIFile->fileStem.section(".", 0, 0)] = aIWIFile; +// } -void XTreeWidget::AddDDSFile(DDSFile* aDDSFile) { - const QString ddsFileName = QString(aDDSFile->fileStem + ".dds"); +// void XTreeWidget::AddDDSFile(DDSFile* aDDSFile) { +// const QString ddsFileName = QString(aDDSFile->fileStem + ".dds"); - for (int i = 0; i < invisibleRootItem()->childCount(); i++) { - auto ddsFileItem = invisibleRootItem()->child(i); - if (ddsFileItem->text(0) == ddsFileName) { - delete ddsFileItem; - } - } +// for (int i = 0; i < invisibleRootItem()->childCount(); i++) { +// auto ddsFileItem = invisibleRootItem()->child(i); +// if (ddsFileItem->text(0) == ddsFileName) { +// delete ddsFileItem; +// } +// } - XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this); - ddsItem->setIcon(0, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); - ddsItem->setText(0, ddsFileName); - mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile; -} +// XTreeWidgetItem *ddsItem = new XTreeWidgetItem(this); +// ddsItem->setIcon(0, Utils::CreateAssetIcon(ASSET_TYPE_IMAGE)); +// ddsItem->setText(0, ddsFileName); +// mDDSFiles[aDDSFile->fileStem.section(".", 0, 0)] = aDDSFile; +// } diff --git a/app/xtreewidget.h b/app/xtreewidget.h index a1c1645..24be5d8 100644 --- a/app/xtreewidget.h +++ b/app/xtreewidget.h @@ -2,8 +2,8 @@ #define XTREEWIDGET_H #include "d3dbsp_structs.h" -#include "ddsfile.h" -#include "iwifile.h" +//#include "iwifile.h" +//#include "ddsfile.h" #include "fastfile.h" #include "xloadedsound.h" #include "xtreewidgetitem.h" @@ -25,8 +25,8 @@ public: void AddFastFile(FastFile* aFastFile); void AddZoneFile(const ZoneFile *aZoneFile, XTreeWidgetItem *aParentItem = nullptr); - void AddIWIFile(IWIFile* aIWIFile); - void AddDDSFile(DDSFile* aDDSFile); + //void AddIWIFile(IWIFile* aIWIFile); + //void AddDDSFile(IWIFile* aDDSFile); const ZoneFile *FindZoneFile(const QString aStem); const FastFile* FindFastFile(const QString aStem); @@ -35,9 +35,9 @@ public: bool HasFastFile(const QString aStem); void CloseFastFile(const QString aFFName); + void AddAsset(XAsset *aAsset, const QString &aZoneFileName, XTreeWidgetItem *aRootItem); signals: - void DDSFileSelected(const DDSFile* aDDSFile, const QString aParentName); - void IWIFileSelected(const IWIFile* aIWIFile, const QString aParentName); + //void IWIFileSelected(const IWIFile* aIWIFile, const QString aParentName); void FastFileSelected(const FastFile* aFastFile, const QString aParentName); void ZoneFileSelected(const ZoneFile* aZoneFile, const QString aParentName); void LocalStringSelected(const ZoneFile* aZoneFile, const QString aParentName); @@ -60,8 +60,10 @@ protected: private: QMap mFastFiles; QMap mZoneFiles; - QMap mDDSFiles; - QMap mIWIFiles; + //QMap mDDSFiles; + //QMap mIWIFiles; + + QMap> mRootItemMap; }; #endif // XTREEWIDGET_H diff --git a/app/xtreewidgetitem.cpp b/app/xtreewidgetitem.cpp index affe42e..a428770 100644 --- a/app/xtreewidgetitem.cpp +++ b/app/xtreewidgetitem.cpp @@ -3,27 +3,19 @@ XTreeWidgetItem::XTreeWidgetItem(QTreeWidget *parent, bool group) : QTreeWidgetItem(parent) , isGroup(group) - , mCategory(CATEGORY_NONE) { + , mAssetType(ASSET_TYPE_NONE) + , mAssetPtr(nullptr) { } XTreeWidgetItem::XTreeWidgetItem(QTreeWidgetItem *parent, bool group) : QTreeWidgetItem(parent) , isGroup(group) - , mCategory(CATEGORY_NONE) { + , mAssetType(ASSET_TYPE_NONE) + , mAssetPtr(nullptr) { } -void XTreeWidgetItem::SetCategory(TREE_CATEGORY category) -{ - mCategory = category; -} - -TREE_CATEGORY XTreeWidgetItem::GetCategory() -{ - return mCategory; -} - bool XTreeWidgetItem::operator<(const QTreeWidgetItem &other) const { // Attempt to cast the other item to our custom type. const XTreeWidgetItem* otherItem = dynamic_cast(&other); @@ -54,3 +46,33 @@ XTreeWidgetItem& XTreeWidgetItem::operator=(const XTreeWidgetItem &other) } return *this; } + +XAssetType XTreeWidgetItem::AssetType() const +{ + return mAssetType; +} + +void XTreeWidgetItem::SetAssetType(XAssetType aAssetType) +{ + mAssetType = aAssetType; +} + +bool XTreeWidgetItem::GetIsGroup() const +{ + return isGroup; +} + +void XTreeWidgetItem::SetIsGroup(bool aIsGroup) +{ + isGroup = aIsGroup; +} + +XAsset *XTreeWidgetItem::AssetPtr() const +{ + return mAssetPtr; +} + +void XTreeWidgetItem::SetAssetPtr(XAsset *aAssetPtr) +{ + mAssetPtr = aAssetPtr; +} diff --git a/app/xtreewidgetitem.h b/app/xtreewidgetitem.h index 213bc36..b6b89f9 100644 --- a/app/xtreewidgetitem.h +++ b/app/xtreewidgetitem.h @@ -1,35 +1,36 @@ #ifndef XTREEWIDGETITEM_H #define XTREEWIDGETITEM_H +#include "xassettype.h" #include #include -enum TREE_CATEGORY { - CATEGORY_NONE = 0x00, - CATEGORY_FILE = 0x01, - CATEGORY_TYPE = 0x02 -}; +class XAsset; // Custom item class class XTreeWidgetItem : public QTreeWidgetItem { public: - // Flag to indicate if the item is a collapsible group/header. - bool isGroup; - - // Constructors: default to non-group unless specified. XTreeWidgetItem(QTreeWidget *parent, bool group = false); XTreeWidgetItem(QTreeWidgetItem *parent, bool group = false); - - void SetCategory(TREE_CATEGORY category); - TREE_CATEGORY GetCategory(); + ~XTreeWidgetItem() = default; // Override the less-than operator to customize sorting. bool operator<(const QTreeWidgetItem &other) const override; XTreeWidgetItem &operator =(const XTreeWidgetItem &other); + XAssetType AssetType() const; + void SetAssetType(XAssetType aAssetType); + + bool GetIsGroup() const; + void SetIsGroup(bool aIsGroup); + XAsset *AssetPtr() const; + void SetAssetPtr(XAsset *aAssetPtr); + private: - TREE_CATEGORY mCategory; + bool isGroup; + XAssetType mAssetType; + XAsset* mAssetPtr; }; diff --git a/app/zonefileviewer.cpp b/app/zonefileviewer.cpp index b3ca3a2..59719a5 100644 --- a/app/zonefileviewer.cpp +++ b/app/zonefileviewer.cpp @@ -52,14 +52,13 @@ void ZoneFileViewer::HighlightRecordInOrder() { void ZoneFileViewer::SortTags(const QString &aSearchText) { ui->listWidget_Tags->clear(); - const QStringList tags = mZoneFile->GetTags(); if (aSearchText.isEmpty()) { - ui->listWidget_Tags->addItems(tags); + ui->listWidget_Tags->addItems(mTags); return; } QStringList sortedTags; - foreach (const QString tag, tags) { + foreach (const QString tag, mTags) { if (tag.contains(aSearchText)) { sortedTags << tag; } @@ -72,17 +71,22 @@ void ZoneFileViewer::SortTags(const QString &aSearchText) { void ZoneFileViewer::SetZoneFile(const ZoneFile* aZoneFile) { mZoneFile = aZoneFile; + auto rawTags = aZoneFile->GetAssetList().GetStringList().ScriptStrings(); + for (int i = 0; i < rawTags.size(); i++) + { + mTags.push_back(rawTags[i].GetString()); + } + ui->tableWidget_RecordCounts->clearContents(); ui->tableWidget_RecordOrder->clearContents(); ui->listWidget_Tags->clear(); - const QStringList tags = mZoneFile->GetTags(); - ui->listWidget_Tags->addItems(tags); + ui->listWidget_Tags->addItems(mTags); ui->label_Title->setText(mZoneFile->GetBaseStem() + ".zone"); - ui->groupBox_Tags->setTitle(QString("Tags (%1)").arg(tags.size())); + ui->groupBox_Tags->setTitle(QString("Tags (%1)").arg(mTags.size())); - if (tags.isEmpty()) { + if (mTags.isEmpty()) { ui->groupBox_Tags->hide(); } else { ui->groupBox_Tags->show(); diff --git a/app/zonefileviewer.h b/app/zonefileviewer.h index 6a95549..ca83e91 100644 --- a/app/zonefileviewer.h +++ b/app/zonefileviewer.h @@ -28,6 +28,7 @@ public slots: private: Ui::ZoneFileViewer *ui; const ZoneFile* mZoneFile; + QStringList mTags; }; #endif // ZONEFILEVIEWER_H diff --git a/libs/compression/compression.cpp b/libs/compression/compression.cpp index 850e72a..b9153f0 100644 --- a/libs/compression/compression.cpp +++ b/libs/compression/compression.cpp @@ -336,7 +336,7 @@ QByteArray Compression::DecompressLZO(const QByteArray &aCompressedData, quint32 } QByteArray Compression::DecompressOodle(const QByteArray &aCompressedData, quint32 aDecompressedSize) { - return pDecompressOodle(aCompressedData, aCompressedData.length(), aDecompressedSize); + return pDecompressOodle(aCompressedData, aCompressedData.size(), aDecompressedSize); } QByteArray Compression::CompressOodle(const QByteArray &aData) { @@ -352,18 +352,16 @@ quint32 Compression::pGetOodleCompressedBounds(quint32 aBufferSize) { } QByteArray Compression::pCompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize, OodleFormat aformat, OodleCompressionLevel alevel) { - QLibrary oodleLib("oo2core_8_win64"); - - if (!oodleLib.load()) { - qDebug() << "Failed to load DLL:" << oodleLib.errorString(); + QLibrary lib("../../../third_party/oodle_lib/dll/oo2core_8_win64.dll"); // adjust path if needed + if (!lib.load()) { + qDebug() << "Failed to load:" << lib.errorString(); return QByteArray(); } - OodleLZ_CompressFunc OodleLZ_Compress = - (OodleLZ_CompressFunc)oodleLib.resolve("OodleLZ_Compress"); + OodleLZ_CompressFunc OodleLZ_Compress = (OodleLZ_CompressFunc)lib.resolve("OodleLZ_Compress"); if (!OodleLZ_Compress) { - qDebug() << "Failed to resolve function:" << oodleLib.errorString(); + qDebug() << "Failed to resolve OodleLZ_Compress:" << lib.errorString(); return QByteArray(); } @@ -375,26 +373,58 @@ QByteArray Compression::pCompressOodle(QByteArray aBuffer, quint32 aBufferSize, return QByteArray(reinterpret_cast(outputBuffer), aOutputBufferSize); } -QByteArray Compression::pDecompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize) { - QLibrary oodleLib("oo2core_8_win64"); - - if (!oodleLib.load()) { - qDebug() << "Failed to load DLL:" << oodleLib.errorString(); - return QByteArray(); +QByteArray Compression::pDecompressOodle(const QByteArray &aBuffer, + quint32 aBufferSize, + quint32 aOutputBufferSize) +{ + QLibrary lib("../../../third_party/oodle_lib/dll/oo2core_8_win64.dll"); + if (!lib.load()) { + qWarning() << "Failed to load Oodle DLL:" << lib.errorString(); + return {}; } OodleLZ_DecompressFunc OodleLZ_Decompress = - (OodleLZ_DecompressFunc)oodleLib.resolve("OodleLZ_Decompress"); - + reinterpret_cast(lib.resolve("OodleLZ_Decompress")); if (!OodleLZ_Decompress) { - qDebug() << "Failed to resolve function:" << oodleLib.errorString(); - return QByteArray(); + qWarning() << "Failed to resolve OodleLZ_Decompress:" << lib.errorString(); + return {}; } - std::byte *outputBuffer = new std::byte[aOutputBufferSize]; + QByteArray out(aOutputBufferSize + 1, Qt::Uninitialized); - if (aBuffer.length() > 0 && aBufferSize > 0 && aOutputBufferSize > 0) - OodleLZ_Decompress(reinterpret_cast(aBuffer.data()), aBufferSize, outputBuffer, aOutputBufferSize, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + if (aBuffer.isEmpty() || aBufferSize == 0 || aOutputBufferSize == 0) { + qWarning() << "Invalid Oodle parameters (empty input or size 0)"; + return {}; + } - return QByteArray(reinterpret_cast(outputBuffer), aOutputBufferSize); + int result = OodleLZ_Decompress( + aBuffer.constData(), + static_cast(aBufferSize), + out.data(), + static_cast(aOutputBufferSize), + 1, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 3); + + if (result < 0) { + qWarning() << "OodleLZ_Decompress failed with code" << result; + return {}; + } + + if (result > out.size()) { + qWarning() << "Oodle returned more than expected:" << result + << "expected" << aOutputBufferSize; + return out; + } + + out.resize(result); + + return out; } diff --git a/libs/compression/compression.h b/libs/compression/compression.h index 8026ece..7c9f685 100644 --- a/libs/compression/compression.h +++ b/libs/compression/compression.h @@ -41,7 +41,22 @@ enum OodleCompressionLevel { }; typedef int (*OodleLZ_CompressFunc)(OodleFormat Format, std::byte *Buffer, long BufferSize, std::byte *OutputBuffer, OodleCompressionLevel Level, uint a, uint b, uint c); -typedef int (*OodleLZ_DecompressFunc)(std::byte* Buffer, long BufferSize, std::byte* OutputBuffer, long OutputBufferSize, uint a, uint b, uint c, uint d, uint e, uint f, uint g, uint h, uint i, int ThreadModule); +typedef int (__stdcall *OodleLZ_DecompressFunc)( + const void *compBuf, + int64_t compBufSize, + void *rawBuf, + int64_t rawLen, + uint32_t fuzzSafe, + uint32_t checkCRC, + uint32_t verbosity, + void *decBufBase, + size_t decBufSize, + void *fpCallback, + void *callbackUserData, + void *decoderMemory, + size_t decoderMemorySize, + int threadPhase +); class Compression { public: @@ -80,7 +95,7 @@ private: static quint32 pGetOodleCompressedBounds(quint32 aBufferSize); static QByteArray pCompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize, OodleFormat aformat, OodleCompressionLevel alevel); - static QByteArray pDecompressOodle(QByteArray aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize); + static QByteArray pDecompressOodle(const QByteArray &aBuffer, quint32 aBufferSize, quint32 aOutputBufferSize); }; diff --git a/libs/fastfile/360/fastfile_cod10_360.cpp b/libs/fastfile/360/fastfile_cod10_360.cpp index ef47f9a..1508213 100644 --- a/libs/fastfile/360/fastfile_cod10_360.cpp +++ b/libs/fastfile/360/fastfile_cod10_360.cpp @@ -12,8 +12,6 @@ FastFile_COD10_360::FastFile_COD10_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD10"); } FastFile_COD10_360::FastFile_COD10_360(const QByteArray& aData) @@ -103,6 +101,7 @@ bool FastFile_COD10_360::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD10_360* zoneFile = new ZoneFile_COD10_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod11_360.cpp b/libs/fastfile/360/fastfile_cod11_360.cpp index 4ba4dd7..182a4fe 100644 --- a/libs/fastfile/360/fastfile_cod11_360.cpp +++ b/libs/fastfile/360/fastfile_cod11_360.cpp @@ -15,8 +15,6 @@ FastFile_COD11_360::FastFile_COD11_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD11"); - SetPlatform("PC"); } FastFile_COD11_360::FastFile_COD11_360(const QByteArray& aData) @@ -141,6 +139,7 @@ bool FastFile_COD11_360::Load(const QByteArray aData) { // Load the zone file with decompressed data ZoneFile_COD11_360* zoneFile = new ZoneFile_COD11_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod12_360.cpp b/libs/fastfile/360/fastfile_cod12_360.cpp index a8804d6..285a34a 100644 --- a/libs/fastfile/360/fastfile_cod12_360.cpp +++ b/libs/fastfile/360/fastfile_cod12_360.cpp @@ -15,8 +15,6 @@ FastFile_COD12_360::FastFile_COD12_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD12"); - SetPlatform("PC"); } FastFile_COD12_360::FastFile_COD12_360(const QByteArray& aData) @@ -141,6 +139,7 @@ bool FastFile_COD12_360::Load(const QByteArray aData) { // Load the zone file with decompressed data ZoneFile_COD12_360* zoneFile = new ZoneFile_COD12_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod2_360.cpp b/libs/fastfile/360/fastfile_cod2_360.cpp index ce49fc1..8f76708 100644 --- a/libs/fastfile/360/fastfile_cod2_360.cpp +++ b/libs/fastfile/360/fastfile_cod2_360.cpp @@ -14,8 +14,6 @@ FastFile_COD2_360::FastFile_COD2_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD2"); } FastFile_COD2_360::FastFile_COD2_360(const QByteArray& aData) @@ -81,6 +79,7 @@ bool FastFile_COD2_360::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD2_360* zoneFile = new ZoneFile_COD2_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod4_360.cpp b/libs/fastfile/360/fastfile_cod4_360.cpp index 48c85fb..74a2330 100644 --- a/libs/fastfile/360/fastfile_cod4_360.cpp +++ b/libs/fastfile/360/fastfile_cod4_360.cpp @@ -15,8 +15,6 @@ FastFile_COD4_360::FastFile_COD4_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD4"); } FastFile_COD4_360::FastFile_COD4_360(const QByteArray& aData) @@ -130,6 +128,7 @@ bool FastFile_COD4_360::Load(const QByteArray aData) { ZoneFile_COD4_360* zoneFile = new ZoneFile_COD4_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod5_360.cpp b/libs/fastfile/360/fastfile_cod5_360.cpp index 8f6b65e..834ce96 100644 --- a/libs/fastfile/360/fastfile_cod5_360.cpp +++ b/libs/fastfile/360/fastfile_cod5_360.cpp @@ -15,8 +15,6 @@ FastFile_COD5_360::FastFile_COD5_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD5"); } FastFile_COD5_360::FastFile_COD5_360(const QByteArray& aData) @@ -82,6 +80,7 @@ bool FastFile_COD5_360::Load(const QByteArray aData) { ZoneFile_COD5_360* zoneFile = new ZoneFile_COD5_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod6_360.cpp b/libs/fastfile/360/fastfile_cod6_360.cpp index b0990f5..989e0fe 100644 --- a/libs/fastfile/360/fastfile_cod6_360.cpp +++ b/libs/fastfile/360/fastfile_cod6_360.cpp @@ -15,8 +15,6 @@ FastFile_COD6_360::FastFile_COD6_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD6"); } FastFile_COD6_360::FastFile_COD6_360(const QByteArray& aData) @@ -115,6 +113,7 @@ bool FastFile_COD6_360::Load(const QByteArray aData) { ZoneFile_COD6_360* zoneFile = new ZoneFile_COD6_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod7_360.cpp b/libs/fastfile/360/fastfile_cod7_360.cpp index c5ae73f..c63f184 100644 --- a/libs/fastfile/360/fastfile_cod7_360.cpp +++ b/libs/fastfile/360/fastfile_cod7_360.cpp @@ -14,8 +14,6 @@ FastFile_COD7_360::FastFile_COD7_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD7"); } FastFile_COD7_360::FastFile_COD7_360(const QByteArray& aData) @@ -140,6 +138,7 @@ bool FastFile_COD7_360::Load(const QByteArray aData) { ZoneFile_COD7_360* zoneFile = new ZoneFile_COD7_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod7_5_360.cpp b/libs/fastfile/360/fastfile_cod7_5_360.cpp index efc12af..0b7df8d 100644 --- a/libs/fastfile/360/fastfile_cod7_5_360.cpp +++ b/libs/fastfile/360/fastfile_cod7_5_360.cpp @@ -14,8 +14,6 @@ FastFile_COD7_5_360::FastFile_COD7_5_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD7.5"); } FastFile_COD7_5_360::FastFile_COD7_5_360(const QByteArray& aData) @@ -138,6 +136,7 @@ bool FastFile_COD7_5_360::Load(const QByteArray aData) { ZoneFile_COD7_360* zoneFile = new ZoneFile_COD7_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod8_360.cpp b/libs/fastfile/360/fastfile_cod8_360.cpp index 7f8be32..91df21b 100644 --- a/libs/fastfile/360/fastfile_cod8_360.cpp +++ b/libs/fastfile/360/fastfile_cod8_360.cpp @@ -12,8 +12,6 @@ FastFile_COD8_360::FastFile_COD8_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD8"); } FastFile_COD8_360::FastFile_COD8_360(const QByteArray& aData) @@ -101,6 +99,7 @@ bool FastFile_COD8_360::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD8_360* zoneFile = new ZoneFile_COD8_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/360/fastfile_cod9_360.cpp b/libs/fastfile/360/fastfile_cod9_360.cpp index bf2b7b8..d7aa799 100644 --- a/libs/fastfile/360/fastfile_cod9_360.cpp +++ b/libs/fastfile/360/fastfile_cod9_360.cpp @@ -12,8 +12,6 @@ FastFile_COD9_360::FastFile_COD9_360() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("360"); - SetGame("COD9"); } FastFile_COD9_360::FastFile_COD9_360(const QByteArray& aData) @@ -105,6 +103,7 @@ bool FastFile_COD9_360::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD9_360* zoneFile = new ZoneFile_COD9_360(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod10_pc.cpp b/libs/fastfile/PC/fastfile_cod10_pc.cpp index 865707c..6389e51 100644 --- a/libs/fastfile/PC/fastfile_cod10_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod10_pc.cpp @@ -12,8 +12,6 @@ FastFile_COD10_PC::FastFile_COD10_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD10"); - SetPlatform("PC"); } FastFile_COD10_PC::FastFile_COD10_PC(const QByteArray& aData) @@ -80,12 +78,10 @@ bool FastFile_COD10_PC::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD9"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); } @@ -122,6 +118,7 @@ bool FastFile_COD10_PC::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD10_PC* zoneFile = new ZoneFile_COD10_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod11_pc.cpp b/libs/fastfile/PC/fastfile_cod11_pc.cpp index 1950b2a..222a832 100644 --- a/libs/fastfile/PC/fastfile_cod11_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod11_pc.cpp @@ -12,8 +12,6 @@ FastFile_COD11_PC::FastFile_COD11_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD11"); - SetPlatform("PC"); } FastFile_COD11_PC::FastFile_COD11_PC(const QByteArray& aData) @@ -116,6 +114,7 @@ bool FastFile_COD11_PC::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD11_PC* zoneFile = new ZoneFile_COD11_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod12_pc.cpp b/libs/fastfile/PC/fastfile_cod12_pc.cpp index 89cd449..daf7eda 100644 --- a/libs/fastfile/PC/fastfile_cod12_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod12_pc.cpp @@ -15,8 +15,6 @@ FastFile_COD12_PC::FastFile_COD12_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD12"); - SetPlatform("PC"); } FastFile_COD12_PC::FastFile_COD12_PC(const QByteArray& aData) diff --git a/libs/fastfile/PC/fastfile_cod21_pc.cpp b/libs/fastfile/PC/fastfile_cod21_pc.cpp new file mode 100644 index 0000000..a2c4b7a --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod21_pc.cpp @@ -0,0 +1,209 @@ +#include "fastfile_cod21_pc.h" +#include "zonefile_cod21_pc.h" + +#include "utils.h" +#include "compression.h" +#include "encryption.h" + +#include +#include + +FastFile_COD21_PC::FastFile_COD21_PC() + : FastFile() { + SetCompany(COMPANY_INFINITY_WARD); + SetType(FILETYPE_FAST_FILE); + SetSignage(SIGNAGE_SIGNED); + SetMagic(0); + SetVersion(0); +} + +FastFile_COD21_PC::FastFile_COD21_PC(const QByteArray& aData) + : FastFile_COD21_PC() { + + if (!aData.isEmpty()) { + Load(aData); + } +} + +FastFile_COD21_PC::FastFile_COD21_PC(const QString aFilePath) + : FastFile_COD21_PC() { + + if (!aFilePath.isEmpty()) { + Load(aFilePath); + } +} + +FastFile_COD21_PC::~FastFile_COD21_PC() { + +} + +QByteArray FastFile_COD21_PC::GetBinaryData() const { + return QByteArray(); +} + +bool FastFile_COD21_PC::Load(const QString aFilePath) { + if (aFilePath.isEmpty()) { + return false; + } + + // Check fastfile can be read + QFile *file = new QFile(aFilePath); + if (!file->open(QIODevice::ReadOnly)) { + qDebug() << QString("Error: Failed to open FastFile: %1!").arg(aFilePath); + return false; + } + + // Decompress fastfile and close + const QString fastFileStem = aFilePath.section("/", -1, -1).split('.').first(); + SetStem(fastFileStem); + if (!Load(file->readAll())) { + qDebug() << "Error: Failed to load fastfile: " << fastFileStem; + return false; + } + + file->close(); + + // Open zone file after decompressing ff and writing + return true; +} + +bool FastFile_COD21_PC::Load(const QByteArray aData) { + QByteArray decompressedData; + + // Create a XDataStream on the input data. + XDataStream fastFileStream(aData); + fastFileStream.setByteOrder(XDataStream::LittleEndian); + auto dev = fastFileStream.device(); + + if (dev->bytesAvailable() < 12) { + qWarning() << "Not enough data for block header"; + return false; + } + + // Skip to start of fastfile + quint64 startIndex = aData.indexOf("IWCIWffs100"); + + if (startIndex == -1) + { + qDebug() << "Failed to find data start!"; + return true; + } + + fastFileStream.skipRawData(startIndex + 11); + qDebug() << "Start index: " << startIndex + 11; + + // Skip RSA hashes + fastFileStream.skipRawData(32760); + + qint32 decompressedDataLen = fastFileStream.ParseInt32(); + qDebug() << "Decompressed Data Len: " << decompressedDataLen; + + fastFileStream.skipRawData(3); + + qint8 compressionType = fastFileStream.ParseInt8(); + qDebug() << "Compression Type: " << compressionType; + + long decompressedDataCount = 0; + int loopCount = 1; + while (decompressedDataCount < decompressedDataLen) + { + qDebug() << QString("Block Offset: {0:%1}, total: {1:%2}").arg(fastFileStream.device()->pos()).arg(decompressedDataCount); + + if (loopCount == 512) + { + // Skip an RSA block + fastFileStream.skipRawData(0x4000); + loopCount = 0; + } + qint32 compLenRaw = fastFileStream.ParseInt32(); + qDebug() << "Test: " << fastFileStream.device()->pos(); + qint32 compressedLen = (compLenRaw + 3) & ~3; + qint32 decompressedLen = fastFileStream.ParseInt32(); + + if (dev->bytesAvailable() < compressedLen) { + qDebug() << "Too Much at: " << fastFileStream.device()->pos(); + qWarning() << "Not enough data for compressed block. Want" + << compressedLen << "have" << dev->bytesAvailable(); + break; + } + + fastFileStream.skipRawData(4); // padding + + QByteArray compressedAligned(compressedLen, Qt::Uninitialized); + + // Read the full aligned block + if (fastFileStream.readRawData(compressedAligned.data(), compressedLen) != compressedLen) { + qWarning() << "Unexpected EOF while reading aligned compressed block"; + //return false; + } + + // Only first compLenRaw bytes are real data + QByteArray compressedChunk = compressedAligned.left(compLenRaw); + + QByteArray decompressedChunk; + switch (compressionType) + { + // Decompress None + case 1: + decompressedChunk = compressedChunk; + break; + + // unknown + case 4: + case 5: + qDebug() << "unimplemented compression type!"; + return false; + + // Decompress Oodle + case 6: + case 7: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + qDebug() << "Calling Oodle with compLenRaw=" << compLenRaw + << "aligned=" << compressedLen + << "decompressedLen=" << decompressedLen; + decompressedChunk = Compression::DecompressOodle(compressedChunk, decompressedLen); + break; + + default: + qDebug() << "Unknown type of compression!"; + return false; + } + + if (decompressedChunk.isNull()) + { + qDebug() << "Decompressor returned null!"; + continue; + } + + if (decompressedDataCount + decompressedLen > decompressedDataLen) { + qWarning() << "Decompressed overrun:" << decompressedDataCount + decompressedLen + << ">" << decompressedDataLen; + decompressedLen = decompressedDataLen - decompressedDataCount; + decompressedChunk.truncate(decompressedLen); + } + + decompressedData.append(decompressedChunk); + + decompressedDataCount += decompressedLen; + loopCount++; + } + Utils::ExportData(GetBaseStem() + ".zone", decompressedData); + + // // Load the zone file with the decompressed data (using an Xbox platform flag). + ZoneFile_COD21_PC* zoneFile = new ZoneFile_COD21_PC(); + zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); + if (!zoneFile->Load(decompressedData)) { + qWarning() << "Failed to load ZoneFile!"; + return false; + } + SetZoneFile(zoneFile); + + return true; +} + diff --git a/libs/fastfile/PC/fastfile_cod21_pc.h b/libs/fastfile/PC/fastfile_cod21_pc.h new file mode 100644 index 0000000..e029131 --- /dev/null +++ b/libs/fastfile/PC/fastfile_cod21_pc.h @@ -0,0 +1,20 @@ +#ifndef FASTFILE_COD21_PC_H +#define FASTFILE_COD21_PC_H + +#include "fastfile.h" + +class FastFile_COD21_PC : public FastFile +{ +public: + FastFile_COD21_PC(); + FastFile_COD21_PC(const QByteArray &aData); + FastFile_COD21_PC(const QString aFilePath); + ~FastFile_COD21_PC(); + + QByteArray GetBinaryData() const override; + + bool Load(const QString aFilePath) override; + bool Load(const QByteArray aData) override; +}; + +#endif // FASTFILE_COD21_PC_H diff --git a/libs/fastfile/PC/fastfile_cod4_pc.cpp b/libs/fastfile/PC/fastfile_cod4_pc.cpp index bd39b40..9f05206 100644 --- a/libs/fastfile/PC/fastfile_cod4_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod4_pc.cpp @@ -15,8 +15,6 @@ FastFile_COD4_PC::FastFile_COD4_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("PC"); - SetGame("COD4"); } FastFile_COD4_PC::FastFile_COD4_PC(const QByteArray& aData) @@ -44,7 +42,7 @@ QByteArray FastFile_COD4_PC::GetBinaryData() const { } bool FastFile_COD4_PC::Load(const QString aFilePath) { - StatusBarManager::instance().updateStatus("Loading " + GetGame() + " Fast File w/path", 1000); + StatusBarManager::instance().updateStatus("Loading COD" + GetCommonInfo().GetGameString() + " Fast File w/path", 1000); if (aFilePath.isEmpty()) { return false; @@ -86,6 +84,7 @@ bool FastFile_COD4_PC::Load(const QByteArray aData) { ZoneFile_COD4_PC* zoneFile = new ZoneFile_COD4_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod5_pc.cpp b/libs/fastfile/PC/fastfile_cod5_pc.cpp index e8bcd36..b51c5ec 100644 --- a/libs/fastfile/PC/fastfile_cod5_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod5_pc.cpp @@ -15,8 +15,6 @@ FastFile_COD5_PC::FastFile_COD5_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("PC"); - SetGame("COD5"); } FastFile_COD5_PC::FastFile_COD5_PC(const QByteArray& aData) @@ -86,6 +84,7 @@ bool FastFile_COD5_PC::Load(const QByteArray aData) { ZoneFile_COD5_PC* zoneFile = new ZoneFile_COD5_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod6_pc.cpp b/libs/fastfile/PC/fastfile_cod6_pc.cpp index 1aa09ef..6bd932d 100644 --- a/libs/fastfile/PC/fastfile_cod6_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod6_pc.cpp @@ -15,8 +15,6 @@ FastFile_COD6_PC::FastFile_COD6_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetPlatform("PC"); - SetGame("COD6"); } FastFile_COD6_PC::FastFile_COD6_PC(const QByteArray& aData) @@ -101,6 +99,7 @@ bool FastFile_COD6_PC::Load(const QByteArray aData) { ZoneFile_COD6_PC* zoneFile = new ZoneFile_COD6_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod7_pc.cpp b/libs/fastfile/PC/fastfile_cod7_pc.cpp index d33f148..1bb5483 100644 --- a/libs/fastfile/PC/fastfile_cod7_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod7_pc.cpp @@ -1,9 +1,8 @@ #include "fastfile_cod7_pc.h" -#include "zonefile_cod7_pc.h" +//#include "zonefile_cod7_pc.h" #include "utils.h" #include "compression.h" -#include "encryption.h" #include #include @@ -15,8 +14,6 @@ FastFile_COD7_PC::FastFile_COD7_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD7"); - SetPlatform("PC"); } FastFile_COD7_PC::FastFile_COD7_PC(const QByteArray& aData) @@ -83,8 +80,6 @@ bool FastFile_COD7_PC::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform("360"); - SetGame("COD7"); // Assume the first 12 bytes are a header; the rest is zlib-compressed zone data. const QByteArray compressedData = aData.mid(12); @@ -92,13 +87,14 @@ bool FastFile_COD7_PC::Load(const QByteArray aData) { Utils::ExportData(GetBaseStem() + ".zone", decompressedData); - ZoneFile_COD7_PC* zoneFile = new ZoneFile_COD7_PC(); - zoneFile->SetStem(GetBaseStem() + ".zone"); - if (!zoneFile->Load(decompressedData)) { - qWarning() << "Failed to load ZoneFile!"; - return false; - } - SetZoneFile(zoneFile); + // ZoneFile_COD7_PC* zoneFile = new ZoneFile_COD7_PC(); + // zoneFile->SetStem(GetBaseStem() + ".zone"); + // zoneFile->SetCommonInfo(&mCommonInfo); + // if (!zoneFile->Load(decompressedData)) { + // qWarning() << "Failed to load ZoneFile!"; + // return false; + // } + // SetZoneFile(zoneFile); return true; } diff --git a/libs/fastfile/PC/fastfile_cod8_pc.cpp b/libs/fastfile/PC/fastfile_cod8_pc.cpp index 52f8d5f..d62d07a 100644 --- a/libs/fastfile/PC/fastfile_cod8_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod8_pc.cpp @@ -15,8 +15,6 @@ FastFile_COD8_PC::FastFile_COD8_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD8"); - SetPlatform("PC"); } FastFile_COD8_PC::FastFile_COD8_PC(const QByteArray& aData) @@ -88,6 +86,7 @@ bool FastFile_COD8_PC::Load(const QByteArray aData) { ZoneFile_COD8_PC* zoneFile = new ZoneFile_COD8_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PC/fastfile_cod9_pc.cpp b/libs/fastfile/PC/fastfile_cod9_pc.cpp index de4d678..97ab377 100644 --- a/libs/fastfile/PC/fastfile_cod9_pc.cpp +++ b/libs/fastfile/PC/fastfile_cod9_pc.cpp @@ -12,8 +12,6 @@ FastFile_COD9_PC::FastFile_COD9_PC() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD9"); - SetPlatform("PC"); } FastFile_COD9_PC::FastFile_COD9_PC(const QByteArray& aData) @@ -174,6 +172,7 @@ bool FastFile_COD9_PC::Load(const QByteArray aData) { // Load zone file ZoneFile_COD9_PC* zoneFile = new ZoneFile_COD9_PC(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(finalZone)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod10_ps3.cpp b/libs/fastfile/PS3/fastfile_cod10_ps3.cpp index 753f406..59a0eed 100644 --- a/libs/fastfile/PS3/fastfile_cod10_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod10_ps3.cpp @@ -12,8 +12,6 @@ FastFile_COD10_PS3::FastFile_COD10_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD10"); - SetPlatform("PS3"); } FastFile_COD10_PS3::FastFile_COD10_PS3(const QByteArray& aData) @@ -80,20 +78,18 @@ bool FastFile_COD10_PS3::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD9"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); } // Select key based on game. QByteArray key; - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); } @@ -122,6 +118,7 @@ bool FastFile_COD10_PS3::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD10_PS3* zoneFile = new ZoneFile_COD10_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod11_ps3.cpp b/libs/fastfile/PS3/fastfile_cod11_ps3.cpp index 45b94ca..8b509c1 100644 --- a/libs/fastfile/PS3/fastfile_cod11_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod11_ps3.cpp @@ -13,8 +13,6 @@ FastFile_COD11_PS3::FastFile_COD11_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD11"); - SetPlatform("PS3"); } FastFile_COD11_PS3::FastFile_COD11_PS3(const QByteArray& aData) @@ -140,6 +138,7 @@ bool FastFile_COD11_PS3::Load(const QByteArray aData) { // Load the zone file with decompressed data ZoneFile_COD11_PS3* zoneFile = new ZoneFile_COD11_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod12_ps3.cpp b/libs/fastfile/PS3/fastfile_cod12_ps3.cpp index ae8f481..541e2b2 100644 --- a/libs/fastfile/PS3/fastfile_cod12_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod12_ps3.cpp @@ -12,8 +12,6 @@ FastFile_COD12_PS3::FastFile_COD12_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD12"); - SetPlatform("PS3"); } FastFile_COD12_PS3::FastFile_COD12_PS3(const QByteArray& aData) @@ -80,20 +78,18 @@ bool FastFile_COD12_PS3::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD9"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); } // Select key based on game. QByteArray key; - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); } @@ -122,6 +118,7 @@ bool FastFile_COD12_PS3::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD12_PS3* zoneFile = new ZoneFile_COD12_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod4_ps3.cpp b/libs/fastfile/PS3/fastfile_cod4_ps3.cpp index a8743fb..e88c060 100644 --- a/libs/fastfile/PS3/fastfile_cod4_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod4_ps3.cpp @@ -15,8 +15,6 @@ FastFile_COD4_PS3::FastFile_COD4_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD4"); - SetPlatform("PS3"); } FastFile_COD4_PS3::FastFile_COD4_PS3(const QByteArray& aData) @@ -108,6 +106,7 @@ bool FastFile_COD4_PS3::Load(const QByteArray aData) { ZoneFile_COD4_PS3* zoneFile = new ZoneFile_COD4_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod5_ps3.cpp b/libs/fastfile/PS3/fastfile_cod5_ps3.cpp index 5c98ca9..8aec701 100644 --- a/libs/fastfile/PS3/fastfile_cod5_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod5_ps3.cpp @@ -15,8 +15,6 @@ FastFile_COD5_PS3::FastFile_COD5_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD5"); - SetPlatform("PS3"); } FastFile_COD5_PS3::FastFile_COD5_PS3(const QByteArray& aData) @@ -108,6 +106,7 @@ bool FastFile_COD5_PS3::Load(const QByteArray aData) { ZoneFile_COD5_PS3* zoneFile = new ZoneFile_COD5_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod6_ps3.cpp b/libs/fastfile/PS3/fastfile_cod6_ps3.cpp index 884886a..1bf501e 100644 --- a/libs/fastfile/PS3/fastfile_cod6_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod6_ps3.cpp @@ -15,8 +15,6 @@ FastFile_COD6_PS3::FastFile_COD6_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD6"); - SetPlatform("PS3"); } FastFile_COD6_PS3::FastFile_COD6_PS3(const QByteArray& aData) @@ -101,6 +99,7 @@ bool FastFile_COD6_PS3::Load(const QByteArray aData) { ZoneFile_COD6_PS3* zoneFile = new ZoneFile_COD6_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/PS3/fastfile_cod7_ps3.cpp b/libs/fastfile/PS3/fastfile_cod7_ps3.cpp index 5ec48d2..3d6bc2d 100644 --- a/libs/fastfile/PS3/fastfile_cod7_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod7_ps3.cpp @@ -15,8 +15,6 @@ FastFile_COD7_PS3::FastFile_COD7_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD7"); - SetPlatform("PS3"); } FastFile_COD7_PS3::FastFile_COD7_PS3(const QByteArray& aData) @@ -84,6 +82,7 @@ bool FastFile_COD7_PS3::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD7_PS3* zoneFile = new ZoneFile_COD7_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); diff --git a/libs/fastfile/PS3/fastfile_cod8_ps3.cpp b/libs/fastfile/PS3/fastfile_cod8_ps3.cpp index 65b7efb..c44cd9a 100644 --- a/libs/fastfile/PS3/fastfile_cod8_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod8_ps3.cpp @@ -15,8 +15,6 @@ FastFile_COD8_PS3::FastFile_COD8_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD8"); - SetPlatform("PS3"); } FastFile_COD8_PS3::FastFile_COD8_PS3(const QByteArray& aData) @@ -83,23 +81,22 @@ bool FastFile_COD8_PS3::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD7"); ZoneFile_COD8_PS3* zoneFile = new ZoneFile_COD8_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); // Select key based on game. QByteArray key; fastFileStream.skipRawData(4); - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { key = QByteArray::fromHex("1ac1d12d527c59b40eca619120ff8217ccff09cd16896f81b829c7f52793405d"); - } else if (GetPlatform() == "PS3") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PS3) { key = QByteArray::fromHex("46D3F997F29C9ACE175B0DAE3AB8C0C1B8E423E2E3BF7E3C311EA35245BF193A"); // or // key = QByteArray::fromHex("0C99B3DDB8D6D0845D1147E470F28A8BF2AE69A8A9F534767B54E9180FF55370"); diff --git a/libs/fastfile/PS3/fastfile_cod9_ps3.cpp b/libs/fastfile/PS3/fastfile_cod9_ps3.cpp index 7c48e8e..338b7ba 100644 --- a/libs/fastfile/PS3/fastfile_cod9_ps3.cpp +++ b/libs/fastfile/PS3/fastfile_cod9_ps3.cpp @@ -12,8 +12,6 @@ FastFile_COD9_PS3::FastFile_COD9_PS3() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD9"); - SetPlatform("PS3"); } FastFile_COD9_PS3::FastFile_COD9_PS3(const QByteArray& aData) @@ -80,20 +78,18 @@ bool FastFile_COD9_PS3::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD9"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); } // Select key based on game. QByteArray key; - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); } @@ -114,9 +110,9 @@ bool FastFile_COD9_PS3::Load(const QByteArray aData) { QByteArray rsaSignature(256, Qt::Uninitialized); fastFileStream.readRawData(rsaSignature.data(), 256); - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { //decompressedData = Compressor::cod9_decryptFastFile(aData); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { //decompressedData = Encryption::decryptFastFile_BO2(aData); } @@ -130,6 +126,7 @@ bool FastFile_COD9_PS3::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD9_PS3* zoneFile = new ZoneFile_COD9_PS3(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/Wii/fastfile_cod4_wii.cpp b/libs/fastfile/Wii/fastfile_cod4_wii.cpp index 9830d5f..0551e85 100644 --- a/libs/fastfile/Wii/fastfile_cod4_wii.cpp +++ b/libs/fastfile/Wii/fastfile_cod4_wii.cpp @@ -14,8 +14,6 @@ FastFile_COD4_Wii::FastFile_COD4_Wii() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD4"); - SetPlatform("Wii"); } FastFile_COD4_Wii::FastFile_COD4_Wii(const QByteArray& aData) @@ -75,6 +73,7 @@ bool FastFile_COD4_Wii::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD4_Wii* zoneFile = new ZoneFile_COD4_Wii(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/Wii/fastfile_cod7_wii.cpp b/libs/fastfile/Wii/fastfile_cod7_wii.cpp index 50a31e0..d1cea87 100644 --- a/libs/fastfile/Wii/fastfile_cod7_wii.cpp +++ b/libs/fastfile/Wii/fastfile_cod7_wii.cpp @@ -14,8 +14,6 @@ FastFile_COD7_Wii::FastFile_COD7_Wii() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD7"); - SetPlatform("Wii"); } FastFile_COD7_Wii::FastFile_COD7_Wii(const QByteArray& aData) @@ -80,8 +78,6 @@ bool FastFile_COD7_Wii::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD7"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); @@ -103,6 +99,7 @@ bool FastFile_COD7_Wii::Load(const QByteArray aData) { ZoneFile_COD7_Wii* zoneFile = new ZoneFile_COD7_Wii(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/Wii/fastfile_cod8_wii.cpp b/libs/fastfile/Wii/fastfile_cod8_wii.cpp index 696a65e..6291c28 100644 --- a/libs/fastfile/Wii/fastfile_cod8_wii.cpp +++ b/libs/fastfile/Wii/fastfile_cod8_wii.cpp @@ -14,8 +14,6 @@ FastFile_COD8_Wii::FastFile_COD8_Wii() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD8"); - SetPlatform("Wii"); } FastFile_COD8_Wii::FastFile_COD8_Wii(const QByteArray& aData) @@ -90,6 +88,7 @@ bool FastFile_COD8_Wii::Load(const QByteArray aData) { ZoneFile_COD8_Wii* zoneFile = new ZoneFile_COD8_Wii(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp b/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp index f6b34ca..e793fa1 100644 --- a/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp +++ b/libs/fastfile/WiiU/fastfile_cod10_wiiu.cpp @@ -12,8 +12,6 @@ FastFile_COD10_WiiU::FastFile_COD10_WiiU() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD10"); - SetPlatform("WiiU"); } FastFile_COD10_WiiU::FastFile_COD10_WiiU(const QByteArray& aData) @@ -78,20 +76,18 @@ bool FastFile_COD10_WiiU::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD9"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); } // Select key based on game. QByteArray key; - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); } @@ -112,9 +108,9 @@ bool FastFile_COD10_WiiU::Load(const QByteArray aData) { QByteArray rsaSignature(256, Qt::Uninitialized); fastFileStream.readRawData(rsaSignature.data(), 256); - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { //decompressedData = Compressor::cod9_decryptFastFile(aData); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { //decompressedData = Encryption::decryptFastFile_BO2(aData); } @@ -128,6 +124,7 @@ bool FastFile_COD10_WiiU::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD10_WiiU *zoneFile = new ZoneFile_COD10_WiiU(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp b/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp index de6b99c..9e333af 100644 --- a/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp +++ b/libs/fastfile/WiiU/fastfile_cod9_wiiu.cpp @@ -12,8 +12,6 @@ FastFile_COD9_WiiU::FastFile_COD9_WiiU() SetSignage(SIGNAGE_UNSIGNED); SetMagic(0); SetVersion(0); - SetGame("COD9"); - SetPlatform("WiiU"); } FastFile_COD9_WiiU::FastFile_COD9_WiiU(const QByteArray& aData) @@ -78,20 +76,18 @@ bool FastFile_COD9_WiiU::Load(const QByteArray aData) { SetMagic(pParseFFMagic(&fastFileStream)); quint32 version = pParseFFVersion(&fastFileStream); SetVersion(version); - SetPlatform(pCalculateFFPlatform(version)); - SetGame("COD9"); // For COD7/COD9, use BigEndian. fastFileStream.setByteOrder(XDataStream::BigEndian); - if (GetPlatform() == "PC") { + if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { fastFileStream.setByteOrder(XDataStream::LittleEndian); } // Select key based on game. QByteArray key; - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { key = QByteArray::fromHex("0E50F49F412317096038665622DD091332A209BA0A05A00E1377CEDB0A3CB1D3"); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { key = QByteArray::fromHex("641D8A2FE31D3AA63622BBC9CE8587229D42B0F8ED9B924130BF88B65EDC50BE"); } @@ -112,9 +108,9 @@ bool FastFile_COD9_WiiU::Load(const QByteArray aData) { QByteArray rsaSignature(256, Qt::Uninitialized); fastFileStream.readRawData(rsaSignature.data(), 256); - if (GetPlatform() == "360") { + if (GetCommonInfo().GetPlatform() == PLATFORM_XBOX) { //decompressedData = Compressor::cod9_decryptFastFile(aData); - } else if (GetPlatform() == "PC") { + } else if (GetCommonInfo().GetPlatform() == PLATFORM_PC) { //decompressedData = Encryption::decryptFastFile_BO2(aData); } @@ -128,6 +124,7 @@ bool FastFile_COD9_WiiU::Load(const QByteArray aData) { // Load the zone file with the decompressed data (using an Xbox platform flag). ZoneFile_COD9_WiiU* zoneFile = new ZoneFile_COD9_WiiU(); zoneFile->SetStem(GetBaseStem() + ".zone"); + zoneFile->SetCommonInfo(&mCommonInfo); if (!zoneFile->Load(decompressedData)) { qWarning() << "Failed to load ZoneFile!"; return false; diff --git a/libs/fastfile/fastfile.cpp b/libs/fastfile/fastfile.cpp index 685efad..ccc5450 100644 --- a/libs/fastfile/fastfile.cpp +++ b/libs/fastfile/fastfile.cpp @@ -7,15 +7,15 @@ #include FastFile::FastFile() - : mStem(""), - mType(FILETYPE_NONE), - mCompany(COMPANY_NONE), - mSignage(SIGNAGE_NONE), - mMagic(""), - mVersion(0), - mZoneFile(nullptr), - mGame(""), - mPlatform("") { + : mCommonInfo(), + mStem(""), + mType(FILETYPE_NONE), + mCompany(COMPANY_NONE), + mSignage(SIGNAGE_NONE), + mMagic(""), + mVersion(0), + mZoneFile(nullptr) +{ } @@ -24,15 +24,15 @@ FastFile::FastFile(const QByteArray &aData) { } FastFile::FastFile(FastFile &fastFile) - : mStem(fastFile.GetStem()), - mType(fastFile.GetType()), - mCompany(fastFile.GetCompany()), - mSignage(fastFile.GetSignage()), - mMagic(fastFile.GetMagic()), - mVersion(fastFile.GetVersion()), - mZoneFile(fastFile.GetZoneFile()), - mGame(fastFile.GetGame()), - mPlatform(fastFile.GetPlatform()) { + : mCommonInfo(fastFile.GetCommonInfo()), + mStem(fastFile.GetStem()), + mType(fastFile.GetType()), + mCompany(fastFile.GetCompany()), + mSignage(fastFile.GetSignage()), + mMagic(fastFile.GetMagic()), + mVersion(fastFile.GetVersion()), + mZoneFile(fastFile.GetZoneFile()) +{ } @@ -72,14 +72,6 @@ const ZoneFile* FastFile::GetZoneFile() const { return mZoneFile; } -QString FastFile::GetGame() const { - return mGame; -} - -QString FastFile::GetPlatform() const { - return mPlatform; -} - void FastFile::SetStem(const QString aStem) { mStem = aStem; } @@ -108,13 +100,6 @@ void FastFile::SetZoneFile(const ZoneFile* aZoneFile) { mZoneFile = aZoneFile; } -void FastFile::SetGame(const QString aGame) { mGame = aGame; -} - -void FastFile::SetPlatform(const QString aPlatform) { - mPlatform = aPlatform; -} - FF_COMPANY FastFile::pParseFFCompany(XDataStream *afastFileStream, quint32 &aCompanyInt) { LogManager::instance().addEntry("Parsing company into reference..."); // Check for null datastream ptr @@ -272,6 +257,27 @@ FastFile* FastFile::Open(const QString &aFilePath) { return fastFile; } + +XCommonInfo FastFile::GetCommonInfo() const +{ + return mCommonInfo; +} + +void FastFile::SetCommonInfo(const XCommonInfo &newCommonInfo) +{ + mCommonInfo = newCommonInfo; +} + +bool FastFile::Debug() const +{ + return mDebug; +} + +void FastFile::SetDebug(bool aDebug) +{ + mDebug = aDebug; +} + bool FastFile::ExportFastFile(const QString aFastFilePath) const { QFile fastFile(aFastFilePath); if (!fastFile.open(QIODevice::WriteOnly)) { diff --git a/libs/fastfile/fastfile.h b/libs/fastfile/fastfile.h index 62a71fd..8475c8c 100644 --- a/libs/fastfile/fastfile.h +++ b/libs/fastfile/fastfile.h @@ -2,8 +2,9 @@ #define FASTFILE_H #include "enums.h" -#include "utils.h" #include "zonefile.h" +#include "xcommoninfo.h" +#include "utils.h" #include #include @@ -33,8 +34,6 @@ public: virtual QString GetMagic() const; virtual quint32 GetVersion() const; virtual const ZoneFile *GetZoneFile() const; - virtual QString GetGame() const; - virtual QString GetPlatform() const; virtual void SetStem(const QString aStem); virtual void SetType(const FF_FILETYPE aType); @@ -43,8 +42,6 @@ public: virtual void SetMagic(const QString aMagic); virtual void SetVersion(const quint32 aVersion); virtual void SetZoneFile(const ZoneFile* aZoneFile); - virtual void SetGame(const QString aGame); - virtual void SetPlatform(const QString aPlatform); static FF_COMPANY pParseFFCompany(XDataStream *afastFileStream, quint32 &aCompanyInt); static FF_COMPANY pParseFFCompany(XDataStream *afastFileStream); @@ -57,6 +54,15 @@ public: static FastFile* Open(const QString& aFilePath); + XCommonInfo GetCommonInfo() const; + void SetCommonInfo(const XCommonInfo &newCommonInfo); + + bool Debug() const; + void SetDebug(bool aDebug); + +protected: + XCommonInfo mCommonInfo; + private: QString mStem; FF_FILETYPE mType; @@ -65,8 +71,8 @@ private: QString mMagic; quint32 mVersion; const ZoneFile* mZoneFile; - QString mGame; - QString mPlatform; + + bool mDebug; }; #endif // FASTFILE_H diff --git a/libs/fastfile/fastfile_factory.h b/libs/fastfile/fastfile_factory.h index 162be37..47c08de 100644 --- a/libs/fastfile/fastfile_factory.h +++ b/libs/fastfile/fastfile_factory.h @@ -15,6 +15,7 @@ #include "360/fastfile_cod12_360.h" //#include "PS3/fastfile_cod3_ps3.h" +#include "PC/fastfile_cod21_pc.h" #include "PS3/fastfile_cod4_ps3.h" #include "PS3/fastfile_cod5_ps3.h" #include "PS3/fastfile_cod6_ps3.h" @@ -45,39 +46,14 @@ #include #include -#include #include #include class FastFile; -enum FastFile_Platform { - PLATFORM_NONE = 0x00, - PLATFORM_PC = 0x01, - PLATFORM_360 = 0x02, - PLATFORM_PS3 = 0x03, - PLATFORM_WII = 0x04, - PLATFORM_WIIU = 0x05 -}; - -enum FastFile_Game { - GAME_NONE = 0x00, - GAME_COD2 = 0x01, - GAME_COD4 = 0x02, - GAME_COD5 = 0x03, - GAME_COD6 = 0x04, - GAME_COD7 = 0x05, - GAME_COD7_5 = 0x06, - GAME_COD8 = 0x07, - GAME_COD9 = 0x08, - GAME_COD10 = 0x09, - GAME_COD11 = 0x10, - GAME_COD12 = 0x11 -}; - class FastFileFactory { public: - static FastFile* Create(const QString& aFilePath, FastFile_Platform aPlatform = PLATFORM_NONE, FastFile_Game aGame = GAME_NONE) { + static FastFile* Create(const QString& aFilePath, XPlatform aPlatform = PLATFORM_NONE, XGame aGame = GAME_NONE) { QFile fastFile(aFilePath); if (!fastFile.open(QIODevice::ReadOnly)) { qDebug() << "Factory failed to open fast file: " << aFilePath; @@ -96,7 +72,7 @@ public: aGame = pGetGame(data); } - if (aPlatform == PLATFORM_360) { + if (aPlatform == PLATFORM_XBOX) { if (aGame == GAME_COD2) { resultFF = new FastFile_COD2_360(aFilePath); } else if (aGame == GAME_COD4) { @@ -173,9 +149,15 @@ public: resultFF = new FastFile_COD10_WiiU(aFilePath); } } + + if (resultFF) + { + resultFF->SetCommonInfo(XCommonInfo(aGame, aPlatform)); + } + return resultFF; } - static FastFile* Create(const QByteArray& aData, const QString aStem = "no_name", FastFile_Platform aPlatform = PLATFORM_NONE, FastFile_Game aGame = GAME_NONE) { + static FastFile* Create(const QByteArray& aData, const QString aStem = "no_name", XPlatform aPlatform = PLATFORM_NONE, XGame aGame = GAME_NONE) { FastFile* resultFF = nullptr; if (aPlatform == PLATFORM_NONE) { @@ -185,7 +167,7 @@ public: aGame = pGetGame(aData); } - if (aPlatform == PLATFORM_360) { + if (aPlatform == PLATFORM_XBOX) { if (aGame == GAME_COD2) { resultFF = new FastFile_COD2_360(); } else if (aGame == GAME_COD4) { @@ -228,6 +210,8 @@ public: resultFF = new FastFile_COD11_PC(); } else if (aGame == GAME_COD12) { resultFF = new FastFile_COD12_PC(); + } else if (aGame == GAME_COD21) { + resultFF = new FastFile_COD21_PC(); } } else if (aPlatform == PLATFORM_PS3) { if (aGame == GAME_COD4) { @@ -266,8 +250,10 @@ public: } if (resultFF) { resultFF->SetStem(aStem); + resultFF->SetCommonInfo(XCommonInfo(aGame, aPlatform)); resultFF->Load(aData); } + return resultFF; } private: @@ -286,33 +272,38 @@ private: return sections; } - static FastFile_Platform pGetPlatform(const QByteArray& aData) { + static XPlatform pGetPlatform(const QByteArray& aData) { const QStringList sections = pGetDataSections(aData); - if (sections[0] == "0000" || sections[0] == "4E58") { - return PLATFORM_360; - } else if (sections[4] == "0000") { + if (pGetGame(aData) == GAME_COD21) + { + return PLATFORM_PC; + } + else if (sections[0] == "0000" || sections[0] == "4E58") { + return PLATFORM_XBOX; + } + else if (sections[4] == "0000") { if (sections[5] == "0001" && sections[6] == "78DA") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[5] == "0001" && sections[6] == "4957") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[5] == "0183" && sections[6] == "7801") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[5] == "01D9" && sections[6] == "0000") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[6] == "0101" && sections[7] == "CA3E") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[6] == "0000" && sections[7] == "0001") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[6] == "0101" && sections[7] == "CC76") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[6] == "0101" && sections[7] == "0101") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[2] == "7831") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[0] == "5331" && sections[2] == "7531") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[2] == "3030" && sections[3] == "3030") { - return PLATFORM_360; + return PLATFORM_XBOX; } else if (sections[5] == "01A2" && sections[6] == "7801") { return PLATFORM_WII; } else if (sections[5] == "01DD" && sections[6] == "7801") { @@ -328,7 +319,7 @@ private: return PLATFORM_PS3; } - static FastFile_Game pGetGame(const QByteArray& aData) { + static XGame pGetGame(const QByteArray& aData) { const QStringList sections = pGetDataSections(aData); if (sections[0] == "0000") { return GAME_COD2; @@ -353,6 +344,8 @@ private: return GAME_COD11; } else if (sections[2] == "3030") { return GAME_COD12; + } else if (sections[2] == "6131" || sections[2] == "6431") { + return GAME_COD21; } return GAME_NONE; } diff --git a/libs/iwifile/iwifile.cpp b/libs/iwifile/iwifile.cpp index 8ec6e63..78ae08e 100644 --- a/libs/iwifile/iwifile.cpp +++ b/libs/iwifile/iwifile.cpp @@ -1,5 +1,4 @@ #include "iwifile.h" -#include "ddsfile.h" IWIFile::IWIFile() : fileStem(), @@ -81,39 +80,39 @@ IWIFile::IWIFile(const QString &aFilePath) : file.close(); } -IWIFile::IWIFile(const DDSFile &aDDSFile) { - // Ensure the DDS file has mipmaps - if (aDDSFile.mipmaps.isEmpty()) { - qDebug() << "Error: No mipmaps found in DDS file!"; - return; - } +// IWIFile::IWIFile(const DDSFile &aDDSFile) { +// // Ensure the DDS file has mipmaps +// if (aDDSFile.mipmaps.isEmpty()) { +// qDebug() << "Error: No mipmaps found in DDS file!"; +// return; +// } - // Create IWIFile object - fileStem = aDDSFile.fileStem; +// // Create IWIFile object +// fileStem = aDDSFile.fileStem; - // Set header (Magic & Version) - memcpy(header.Magic, "IWi", 3); - header.Version = 0x06; // Default to CoD4/CoD5 version +// // Set header (Magic & Version) +// memcpy(header.Magic, "IWi", 3); +// header.Version = 0x06; // Default to CoD4/CoD5 version - // Set IWI Texture Info - info.Format = static_cast(aDDSFile.header.pixelFormat.format); - info.Width = aDDSFile.header.width; - info.Height = aDDSFile.header.height; - info.Depth = 1; // Default depth for 2D textures - info.Usage = 0; // No specific usage +// // Set IWI Texture Info +// info.Format = static_cast(aDDSFile.header.pixelFormat.format); +// info.Width = aDDSFile.header.width; +// info.Height = aDDSFile.header.height; +// info.Depth = 1; // Default depth for 2D textures +// info.Usage = 0; // No specific usage - // Convert DDS mipmaps to IWI mipmaps - int offset = 28; // Standard offset start - for (const auto& ddsMipmap : aDDSFile.mipmaps) { - IWIMipmap iwiMipmap; - iwiMipmap.offset = offset; - iwiMipmap.size = ddsMipmap.data.size(); - iwiMipmap.data = ddsMipmap.data; +// // Convert DDS mipmaps to IWI mipmaps +// int offset = 28; // Standard offset start +// for (const auto& ddsMipmap : aDDSFile.mipmaps) { +// IWIMipmap iwiMipmap; +// iwiMipmap.offset = offset; +// iwiMipmap.size = ddsMipmap.data.size(); +// iwiMipmap.data = ddsMipmap.data; - offset += iwiMipmap.size; - mipmaps.append(iwiMipmap); - } -} +// offset += iwiMipmap.size; +// mipmaps.append(iwiMipmap); +// } +// } IWIFile::IWIFile(const IWIFile &iwiFile) { fileStem = iwiFile.fileStem; @@ -210,79 +209,81 @@ bool IWIFile::SaveIWI() const { return true; } -bool IWIFile::SaveDDS() const { - SetupExportDirs(); - QFile file("exports/dds/" + fileStem + ".dds"); - if (!file.open(QIODevice::WriteOnly)) { - qDebug() << "Error: Unable to write DDS file " << fileStem + ".dds"; - return false; - } +// bool IWIFile::SaveDDS() const { +// SetupExportDirs(); +// QFile file("exports/dds/" + fileStem + ".dds"); +// if (!file.open(QIODevice::WriteOnly)) { +// qDebug() << "Error: Unable to write DDS file " << fileStem + ".dds"; +// return false; +// } - DDSHeader ddsHeader = {}; - ddsHeader.magic = 0x20534444; // 'DDS ' - ddsHeader.size = 124; - ddsHeader.flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE; - ddsHeader.height = info.Height; - ddsHeader.width = info.Width; - ddsHeader.depth = 0; - ddsHeader.mipMapCount = mipmaps.size(); +// DDSHeader ddsHeader = {}; +// ddsHeader.magic = 0x20534444; // 'DDS ' +// ddsHeader.size = 124; +// ddsHeader.flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_LINEARSIZE; +// ddsHeader.height = info.Height; +// ddsHeader.width = info.Width; +// ddsHeader.depth = 0; +// ddsHeader.mipMapCount = mipmaps.size(); - DDSPixelFormat ddsPixelFormat = DDSFile::CalculatePixelFormat(info.Format); - if (ddsPixelFormat.flags & DDPF_FOURCC) { - ddsHeader.flags |= DDSD_LINEARSIZE; - } else { - ddsHeader.flags |= DDSD_PITCH; - } - ddsHeader.pixelFormat = ddsPixelFormat; +// DDSPixelFormat ddsPixelFormat = DDSFile::CalculatePixelFormat(info.Format); +// if (ddsPixelFormat.flags & DDPF_FOURCC) { +// ddsHeader.flags |= DDSD_LINEARSIZE; +// } else { +// ddsHeader.flags |= DDSD_PITCH; +// } +// ddsHeader.pixelFormat = ddsPixelFormat; - // Calculate pitch/linear size - if (ddsPixelFormat.flags & DDPF_FOURCC) { - int blockSize = (ddsPixelFormat.format == 0x31545844) ? 8 : 16; - ddsHeader.pitchOrLinearSize = fmax(1, (ddsHeader.width + 3) / 4) * blockSize * (ddsHeader.height / 4); - } else { - ddsHeader.pitchOrLinearSize = ddsHeader.width * (ddsPixelFormat.rgbBitCount / 8); - } +// // Calculate pitch/linear size +// if (ddsPixelFormat.flags & DDPF_FOURCC) { +// int blockSize = (ddsPixelFormat.format == 0x31545844) ? 8 : 16; +// ddsHeader.pitchOrLinearSize = fmax(1, (ddsHeader.width + 3) / 4) * blockSize * (ddsHeader.height / 4); +// } else { +// ddsHeader.pitchOrLinearSize = ddsHeader.width * (ddsPixelFormat.rgbBitCount / 8); +// } - DDSCaps ddsCaps = {}; - ddsCaps.caps1 = DDSCAPS_TEXTURE; - ddsCaps.caps2 = 0; - ddsCaps.dDSX = 0; - ddsCaps.reserved = 0; - ddsHeader.caps = ddsCaps; +// DDSCaps ddsCaps = {}; +// ddsCaps.caps1 = DDSCAPS_TEXTURE; +// ddsCaps.caps2 = 0; +// ddsCaps.dDSX = 0; +// ddsCaps.reserved = 0; +// ddsHeader.caps = ddsCaps; - QDataStream out(&file); - out.setByteOrder(QDataStream::LittleEndian); +// QDataStream out(&file); +// out.setByteOrder(QDataStream::LittleEndian); - // Write DDS header - out.writeRawData(reinterpret_cast(&ddsHeader), sizeof(DDSHeader)); +// // Write DDS header +// out.writeRawData(reinterpret_cast(&ddsHeader), sizeof(DDSHeader)); - for (auto mipmap : mipmaps) { - if (!mipmap.data.size()) { continue; } +// for (auto mipmap : mipmaps) { +// if (!mipmap.data.size()) { continue; } - // Write mipmap data - out.writeRawData(reinterpret_cast(mipmap.data.constData()), mipmap.data.size()); - } - file.close(); +// // Write mipmap data +// out.writeRawData(reinterpret_cast(mipmap.data.constData()), mipmap.data.size()); +// } +// file.close(); - return true; -} +// return true; +// } bool IWIFile::SavePNG() const { - DDSFile ddsFile(*this); - if (!ddsFile.SavePNG()) { - qDebug() << "Error: Failed to save PNG file: " << fileStem + ".png"; - return false; - } - return true; + // DDSFile ddsFile(*this); + // if (!ddsFile.SavePNG()) { + // qDebug() << "Error: Failed to save PNG file: " << fileStem + ".png"; + // return false; + // } + // return true; + return false; } bool IWIFile::SaveJPG() const { - DDSFile ddsFile(*this); - if (!ddsFile.SavePNG()) { - qDebug() << "Error: Failed to save JPG file: " << fileStem + ".jpg"; - return false; - } - return true; + // DDSFile ddsFile(*this); + // if (!ddsFile.SavePNG()) { + // qDebug() << "Error: Failed to save JPG file: " << fileStem + ".jpg"; + // return false; + // } + // return true; + return false; } // Check if the IWI version is supported diff --git a/libs/iwifile/iwifile.h b/libs/iwifile/iwifile.h index 47bf577..f0270a9 100644 --- a/libs/iwifile/iwifile.h +++ b/libs/iwifile/iwifile.h @@ -9,8 +9,6 @@ #include #include -#include "ddsfile.h" - // Supported versions static const QVector supportedVersions = { 0x05, // CoD2 @@ -50,7 +48,6 @@ public: IWIFile(); IWIFile(const QString &aFilePath); - IWIFile(const DDSFile &aDDSFile); IWIFile(const IWIFile &iwiFile); IWIFile& operator=(const IWIFile& other); ~IWIFile(); diff --git a/libs/xassets/xanimdeltapart.cpp b/libs/xassets/xanimdeltapart.cpp index 5c7b023..62c7093 100644 --- a/libs/xassets/xanimdeltapart.cpp +++ b/libs/xassets/xanimdeltapart.cpp @@ -9,10 +9,8 @@ XAnimDeltaPart::XAnimDeltaPart() } void XAnimDeltaPart::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - mTrans.ParsePtr(aStream); - mQuat.ParsePtr(aStream); - } + mTrans.ParsePtr(aStream); + mQuat.ParsePtr(aStream); } void XAnimDeltaPart::Clear() diff --git a/libs/xassets/xanimdeltapartquat.cpp b/libs/xassets/xanimdeltapartquat.cpp index cde96ac..094f23d 100644 --- a/libs/xassets/xanimdeltapartquat.cpp +++ b/libs/xassets/xanimdeltapartquat.cpp @@ -7,12 +7,10 @@ XAnimDeltaPartQuat::XAnimDeltaPartQuat() } void XAnimDeltaPartQuat::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - mSize = aStream->ParseUInt32(QString("%1 size").arg(GetName())); + mSize = aStream->ParseUInt32(QString("%1 size").arg(GetName())); - // Parse data - mData.ParseData(aStream); - } + // Parse data + mData.ParseData(aStream); } quint32 XAnimDeltaPartQuat::GetSize() const { diff --git a/libs/xassets/xanimdeltapartquatdata.cpp b/libs/xassets/xanimdeltapartquatdata.cpp index 52a4402..1f1cd2e 100644 --- a/libs/xassets/xanimdeltapartquatdata.cpp +++ b/libs/xassets/xanimdeltapartquatdata.cpp @@ -7,10 +7,8 @@ XAnimDeltaPartQuatData::XAnimDeltaPartQuatData() } void XAnimDeltaPartQuatData::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - // Parse frames - mFrames.ParseData(aStream); - } + // Parse frames + mFrames.ParseData(aStream); } const XAnimDeltaPartQuatDataFrames& XAnimDeltaPartQuatData::GetFrames() const { diff --git a/libs/xassets/xanimdeltapartquatdataframes.cpp b/libs/xassets/xanimdeltapartquatdataframes.cpp index 0a22794..b21fd06 100644 --- a/libs/xassets/xanimdeltapartquatdataframes.cpp +++ b/libs/xassets/xanimdeltapartquatdataframes.cpp @@ -37,15 +37,13 @@ void XAnimDeltaPartQuatDataFrames::SetIndices(const XAnimDynamicIndices& indices } void XAnimDeltaPartQuatDataFrames::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - mFramesPtr = aStream->ParseInt32(QString("%1 frames ptr").arg(GetName())); + mFramesPtr = aStream->ParseInt32(QString("%1 frames ptr").arg(GetName())); - mFrames[0] = aStream->ParseInt16(QString("%1 frame %2").arg(GetName()).arg(0)); - mFrames[1] = aStream->ParseInt16(QString("%1 frame %2").arg(GetName()).arg(1)); + mFrames[0] = aStream->ParseInt16(QString("%1 frame %2").arg(GetName()).arg(0)); + mFrames[1] = aStream->ParseInt16(QString("%1 frame %2").arg(GetName()).arg(1)); - // Parse indices - mIndices.ParseData(aStream); - } + // Parse indices + mIndices.ParseData(aStream); } void XAnimDeltaPartQuatDataFrames::Clear() diff --git a/libs/xassets/xanimdynamicframes.cpp b/libs/xassets/xanimdynamicframes.cpp index 2adfedb..17a0046 100644 --- a/libs/xassets/xanimdynamicframes.cpp +++ b/libs/xassets/xanimdynamicframes.cpp @@ -8,15 +8,9 @@ XAnimDynamicFrames::XAnimDynamicFrames() } void XAnimDynamicFrames::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - qint32 framePtr = aStream->ParseInt32(QString("%1 frames ptr").arg(GetName())); - if (framePtr == -1) - { - mFrames[0] = aStream->ParseUInt8(QString("%1 frame %2").arg(GetName()).arg(0)); - mFrames[1] = aStream->ParseUInt8(QString("%1 frame %2").arg(GetName()).arg(1)); - mFrames[2] = aStream->ParseUInt8(QString("%1 frame %2").arg(GetName()).arg(2)); - } - } + mFrames[0] = aStream->ParseUInt8(QString("%1 frame %2").arg(GetName()).arg(0)); + mFrames[1] = aStream->ParseUInt8(QString("%1 frame %2").arg(GetName()).arg(1)); + mFrames[2] = aStream->ParseUInt8(QString("%1 frame %2").arg(GetName()).arg(2)); } void XAnimDynamicFrames::Clear() diff --git a/libs/xassets/xanimdynamicindices.cpp b/libs/xassets/xanimdynamicindices.cpp index 5d58744..42081e1 100644 --- a/libs/xassets/xanimdynamicindices.cpp +++ b/libs/xassets/xanimdynamicindices.cpp @@ -8,9 +8,7 @@ XAnimDynamicIndices::XAnimDynamicIndices() } void XAnimDynamicIndices::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - mIndices[0] = aStream->ParseUInt8(QString("%1 index").arg(GetName())); - } + mIndices[0] = aStream->ParseUInt8(QString("%1 index").arg(GetName())); } void XAnimDynamicIndices::Clear() diff --git a/libs/xassets/xanimindices.cpp b/libs/xassets/xanimindices.cpp index 012020d..986fca7 100644 --- a/libs/xassets/xanimindices.cpp +++ b/libs/xassets/xanimindices.cpp @@ -7,14 +7,9 @@ XAnimIndices::XAnimIndices() SetName("Animation Indices"); } -void XAnimIndices::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - qint32 indexPtr = aStream->ParseInt32(QString("%1 index ptr").arg(GetName())); - if (indexPtr == -1) - { - mIndex = aStream->ParseUInt32(QString("%1 index").arg(GetName())); - } - } +void XAnimIndices::ParseData(XDataStream *aStream) +{ + mIndex = aStream->ParseUInt32(QString("%1 index").arg(GetName())); } void XAnimIndices::Clear() diff --git a/libs/xassets/xanimnotifyinfo.cpp b/libs/xassets/xanimnotifyinfo.cpp index 7d88ef5..f2d0c93 100644 --- a/libs/xassets/xanimnotifyinfo.cpp +++ b/libs/xassets/xanimnotifyinfo.cpp @@ -8,12 +8,10 @@ XAnimNotifyInfo::XAnimNotifyInfo() SetName("Animation Notify Info"); } -void XAnimNotifyInfo::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - - mName = aStream->ParseUInt32(QString("%1 name").arg(GetName())); - mTime = aStream->ParseSingle(QString("%1 time").arg(GetName())); - } +void XAnimNotifyInfo::ParseData(XDataStream *aStream) +{ + mName = aStream->ParseUInt32(QString("%1 name").arg(GetName())); + mTime = aStream->ParseSingle(QString("%1 time").arg(GetName())); } void XAnimNotifyInfo::Clear() diff --git a/libs/xassets/xanimparts.cpp b/libs/xassets/xanimparts.cpp index 7942cb4..21b72a5 100644 --- a/libs/xassets/xanimparts.cpp +++ b/libs/xassets/xanimparts.cpp @@ -14,7 +14,7 @@ XAnimParts::XAnimParts() , mBoneCount(12) , mNotifyCount(0) , mAssetType(0) - , mPad(false) + , mIsDefault(false) , mRandomDataShortCount(0) , mIndexCount(0) , mFramerate(0.0f) @@ -34,85 +34,86 @@ XAnimParts::XAnimParts() SetName("Animation Parts"); } -void XAnimParts::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { +void XAnimParts::ParseData(XDataStream *aStream) +{ + mName.ParsePtr(aStream, false); - mName.ParsePtr(aStream, false); + // Parse all fields + mDataByteCount = aStream->ParseUInt16(QString("%1 data byte count").arg(GetName())); + mDataShortCount = aStream->ParseUInt16(QString("%1 data short count").arg(GetName())); + mDataIntCount = aStream->ParseUInt16(QString("%1 data int count").arg(GetName())); + mRandomDataByteCount = aStream->ParseUInt16(QString("%1 random date byte count").arg(GetName())); + mRandomDataIntCount = aStream->ParseUInt16(QString("%1 random data int count").arg(GetName())); + mNumFrames = aStream->ParseUInt16(QString("%1 # frames").arg(GetName())); - // Parse all fields - mDataByteCount = aStream->ParseUInt32(QString("%1 data byte count").arg(GetName())); - mDataShortCount = aStream->ParseUInt32(QString("%1 data short count").arg(GetName())); - mDataIntCount = aStream->ParseUInt32(QString("%1 data int count").arg(GetName())); - mRandomDataByteCount = aStream->ParseUInt32(QString("%1 random date byte count").arg(GetName())); - mRandomDataIntCount = aStream->ParseUInt32(QString("%1 random data int count").arg(GetName())); - mNumFrames = aStream->ParseUInt32(QString("%1 # frames").arg(GetName())); + mIsLoop = aStream->ParseUInt8(QString("%1 loop").arg(GetName())); + mIsDelta = aStream->ParseUInt8(QString("%1 delta").arg(GetName())); + aStream->skipRawData(2); - quint8 loopDelta = aStream->ParseUInt8(QString("%1 loop delta").arg(GetName())); - mIsLoop = (loopDelta & 0x1) != 0; - mIsDelta = (loopDelta & 0x2) != 0; - - for (int i = 0; i < 12; i++) - { - mBoneCount[i] = aStream->ParseUInt8(QString("%1 bone count %2").arg(GetName()).arg(i)); - } - - mNotifyCount = aStream->ParseUInt8(QString("%1 notify count").arg(GetName())); - mAssetType = aStream->ParseUInt8(QString("%1 asset type").arg(GetName())); - mPad = aStream->ParseUInt32(QString("%1 pad").arg(GetName())) != 0; - - qint32 namesPtr, dataBytePtr, dataShortPtr, dataIntPtr, - randomDataShortPtr, randomDataBytePtr, randomDataIntPtr; - - mRandomDataShortCount = aStream->ParseUInt32(QString("%1 random data short count").arg(GetName())); - mIndexCount = aStream->ParseUInt32(QString("%1 index count").arg(GetName())); - mFramerate = aStream->ParseSingle(QString("%1 frame rate").arg(GetName())); - mFrequency = aStream->ParseSingle(QString("%1 frequency").arg(GetName())); - namesPtr = aStream->ParseInt32(QString("%1 names ptr").arg(GetName())); - dataBytePtr = aStream->ParseInt32(QString("%1 data byte ptr").arg(GetName())); - dataShortPtr = aStream->ParseInt32(QString("%1 data short ptr").arg(GetName())); - dataIntPtr = aStream->ParseInt32(QString("%1 data int ptr").arg(GetName())); - randomDataShortPtr = aStream->ParseInt32(QString("%1 random data short ptr").arg(GetName())); - randomDataBytePtr = aStream->ParseInt32(QString("%1 random data byte ptr").arg(GetName())); - randomDataIntPtr = aStream->ParseInt32(QString("%1 random data int ptr").arg(GetName())); - - // Parse indices - mIndices.ParseData(aStream); - mNotify.ParsePtr(aStream, false); - mDeltaPart.ParsePtr(aStream, false); - - mName.ParseData(aStream); - if (namesPtr) - { - mNames = aStream->ParseInt32(QString("%1 names").arg(GetName())); - } - mNotify.ParseData(aStream); - mDeltaPart.ParseData(aStream); - if (dataBytePtr) - { - mDataByte = aStream->ParseUInt8(QString("%1 data byte").arg(GetName())); - } - if (dataShortPtr) - { - mDataShort = aStream->ParseInt16(QString("%1 data short").arg(GetName())); - } - if (dataIntPtr) - { - mDataInt = aStream->ParseInt32(QString("%1 data int").arg(GetName())); - } - if (randomDataShortPtr) - { - mRandomDataShort = aStream->ParseInt16(QString("%1 random data short").arg(GetName())); - } - if (randomDataBytePtr) - { - mRandomDataByte = aStream->ParseUInt8(QString("%1 random data byte").arg(GetName())); - } - if (randomDataIntPtr) - { - mRandomDataInt = aStream->ParseInt32(QString("%1 random data int").arg(GetName())); - } - mIndices.ParseData(aStream); + for (int i = 0; i < 10; i++) + { + mBoneCount[i] = aStream->ParseUInt8(QString("%1 bone count %2").arg(GetName()).arg(i)); } + aStream->skipRawData(2); + + mNotifyCount = aStream->ParseUInt8(QString("%1 notify count").arg(GetName())); + mAssetType = aStream->ParseUInt8(QString("%1 asset type").arg(GetName())); + mIsDefault = aStream->ParseUInt8(QString("%1 pad").arg(GetName())); + aStream->skipRawData(1); + + qint32 namesPtr, dataBytePtr, dataShortPtr, dataIntPtr, + randomDataShortPtr, randomDataBytePtr, randomDataIntPtr; + + mRandomDataShortCount = aStream->ParseUInt32(QString("%1 random data short count").arg(GetName())); + mIndexCount = aStream->ParseUInt32(QString("%1 index count").arg(GetName())); + mFramerate = aStream->ParseSingle(QString("%1 frame rate").arg(GetName())); + mFrequency = aStream->ParseSingle(QString("%1 frequency").arg(GetName())); + namesPtr = aStream->ParseInt32(QString("%1 names ptr").arg(GetName())); + dataBytePtr = aStream->ParseInt32(QString("%1 data byte ptr").arg(GetName())); + dataShortPtr = aStream->ParseInt32(QString("%1 data short ptr").arg(GetName())); + dataIntPtr = aStream->ParseInt32(QString("%1 data int ptr").arg(GetName())); + randomDataShortPtr = aStream->ParseInt32(QString("%1 random data short ptr").arg(GetName())); + randomDataBytePtr = aStream->ParseInt32(QString("%1 random data byte ptr").arg(GetName())); + randomDataIntPtr = aStream->ParseInt32(QString("%1 random data int ptr").arg(GetName())); + + // Parse indices + mIndices.ParsePtr(aStream, false); + mNotify.ParsePtr(aStream, false); + mDeltaPart.ParsePtr(aStream, false); + + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); + if (namesPtr) + { + mNames = aStream->ParseInt32(QString("%1 names").arg(GetName())); + } + mNotify.ParseDataSafe(aStream); + mDeltaPart.ParseDataSafe(aStream); + if (dataBytePtr) + { + mDataByte = aStream->ParseUInt8(QString("%1 data byte").arg(GetName())); + } + if (dataShortPtr) + { + mDataShort = aStream->ParseInt16(QString("%1 data short").arg(GetName())); + } + if (dataIntPtr) + { + mDataInt = aStream->ParseInt32(QString("%1 data int").arg(GetName())); + } + if (randomDataShortPtr) + { + mRandomDataShort = aStream->ParseInt16(QString("%1 random data short").arg(GetName())); + } + if (randomDataBytePtr) + { + mRandomDataByte = aStream->ParseUInt8(QString("%1 random data byte").arg(GetName())); + } + if (randomDataIntPtr) + { + mRandomDataInt = aStream->ParseInt32(QString("%1 random data int").arg(GetName())); + } + mIndices.ParseDataSafe(aStream); } void XAnimParts::Clear() diff --git a/libs/xassets/xanimparts.h b/libs/xassets/xanimparts.h index 35f5c94..fa969cc 100644 --- a/libs/xassets/xanimparts.h +++ b/libs/xassets/xanimparts.h @@ -35,7 +35,7 @@ private: quint8 mNotifyCount = 0; quint8 mAssetType = 0; - bool mPad = false; + bool mIsDefault = false; quint32 mRandomDataShortCount = 0; quint32 mIndexCount = 0; diff --git a/libs/xassets/xanimparttrans.cpp b/libs/xassets/xanimparttrans.cpp index 4eb8434..433bf07 100644 --- a/libs/xassets/xanimparttrans.cpp +++ b/libs/xassets/xanimparttrans.cpp @@ -19,13 +19,11 @@ XAnimPartTrans::XAnimPartTrans(const XAnimPartTrans &aSrc) } void XAnimPartTrans::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - mSize = aStream->ParseUInt32(QString("%1 size").arg(GetName())); - mIsSmallTrans = aStream->ParseUInt8(QString("%1 is small trans").arg(GetName())) != 0; + mSize = aStream->ParseUInt32(QString("%1 size").arg(GetName())); + mIsSmallTrans = aStream->ParseUInt8(QString("%1 is small trans").arg(GetName())) != 0; - // Parse data - mData.ParseData(aStream); - } + // Parse data + mData.ParseData(aStream); } void XAnimPartTrans::Clear() diff --git a/libs/xassets/xanimparttransdata.cpp b/libs/xassets/xanimparttransdata.cpp index 1c135e6..1cc269e 100644 --- a/libs/xassets/xanimparttransdata.cpp +++ b/libs/xassets/xanimparttransdata.cpp @@ -17,11 +17,9 @@ XAnimPartTransData::XAnimPartTransData(const XAnimPartTransData &aSrc) } void XAnimPartTransData::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - // We need to determine which part of the union to parse - // For simplicity, we'll assume it's always frames for now - mFrames.ParseData(aStream); - } + // We need to determine which part of the union to parse + // For simplicity, we'll assume it's always frames for now + mFrames.ParseData(aStream); } void XAnimPartTransData::Clear() diff --git a/libs/xassets/xanimparttransframes.cpp b/libs/xassets/xanimparttransframes.cpp index ae458b4..08aaa7d 100644 --- a/libs/xassets/xanimparttransframes.cpp +++ b/libs/xassets/xanimparttransframes.cpp @@ -11,20 +11,18 @@ XAnimPartTransFrames::XAnimPartTransFrames() } void XAnimPartTransFrames::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - mMins[0] = aStream->ParseSingle(QString("%1 min %2").arg(GetName()).arg(0)); - mMins[1] = aStream->ParseSingle(QString("%1 min %2").arg(GetName()).arg(1)); - mMins[2] = aStream->ParseSingle(QString("%1 min %2").arg(GetName()).arg(2)); - mMaxs[0] = aStream->ParseSingle(QString("%1 max %2").arg(GetName()).arg(0)); - mMaxs[1] = aStream->ParseSingle(QString("%1 max %2").arg(GetName()).arg(1)); - mMaxs[2] = aStream->ParseSingle(QString("%1 max %2").arg(GetName()).arg(2)); + mMins[0] = aStream->ParseSingle(QString("%1 min %2").arg(GetName()).arg(0)); + mMins[1] = aStream->ParseSingle(QString("%1 min %2").arg(GetName()).arg(1)); + mMins[2] = aStream->ParseSingle(QString("%1 min %2").arg(GetName()).arg(2)); + mMaxs[0] = aStream->ParseSingle(QString("%1 max %2").arg(GetName()).arg(0)); + mMaxs[1] = aStream->ParseSingle(QString("%1 max %2").arg(GetName()).arg(1)); + mMaxs[2] = aStream->ParseSingle(QString("%1 max %2").arg(GetName()).arg(2)); - // Parse frames - mFrames.ParseData(aStream); + // Parse frames + mFrames.ParsePtr(aStream); - // Parse indices - mIndices.ParseData(aStream); - } + // Parse indices + mIndices.ParseData(aStream); } void XAnimPartTransFrames::Clear() diff --git a/libs/xassets/xasset.cpp b/libs/xassets/xasset.cpp index 974657f..767cd44 100644 --- a/libs/xassets/xasset.cpp +++ b/libs/xassets/xasset.cpp @@ -23,6 +23,9 @@ XAsset::XAsset() : mPtr(0) , mType(ASSET_TYPE_NONE) , mName("Unknown Asset") + , mDisplayName("Unknown") + , mCommonInfo(nullptr) + , mSubAssets() { } @@ -79,7 +82,15 @@ void XAsset::Clear() void XAsset::ParsePtr(XDataStream *aStream, bool aDataFlag) { mPtr = aStream->ParseInt32(QString("%1 ptr").arg(GetName())); - if (aDataFlag && mPtr == -1) + if (aDataFlag) + { + ParseDataSafe(aStream); + } +} + +void XAsset::ParseDataSafe(XDataStream *aStream) +{ + if (GetPtr() == -1) { ParseData(aStream); } @@ -146,6 +157,8 @@ XAsset* XAsset::Create(XAssetType aAssetType) return new XModelPieces(); case ASSET_TYPE_PHYSPRESET: return new XPhysPreset(); + case ASSET_TYPE_SCRIPT_PARSE_TREE: + return new XRawFile(); // case ASSET_TYPE_UI_MAP: // case ASSET_TYPE_AITYPE: // case ASSET_TYPE_MPTYPE: @@ -237,7 +250,7 @@ QString XAsset::XAssetTypeToString(XAssetType type) { return "String"; case ASSET_TYPE_ASSETLIST: return "AssetList"; - case ASSET_TYPE_COLLISION_MAP: + case ASSET_TYPE_COL_MAP_MP: return "CollisionMap"; case ASSET_TYPE_GFX_MAP: return "GfxMap"; @@ -430,4 +443,39 @@ QString XAsset::XAssetTypeToString(XAssetType type) { } } +const XCommonInfo *XAsset::GetCommonInfo() const +{ + return mCommonInfo; +} + +void XAsset::SetCommonInfo(const XCommonInfo *newCommonInfo) +{ + mCommonInfo = newCommonInfo; +} + +QString XAsset::DisplayName() const +{ + return mDisplayName; +} + +void XAsset::SetDisplayName(const QString &aDisplayName) +{ + mDisplayName = aDisplayName; +} + +QVector XAsset::SubAssets() const +{ + return mSubAssets; +} + +void XAsset::SetSubAssets(const QVector &aSubAssets) +{ + mSubAssets = aSubAssets; +} + +void XAsset::AddSubAsset(XAsset* aSubAsset) +{ + mSubAssets.push_back(aSubAsset); +} + bool XAsset::mDebug = true; diff --git a/libs/xassets/xasset.h b/libs/xassets/xasset.h index 3fc67e7..01f5398 100644 --- a/libs/xassets/xasset.h +++ b/libs/xassets/xasset.h @@ -2,16 +2,19 @@ #define XASSET_H #include "xassettype.h" - #include "xdatastream.h" +#include "xcommoninfo.h" + #include #include #include +class ZoneFile; + class XAsset { public: - XAsset(); + explicit XAsset(); virtual ~XAsset() = default; void SetPtr(qint32 aPtr); @@ -29,16 +32,32 @@ public: virtual void Clear(); virtual void ParsePtr(XDataStream *aStream, bool aDataFlag = true); virtual void ParseData(XDataStream *aStream) = 0; + virtual void ParseDataSafe(XDataStream *aStream); static XAsset* Create(XAssetType aAssetType); static QString XAssetTypeToString(XAssetType type); static bool mDebug; + const XCommonInfo *GetCommonInfo() const; + void SetCommonInfo(const XCommonInfo *newCommonInfo); + + QString DisplayName() const; + void SetDisplayName(const QString &aDisplayName); + + QVector SubAssets() const; + void SetSubAssets(const QVector &aSubAssets); + void AddSubAsset(XAsset *aSubAsset); + private: qint32 mPtr; XAssetType mType; QString mName; + QString mDisplayName; + + const XCommonInfo* mCommonInfo; + + QVector mSubAssets; }; #endif // XASSET_H diff --git a/libs/xassets/xassetlist.cpp b/libs/xassets/xassetlist.cpp index caf73ba..22e64cf 100644 --- a/libs/xassets/xassetlist.cpp +++ b/libs/xassets/xassetlist.cpp @@ -57,16 +57,13 @@ void XAssetList::ParseData(XDataStream *aStream) { for (int i = 0; i < mAssetHeaders.size(); i++) { - if (aStream->device()->pos() > 98000) - { - qDebug() << "test"; - } XAssetHeader assetHeader = mAssetHeaders[i]; XAsset* asset = XAsset::Create(assetHeader.GetAssetType()); if (asset) { asset->SetPtr(assetHeader.GetAssetPtr()); - asset->ParseData(aStream); + asset->SetCommonInfo(GetCommonInfo()); + asset->ParseDataSafe(aStream); mAssets.append(asset); } diff --git a/libs/xassets/xassettype.h b/libs/xassets/xassettype.h index a1631e8..b5e00ff 100644 --- a/libs/xassets/xassettype.h +++ b/libs/xassets/xassettype.h @@ -1,8 +1,6 @@ #ifndef XASSETTYPE_H #define XASSETTYPE_H -#include - enum XAssetType { ASSET_TYPE_XMODELPIECES, @@ -11,6 +9,7 @@ enum XAssetType ASSET_TYPE_XMODEL, ASSET_TYPE_MATERIAL, ASSET_TYPE_PIXELSHADER, + ASSET_TYPE_VERTEXSHADER, ASSET_TYPE_TECHNIQUE_SET, ASSET_TYPE_IMAGE, ASSET_TYPE_SOUND, @@ -26,7 +25,7 @@ enum XAssetType ASSET_TYPE_LIGHT_DEF, ASSET_TYPE_UI_MAP, ASSET_TYPE_FONT, - ASSET_TYPE_MENULIST, + ASSET_TYPE_MENULIST, // Sometimes referred to as MENUFILE ASSET_TYPE_MENU, ASSET_TYPE_LOCALIZE_ENTRY, ASSET_TYPE_WEAPON, @@ -43,11 +42,13 @@ enum XAssetType ASSET_TYPE_STRING, ASSET_TYPE_ASSETLIST, - ASSET_TYPE_COLLISION_MAP, + ASSET_TYPE_COL_MAP_MP, ASSET_TYPE_GFX_MAP, ASSET_TYPE_D3DBSP, ASSET_TYPE_GAME_MAP_SP, + ASSET_TYPE_GAME_MAP_MP, ASSET_TYPE_COL_MAP_SP, + ASSET_TYPE_COM_MAP, ASSET_TYPE_DESTRUCTIBLE, ASSET_TYPE_SHOCK_FILE, ASSET_TYPE_PHYSCOLLMAP, diff --git a/libs/xassets/xcardmemory.cpp b/libs/xassets/xcardmemory.cpp index 5d61481..b468f82 100644 --- a/libs/xassets/xcardmemory.cpp +++ b/libs/xassets/xcardmemory.cpp @@ -2,7 +2,7 @@ XCardMemory::XCardMemory() : XAsset() - , mPlatform(0) + , mPlatform(2) { SetName("Card Memory"); } @@ -12,17 +12,18 @@ XCardMemory::~XCardMemory() } -qint32 XCardMemory::GetPlatform() const +QVector XCardMemory::GetPlatform() const { return mPlatform; } void XCardMemory::ParseData(XDataStream *aStream) { - mPlatform = aStream->ParseInt32(QString("%1 platform").arg(GetName())); + mPlatform[0] = aStream->ParseInt32(QString("%1 platform 1").arg(GetName())); + mPlatform[1] = aStream->ParseInt32(QString("%1 platform 2").arg(GetName())); } void XCardMemory::Clear() { - mPlatform = 0; + mPlatform.clear(); } diff --git a/libs/xassets/xcardmemory.h b/libs/xassets/xcardmemory.h index 451d8f9..2c2368d 100644 --- a/libs/xassets/xcardmemory.h +++ b/libs/xassets/xcardmemory.h @@ -9,13 +9,13 @@ public: explicit XCardMemory(); ~XCardMemory(); - qint32 GetPlatform() const; + QVector GetPlatform() const; virtual void ParseData(XDataStream* aStream) override; virtual void Clear() override; private: - qint32 mPlatform; + QVector mPlatform; }; #endif // XCARDMEMORY_H diff --git a/libs/xassets/xcollisionpartition.cpp b/libs/xassets/xcollisionpartition.cpp index 8c12ece..ea2c37d 100644 --- a/libs/xassets/xcollisionpartition.cpp +++ b/libs/xassets/xcollisionpartition.cpp @@ -17,17 +17,15 @@ XCollisionPartition::~XCollisionPartition() void XCollisionPartition::ParseData(XDataStream *aStream) { if (GetPtr() == -1) { - *aStream - >> mTriCount - >> mBorderCount; + mTriCount = aStream->ParseUInt8(QString("%1 tri count").arg(GetName())); + mBorderCount = aStream->ParseUInt8(QString("%1 border count").arg(GetName())); aStream->skipRawData(2); - qint32 bordersPtr; - *aStream - >> mFirstTri - >> bordersPtr; + mFirstTri = aStream->ParseUInt32(QString("%1 first tri").arg(GetName())); + qint32 bordersPtr; + bordersPtr = aStream->ParseUInt32(QString("%1 first tri").arg(GetName())); if (bordersPtr == -1) { for (int i = 0; i < mBorderCount; i++) diff --git a/libs/xassets/xcollisionpartition.h b/libs/xassets/xcollisionpartition.h index 6da08af..4a5252d 100644 --- a/libs/xassets/xcollisionpartition.h +++ b/libs/xassets/xcollisionpartition.h @@ -18,7 +18,7 @@ public: private: quint8 mTriCount; quint8 mBorderCount; - int mFirstTri; + qint32 mFirstTri; QVector mBorders; }; diff --git a/libs/xassets/xcommoninfo.cpp b/libs/xassets/xcommoninfo.cpp new file mode 100644 index 0000000..c061005 --- /dev/null +++ b/libs/xassets/xcommoninfo.cpp @@ -0,0 +1,44 @@ +#include "xcommoninfo.h" + +XCommonInfo::XCommonInfo() {} + +XCommonInfo::XCommonInfo(const XGame &aGame, const XPlatform &aPlatform) + : mGame(aGame) + , mPlatform(aPlatform) {} + +XGame XCommonInfo::GetGame() const +{ + return mGame; +} + +QString XCommonInfo::GetGameString() const +{ + if (mGame == GAME_NONE) return "UNKNOWN"; + else if (mGame == GAME_COD7_5) return "COD7.5"; + return QString("COD%1").arg(mGame); +} + +void XCommonInfo::SetGame(XGame newGame) +{ + mGame = newGame; +} + +XPlatform XCommonInfo::GetPlatform() const +{ + return mPlatform; +} + +QString XCommonInfo::GetPlatformString() const +{ + if (mPlatform == PLATFORM_XBOX) return "Xbox"; + else if (mPlatform == PLATFORM_PS3) return "PS3"; + else if (mPlatform == PLATFORM_PC) return "PC"; + else if (mPlatform == PLATFORM_WII) return "Wii"; + else if (mPlatform == PLATFORM_WIIU) return "Wii U"; + return "UNKNOWN"; +} + +void XCommonInfo::SetPlatform(XPlatform newPlatform) +{ + mPlatform = newPlatform; +} diff --git a/libs/xassets/xcommoninfo.h b/libs/xassets/xcommoninfo.h new file mode 100644 index 0000000..fc1ea9e --- /dev/null +++ b/libs/xassets/xcommoninfo.h @@ -0,0 +1,26 @@ +#ifndef XCOMMONINFO_H +#define XCOMMONINFO_H + +#include "xgame.h" +#include "xplatform.h" + +class XCommonInfo +{ +public: + XCommonInfo(); + XCommonInfo(const XGame& aGame, const XPlatform& aPlatform); + + XGame GetGame() const; + QString GetGameString() const; + void SetGame(XGame newGame); + + XPlatform GetPlatform() const; + QString GetPlatformString() const; + void SetPlatform(XPlatform newPlatform); + +private: + XGame mGame; + XPlatform mPlatform; +}; + +#endif // XCOMMONINFO_H diff --git a/libs/xassets/xcomworld.cpp b/libs/xassets/xcomworld.cpp index 6a05fbc..107192c 100644 --- a/libs/xassets/xcomworld.cpp +++ b/libs/xassets/xcomworld.cpp @@ -31,15 +31,17 @@ void XComWorld::ParseData(XDataStream *aStream) { mName->ParsePtr(aStream, false); - quint32 primaryLightPtr; - *aStream - >> mInUse - >> mPrimaryLightCount - >> primaryLightPtr; + mInUse = aStream->ParseUInt8(QString("%1 in use").arg(GetName())); + aStream->skipRawData(3); + + mPrimaryLightCount = aStream->ParseUInt32(QString("%1 primary light count").arg(GetName())); + + quint32 primaryLightsPtr; + primaryLightsPtr = aStream->ParseUInt32(QString("%1 primary lights ptr").arg(GetName())); mName->ParseData(aStream); - if (primaryLightPtr) + if (primaryLightsPtr) { if (mPrimaryLights != nullptr) { diff --git a/libs/xassets/xcstaticmodelwritable.cpp b/libs/xassets/xcstaticmodelwritable.cpp index dbaf6b3..e7164ca 100644 --- a/libs/xassets/xcstaticmodelwritable.cpp +++ b/libs/xassets/xcstaticmodelwritable.cpp @@ -7,15 +7,8 @@ XCStaticModelWritable::XCStaticModelWritable() SetName("C Static Model Writable"); } -XCStaticModelWritable::~XCStaticModelWritable() -{ - -} - void XCStaticModelWritable::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) { - *aStream >> mNextModelInWorldSector; - } + mNextModelInWorldSector = aStream->ParseUInt32(QString("%1 next model in world sector").arg(GetName())); } quint32 XCStaticModelWritable::GetNextModelInWorldSector() const { diff --git a/libs/xassets/xcstaticmodelwritable.h b/libs/xassets/xcstaticmodelwritable.h index 3deb4d2..856c7ef 100644 --- a/libs/xassets/xcstaticmodelwritable.h +++ b/libs/xassets/xcstaticmodelwritable.h @@ -7,7 +7,6 @@ class XCStaticModelWritable : public XAsset { public: explicit XCStaticModelWritable(); - ~XCStaticModelWritable(); void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xd3dindexbuffer.cpp b/libs/xassets/xd3dindexbuffer.cpp index 4878284..5b4fd64 100644 --- a/libs/xassets/xd3dindexbuffer.cpp +++ b/libs/xassets/xd3dindexbuffer.cpp @@ -12,18 +12,8 @@ void XD3DIndexBuffer::ParseData(XDataStream *aStream) { XD3DResource::ParseData(aStream); - *aStream >> mAddress; - if (IsDebug()) - { - qDebug() << QString("[%1] mAddress = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mAddress); - } - - - *aStream >> mSize; - if (IsDebug()) - { - qDebug() << QString("[%1] mSize = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mSize); - } + mAddress = aStream->ParseUInt32(QString("%1 address").arg(GetName())); + mSize = aStream->ParseUInt32(QString("%1 size").arg(GetName())); } void XD3DIndexBuffer::Clear() diff --git a/libs/xassets/xd3dresource.cpp b/libs/xassets/xd3dresource.cpp index 93c5a2f..e8f0f69 100644 --- a/libs/xassets/xd3dresource.cpp +++ b/libs/xassets/xd3dresource.cpp @@ -19,41 +19,12 @@ XD3DResource::~XD3DResource() void XD3DResource::ParseData(XDataStream *aStream) { - *aStream >> mCommon; - if (IsDebug()) - { - qDebug() << QString("[%1] mCommon = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mCommon); - } - - *aStream >> mReferenceCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mReferenceCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mReferenceCount); - } - - *aStream >> mFence; - if (IsDebug()) - { - qDebug() << QString("[%1] mFence = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mFence); - } - - *aStream >> mReadFence; - if (IsDebug()) - { - qDebug() << QString("[%1] mReadFence = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mReadFence); - } - - *aStream >> mIdentifier; - if (IsDebug()) - { - qDebug() << QString("[%1] mIdentifier = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mIdentifier); - } - - *aStream >> mBaseFlush; - if (IsDebug()) - { - qDebug() << QString("[%1] mBaseFlush = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mBaseFlush); - } + mCommon = aStream->ParseUInt32(QString("%1 common").arg(GetName())); + mReferenceCount = aStream->ParseUInt32(QString("%1 reference count").arg(GetName())); + mFence = aStream->ParseUInt32(QString("%1 fence").arg(GetName())); + mReadFence = aStream->ParseUInt32(QString("%1 read fence").arg(GetName())); + mIdentifier = aStream->ParseUInt32(QString("%1 identifier").arg(GetName())); + mBaseFlush = aStream->ParseUInt32(QString("%1 base flush").arg(GetName())); } void XD3DResource::Clear() diff --git a/libs/xassets/xdmaterial.cpp b/libs/xassets/xdmaterial.cpp index df5c66f..fbaba14 100644 --- a/libs/xassets/xdmaterial.cpp +++ b/libs/xassets/xdmaterial.cpp @@ -16,9 +16,8 @@ void XDMaterial::ParseData(XDataStream *aStream) { if (GetPtr() == -1) { mMaterial = XString::ParseCustom(aStream); - *aStream - >> mSurfaceFlags - >> mContentFlags; + mSurfaceFlags = aStream->ParseInt32(QString("%1 surface flags").arg(GetName())); + mContentFlags = aStream->ParseInt32(QString("%1 content flags").arg(GetName())); } } diff --git a/libs/xassets/xdmaterial.h b/libs/xassets/xdmaterial.h index f14aae4..6247018 100644 --- a/libs/xassets/xdmaterial.h +++ b/libs/xassets/xdmaterial.h @@ -23,8 +23,8 @@ public: private: QString mMaterial = ""; - int mSurfaceFlags = 0; - int mContentFlags = 0; + qint32 mSurfaceFlags = 0; + qint32 mContentFlags = 0; }; #endif // XDMATERIAL_H diff --git a/libs/xassets/xdobjanimmat.cpp b/libs/xassets/xdobjanimmat.cpp index 3beb3ff..93c1b9a 100644 --- a/libs/xassets/xdobjanimmat.cpp +++ b/libs/xassets/xdobjanimmat.cpp @@ -20,21 +20,15 @@ void XDObjAnimMat::ParseData(XDataStream *aStream) { for (int i = 0; i < 4; i++) { - quint32 rawQuat; - *aStream >> rawQuat; - memcpy(&mQuat[i], &rawQuat, sizeof(mQuat[i])); + mQuat.push_back(aStream->ParseSingle(QString("%1 quat %2").arg(GetName()).arg(i))); } for (int i = 0; i < 3; i++) { - quint32 rawTrans; - *aStream >> rawTrans; - memcpy(&mTrans[i], &rawTrans, sizeof(mTrans[i])); + mTrans.push_back(aStream->ParseSingle(QString("%1 trans %2").arg(GetName()).arg(i))); } - quint32 rawTransWeight; - *aStream >> rawTransWeight; - memcpy(&mTransWeight, &rawTransWeight, sizeof(mTransWeight)); + mTransWeight = aStream->ParseSingle(QString("%1 trans weight").arg(GetName())); } } diff --git a/libs/xassets/xdynentityclient.cpp b/libs/xassets/xdynentityclient.cpp index fad77ef..99e4156 100644 --- a/libs/xassets/xdynentityclient.cpp +++ b/libs/xassets/xdynentityclient.cpp @@ -19,11 +19,10 @@ void XDynEntityClient::ParseData(XDataStream *aStream) { if (GetPtr()) { - *aStream - >> mPhysObjId - >> mFlags - >> mLightingHandle - >> mHealth; + mPhysObjId = aStream->ParseInt32(QString("%1 phys obj id").arg(GetName())); + mFlags = aStream->ParseUInt32(QString("%1 flags").arg(GetName())); + mLightingHandle = aStream->ParseUInt32(QString("%1 lighting handle").arg(GetName())); + mHealth = aStream->ParseInt32(QString("%1 health").arg(GetName())); } } diff --git a/libs/xassets/xdynentityclient.h b/libs/xassets/xdynentityclient.h index baf54e4..5adf79c 100644 --- a/libs/xassets/xdynentityclient.h +++ b/libs/xassets/xdynentityclient.h @@ -13,10 +13,10 @@ public: void Clear() override; private: - int mPhysObjId; + qint32 mPhysObjId; quint32 mFlags; quint32 mLightingHandle; - int mHealth; + qint32 mHealth; }; #endif // XDYNENTITYCLIENT_H diff --git a/libs/xassets/xdynentitycoll.cpp b/libs/xassets/xdynentitycoll.cpp index c50bbcd..d6c9001 100644 --- a/libs/xassets/xdynentitycoll.cpp +++ b/libs/xassets/xdynentitycoll.cpp @@ -17,16 +17,14 @@ XDynEntityColl::~XDynEntityColl() void XDynEntityColl::ParseData(XDataStream *aStream) { - if (GetPtr()) { - *aStream - >> mSector - >> mNextEntInSector - >> mLinkMins[0] - >> mLinkMins[1] - >> mLinkMaxs[0] - >> mLinkMaxs[1]; + mSector = aStream->ParseUInt32(QString("%1 sector").arg(GetName())); + mNextEntInSector = aStream->ParseUInt32(QString("%1 next ent in sector").arg(GetName())); + mLinkMins[0] = aStream->ParseSingle(QString("%1 link min 1").arg(GetName())); + mLinkMins[1] = aStream->ParseSingle(QString("%1 link min 2").arg(GetName())); + mLinkMaxs[0] = aStream->ParseSingle(QString("%1 link max 1").arg(GetName())); + mLinkMaxs[1] = aStream->ParseSingle(QString("%1 link max 2").arg(GetName())); } } diff --git a/libs/xassets/xdynentitydef.cpp b/libs/xassets/xdynentitydef.cpp index 3431ac4..655d6f6 100644 --- a/libs/xassets/xdynentitydef.cpp +++ b/libs/xassets/xdynentitydef.cpp @@ -31,19 +31,18 @@ void XDynEntityDef::ParseData(XDataStream *aStream) mPose.ParseData(aStream); mModel.ParsePtr(aStream, false); - *aStream - >> mBrushModel - >> mPhysicsBrushModel; + mBrushModel = aStream->ParseUInt32(QString("%1 brush model").arg(GetName())); + mPhysicsBrushModel = aStream->ParseUInt32(QString("%1 physics brush model").arg(GetName())); mDestroyFx.ParsePtr(aStream, false); mDestroyPieces.ParsePtr(aStream, false); mPhysPreset.ParsePtr(aStream, false); - *aStream >> mHealth; + mHealth = aStream->ParseUInt32(QString("%1 health").arg(GetName())); mMass.ParseData(aStream); - *aStream >> mContents; + mContents = aStream->ParseUInt32(QString("%1 contents").arg(GetName())); mModel.ParseData(aStream); mDestroyFx.ParseData(aStream); diff --git a/libs/xassets/xdynentitydef.h b/libs/xassets/xdynentitydef.h index bcaf2a2..a782386 100644 --- a/libs/xassets/xdynentitydef.h +++ b/libs/xassets/xdynentitydef.h @@ -33,9 +33,9 @@ private: XFxEffectDef mDestroyFx; XModelPieces mDestroyPieces; XPhysPreset mPhysPreset; - int mHealth; + qint32 mHealth; XPhysMass mMass; - int mContents; + qint32 mContents; }; #endif // XDYNENTITYDEF_H diff --git a/libs/xassets/xdynentitypose.cpp b/libs/xassets/xdynentitypose.cpp index af980cf..d04dcfc 100644 --- a/libs/xassets/xdynentitypose.cpp +++ b/libs/xassets/xdynentitypose.cpp @@ -19,7 +19,7 @@ void XDynEntityPose::ParseData(XDataStream *aStream) { mPose.ParseData(aStream); - *aStream >> mRadius; + mRadius = aStream->ParseSingle(QString("%1 radius").arg(GetName())); } } diff --git a/libs/xassets/xeffectdef.cpp b/libs/xassets/xeffectdef.cpp index 5069eda..8767412 100644 --- a/libs/xassets/xeffectdef.cpp +++ b/libs/xassets/xeffectdef.cpp @@ -21,7 +21,7 @@ XEffectDef::~XEffectDef() void XEffectDef::Clear() { - mName.clear(); + mName.Clear(); mFlags = 0; mTotalSize = 0; mMsecLoopingLife = 0; @@ -33,7 +33,24 @@ void XEffectDef::Clear() void XEffectDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + mName.ParsePtr(aStream, false); - // TODO: Fill in XEffectDef::ParseData + mFlags = aStream->ParseInt32(QString("%1 flags").arg(GetName())); + mTotalSize = aStream->ParseInt32(QString("%1 total size").arg(GetName())); + mMsecLoopingLife = aStream->ParseInt32(QString("%1 looping life (ms)").arg(GetName())); + mElemDefCountLooping = aStream->ParseInt32(QString("%1 looping count").arg(GetName())); + mElemDefCountOneShot = aStream->ParseInt32(QString("%1 one shot count").arg(GetName())); + mElemDefCountEmission = aStream->ParseInt32(QString("%1 emission count").arg(GetName())); + + qint32 elemDefsPtr = aStream->ParseInt32(QString("%1 element def ptr").arg(GetName())); + if (elemDefsPtr) + { + int elemCount = mElemDefCountLooping + mElemDefCountOneShot + mElemDefCountEmission; + for (int i = 0; i < elemCount; i++) + { + XFxElemDef newElemDef; + newElemDef.ParseData(aStream); + mElemDefs.push_back(newElemDef); + } + } } diff --git a/libs/xassets/xeffectdef.h b/libs/xassets/xeffectdef.h index ef2b5fa..184c7bc 100644 --- a/libs/xassets/xeffectdef.h +++ b/libs/xassets/xeffectdef.h @@ -16,14 +16,14 @@ public: void ParseData(XDataStream *aStream) override; private: - QString mName; + XString mName; - int mFlags; - int mTotalSize; - int mMsecLoopingLife; - int mElemDefCountLooping; - int mElemDefCountOneShot; - int mElemDefCountEmission; + qint32 mFlags; + qint32 mTotalSize; + qint32 mMsecLoopingLife; + qint32 mElemDefCountLooping; + qint32 mElemDefCountOneShot; + qint32 mElemDefCountEmission; QVector mElemDefs; }; diff --git a/libs/xassets/xeffectdefref.cpp b/libs/xassets/xeffectdefref.cpp index b69ba58..722bf2c 100644 --- a/libs/xassets/xeffectdefref.cpp +++ b/libs/xassets/xeffectdefref.cpp @@ -16,14 +16,17 @@ XEffectDefRef::~XEffectDefRef() void XEffectDefRef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XEffectDefRef::ParseData + mName.ParsePtr(aStream); + if (mName.GetPtr() && mName.GetPtr() != -1) + { + qDebug() << "DB_FindXAssetHeader(0x1A, " << mName.GetPtr() << ", v1)"; + // TODO: Find asset/asset header + // Shouldn't affect parsing + } } void XEffectDefRef::Clear() { - delete mHandle; - mHandle = new XEffectDef(); + mHandle->Clear(); mName.Clear(); } diff --git a/libs/xassets/xentryinternaldata.cpp b/libs/xassets/xentryinternaldata.cpp index 4e07974..26e3e2d 100644 --- a/libs/xassets/xentryinternaldata.cpp +++ b/libs/xassets/xentryinternaldata.cpp @@ -10,9 +10,7 @@ XEntryInternalData::XEntryInternalData() void XEntryInternalData::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XEntryInternalData::ParseData + mOperand.ParseData(aStream); } void XEntryInternalData::Clear() diff --git a/libs/xassets/xexpressionentry.cpp b/libs/xassets/xexpressionentry.cpp index 901f9e0..c26fcb2 100644 --- a/libs/xassets/xexpressionentry.cpp +++ b/libs/xassets/xexpressionentry.cpp @@ -10,9 +10,8 @@ XExpressionEntry::XExpressionEntry() void XExpressionEntry::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XExpressionEntry::ParseData + mType = aStream->ParseInt32(QString("%1 type").arg(GetName())); + mData.ParseData(aStream); } void XExpressionEntry::Clear() diff --git a/libs/xassets/xexpressionentry.h b/libs/xassets/xexpressionentry.h index 14a2ad2..092dd56 100644 --- a/libs/xassets/xexpressionentry.h +++ b/libs/xassets/xexpressionentry.h @@ -14,7 +14,7 @@ public: void Clear() override; private: - int mType; + qint32 mType; XEntryInternalData mData; }; diff --git a/libs/xassets/xfile.cpp b/libs/xassets/xfile.cpp index 7fe6437..bb14c0c 100644 --- a/libs/xassets/xfile.cpp +++ b/libs/xassets/xfile.cpp @@ -1,4 +1,5 @@ #include "xfile.h" +#include "xcommoninfo.h" #include @@ -10,13 +11,19 @@ XFile::XFile() void XFile::ParseData(XDataStream *aStream) { - quint32 contentLength; - *aStream - >> contentLength; - contentLength += 44; + quint32 contentLength = aStream->ParseUInt32(QString("%1 content length").arg(GetName())); + if (GetCommonInfo()->GetGame() == GAME_COD5) + { + contentLength += 36; + aStream->skipRawData(8 * 4); + } + else + { + contentLength += 44; + aStream->skipRawData(10 * 4); + } qDebug() << "Content size: " << contentLength; - aStream->skipRawData(8 * 4); } void XFile::Clear() diff --git a/libs/xassets/xfont.cpp b/libs/xassets/xfont.cpp index c166027..5491e46 100644 --- a/libs/xassets/xfont.cpp +++ b/libs/xassets/xfont.cpp @@ -44,9 +44,10 @@ void XFont::ParseData(XDataStream *aStream) *aStream >> glyphsPtr; - mFontName.ParseData(aStream); - mMaterial.ParseData(aStream); - mGlowMaterial.ParseData(aStream); + mFontName.ParseDataSafe(aStream); + SetDisplayName(mFontName.GetString()); + mMaterial.ParseDataSafe(aStream); + mGlowMaterial.ParseDataSafe(aStream); if (glyphsPtr == -1) { diff --git a/libs/xassets/xfxeffectdef.cpp b/libs/xassets/xfxeffectdef.cpp index d62ba8d..a3ed736 100644 --- a/libs/xassets/xfxeffectdef.cpp +++ b/libs/xassets/xfxeffectdef.cpp @@ -38,7 +38,7 @@ void XFxEffectDef::ParseData(XDataStream *aStream) mElemDefCountEmission = aStream->ParseInt32(QString("%1 elem def count emission").arg(GetName())); elemDefsPtr = aStream->ParseInt32(QString("%1 elem defs ptr").arg(GetName())); - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); if (elemDefsPtr) { diff --git a/libs/xassets/xfxelematlas.cpp b/libs/xassets/xfxelematlas.cpp index 759d1d2..0709654 100644 --- a/libs/xassets/xfxelematlas.cpp +++ b/libs/xassets/xfxelematlas.cpp @@ -26,7 +26,11 @@ void XFxElemAtlas::Clear() void XFxElemAtlas::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XFxElemAtlas::ParseData + mBehavior = aStream->ParseUInt8(QString("%1 behavior").arg(GetName())); + mIndex = aStream->ParseUInt8(QString("%1 index").arg(GetName())); + mFps = aStream->ParseUInt8(QString("%1 fps").arg(GetName())); + mLoopCount = aStream->ParseUInt8(QString("%1 loop count").arg(GetName())); + mColIndexBits = aStream->ParseUInt8(QString("%1 column index bits").arg(GetName())); + mRowIndexBits = aStream->ParseUInt8(QString("%1 row index bits").arg(GetName())); + mEntryCount = aStream->ParseInt16(QString("%1 entry count").arg(GetName())); } diff --git a/libs/xassets/xfxelemdef.cpp b/libs/xassets/xfxelemdef.cpp index 0cef2bb..9daff7f 100644 --- a/libs/xassets/xfxelemdef.cpp +++ b/libs/xassets/xfxelemdef.cpp @@ -23,9 +23,7 @@ XFxElemDef::XFxElemDef() , mVisualCount(0) , mVelIntervalCount(0) , mVisStateIntervalCount(0) - , mVelSamplesPtr(0) , mVelSamples() - , mVisSamplesPtr(0) , mVisSamples() , mVisuals() , mCollMins() @@ -71,9 +69,7 @@ void XFxElemDef::Clear() mVisualCount = 0; mVelIntervalCount = 0; mVisStateIntervalCount = 0; - mVelSamplesPtr = 0; mVelSamples.clear(); - mVisSamplesPtr = 0; mVisSamples.clear(); mVisuals.Clear(); mCollMins = QVector3D(); @@ -137,14 +133,14 @@ void XFxElemDef::ParseData(XDataStream *aStream) mCollMaxs.setY(aStream->ParseSingle(QString("%1 coll maxs y").arg(GetName()))); mCollMaxs.setZ(aStream->ParseSingle(QString("%1 coll maxs z").arg(GetName()))); - mEffectOnImpact.ParseData(aStream); - mEffectOnDeath.ParseData(aStream); - mEffectEmitted.ParseData(aStream); + mEffectOnImpact.ParsePtr(aStream, false); + mEffectOnDeath.ParsePtr(aStream, false); + mEffectEmitted.ParsePtr(aStream, false); mEmitDist.ParseData(aStream); mEmitDistVariance.ParseData(aStream); - qint32 trailDefPtr; - trailDefPtr = aStream->ParseInt32(QString("%1 trail def ptr").arg(GetName())); + mTrailDef.ParsePtr(aStream, false); + mSortOrder = aStream->ParseUInt8(QString("%1 sort order").arg(GetName())); mLightingFrac = aStream->ParseUInt8(QString("%1 lighting frac").arg(GetName())); mUseItemClip = aStream->ParseUInt8(QString("%1 use item clip").arg(GetName())); @@ -171,5 +167,9 @@ void XFxElemDef::ParseData(XDataStream *aStream) } } - // TODO: Finish this ugh + mVisuals.ParseData(aStream); + mEffectOnImpact.ParseData(aStream); + mEffectOnDeath.ParseData(aStream); + mEffectEmitted.ParseData(aStream); + mTrailDef.ParseData(aStream); } diff --git a/libs/xassets/xfxelemdef.h b/libs/xassets/xfxelemdef.h index 362f914..6193c58 100644 --- a/libs/xassets/xfxelemdef.h +++ b/libs/xassets/xfxelemdef.h @@ -22,7 +22,7 @@ public: void ParseData(XDataStream *aStream) override; private: - int mFlags; + qint32 mFlags; XFxSpawnDef mSpawn; XFxFloatRange mSpawnRange; XFxFloatRange mFadeInRange; @@ -43,9 +43,7 @@ private: quint8 mVisualCount; quint8 mVelIntervalCount; quint8 mVisStateIntervalCount; - qint32 mVelSamplesPtr; QVector mVelSamples; - qint32 mVisSamplesPtr; QVector mVisSamples; XFxElemDefVisuals mVisuals; QVector3D mCollMins; diff --git a/libs/xassets/xfxelemvec3range.cpp b/libs/xassets/xfxelemvec3range.cpp index f2cba42..9622e53 100644 --- a/libs/xassets/xfxelemvec3range.cpp +++ b/libs/xassets/xfxelemvec3range.cpp @@ -8,11 +8,6 @@ XFxElemVec3Range::XFxElemVec3Range() SetName("Element Vec3 Range"); } -XFxElemVec3Range::~XFxElemVec3Range() -{ - -} - void XFxElemVec3Range::Clear() { mBase = QVector3D(); @@ -21,11 +16,13 @@ void XFxElemVec3Range::Clear() void XFxElemVec3Range::ParseData(XDataStream *aStream) { - *aStream - >> mBase[0] - >> mBase[1] - >> mBase[2] - >> mAmplitude[0] - >> mAmplitude[1] - >> mAmplitude[2]; + for (int i = 0; i < 3; i++) + { + mBase[i] = aStream->ParseSingle(QString("%1 base %2").arg(GetName()).arg(i)); + } + + for (int i = 0; i < 3; i++) + { + mAmplitude[i] = aStream->ParseSingle(QString("%1 amplitude %2").arg(GetName()).arg(i)); + } } diff --git a/libs/xassets/xfxelemvec3range.h b/libs/xassets/xfxelemvec3range.h index ac59eaa..12cd6a9 100644 --- a/libs/xassets/xfxelemvec3range.h +++ b/libs/xassets/xfxelemvec3range.h @@ -9,7 +9,6 @@ class XFxElemVec3Range : public XAsset { public: explicit XFxElemVec3Range(); - ~XFxElemVec3Range(); void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xfxelemvelstateinframe.cpp b/libs/xassets/xfxelemvelstateinframe.cpp index 1f22637..d0265bf 100644 --- a/libs/xassets/xfxelemvelstateinframe.cpp +++ b/libs/xassets/xfxelemvelstateinframe.cpp @@ -8,11 +8,6 @@ XFxElemVelStateInFrame::XFxElemVelStateInFrame() SetName("Element Vel State in Frame"); } -XFxElemVelStateInFrame::~XFxElemVelStateInFrame() -{ - -} - void XFxElemVelStateInFrame::Clear() { mVelocity.Clear(); diff --git a/libs/xassets/xfxelemvelstateinframe.h b/libs/xassets/xfxelemvelstateinframe.h index cbc9a65..3abb80f 100644 --- a/libs/xassets/xfxelemvelstateinframe.h +++ b/libs/xassets/xfxelemvelstateinframe.h @@ -8,7 +8,6 @@ class XFxElemVelStateInFrame : public XAsset { public: explicit XFxElemVelStateInFrame(); - ~XFxElemVelStateInFrame(); void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xfxfloatrange.cpp b/libs/xassets/xfxfloatrange.cpp index 17055be..781d2c2 100644 --- a/libs/xassets/xfxfloatrange.cpp +++ b/libs/xassets/xfxfloatrange.cpp @@ -8,11 +8,6 @@ XFxFloatRange::XFxFloatRange() SetName("Float Range"); } -XFxFloatRange::~XFxFloatRange() -{ - -} - void XFxFloatRange::Clear() { mBase = 0; @@ -21,7 +16,6 @@ void XFxFloatRange::Clear() void XFxFloatRange::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XFxFloatRange::ParseData + mBase = aStream->ParseSingle(QString("%1 base").arg(GetName())); + mAmplitude = aStream->ParseSingle(QString("%1 base").arg(GetName())); } diff --git a/libs/xassets/xfxfloatrange.h b/libs/xassets/xfxfloatrange.h index 34c36f5..2883e7b 100644 --- a/libs/xassets/xfxfloatrange.h +++ b/libs/xassets/xfxfloatrange.h @@ -7,7 +7,6 @@ class XFxFloatRange : public XAsset { public: explicit XFxFloatRange(); - ~XFxFloatRange(); void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xfximpactentry.cpp b/libs/xassets/xfximpactentry.cpp index 5e116ed..7319caf 100644 --- a/libs/xassets/xfximpactentry.cpp +++ b/libs/xassets/xfximpactentry.cpp @@ -2,30 +2,39 @@ XFxImpactEntry::XFxImpactEntry() : XAsset() - , mNonFleshPtrs() , mNonFlesh() - , mFleshPtrs() , mFlesh() { SetName("Impact Entry"); } -XFxImpactEntry::~XFxImpactEntry() -{ - -} - void XFxImpactEntry::Clear() { - mNonFleshPtrs.clear(); mNonFlesh.clear(); - mFleshPtrs.clear(); mFlesh.clear(); } void XFxImpactEntry::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + for (int i = 0; i < 29; i++) + { + XEffectDef newNonFlesh; + newNonFlesh.ParsePtr(aStream, false); + mNonFlesh.push_back(newNonFlesh); + } + for (int i = 0; i < 29; i++) + { + mNonFlesh[i].ParseDataSafe(aStream); + } - // TODO: Fill in XFxImpactEntry::ParseData + for (int i = 0; i < 4; i++) + { + XEffectDef newFlesh; + newFlesh.ParsePtr(aStream, false); + mFlesh.push_back(newFlesh); + } + for (int i = 0; i < mFlesh.size(); i++) + { + mFlesh[i].ParseDataSafe(aStream); + } } diff --git a/libs/xassets/xfximpactentry.h b/libs/xassets/xfximpactentry.h index 7cb2138..5546983 100644 --- a/libs/xassets/xfximpactentry.h +++ b/libs/xassets/xfximpactentry.h @@ -8,16 +8,13 @@ class XFxImpactEntry : public XAsset { public: explicit XFxImpactEntry(); - ~XFxImpactEntry(); + ~XFxImpactEntry() = default; void Clear() override; void ParseData(XDataStream *aStream) override; private: - QVector mNonFleshPtrs; QVector mNonFlesh; - - QVector mFleshPtrs; QVector mFlesh; }; diff --git a/libs/xassets/xfximpacttable.cpp b/libs/xassets/xfximpacttable.cpp index ec53b5b..2f40592 100644 --- a/libs/xassets/xfximpacttable.cpp +++ b/libs/xassets/xfximpacttable.cpp @@ -2,31 +2,33 @@ XFxImpactTable::XFxImpactTable() : XAsset() - , mNamePtr(0) - , mName("") - , mTablePtr(0) + , mName() , mTable() { SetType(ASSET_TYPE_IMPACT_FX); SetName("Impact Table"); } -XFxImpactTable::~XFxImpactTable() -{ - -} - void XFxImpactTable::Clear() { - mNamePtr = 0; - mName = ""; - mTablePtr = 0; - mTable = QVector(); + mName.Clear(); + mTable.clear(); } void XFxImpactTable::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + mName.ParsePtr(aStream, false); + qint32 tablePtr = aStream->ParseInt32(QString("%1 impact table ptr").arg(GetName())); - // TODO: Fill in XFxImpactTable::ParseData + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); + + if (tablePtr) + { + for (int i = 0; i < 12; i++) + { + XFxImpactEntry newImpactEntry; + newImpactEntry.ParseData(aStream); + } + } } diff --git a/libs/xassets/xfximpacttable.h b/libs/xassets/xfximpacttable.h index 12f1a05..4722cc0 100644 --- a/libs/xassets/xfximpacttable.h +++ b/libs/xassets/xfximpacttable.h @@ -8,15 +8,13 @@ class XFxImpactTable : public XAsset { public: explicit XFxImpactTable(); - ~XFxImpactTable(); + ~XFxImpactTable() = default; void Clear() override; void ParseData(XDataStream *aStream) override; private: - qint32 mNamePtr; - QString mName; - qint32 mTablePtr; + XString mName; QVector mTable; }; diff --git a/libs/xassets/xfxintrange.cpp b/libs/xassets/xfxintrange.cpp index 919ca44..6852e90 100644 --- a/libs/xassets/xfxintrange.cpp +++ b/libs/xassets/xfxintrange.cpp @@ -8,11 +8,6 @@ XFxIntRange::XFxIntRange() SetName("Int Range"); } -XFxIntRange::~XFxIntRange() -{ - -} - void XFxIntRange::Clear() { mBase = 0; @@ -21,7 +16,6 @@ void XFxIntRange::Clear() void XFxIntRange::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XFxIntRange::ParseData + mBase = aStream->ParseInt32(QString("%1 base").arg(GetName())); + mAmplitude = aStream->ParseInt32(QString("%1 amplitude").arg(GetName())); } diff --git a/libs/xassets/xfxintrange.h b/libs/xassets/xfxintrange.h index db3329f..05ffd41 100644 --- a/libs/xassets/xfxintrange.h +++ b/libs/xassets/xfxintrange.h @@ -7,14 +7,13 @@ class XFxIntRange : public XAsset { public: explicit XFxIntRange(); - ~XFxIntRange(); void Clear() override; void ParseData(XDataStream *aStream) override; private: - int mBase; - int mAmplitude; + qint32 mBase; + qint32 mAmplitude; }; #endif // XFXINTRANGE_H diff --git a/libs/xassets/xfxspawndef.cpp b/libs/xassets/xfxspawndef.cpp index c8b0123..3b13d66 100644 --- a/libs/xassets/xfxspawndef.cpp +++ b/libs/xassets/xfxspawndef.cpp @@ -21,7 +21,7 @@ void XFxSpawnDef::Clear() void XFxSpawnDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XFxSpawnDef::ParseData + // TODO: Determine when to parse one shot instead + // Shouldn't affect general asset parsing though + mLooping.ParseData(aStream); } diff --git a/libs/xassets/xfxspawndeflooping.cpp b/libs/xassets/xfxspawndeflooping.cpp index 4696f09..9c3b880 100644 --- a/libs/xassets/xfxspawndeflooping.cpp +++ b/libs/xassets/xfxspawndeflooping.cpp @@ -8,11 +8,6 @@ XFxSpawnDefLooping::XFxSpawnDefLooping() SetName("Spawn Definition Looping"); } -XFxSpawnDefLooping::~XFxSpawnDefLooping() -{ - -} - void XFxSpawnDefLooping::Clear() { mIntervalMsec = 0; @@ -21,7 +16,6 @@ void XFxSpawnDefLooping::Clear() void XFxSpawnDefLooping::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XFxSpawnDefLooping::ParseData + mIntervalMsec = aStream->ParseInt32(QString("%1 interval (ms)").arg(GetName())); + mCount = aStream->ParseInt32(QString("%1 count").arg(GetName())); } diff --git a/libs/xassets/xfxspawndeflooping.h b/libs/xassets/xfxspawndeflooping.h index 629baef..8d4092d 100644 --- a/libs/xassets/xfxspawndeflooping.h +++ b/libs/xassets/xfxspawndeflooping.h @@ -9,7 +9,6 @@ class XFxSpawnDefLooping : public XAsset { public: explicit XFxSpawnDefLooping(); - ~XFxSpawnDefLooping(); void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xfxspawndefoneshot.cpp b/libs/xassets/xfxspawndefoneshot.cpp index 4fc4efa..1c991ea 100644 --- a/libs/xassets/xfxspawndefoneshot.cpp +++ b/libs/xassets/xfxspawndefoneshot.cpp @@ -7,11 +7,6 @@ XFxSpawnDefOneShot::XFxSpawnDefOneShot() SetName("Spawn Definition Oneshot"); } -XFxSpawnDefOneShot::~XFxSpawnDefOneShot() -{ - -} - void XFxSpawnDefOneShot::Clear() { mCount.Clear(); @@ -19,7 +14,5 @@ void XFxSpawnDefOneShot::Clear() void XFxSpawnDefOneShot::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XFxSpawnDefOneShot::ParseData + mCount.ParseData(aStream); } diff --git a/libs/xassets/xfxspawndefoneshot.h b/libs/xassets/xfxspawndefoneshot.h index 6189b5c..47d577b 100644 --- a/libs/xassets/xfxspawndefoneshot.h +++ b/libs/xassets/xfxspawndefoneshot.h @@ -8,7 +8,6 @@ class XFxSpawnDefOneShot : public XAsset { public: explicit XFxSpawnDefOneShot(); - ~XFxSpawnDefOneShot(); void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xfxtraildef.cpp b/libs/xassets/xfxtraildef.cpp index 5d530f2..96830ec 100644 --- a/libs/xassets/xfxtraildef.cpp +++ b/libs/xassets/xfxtraildef.cpp @@ -13,11 +13,6 @@ XFxTrailDef::XFxTrailDef() SetName("Trail Definition"); } -XFxTrailDef::~XFxTrailDef() -{ - -} - void XFxTrailDef::Clear() { mScrollTimeMsec = 0; @@ -31,7 +26,32 @@ void XFxTrailDef::Clear() void XFxTrailDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + mScrollTimeMsec = aStream->ParseInt32(QString("%1 scroll time (ms)").arg(GetName())); + mRepeatDist = aStream->ParseInt32(QString("%1 repeat dist").arg(GetName())); + mSplitDist = aStream->ParseInt32(QString("%1 split dist").arg(GetName())); + mVertCount = aStream->ParseInt32(QString("%1 vert count").arg(GetName())); - // TODO: Fill in XFxTrailDef::ParseData + qint32 vertsPtr = aStream->ParseInt32(QString("%1 verts ptr").arg(GetName())); + + mIndCount = aStream->ParseUInt32(QString("%1 sort order").arg(GetName())); + + qint32 indicesPtr = aStream->ParseInt32(QString("%1 indices ptr").arg(GetName())); + + if (vertsPtr) + { + for (int i = 0; i < mVertCount; i++) + { + XFxTrailVertex newVert; + newVert.ParseData(aStream); + mVerts.push_back(newVert); + } + } + + if (indicesPtr) + { + for (int i = 0; i < mIndCount; i++) + { + mIndices.push_back(aStream->ParseUInt16(QString("%1 index %2").arg(GetName()).arg(i))); + } + } } diff --git a/libs/xassets/xfxtraildef.h b/libs/xassets/xfxtraildef.h index d6dd868..16deefc 100644 --- a/libs/xassets/xfxtraildef.h +++ b/libs/xassets/xfxtraildef.h @@ -10,18 +10,17 @@ class XFxTrailDef : public XAsset { public: explicit XFxTrailDef(); - ~XFxTrailDef(); void Clear() override; void ParseData(XDataStream *aStream) override; private: - int mScrollTimeMsec; - int mRepeatDist; - int mSplitDist; - int mVertCount; + qint32 mScrollTimeMsec; + qint32 mRepeatDist; + qint32 mSplitDist; + qint32 mVertCount; QVector mVerts; - int mIndCount; + qint32 mIndCount; QVector mIndices; }; diff --git a/libs/xassets/xfxtrailvertex.cpp b/libs/xassets/xfxtrailvertex.cpp index e8fd3c1..cbd909f 100644 --- a/libs/xassets/xfxtrailvertex.cpp +++ b/libs/xassets/xfxtrailvertex.cpp @@ -6,12 +6,7 @@ XFxTrailVertex::XFxTrailVertex() , mNormal() , mTexCoord(0) { - SetName("Trail Vertex"); -} - -XFxTrailVertex::~XFxTrailVertex() -{ - + SetName("FX Trail Vertex"); } void XFxTrailVertex::Clear() @@ -23,7 +18,11 @@ void XFxTrailVertex::Clear() void XFxTrailVertex::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + mPos.setX(aStream->ParseSingle(QString("%1 pos x").arg(GetName()))); + mPos.setX(aStream->ParseSingle(QString("%1 pos y").arg(GetName()))); - // TODO: Fill in XFxTrailVertex::ParseData + mNormal.setX(aStream->ParseSingle(QString("%1 normal x").arg(GetName()))); + mNormal.setX(aStream->ParseSingle(QString("%1 normal y").arg(GetName()))); + + mTexCoord = aStream->ParseSingle(QString("%1 tex coord").arg(GetName())); } diff --git a/libs/xassets/xfxtrailvertex.h b/libs/xassets/xfxtrailvertex.h index 4b2eb7a..34e265d 100644 --- a/libs/xassets/xfxtrailvertex.h +++ b/libs/xassets/xfxtrailvertex.h @@ -9,7 +9,6 @@ class XFxTrailVertex : public XAsset { public: explicit XFxTrailVertex(); - ~XFxTrailVertex(); void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xgame.h b/libs/xassets/xgame.h index e879a61..4792b3e 100644 --- a/libs/xassets/xgame.h +++ b/libs/xassets/xgame.h @@ -1,17 +1,23 @@ #ifndef XGAME_H #define XGAME_H -enum XGame { - GAME_NONE = 0x00, // No game - GAME_COD1 = 0x01, // Call of Duty - GAME_COD2 = 0x02, // Call of Duty 2 - GAME_COD3 = 0x03, // Call of Duty 3 - GAME_COD4 = 0x04, // Modern Warware 1 - GAME_COD5 = 0x05, // World at War - GAME_COD6 = 0x06, // Modern Warfare 2 - GAME_COD7 = 0x07, // Black Ops 1 - GAME_COD8 = 0x08, // Modern Warfare 3 - GAME_COD9 = 0x09 // Black Ops 2 +enum XGame +{ + GAME_NONE = 0, // No game + GAME_COD1 = 1, // Call of Duty + GAME_COD2 = 2, // Call of Duty 2 + GAME_COD3 = 3, // Call of Duty 3 + GAME_COD4 = 4, // Modern Warware 1 + GAME_COD5 = 5, // World at War + GAME_COD6 = 6, // Modern Warfare 2 + GAME_COD7 = 7, // Black Ops 1 + GAME_COD7_5 = 75, // Future Warfare + GAME_COD8 = 8, // Modern Warfare 3 + GAME_COD9 = 9, // Black Ops 2 + GAME_COD10 = 10, // + GAME_COD11 = 11, // + GAME_COD12 = 12, // Black Ops 3 + GAME_COD21 = 21 // Black Ops 6/7 }; #endif // XGAME_H diff --git a/libs/xassets/xgfxcolor.cpp b/libs/xassets/xgfxcolor.cpp index 8bd1f5f..adcddbf 100644 --- a/libs/xassets/xgfxcolor.cpp +++ b/libs/xassets/xgfxcolor.cpp @@ -2,35 +2,16 @@ XGfxColor::XGfxColor() : XAsset() - , mArray(4) + , mArray() { SetName("GFX Color"); } void XGfxColor::ParseData(XDataStream *aStream) { - *aStream >> mArray[0]; - if (IsDebug()) + for (int i = 0; i < 4; i++) { - qDebug() << QString("[%1] mArray[0] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mArray[0]); - } - - *aStream >> mArray[1]; - if (IsDebug()) - { - qDebug() << QString("[%1] mArray[1] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mArray[1]); - } - - *aStream >> mArray[2]; - if (IsDebug()) - { - qDebug() << QString("[%1] mArray[2] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mArray[2]); - } - - *aStream >> mArray[3]; - if (IsDebug()) - { - qDebug() << QString("[%1] mArray[3] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mArray[3]); + mArray.push_back(aStream->ParseUInt8(QString("%1 array at %2").arg(GetName()).arg(i))); } } diff --git a/libs/xassets/xgfxdrawsurffields.cpp b/libs/xassets/xgfxdrawsurffields.cpp index 7da31aa..728b647 100644 --- a/libs/xassets/xgfxdrawsurffields.cpp +++ b/libs/xassets/xgfxdrawsurffields.cpp @@ -2,6 +2,7 @@ XGfxDrawSurfFields::XGfxDrawSurfFields() : XAsset() + , mRawData(0) , mObjectId(0) , mReflectionProbeIndex(0) , mCustomIndex(0) @@ -18,14 +19,9 @@ XGfxDrawSurfFields::XGfxDrawSurfFields() void XGfxDrawSurfFields::ParseData(XDataStream *aStream) { // Read the raw 64-bit value from the stream - quint64 raw; - *aStream >> raw; - if (IsDebug()) - { - qDebug() << QString("[%1] raw = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(raw); - } + mRawData = aStream->ParseUInt64(QString("%1 raw value").arg(GetName())); - // Decode bitfields from the 64-bit packed value + // TODO: Decode bitfields from the 64-bit packed value // mObjectId =- raw & 0xFFFF; // bits 0-15 // mReflectionProbeIndex = (raw >> 16) & 0xFF; // bits 16-23 // mCustomIndex = (raw >> 24) & 0x1F; // bits 24-28 diff --git a/libs/xassets/xgfxdrawsurffields.h b/libs/xassets/xgfxdrawsurffields.h index fe3b47f..b9c6240 100644 --- a/libs/xassets/xgfxdrawsurffields.h +++ b/libs/xassets/xgfxdrawsurffields.h @@ -12,6 +12,8 @@ public: virtual void Clear() override; private: + quint64 mRawData; + quint64 mObjectId; quint64 mReflectionProbeIndex; quint64 mCustomIndex; diff --git a/libs/xassets/xgfximage.cpp b/libs/xassets/xgfximage.cpp index 35fb6d8..b475646 100644 --- a/libs/xassets/xgfximage.cpp +++ b/libs/xassets/xgfximage.cpp @@ -4,7 +4,10 @@ XGfxImage::XGfxImage() : XAsset() , mMapType() , mTexture() + , mPicmip() + , mNoPicmip(false) , mSemantic(0) + , mTrack(0) , mCardMemory() , mWidth(0) , mHeight(0) @@ -21,11 +24,6 @@ XGfxImage::XGfxImage() SetName("GFX Image"); } -XGfxImage::~XGfxImage() -{ - -} - void XGfxImage::ParseData(XDataStream *aStream) { if (GetPtr() == -1) @@ -33,10 +31,12 @@ void XGfxImage::ParseData(XDataStream *aStream) mMapType = (XMapType)aStream->ParseUInt32(QString("%1 map type").arg(GetName())); mTexture.ParsePtr(aStream, false); + mPicmip.ParseData(aStream); mSemantic = aStream->ParseUInt8(QString("%1 semantic").arg(GetName())); + mTrack = aStream->ParseUInt8(QString("%1 track").arg(GetName())); - aStream->skipRawData(3); + aStream->skipRawData(4); mCardMemory.ParseData(aStream); @@ -47,23 +47,32 @@ void XGfxImage::ParseData(XDataStream *aStream) mDepth = aStream->ParseUInt16(QString("%1 depth").arg(GetName())); mCategory = aStream->ParseUInt8(QString("%1 category").arg(GetName())); mDelayLoadPixels = aStream->ParseUInt8(QString("%1 delay load pixels").arg(GetName())); - pixelsPtr = aStream->ParseInt32(QString("%1 pixels ptr").arg(GetName())); - mBaseSize = aStream->ParseUInt32(QString("%1 base size").arg(GetName())); - mStreamSlot = aStream->ParseUInt16(QString("%1 stream slot").arg(GetName())); - mStreaming = aStream->ParseUInt8(QString("%1 streaming").arg(GetName())); - aStream->skipRawData(1); + if (GetCommonInfo()->GetGame() == GAME_COD4) + { + pixelsPtr = 0; + } + else + { + pixelsPtr = aStream->ParseInt32(QString("%1 pixels ptr").arg(GetName())); + mBaseSize = aStream->ParseUInt32(QString("%1 base size").arg(GetName())); + mStreamSlot = aStream->ParseUInt16(QString("%1 stream slot").arg(GetName())); + mStreaming = aStream->ParseUInt8(QString("%1 streaming").arg(GetName())); + + aStream->skipRawData(1); + } mName.ParsePtr(aStream); + SetDisplayName(mName.GetString()); //int variableSkip = mDelayLoadPixels ? 2 : 5; //aStream->skipRawData(variableSkip); - if (pixelsPtr == -1) - { - mPixels.resize(mCardMemory.GetPlatform()); - aStream->readRawData(mPixels.data(), mCardMemory.GetPlatform()); - } + //if (pixelsPtr == -1) + //{ + //mPixels.resize(mCardMemory.GetPlatform()); + //aStream->readRawData(mPixels.data(), mCardMemory.GetPlatform()); + //} mTexture.ParseData(aStream); } diff --git a/libs/xassets/xgfximage.h b/libs/xassets/xgfximage.h index 3477c89..c6b0483 100644 --- a/libs/xassets/xgfximage.h +++ b/libs/xassets/xgfximage.h @@ -4,7 +4,9 @@ #include "xasset.h" #include "xcardmemory.h" #include "xgfxtexture.h" +#include "xgfximageloaddef.h" #include "xmaptype.h" +#include "xpicmip.h" #include "xstring.h" #include @@ -14,7 +16,6 @@ class XGfxImage : public XAsset { public: explicit XGfxImage(); - ~XGfxImage(); virtual void ParseData(XDataStream* aStream) override; virtual void Clear() override; @@ -22,7 +23,10 @@ public: private: XMapType mMapType; XGfxTexture mTexture; + XPicmip mPicmip; + bool mNoPicmip; quint8 mSemantic; + quint8 mTrack; XCardMemory mCardMemory; quint16 mWidth; quint16 mHeight; diff --git a/libs/xassets/xgfximageloaddef.cpp b/libs/xassets/xgfximageloaddef.cpp index b3f8605..507a2b3 100644 --- a/libs/xassets/xgfximageloaddef.cpp +++ b/libs/xassets/xgfximageloaddef.cpp @@ -18,11 +18,12 @@ XGfxImageLoadDef::~XGfxImageLoadDef() void XGfxImageLoadDef::ParseData(XDataStream *aStream) { - *aStream - >> mLevelCount - >> mFlags - >> mDimensions - >> mFormat; + mLevelCount = aStream->ParseUInt8(QString("%1 level count").arg(GetName())); + mFlags = aStream->ParseUInt8(QString("%1 flags").arg(GetName())); + mDimensions[0] = aStream->ParseUInt16(QString("%1 dimension 1").arg(GetName())); + mDimensions[1] = aStream->ParseUInt16(QString("%1 dimension 2").arg(GetName())); + mDimensions[2] = aStream->ParseUInt16(QString("%1 dimension 3").arg(GetName())); + mFormat = aStream->ParseUInt32(QString("%1 format").arg(GetName())); mTexture.ParsePtr(aStream); } diff --git a/libs/xassets/xgfxlightdef.cpp b/libs/xassets/xgfxlightdef.cpp index 96abc30..cfd3860 100644 --- a/libs/xassets/xgfxlightdef.cpp +++ b/libs/xassets/xgfxlightdef.cpp @@ -26,8 +26,9 @@ void XGfxLightDef::ParseData(XDataStream *aStream) { mName.ParsePtr(aStream, false); mAttenuation.ParseData(aStream); - *aStream >> mLmapLookupStart; + mLmapLookupStart = aStream->ParseUInt32(QString("%1 lmap lookup start").arg(GetName())); - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); mAttenuation.ParseData(aStream); } diff --git a/libs/xassets/xgfxlightdef.h b/libs/xassets/xgfxlightdef.h index e81411d..2d1f941 100644 --- a/libs/xassets/xgfxlightdef.h +++ b/libs/xassets/xgfxlightdef.h @@ -17,7 +17,7 @@ public: private: XString mName; XGfxLightImage mAttenuation; - int mLmapLookupStart; + qint32 mLmapLookupStart; }; #endif // XGFXLIGHTDEF_H diff --git a/libs/xassets/xgfxpackedvertex.cpp b/libs/xassets/xgfxpackedvertex.cpp index 9a89f13..88d3189 100644 --- a/libs/xassets/xgfxpackedvertex.cpp +++ b/libs/xassets/xgfxpackedvertex.cpp @@ -16,23 +16,11 @@ void XGfxPackedVertex::ParseData(XDataStream *aStream) { if (GetPtr() == -1) { - - quint32 rawCoord; for (int i = 0; i < 3; i++) { - *aStream >> rawCoord; - memcpy(&mXYZ[i], &rawCoord, sizeof(mXYZ[i])); - if (IsDebug()) - { - qDebug() << QString("[%1] mXYZ[%2] = %3").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(i).arg(mXYZ[0]); - } - } - - *aStream >> mBinormalSign; - if (IsDebug()) - { - qDebug() << QString("[%1] mBinormalSign = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mBinormalSign); + mXYZ[i] = aStream->ParseSingle(QString("%1 xyz %2").arg(GetName()).arg(i)); } + mBinormalSign = aStream->ParseSingle(QString("%1 terrain contents").arg(GetName())); mColor.ParseData(aStream); mTexCoord.ParseData(aStream); @@ -43,5 +31,10 @@ void XGfxPackedVertex::ParseData(XDataStream *aStream) void XGfxPackedVertex::Clear() { - + mXYZ = QVector3D(); + mBinormalSign = 0; + mColor.Clear(); + mTexCoord.Clear(); + mNormal.Clear(); + mTangent.Clear(); } diff --git a/libs/xassets/xgfxpixelshaderloaddef.cpp b/libs/xassets/xgfxpixelshaderloaddef.cpp index f066944..a1f8445 100644 --- a/libs/xassets/xgfxpixelshaderloaddef.cpp +++ b/libs/xassets/xgfxpixelshaderloaddef.cpp @@ -2,10 +2,9 @@ XGfxPixelShaderLoadDef::XGfxPixelShaderLoadDef() : XAsset() - , mCachedPart() - , mPhysicalPart() - , mCachedPartSize(0) - , mPhysicalPartSize(0) + , mProgramSize(0) + , mLoadForRenderer(0) + , mProgram() { SetName("GFX Pixel Shader Load Definition"); } @@ -15,39 +14,63 @@ XGfxPixelShaderLoadDef::~XGfxPixelShaderLoadDef() } -quint16 XGfxPixelShaderLoadDef::GetPhysicalPartSize() const -{ - return mPhysicalPartSize; -} - -quint16 XGfxPixelShaderLoadDef::GetCachedPartSize() const -{ - return mCachedPartSize; -} - void XGfxPixelShaderLoadDef::Clear() { - mCachedPart.clear(); - mPhysicalPart.clear(); - mCachedPartSize = 0; - mPhysicalPartSize = 0; + mProgram.clear(); } void XGfxPixelShaderLoadDef::ParseData(XDataStream *aStream) { - qint32 cachedPartPtr, physicalPartPtr; - *aStream - >> cachedPartPtr - >> physicalPartPtr - >> mCachedPartSize - >> mPhysicalPartSize; - - if (physicalPartPtr) + if (IsDebug()) { - aStream->readRawData(mPhysicalPart.data(), mPhysicalPartSize); + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } - if (cachedPartPtr) + + qint32 programPtr = aStream->ParseInt32(QString("%1 program ptr").arg(GetName())); + Q_UNUSED(programPtr); + + mProgramSize = aStream->ParseUInt16(QString("%1 cached part").arg(GetName())); + mLoadForRenderer = aStream->ParseUInt16(QString("%1 physical part").arg(GetName())); +} + +void XGfxPixelShaderLoadDef::ParseProgram(XDataStream *aStream) +{ + mProgram = QByteArray(mProgramSize * 4, Qt::Uninitialized); + aStream->readRawData(mProgram.data(), mProgramSize * 4); + + if (IsDebug()) { - aStream->readRawData(mCachedPart.data(), mCachedPartSize); + qDebug() << QString("[%1] %2: %3").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()).arg(mProgram); } } + +quint16 XGfxPixelShaderLoadDef::ProgramSize() const +{ + return mProgramSize; +} + +void XGfxPixelShaderLoadDef::SetProgramSize(quint16 aProgramSize) +{ + mProgramSize = aProgramSize; +} + +quint16 XGfxPixelShaderLoadDef::LoadForRenderer() const +{ + return mLoadForRenderer; +} + +void XGfxPixelShaderLoadDef::SetLoadForRenderer(quint16 aLoadForRenderer) +{ + mLoadForRenderer = aLoadForRenderer; +} + +QByteArray XGfxPixelShaderLoadDef::Program() const +{ + return mProgram; +} + +void XGfxPixelShaderLoadDef::SetProgram(const QByteArray &aProgram) +{ + mProgram = aProgram; +} + diff --git a/libs/xassets/xgfxpixelshaderloaddef.h b/libs/xassets/xgfxpixelshaderloaddef.h index 7b844f9..61d858a 100644 --- a/libs/xassets/xgfxpixelshaderloaddef.h +++ b/libs/xassets/xgfxpixelshaderloaddef.h @@ -11,17 +11,22 @@ public: explicit XGfxPixelShaderLoadDef(); ~XGfxPixelShaderLoadDef(); - quint16 GetPhysicalPartSize() const; - quint16 GetCachedPartSize() const; - void ParseData(XDataStream *aStream) override; void Clear() override; + void ParseProgram(XDataStream *aStream); + + quint16 ProgramSize() const; + void SetProgramSize(quint16 aProgramSize); + quint16 LoadForRenderer() const; + void SetLoadForRenderer(quint16 aLoadForRenderer); + QByteArray Program() const; + void SetProgram(const QByteArray &aProgram); + private: - QByteArray mCachedPart; - QByteArray mPhysicalPart; - quint16 mCachedPartSize; - quint16 mPhysicalPartSize; + quint16 mProgramSize; + quint16 mLoadForRenderer; + QByteArray mProgram; }; #endif // XGFXPIXELSHADERLOADDEF_H diff --git a/libs/xassets/xgfxplacement.cpp b/libs/xassets/xgfxplacement.cpp index e8a0249..17bb0d7 100644 --- a/libs/xassets/xgfxplacement.cpp +++ b/libs/xassets/xgfxplacement.cpp @@ -15,14 +15,15 @@ XGfxPlacement::~XGfxPlacement() void XGfxPlacement::ParseData(XDataStream *aStream) { - *aStream - >> mQuat[0] - >> mQuat[1] - >> mQuat[2] - >> mQuat[3] - >> mOrigin[0] - >> mOrigin[2] - >> mOrigin[3]; + for (int i = 0; i < 4; i++) + { + mQuat[i] = aStream->ParseSingle(QString("%1 quaternion %2").arg(GetName()).arg(i)); + } + + for (int i = 0; i < 3; i++) + { + mOrigin[i] = aStream->ParseSingle(QString("%1 origin %2").arg(GetName()).arg(i)); + } } void XGfxPlacement::Clear() diff --git a/libs/xassets/xgfxvertexshaderloaddef.cpp b/libs/xassets/xgfxvertexshaderloaddef.cpp index 7a01669..a932da2 100644 --- a/libs/xassets/xgfxvertexshaderloaddef.cpp +++ b/libs/xassets/xgfxvertexshaderloaddef.cpp @@ -2,25 +2,18 @@ XGfxVertexShaderLoadDef::XGfxVertexShaderLoadDef() : XAsset() - , mCachedPart() - , mPhysicalPart() - , mCachedPartSize(0) - , mPhysicalPartSize(0) + , mProgramSize(0) + , mLoadForRenderer(0) + , mProgram() { SetName("GFX Vertex Shader Load Definition"); } -XGfxVertexShaderLoadDef::~XGfxVertexShaderLoadDef() -{ - -} - void XGfxVertexShaderLoadDef::Clear() { - mCachedPart = QByteArray(); - mPhysicalPart = QByteArray(); - mCachedPartSize = 0; - mPhysicalPartSize = 0; + mProgramSize = 0; + mLoadForRenderer = 0; + mProgram.clear(); } void XGfxVertexShaderLoadDef::ParseData(XDataStream *aStream) @@ -29,35 +22,51 @@ void XGfxVertexShaderLoadDef::ParseData(XDataStream *aStream) { qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } - qint32 cachedPartPtr, physicalPartPtr; - *aStream - >> cachedPartPtr - >> physicalPartPtr - >> mCachedPartSize - >> mPhysicalPartSize; + + qint32 programPtr = aStream->ParseInt32(QString("%1 program ptr").arg(GetName())); + Q_UNUSED(programPtr); + + mProgramSize = aStream->ParseUInt16(QString("%1 cached part").arg(GetName())); + mLoadForRenderer = aStream->ParseUInt16(QString("%1 physical part").arg(GetName())); +} + +void XGfxVertexShaderLoadDef::ParseProgram(XDataStream *aStream) +{ + mProgram = QByteArray(mProgramSize * 4, Qt::Uninitialized); + aStream->readRawData(mProgram.data(), mProgramSize * 4); if (IsDebug()) { - qDebug() << QString("[%1] cachedPartPtr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(cachedPartPtr); - qDebug() << QString("[%1] physicalPartPtr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(physicalPartPtr); - qDebug() << QString("[%1] mCachedPartSize = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mCachedPartSize); - qDebug() << QString("[%1] mPerPrimArgCount %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPhysicalPartSize); - } - - if (physicalPartPtr) - { - aStream->readRawData(mPhysicalPart.data(), mPhysicalPartSize); - if (IsDebug()) - { - qDebug() << QString("[%1] mPhysicalPart = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPhysicalPart); - } - } - if (cachedPartPtr) - { - aStream->readRawData(mCachedPart.data(), mCachedPartSize); - if (IsDebug()) - { - qDebug() << QString("[%1] mCachedPart = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mCachedPart); - } + qDebug() << QString("[%1] %2: %3").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()).arg(mProgram); } } + +quint16 XGfxVertexShaderLoadDef::ProgramSize() const +{ + return mProgramSize; +} + +void XGfxVertexShaderLoadDef::SetProgramSize(quint16 aProgramSize) +{ + mProgramSize = aProgramSize; +} + +quint16 XGfxVertexShaderLoadDef::LoadForRenderer() const +{ + return mLoadForRenderer; +} + +void XGfxVertexShaderLoadDef::SetLoadForRenderer(quint16 aLoadForRenderer) +{ + mLoadForRenderer = aLoadForRenderer; +} + +QByteArray XGfxVertexShaderLoadDef::Program() const +{ + return mProgram; +} + +void XGfxVertexShaderLoadDef::SetProgram(const QByteArray &aProgram) +{ + mProgram = aProgram; +} diff --git a/libs/xassets/xgfxvertexshaderloaddef.h b/libs/xassets/xgfxvertexshaderloaddef.h index ea4954a..e02804b 100644 --- a/libs/xassets/xgfxvertexshaderloaddef.h +++ b/libs/xassets/xgfxvertexshaderloaddef.h @@ -9,16 +9,24 @@ class XGfxVertexShaderLoadDef : public XAsset { public: explicit XGfxVertexShaderLoadDef(); - ~XGfxVertexShaderLoadDef(); + ~XGfxVertexShaderLoadDef() = default; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; + void ParseProgram(XDataStream *aStream); + + quint16 ProgramSize() const; + void SetProgramSize(quint16 aProgramSize); + quint16 LoadForRenderer() const; + void SetLoadForRenderer(quint16 aLoadForRenderer); + QByteArray Program() const; + void SetProgram(const QByteArray &aProgram); + private: - QByteArray mCachedPart; - QByteArray mPhysicalPart; - int mCachedPartSize; - int mPhysicalPartSize; + quint16 mProgramSize; + quint16 mLoadForRenderer; + QByteArray mProgram; }; #endif // XGFXCERTEXSHADERLOADDEF_H diff --git a/libs/xassets/xgfxworld.cpp b/libs/xassets/xgfxworld.cpp index 960382c..f150ab2 100644 --- a/libs/xassets/xgfxworld.cpp +++ b/libs/xassets/xgfxworld.cpp @@ -168,7 +168,7 @@ void XGfxWorld::ParseData(XDataStream *aStream) { mDpvs.ParseData(aStream); mDpvsDyn.ParseData(aStream); - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); mBaseName.ParseData(aStream); if (indicesPtr) { diff --git a/libs/xassets/xitemdef.cpp b/libs/xassets/xitemdef.cpp index 8429ecf..79ea27d 100644 --- a/libs/xassets/xitemdef.cpp +++ b/libs/xassets/xitemdef.cpp @@ -1,9 +1,11 @@ #include "xitemdef.h" +#include "xmenudef.h" + XItemDef::XItemDef() : XAsset() , mWindow() - , mTextRect() + , mTextRect(4) , mType(0) , mDataType(0) , mAlignment(0) @@ -15,26 +17,26 @@ XItemDef::XItemDef() , mTextStyle(0) , mGameMsgWindowIndex(0) , mGameMsgWindowMode(0) - , mtext("") + , mText() , mItemFlags(0) , mParent(new XMenuDef()) - , mMouseEnterText("") - , mMouseExitText("") - , mMouseEnter("") - , mMouseExit("") - , mAction("") - , mOnAccept("") - , mOnFocus("") - , mLeaveFocus("") - , mDvar("") - , mDvarTest("") - , mOnKey(new XItemKeyHandler()) - , mEnableDvar("") + , mMouseEnterText() + , mMouseExitText() + , mMouseEnter() + , mMouseExit() + , mAction() + , mOnAccept() + , mOnFocus() + , mLeaveFocus() + , mDvar() + , mDvarTest() + , mOnKey() + , mEnableDvar() , mDvarFlags(0) - , mFocusSound(new XSoundAliasList()) + , mFocusSound() , mSpecial(0.0f) - , mCursorPos() - , mTypeData() + , mCursorPos(4) + , mTypeData(*this) , mImageTrack(0) , mVisibleExp() , mTextExp() @@ -48,11 +50,6 @@ XItemDef::XItemDef() SetName("Item Definition"); } -XItemDef::~XItemDef() -{ - -} - int XItemDef::GetType() const { return mType; @@ -60,12 +57,266 @@ int XItemDef::GetType() const void XItemDef::Clear() { - + mWindow.Clear(); + mTextRect.clear(); + mType = 0; + mDataType = 0; + mAlignment = 0; + mFontEnum = 0; + mTextAlignMode = 0; + mTextalignx = 0.0f; + mTextaligny = 0.0f; + mTextscale = 0.0f; + mTextStyle = 0; + mGameMsgWindowIndex = 0; + mGameMsgWindowMode = 0; + mText.Clear(); + mItemFlags = 0; + mParent->Clear(); + mMouseEnterText.Clear(); + mMouseExitText.Clear(); + mMouseEnter.Clear(); + mMouseExit.Clear(); + mAction.Clear(); + mOnAccept.Clear(); + mOnFocus.Clear(); + mLeaveFocus.Clear(); + mDvar.Clear(); + mDvarTest.Clear(); + mOnKey.Clear(); + mEnableDvar.Clear(); + mDvarFlags = 0; + mFocusSound.Clear(); + mSpecial = 0.0f; + //mCursorPos; + mTypeData.Clear(); + mImageTrack = 0; + mVisibleExp.Clear(); + mTextExp.Clear(); + mMaterialExp.Clear(); + mRectXExp.Clear(); + mRectYExp.Clear(); + mRectWExp.Clear(); + mRectHExp.Clear(); + mForecolorAExp.Clear(); } void XItemDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + mWindow.SetCommonInfo(GetCommonInfo()); + mWindow.ParseData(aStream); - // TODO: Fill in XItemDef::ParseData + for (int i = 0; i < 1; i++) + { + mTextRect[i].ParseData(aStream); + } + + mType = aStream->ParseInt32(QString("%1 type").arg(GetName())); + mDataType = aStream->ParseInt32(QString("%1 data type").arg(GetName())); + mAlignment = aStream->ParseInt32(QString("%1 alignment").arg(GetName())); + mFontEnum = aStream->ParseInt32(QString("%1 font enum").arg(GetName())); + mTextAlignMode = aStream->ParseInt32(QString("%1 text align mode").arg(GetName())); + mTextalignx = aStream->ParseSingle(QString("%1 text align x").arg(GetName())); + mTextaligny = aStream->ParseSingle(QString("%1 text align y").arg(GetName())); + mTextscale = aStream->ParseSingle(QString("%1 text scale").arg(GetName())); + mTextStyle = aStream->ParseInt32(QString("%1 text style").arg(GetName())); + mGameMsgWindowIndex = aStream->ParseInt32(QString("%1 game msg window index").arg(GetName())); + mGameMsgWindowMode = aStream->ParseInt32(QString("%1 game msg window mode").arg(GetName())); + + mText.ParsePtr(aStream, false); + + mItemFlags = aStream->ParseInt32(QString("%1 type").arg(GetName())); + + mParent->ParsePtr(aStream, false); + + mMouseEnterText.ParsePtr(aStream, false); + mMouseExitText.ParsePtr(aStream, false); + mMouseEnter.ParsePtr(aStream, false); + mMouseExit.ParsePtr(aStream, false); + mAction.ParsePtr(aStream, false); + mOnAccept.ParsePtr(aStream, false); + mOnFocus.ParsePtr(aStream, false); + mLeaveFocus.ParsePtr(aStream, false); + mDvar.ParsePtr(aStream, false); + mDvarTest.ParsePtr(aStream, false); + mOnKey.ParsePtr(aStream, false); + mEnableDvar.ParsePtr(aStream, false); + + mDvarFlags = aStream->ParseInt32(QString("%1 dvar flags").arg(GetName())); + + mFocusSound.ParsePtr(aStream, false); + + mSpecial = aStream->ParseSingle(QString("%1 special").arg(GetName())); + + for (int i = 0; i < 1; i++) + { + mCursorPos[i] = aStream->ParseInt32(QString("%1 cursor pos %2").arg(GetName()).arg(i)); + } + + mTypeData.ParseData(aStream); + + mImageTrack = aStream->ParseInt32(QString("%1 image track").arg(GetName())); + + mVisibleExp.SetCommonInfo(GetCommonInfo()); + mVisibleExp.ParseData(aStream); + + mTextExp.SetCommonInfo(GetCommonInfo()); + mTextExp.ParseData(aStream); + + mMaterialExp.SetCommonInfo(GetCommonInfo()); + mMaterialExp.ParseData(aStream); + + mRectXExp.SetCommonInfo(GetCommonInfo()); + mRectXExp.ParseData(aStream); + + mRectYExp.SetCommonInfo(GetCommonInfo()); + mRectYExp.ParseData(aStream); + + mRectWExp.SetCommonInfo(GetCommonInfo()); + mRectWExp.ParseData(aStream); + + mRectHExp.SetCommonInfo(GetCommonInfo()); + mRectHExp.ParseData(aStream); + + mForecolorAExp.SetCommonInfo(GetCommonInfo()); + mForecolorAExp.ParseData(aStream); + + + mWindow.WindowName().ParseData(aStream); + mWindow.Group().ParseData(aStream); + mWindow.Background().ParseData(aStream); + + mText.ParseDataSafe(aStream); + mMouseEnterText.ParseDataSafe(aStream); + mMouseExitText.ParseDataSafe(aStream); + mMouseEnter.ParseDataSafe(aStream); + mMouseExit.ParseDataSafe(aStream); + mAction.ParseDataSafe(aStream); + mOnAccept.ParseDataSafe(aStream); + mOnFocus.ParseDataSafe(aStream); + mLeaveFocus.ParseDataSafe(aStream); + mDvar.ParseDataSafe(aStream); + mDvarTest.ParseDataSafe(aStream); + + mOnKey.ParseDataSafe(aStream); + + mEnableDvar.ParseDataSafe(aStream); + + mFocusSound.ParseDataSafe(aStream); + + mTypeData.ParseData(aStream); + + if (mVisibleExp.EntriesPtr()) + { + for (int i = 0; i < mVisibleExp.Entries().size(); i++) + { + mVisibleExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mTextExp.EntriesPtr()) + { + for (int i = 0; i < mTextExp.Entries().size(); i++) + { + mTextExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mMaterialExp.EntriesPtr()) + { + for (int i = 0; i < mMaterialExp.Entries().size(); i++) + { + mMaterialExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mRectXExp.EntriesPtr()) + { + for (int i = 0; i < mRectXExp.Entries().size(); i++) + { + mRectXExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mRectYExp.EntriesPtr()) + { + for (int i = 0; i < mRectYExp.Entries().size(); i++) + { + mRectYExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mRectWExp.EntriesPtr()) + { + for (int i = 0; i < mRectWExp.Entries().size(); i++) + { + mRectWExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mRectHExp.EntriesPtr()) + { + for (int i = 0; i < mRectHExp.Entries().size(); i++) + { + mRectHExp.Entries()[i].ParsePtr(aStream, false); + } + } + if (mForecolorAExp.EntriesPtr()) + { + for (int i = 0; i < mForecolorAExp.Entries().size(); i++) + { + mForecolorAExp.Entries()[i].ParsePtr(aStream, false); + } + } + + if (mVisibleExp.EntriesPtr()) + { + for (int i = 0; i < mVisibleExp.Entries().size(); i++) + { + mVisibleExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mTextExp.EntriesPtr()) + { + for (int i = 0; i < mTextExp.Entries().size(); i++) + { + mTextExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mMaterialExp.EntriesPtr()) + { + for (int i = 0; i < mMaterialExp.Entries().size(); i++) + { + mMaterialExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mRectXExp.EntriesPtr()) + { + for (int i = 0; i < mRectXExp.Entries().size(); i++) + { + mRectXExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mRectYExp.EntriesPtr()) + { + for (int i = 0; i < mRectYExp.Entries().size(); i++) + { + mRectYExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mRectWExp.EntriesPtr()) + { + for (int i = 0; i < mRectWExp.Entries().size(); i++) + { + mRectWExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mRectHExp.EntriesPtr()) + { + for (int i = 0; i < mRectHExp.Entries().size(); i++) + { + mRectHExp.Entries()[i].ParseDataSafe(aStream); + } + } + if (mForecolorAExp.EntriesPtr()) + { + for (int i = 0; i < mForecolorAExp.Entries().size(); i++) + { + mForecolorAExp.Entries()[i].ParseDataSafe(aStream); + } + } } diff --git a/libs/xassets/xitemdef.h b/libs/xassets/xitemdef.h index 6486e3d..7ae42d8 100644 --- a/libs/xassets/xitemdef.h +++ b/libs/xassets/xitemdef.h @@ -3,17 +3,17 @@ #include "xasset.h" #include "xitemkeyhandler.h" -#include "xmenudef.h" #include "xsoundaliaslist.h" #include "xstatement.h" #include "xwindowdef.h" #include "xitemdefdata.h" +class XMenuDef; + class XItemDef : public XAsset { public: explicit XItemDef(); - ~XItemDef(); int GetType() const; @@ -23,38 +23,38 @@ public: private: XWindowDef mWindow; QVector mTextRect; - int mType; - int mDataType; - int mAlignment; - int mFontEnum; - int mTextAlignMode; + qint32 mType; + qint32 mDataType; + qint32 mAlignment; + qint32 mFontEnum; + qint32 mTextAlignMode; float mTextalignx; float mTextaligny; float mTextscale; - int mTextStyle; - int mGameMsgWindowIndex; - int mGameMsgWindowMode; - QString mtext; - int mItemFlags; - XMenuDef *mParent; - QString mMouseEnterText; - QString mMouseExitText; - QString mMouseEnter; - QString mMouseExit; - QString mAction; - QString mOnAccept; - QString mOnFocus; - QString mLeaveFocus; - QString mDvar; - QString mDvarTest; - XItemKeyHandler *mOnKey; - QString mEnableDvar; - int mDvarFlags; - XSoundAliasList *mFocusSound; + qint32 mTextStyle; + qint32 mGameMsgWindowIndex; + qint32 mGameMsgWindowMode; + XString mText; + qint32 mItemFlags; + XMenuDef* mParent; + XString mMouseEnterText; + XString mMouseExitText; + XString mMouseEnter; + XString mMouseExit; + XString mAction; + XString mOnAccept; + XString mOnFocus; + XString mLeaveFocus; + XString mDvar; + XString mDvarTest; + XItemKeyHandler mOnKey; + XString mEnableDvar; + qint32 mDvarFlags; + XSoundAliasList mFocusSound; float mSpecial; - int mCursorPos[4]; + QVector mCursorPos; XItemDefData mTypeData; - int mImageTrack; + qint32 mImageTrack; XStatement mVisibleExp; XStatement mTextExp; XStatement mMaterialExp; diff --git a/libs/xassets/xitemdefdata.cpp b/libs/xassets/xitemdefdata.cpp index 56c6566..259f958 100644 --- a/libs/xassets/xitemdefdata.cpp +++ b/libs/xassets/xitemdefdata.cpp @@ -23,11 +23,6 @@ XItemDefData::XItemDefData(XItemDef &aParent) } -XItemDefData::~XItemDefData() -{ - delete mParent; -} - void XItemDefData::Clear() { mListBox.Clear(); diff --git a/libs/xassets/xitemdefdata.h b/libs/xassets/xitemdefdata.h index b1ae70e..b2f2b9f 100644 --- a/libs/xassets/xitemdefdata.h +++ b/libs/xassets/xitemdefdata.h @@ -13,7 +13,7 @@ class XItemDefData : public XAsset public: explicit XItemDefData(); XItemDefData(XItemDef& aParent); - ~XItemDefData(); + ~XItemDefData() = default; void Clear() override; void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xitemkeyhandler.cpp b/libs/xassets/xitemkeyhandler.cpp index 45dbc62..e9fd9f1 100644 --- a/libs/xassets/xitemkeyhandler.cpp +++ b/libs/xassets/xitemkeyhandler.cpp @@ -11,27 +11,26 @@ XItemKeyHandler::XItemKeyHandler() XItemKeyHandler::~XItemKeyHandler() { - + if (mNext) + { + delete mNext; + } } void XItemKeyHandler::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + *aStream >> mKey; + + mAction.ParsePtr(aStream, false); + + qint32 nextPtr = aStream->ParseInt32(QString("%1 next ptr").arg(GetName())); + + mAction.ParseDataSafe(aStream); + + if (nextPtr) { - *aStream >> mKey; - - mAction.ParsePtr(aStream, false); - - qint32 nextPtr; - *aStream >> nextPtr; - - mAction.ParseData(aStream); - - if (nextPtr) - { - mNext = new XItemKeyHandler(); - mNext->ParseData(aStream); - } + mNext = new XItemKeyHandler(); + mNext->ParseData(aStream); } } @@ -39,5 +38,9 @@ void XItemKeyHandler::Clear() { mKey = 0; mAction.Clear(); - mNext = nullptr; + + if (mNext) + { + mNext->Clear(); + } } diff --git a/libs/xassets/xitemkeyhandler.h b/libs/xassets/xitemkeyhandler.h index 9f2245b..cb917ff 100644 --- a/libs/xassets/xitemkeyhandler.h +++ b/libs/xassets/xitemkeyhandler.h @@ -14,7 +14,7 @@ public: void Clear() override; private: - int mKey; + qint32 mKey; XString mAction; XItemKeyHandler *mNext; }; diff --git a/libs/xassets/xlistboxdef.cpp b/libs/xassets/xlistboxdef.cpp index 3d64f77..7ca575f 100644 --- a/libs/xassets/xlistboxdef.cpp +++ b/libs/xassets/xlistboxdef.cpp @@ -16,38 +16,69 @@ XListBoxDef::XListBoxDef() , mUsePaging(false) , mSelectBorder() , mDisableColor() - , mSelectIcon(new XMaterial()) + , mSelectIcon() { SetName("List Box Definition"); } -XListBoxDef::~XListBoxDef() -{ - -} - void XListBoxDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + mMousePos = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName())); + mStartPos = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName())); + mEndPos = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName())); + mDrawPadding = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName())); + mElementWidth = aStream->ParseSingle(QString("%1 has been uploaded").arg(GetName())); + mElementHeight = aStream->ParseSingle(QString("%1 has been uploaded").arg(GetName())); + mElementStyle = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName())); + mNumColumns = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName())); - // TODO: Fill in XListBoxDef::ParseData + for (int i = 0; i < 16; i++) + { + XColumnInfo newCol; + newCol.ParseData(aStream); + mColumnInfo.push_back(newCol); + } + + mDoubleClick.ParsePtr(aStream, false); + + mNotselectable = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName()));; + mNoScrollBars = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName()));; + mUsePaging = aStream->ParseInt32(QString("%1 has been uploaded").arg(GetName()));; + + float r = aStream->ParseSingle(QString("%1 select border red").arg(GetName())); + float g = aStream->ParseSingle(QString("%1 select border green").arg(GetName())); + float b = aStream->ParseSingle(QString("%1 select border blue").arg(GetName())); + float a = aStream->ParseSingle(QString("%1 select border alpha").arg(GetName())); + mSelectBorder = QColor(r, g, b, a); + + r = aStream->ParseSingle(QString("%1 disable red").arg(GetName())); + g = aStream->ParseSingle(QString("%1 disable green").arg(GetName())); + b = aStream->ParseSingle(QString("%1 disable blue").arg(GetName())); + a = aStream->ParseSingle(QString("%1 disable alpha").arg(GetName())); + mDisableColor = QColor(r, g, b, a); + + mSelectIcon.ParsePtr(aStream, false); + + mDoubleClick.ParseDataSafe(aStream); + mSelectIcon.ParseDataSafe(aStream); } void XListBoxDef::Clear() { - mStartPos = QVector(4); - mEndPos = QVector(4); + mMousePos = 0; + mStartPos = 0; + mEndPos = 0; mDrawPadding = 0; - mElementWidth = 0; - mElementHeight = 0; + mElementWidth = 0.0f; + mElementHeight = 0.0f; mElementStyle = 0; mNumColumns = 0; - mColumnInfo = QVector(16); - mDoubleClick = ""; - mNotselectable = false; - mNoScrollBars = false; - mUsePaging = false; - mSelectBorder = QVector(4); - mDisableColor = QVector(4); - delete mSelectIcon; + mColumnInfo.clear(); + mDoubleClick.Clear(); + mNotselectable = 0; + mNoScrollBars = 0; + mUsePaging = 0; + mSelectBorder = QColor(); + mDisableColor = QColor(); + mSelectIcon.Clear(); } diff --git a/libs/xassets/xlistboxdef.h b/libs/xassets/xlistboxdef.h index f07f365..ceb5cbf 100644 --- a/libs/xassets/xlistboxdef.h +++ b/libs/xassets/xlistboxdef.h @@ -1,6 +1,7 @@ #ifndef XLISTBOXDEF_H #define XLISTBOXDEF_H +#include "qcolor.h" #include "xasset.h" #include "xcolumninfo.h" #include "xmaterial.h" @@ -9,27 +10,28 @@ class XListBoxDef : public XAsset { public: explicit XListBoxDef(); - ~XListBoxDef(); + ~XListBoxDef() = default; void ParseData(XDataStream *aStream) override; void Clear() override; private: - QVector mStartPos; - QVector mEndPos; - int mDrawPadding; + qint32 mMousePos; + qint32 mStartPos; + qint32 mEndPos; + qint32 mDrawPadding; float mElementWidth; float mElementHeight; - int mElementStyle; - int mNumColumns; + qint32 mElementStyle; + qint32 mNumColumns; QVector mColumnInfo; - QString mDoubleClick; - int mNotselectable; - int mNoScrollBars; - int mUsePaging; - QVector mSelectBorder; - QVector mDisableColor; - XMaterial *mSelectIcon; + XString mDoubleClick; + qint32 mNotselectable; + qint32 mNoScrollBars; + qint32 mUsePaging; + QColor mSelectBorder; + QColor mDisableColor; + XMaterial mSelectIcon; }; #endif // XLISTBOXDEF_H diff --git a/libs/xassets/xlocalizeentry.cpp b/libs/xassets/xlocalizeentry.cpp index b17578d..08d5fd5 100644 --- a/libs/xassets/xlocalizeentry.cpp +++ b/libs/xassets/xlocalizeentry.cpp @@ -20,7 +20,7 @@ XString* XLocalizeEntry::GetValue() const return mValue; } -XString* XLocalizeEntry::GetName() const +XString* XLocalizeEntry::LocalizeEntryName() const { return mName; } @@ -40,6 +40,7 @@ void XLocalizeEntry::ParseData(XDataStream *aStream) mValue->ParseData(aStream); mName->ParseData(aStream); + SetDisplayName(mName->GetString()); } } @@ -53,12 +54,12 @@ void XLocalizeEntry::SetValue(QString aValue) mValue->SetString(aValue); } -void XLocalizeEntry::SetName(XString* aName) +void XLocalizeEntry::SetLocalizeEntryName(XString* aName) { mName = aName; } -void XLocalizeEntry::SetName(QString aName) +void XLocalizeEntry::SetLocalizeEntryName(QString aName) { mName->SetString(aName); } diff --git a/libs/xassets/xlocalizeentry.h b/libs/xassets/xlocalizeentry.h index 1fdee10..5667bb5 100644 --- a/libs/xassets/xlocalizeentry.h +++ b/libs/xassets/xlocalizeentry.h @@ -15,9 +15,9 @@ public: void SetValue(QString aValue); XString* GetValue() const; - void SetName(XString* aName); - void SetName(QString aName); - XString* GetName() const; + void SetLocalizeEntryName(XString* aName); + void SetLocalizeEntryName(QString aName); + XString* LocalizeEntryName() const; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xmapents.cpp b/libs/xassets/xmapents.cpp index fffe95f..858d40f 100644 --- a/libs/xassets/xmapents.cpp +++ b/libs/xassets/xmapents.cpp @@ -29,7 +29,7 @@ void XMapEnts::ParseData(XDataStream *aStream) *aStream >> mNumEntityChars; - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); mEntityString.SetContentLength(mNumEntityChars); mEntityString.ParseData(aStream); diff --git a/libs/xassets/xmaterial.cpp b/libs/xassets/xmaterial.cpp index 983e01f..2313921 100644 --- a/libs/xassets/xmaterial.cpp +++ b/libs/xassets/xmaterial.cpp @@ -3,7 +3,7 @@ XMaterial::XMaterial() : XAsset() , mInfo() - , mStateBitsEntry(26) + , mStateBitsEntry(34) , mTextureCount(0) , mConstantCount(0) , mStateBitsCount(0) @@ -18,62 +18,51 @@ XMaterial::XMaterial() SetName("Material"); } -XMaterial::~XMaterial() -{ - -} - void XMaterial::ParseData(XDataStream *aStream) { mInfo.ParseData(aStream); + AddSubAsset(&mInfo); - for (int i = 0; i < 26; i++) + for (int i = 0; i < 34; i++) { - *aStream >> mStateBitsEntry[i]; - if (IsDebug()) - { - qDebug() << QString("[%1] mStateBitsEntry[%2] = %3").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(i).arg(mStateBitsEntry[i]); - } + mStateBitsEntry[i] = aStream->ParseUInt8(QString("%1 state bits entry %2").arg(GetName()).arg(i + 1)); } - - *aStream >> mTextureCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mTextureCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTextureCount); - } - *aStream >> mConstantCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mConstantCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mConstantCount); - } - *aStream >> mStateBitsCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mStateBitsCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mStateBitsCount); - } - *aStream >> mStateFlags; - if (IsDebug()) - { - qDebug() << QString("[%1] mStateFlags = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mStateFlags); - } - *aStream >> mCameraRegion; - if (IsDebug()) - { - qDebug() << QString("[%1] mCameraRegion = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mCameraRegion); - } + mTextureCount = aStream->ParseUInt8(QString("%1 texture count").arg(GetName())); + mConstantCount = aStream->ParseUInt8(QString("%1 constant count").arg(GetName())); + mStateBitsCount = aStream->ParseUInt8(QString("%1 state bits count").arg(GetName())); + mStateFlags = aStream->ParseUInt8(QString("%1 state flags").arg(GetName())); + mCameraRegion = aStream->ParseUInt8(QString("%1 camera region").arg(GetName())); aStream->skipRawData(1); + mTechniqueSet.SetCommonInfo(GetCommonInfo()); mTechniqueSet.ParsePtr(aStream, false); + mTextureTable.SetCommonInfo(GetCommonInfo()); mTextureTable.ParsePtr(aStream, false); + mConstantTable.SetCommonInfo(GetCommonInfo()); mConstantTable.ParsePtr(aStream, false); + mStateBitsTable.SetCommonInfo(GetCommonInfo()); mStateBitsTable.ParsePtr(aStream, false); - mTechniqueSet.ParseData(aStream); - mTextureTable.ParseData(aStream); - mConstantTable.ParseData(aStream); - mStateBitsTable.ParseData(aStream); + XString materialName = mInfo.MaterialName(); + materialName.SetRemoveString(","); + materialName.ParseDataSafe(aStream); + AddSubAsset(&materialName); + SetDisplayName(materialName.GetString()); + mInfo.SetMaterialName(materialName); + + mTechniqueSet.ParseDataSafe(aStream); + AddSubAsset(&mTechniqueSet); + + mTextureTable.ParseDataSafe(aStream); + AddSubAsset(&mTextureTable); + + mConstantTable.ParseDataSafe(aStream); + AddSubAsset(&mConstantTable); + + mStateBitsTable.ParseDataSafe(aStream); + AddSubAsset(&mStateBitsTable); } void XMaterial::Clear() @@ -90,3 +79,113 @@ void XMaterial::Clear() mConstantTable = XMaterialConstantDef(); mStateBitsTable = XGfxStateBits(); } + +XMaterialInfo XMaterial::Info() const +{ + return mInfo; +} + +void XMaterial::SetInfo(const XMaterialInfo &aInfo) +{ + mInfo = aInfo; +} + +QVector XMaterial::StateBitsEntry() const +{ + return mStateBitsEntry; +} + +void XMaterial::SetStateBitsEntry(const QVector &aStateBitsEntry) +{ + mStateBitsEntry = aStateBitsEntry; +} + +quint8 XMaterial::TextureCount() const +{ + return mTextureCount; +} + +void XMaterial::SetTextureCount(quint8 aTextureCount) +{ + mTextureCount = aTextureCount; +} + +quint8 XMaterial::ConstantCount() const +{ + return mConstantCount; +} + +void XMaterial::SetConstantCount(quint8 aConstantCount) +{ + mConstantCount = aConstantCount; +} + +quint8 XMaterial::StateBitsCount() const +{ + return mStateBitsCount; +} + +void XMaterial::SetStateBitsCount(quint8 aStateBitsCount) +{ + mStateBitsCount = aStateBitsCount; +} + +quint8 XMaterial::StateFlags() const +{ + return mStateFlags; +} + +void XMaterial::SetStateFlags(quint8 aStateFlags) +{ + mStateFlags = aStateFlags; +} + +quint8 XMaterial::CameraRegion() const +{ + return mCameraRegion; +} + +void XMaterial::SetCameraRegion(quint8 aCameraRegion) +{ + mCameraRegion = aCameraRegion; +} + +XMaterialTechniqueSet XMaterial::TechniqueSet() const +{ + return mTechniqueSet; +} + +void XMaterial::SetTechniqueSet(const XMaterialTechniqueSet &aTechniqueSet) +{ + mTechniqueSet = aTechniqueSet; +} + +XMaterialTextureDef XMaterial::TextureTable() const +{ + return mTextureTable; +} + +void XMaterial::SetTextureTable(const XMaterialTextureDef &aTextureTable) +{ + mTextureTable = aTextureTable; +} + +XMaterialConstantDef XMaterial::ConstantTable() const +{ + return mConstantTable; +} + +void XMaterial::SetConstantTable(const XMaterialConstantDef &aConstantTable) +{ + mConstantTable = aConstantTable; +} + +XGfxStateBits XMaterial::StateBitsTable() const +{ + return mStateBitsTable; +} + +void XMaterial::SetStateBitsTable(const XGfxStateBits &aStateBitsTable) +{ + mStateBitsTable = aStateBitsTable; +} diff --git a/libs/xassets/xmaterial.h b/libs/xassets/xmaterial.h index 807f8fa..4a1a600 100644 --- a/libs/xassets/xmaterial.h +++ b/libs/xassets/xmaterial.h @@ -11,11 +11,37 @@ class XMaterial : public XAsset { public: explicit XMaterial(); - ~XMaterial() override; + ~XMaterial() = default; virtual void ParseData(XDataStream* aStream) override; virtual void Clear() override; + XMaterialInfo Info() const; + void SetInfo(const XMaterialInfo &aInfo); + QVector StateBitsEntry() const; + void SetStateBitsEntry(const QVector &aStateBitsEntry); + quint8 TextureCount() const; + void SetTextureCount(quint8 aTextureCount); + quint8 ConstantCount() const; + void SetConstantCount(quint8 aConstantCount); + quint8 StateBitsCount() const; + void SetStateBitsCount(quint8 aStateBitsCount); + quint8 StateFlags() const; + void SetStateFlags(quint8 aStateFlags); + quint8 CameraRegion() const; + void SetCameraRegion(quint8 aCameraRegion); + XMaterialTechniqueSet TechniqueSet() const; + void SetTechniqueSet(const XMaterialTechniqueSet &aTechniqueSet); + XMaterialTextureDef TextureTable() const; + void SetTextureTable(const XMaterialTextureDef &aTextureTable); + XMaterialConstantDef ConstantTable() const; + void SetConstantTable(const XMaterialConstantDef &aConstantTable); + XGfxStateBits StateBitsTable() const; + void SetStateBitsTable(const XGfxStateBits &aStateBitsTable); + + XString MaterialName() const; + void SetMaterialName(const XString &aName); + private: XMaterialInfo mInfo; QVector mStateBitsEntry; diff --git a/libs/xassets/xmaterialargumentdef.cpp b/libs/xassets/xmaterialargumentdef.cpp index aa19dde..d59ca6f 100644 --- a/libs/xassets/xmaterialargumentdef.cpp +++ b/libs/xassets/xmaterialargumentdef.cpp @@ -17,11 +17,6 @@ XMaterialArgumentDef::XMaterialArgumentDef(XMaterialShaderArgument &aParent) SetName("Material Argument Definition"); } -XMaterialArgumentDef::~XMaterialArgumentDef() -{ - -} - void XMaterialArgumentDef::Clear() { @@ -36,7 +31,7 @@ void XMaterialArgumentDef::ParseData(XDataStream *aStream) *aStream >> mCodeSampler; - if (mParent->GetType() == 1 || mParent->GetType() == 7) + if (mParent->GetArgType() == 1 || mParent->GetArgType() == 7) { if (mCodeSampler == -1) { diff --git a/libs/xassets/xmaterialargumentdef.h b/libs/xassets/xmaterialargumentdef.h index 5a9ac84..44021da 100644 --- a/libs/xassets/xmaterialargumentdef.h +++ b/libs/xassets/xmaterialargumentdef.h @@ -10,7 +10,7 @@ class XMaterialArgumentDef : public XAsset public: explicit XMaterialArgumentDef(); XMaterialArgumentDef(XMaterialShaderArgument &aParent); - ~XMaterialArgumentDef(); + ~XMaterialArgumentDef() = default; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xmaterialconstantdef.cpp b/libs/xassets/xmaterialconstantdef.cpp index 29cd794..ef4d75e 100644 --- a/libs/xassets/xmaterialconstantdef.cpp +++ b/libs/xassets/xmaterialconstantdef.cpp @@ -4,7 +4,7 @@ XMaterialConstantDef::XMaterialConstantDef() : XAsset() , mNameHash(0) , mName() - , mLiteral() + , mLiteral(4) { SetName("Material Constant Definition"); } @@ -25,11 +25,10 @@ void XMaterialConstantDef::ParseData(XDataStream *aStream) mName.SetString(QString::fromUtf8(rawName)); - *aStream - >> mLiteral[0] - >> mLiteral[1] - >> mLiteral[2] - >> mLiteral[3]; + mLiteral[0] = aStream->ParseUInt32(QString("%1 literal 1").arg(GetName())); + mLiteral[1] = aStream->ParseUInt32(QString("%1 literal 2").arg(GetName())); + mLiteral[2] = aStream->ParseUInt32(QString("%1 literal 3").arg(GetName())); + mLiteral[3] = aStream->ParseUInt32(QString("%1 literal 4").arg(GetName())); } } diff --git a/libs/xassets/xmaterialinfo.cpp b/libs/xassets/xmaterialinfo.cpp index 72e8d40..0f64b86 100644 --- a/libs/xassets/xmaterialinfo.cpp +++ b/libs/xassets/xmaterialinfo.cpp @@ -2,65 +2,181 @@ XMaterialInfo::XMaterialInfo() : XAsset() - , mName() + , mMaterialName() , mGameFlags(0) , mSortKey(0) , mTextureAtlasRowCount(0) , mTextureAtlasColumnCount(0) , mDrawSurf() , mSurfaceTypeBits(0) + , mHashIndex(0) + , mStateBitsEntry() + , mTextureCount(0) + , mConstantCount(0) + , mStateBitsCount(0) + , mStateFlags(0) + , mCameraRegion(0) { SetName("Material Info"); } -XMaterialInfo::~XMaterialInfo() -{ - -} - void XMaterialInfo::ParseData(XDataStream *aStream) { - mName.ParsePtr(aStream, false); + mMaterialName.ParsePtr(aStream, false); - - *aStream >> mGameFlags; - if (IsDebug()) - { - qDebug() << QString("[%1] mGameFlags = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mGameFlags); - } - - *aStream >> mSortKey; - if (IsDebug()) - { - qDebug() << QString("[%1] mSortKey = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mSortKey); - } - - *aStream >> mTextureAtlasRowCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mTextureAtlasRowCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTextureAtlasRowCount); - } - - *aStream >> mTextureAtlasColumnCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mTextureAtlasColumnCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTextureAtlasColumnCount); - } + mGameFlags = aStream->ParseUInt8(QString("%1 game flags").arg(GetName())); + mSortKey = aStream->ParseUInt8(QString("%1 sort key").arg(GetName())); + mTextureAtlasRowCount = aStream->ParseUInt8(QString("%1 texture atlas row count").arg(GetName())); + mTextureAtlasColumnCount = aStream->ParseUInt8(QString("%1 texture atlas column count").arg(GetName())); mDrawSurf.ParseData(aStream); - *aStream >> mSurfaceTypeBits; - if (IsDebug()) - { - qDebug() << QString("[%1] mSurfaceTypeBits = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mSurfaceTypeBits); - } - - aStream->skipRawData(4); - - mName.ParseData(aStream); + mSurfaceTypeBits = aStream->ParseUInt32(QString("%1 surface type bits").arg(GetName())); + mHashIndex = aStream->ParseUInt16(QString("%1 hash index").arg(GetName())); + aStream->skipRawData(2); } void XMaterialInfo::Clear() { } + +quint8 XMaterialInfo::GameFlags() const +{ + return mGameFlags; +} + +void XMaterialInfo::SetGameFlags(quint8 aGameFlags) +{ + mGameFlags = aGameFlags; +} + +quint8 XMaterialInfo::SortKey() const +{ + return mSortKey; +} + +void XMaterialInfo::SetSortKey(quint8 aSortKey) +{ + mSortKey = aSortKey; +} + +quint8 XMaterialInfo::TextureAtlasRowCount() const +{ + return mTextureAtlasRowCount; +} + +void XMaterialInfo::SetTextureAtlasRowCount(quint8 aTextureAtlasRowCount) +{ + mTextureAtlasRowCount = aTextureAtlasRowCount; +} + +quint8 XMaterialInfo::TextureAtlasColumnCount() const +{ + return mTextureAtlasColumnCount; +} + +void XMaterialInfo::SetTextureAtlasColumnCount(quint8 aTextureAtlasColumnCount) +{ + mTextureAtlasColumnCount = aTextureAtlasColumnCount; +} + +XGfxDrawSurf XMaterialInfo::DrawSurf() const +{ + return mDrawSurf; +} + +void XMaterialInfo::SetDrawSurf(const XGfxDrawSurf &aDrawSurf) +{ + mDrawSurf = aDrawSurf; +} + +quint32 XMaterialInfo::SurfaceTypeBits() const +{ + return mSurfaceTypeBits; +} + +void XMaterialInfo::SetSurfaceTypeBits(quint32 aSurfaceTypeBits) +{ + mSurfaceTypeBits = aSurfaceTypeBits; +} + +XString XMaterialInfo::MaterialName() const +{ + return mMaterialName; +} + +void XMaterialInfo::SetMaterialName(const XString &aMaterialName) +{ + mMaterialName = aMaterialName; +} + +quint32 XMaterialInfo::HashIndex() const +{ + return mHashIndex; +} + +void XMaterialInfo::SetHashIndex(quint32 aHashIndex) +{ + mHashIndex = aHashIndex; +} + +QByteArray XMaterialInfo::StateBitsEntry() const +{ + return mStateBitsEntry; +} + +void XMaterialInfo::SetStateBitsEntry(const QByteArray &aStateBitsEntry) +{ + mStateBitsEntry = aStateBitsEntry; +} + +quint8 XMaterialInfo::TextureCount() const +{ + return mTextureCount; +} + +void XMaterialInfo::SetTextureCount(quint8 aTextureCount) +{ + mTextureCount = aTextureCount; +} + +quint8 XMaterialInfo::ConstantCount() const +{ + return mConstantCount; +} + +void XMaterialInfo::SetConstantCount(quint8 aConstantCount) +{ + mConstantCount = aConstantCount; +} + +quint8 XMaterialInfo::StateBitsCount() const +{ + return mStateBitsCount; +} + +void XMaterialInfo::SetStateBitsCount(quint8 aStateBitsCount) +{ + mStateBitsCount = aStateBitsCount; +} + +quint8 XMaterialInfo::StateFlags() const +{ + return mStateFlags; +} + +void XMaterialInfo::SetStateFlags(quint8 aStateFlags) +{ + mStateFlags = aStateFlags; +} + +quint8 XMaterialInfo::CameraRegion() const +{ + return mCameraRegion; +} + +void XMaterialInfo::SetCameraRegion(quint8 aCameraRegion) +{ + mCameraRegion = aCameraRegion; +} diff --git a/libs/xassets/xmaterialinfo.h b/libs/xassets/xmaterialinfo.h index 0608ba9..f1ad518 100644 --- a/libs/xassets/xmaterialinfo.h +++ b/libs/xassets/xmaterialinfo.h @@ -9,19 +9,57 @@ class XMaterialInfo : public XAsset { public: explicit XMaterialInfo(); - ~XMaterialInfo(); + ~XMaterialInfo() = default; void ParseData(XDataStream *aStream) override; void Clear() override; + quint8 GameFlags() const; + void SetGameFlags(quint8 aGameFlags); + quint8 SortKey() const; + void SetSortKey(quint8 aSortKey); + quint8 TextureAtlasRowCount() const; + void SetTextureAtlasRowCount(quint8 aTextureAtlasRowCount); + quint8 TextureAtlasColumnCount() const; + void SetTextureAtlasColumnCount(quint8 aTextureAtlasColumnCount); + XGfxDrawSurf DrawSurf() const; + void SetDrawSurf(const XGfxDrawSurf &aDrawSurf); + quint32 SurfaceTypeBits() const; + void SetSurfaceTypeBits(quint32 aSurfaceTypeBits); + + XString MaterialName() const; + void SetMaterialName(const XString &aMaterialName); + quint32 HashIndex() const; + void SetHashIndex(quint32 aHashIndex); + QByteArray StateBitsEntry() const; + void SetStateBitsEntry(const QByteArray &aStateBitsEntry); + quint8 TextureCount() const; + void SetTextureCount(quint8 aTextureCount); + quint8 ConstantCount() const; + void SetConstantCount(quint8 aConstantCount); + quint8 StateBitsCount() const; + void SetStateBitsCount(quint8 aStateBitsCount); + quint8 StateFlags() const; + void SetStateFlags(quint8 aStateFlags); + quint8 CameraRegion() const; + void SetCameraRegion(quint8 aCameraRegion); + private: - XString mName; + XString mMaterialName; quint8 mGameFlags; quint8 mSortKey; quint8 mTextureAtlasRowCount; quint8 mTextureAtlasColumnCount; XGfxDrawSurf mDrawSurf; quint32 mSurfaceTypeBits; + quint32 mHashIndex; + QByteArray mStateBitsEntry; + quint8 mTextureCount; + quint8 mConstantCount; + quint8 mStateBitsCount; + quint8 mStateFlags; + quint8 mCameraRegion; + }; #endif // XMATERIALINFO_H diff --git a/libs/xassets/xmaterialpass.cpp b/libs/xassets/xmaterialpass.cpp index 87044b4..39c6fcc 100644 --- a/libs/xassets/xmaterialpass.cpp +++ b/libs/xassets/xmaterialpass.cpp @@ -16,7 +16,7 @@ XMaterialPass::XMaterialPass() , mPerObjArgCount(0) , mStableArgCount(0) , mCustomSamplerFlags(0) - , mPrecompiledIndex(0) + //, mPrecompiledIndex(0) , mArgs() { SetName("Material Pass"); @@ -35,43 +35,48 @@ void XMaterialPass::ParseData(XDataStream *aStream) } mVertexDecl.ParsePtr(aStream, false); - for (int i = 0; i < 15; i++) + if (GetCommonInfo()->GetGame() != GAME_COD4) { - mVertexShaderArray[i].ParsePtr(aStream, false); + for (int i = 0; i < 15; i++) + { + mVertexShaderArray[i].ParsePtr(aStream, false); + } } mVertexShader.ParsePtr(aStream, false); mPixelShader.ParsePtr(aStream, false); - qint32 argsPtr; - *aStream - >> mPerPrimArgCount - >> mPerObjArgCount - >> mStableArgCount - >> mCustomSamplerFlags - >> mPrecompiledIndex; - - aStream->skipRawData(3); - - *aStream >> argsPtr; - - if (IsDebug()) + if (GetCommonInfo()->GetGame() == GAME_COD4) { - qDebug() << QString("[%1] mPerPrimArgCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPerPrimArgCount); - qDebug() << QString("[%1] mPerObjArgCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPerObjArgCount); - qDebug() << QString("[%1] mStableArgCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mStableArgCount); - qDebug() << QString("[%1] mCustomSamplerFlags = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mCustomSamplerFlags); - qDebug() << QString("[%1] mPrecompiledIndex = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPrecompiledIndex); - qDebug() << QString("[%1] argsPtr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(argsPtr); + mPerPrimArgCount = aStream->ParseUInt8(QString("%1 per primary arg count").arg(GetName())); + mPerObjArgCount = aStream->ParseUInt8(QString("%1 per object arg count").arg(GetName())); + mStableArgCount = aStream->ParseUInt8(QString("%1 stable arg count").arg(GetName())); + mCustomSamplerFlags = aStream->ParseUInt8(QString("%1 custom sampler flags").arg(GetName())); + } + else + { + mPerPrimArgCount = aStream->ParseUInt32(QString("%1 per primary arg count").arg(GetName())); + mPerObjArgCount = aStream->ParseUInt32(QString("%1 per object arg count").arg(GetName())); + mStableArgCount = aStream->ParseUInt32(QString("%1 stable arg count").arg(GetName())); + mCustomSamplerFlags = aStream->ParseUInt32(QString("%1 custom sampler flags").arg(GetName())); + mPrecompiledIndex = aStream->ParseUInt32(QString("%1 precompiled index").arg(GetName())); + + aStream->skipRawData(3); } - mVertexDecl.ParseData(aStream); - for (int i = 0; i < 15; i++) + qint32 argsPtr = aStream->ParseInt32(QString("%1 args ptr").arg(GetName())); + + mVertexDecl.ParseDataSafe(aStream); + + if (GetCommonInfo()->GetGame() != GAME_COD4) { - mVertexShaderArray[i].ParseData(aStream); + for (int i = 0; i < mVertexShaderArray.size(); i++) + { + mVertexShaderArray[i].ParseData(aStream); + } } - mVertexShader.ParseData(aStream); - mPixelShader.ParseData(aStream); + mVertexShader.ParseDataSafe(aStream); + mPixelShader.ParseDataSafe(aStream); if (argsPtr) { diff --git a/libs/xassets/xmaterialpass.h b/libs/xassets/xmaterialpass.h index 0dbf7b1..cfb492d 100644 --- a/libs/xassets/xmaterialpass.h +++ b/libs/xassets/xmaterialpass.h @@ -22,11 +22,11 @@ private: QVector mVertexShaderArray; XMaterialVertexShader mVertexShader; XMaterialPixelShader mPixelShader; - int mPerPrimArgCount; - int mPerObjArgCount; - int mStableArgCount; - int mCustomSamplerFlags; - int mPrecompiledIndex; + quint32 mPerPrimArgCount; + quint32 mPerObjArgCount; + quint32 mStableArgCount; + quint32 mCustomSamplerFlags; + quint32 mPrecompiledIndex; QVector mArgs; }; diff --git a/libs/xassets/xmaterialpixelshader.cpp b/libs/xassets/xmaterialpixelshader.cpp index 4bb5564..99f594d 100644 --- a/libs/xassets/xmaterialpixelshader.cpp +++ b/libs/xassets/xmaterialpixelshader.cpp @@ -2,29 +2,50 @@ XMaterialPixelShader::XMaterialPixelShader() : XAsset() - , mName() - , mShaderProgram() + , mShaderName() + , mProgram() { SetType(ASSET_TYPE_PIXELSHADER); SetName("Material Pixel Shader"); } -XMaterialPixelShader::~XMaterialPixelShader() -{ - -} - void XMaterialPixelShader::Clear() { - mName.Clear(); - mShaderProgram.Clear(); + mShaderName.Clear(); + mProgram.Clear(); } void XMaterialPixelShader::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + if (IsDebug()) { - mName.ParsePtr(aStream); - mShaderProgram.ParseData(aStream); + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } + mShaderName.ParsePtr(aStream, false); + mProgram.ParseData(aStream); + + mShaderName.ParseDataSafe(aStream); + SetDisplayName(mShaderName.GetString()); + + mProgram.LoadDef().ParseProgram(aStream); +} + +XString XMaterialPixelShader::ShaderName() const +{ + return mShaderName; +} + +void XMaterialPixelShader::SetShaderName(const XString &aName) +{ + mShaderName = aName; +} + +XMaterialPixelShaderProgram XMaterialPixelShader::ShaderProgram() const +{ + return mProgram; +} + +void XMaterialPixelShader::SetShaderProgram(const XMaterialPixelShaderProgram &aShaderProgram) +{ + mProgram = aShaderProgram; } diff --git a/libs/xassets/xmaterialpixelshader.h b/libs/xassets/xmaterialpixelshader.h index f01de1d..934493c 100644 --- a/libs/xassets/xmaterialpixelshader.h +++ b/libs/xassets/xmaterialpixelshader.h @@ -9,14 +9,19 @@ class XMaterialPixelShader : public XAsset { public: explicit XMaterialPixelShader(); - ~XMaterialPixelShader(); + ~XMaterialPixelShader() = default; void Clear() override; void ParseData(XDataStream *aStream) override; + XString ShaderName() const; + void SetShaderName(const XString &aName); + XMaterialPixelShaderProgram ShaderProgram() const; + void SetShaderProgram(const XMaterialPixelShaderProgram &aShaderProgram); + private: - XString mName; - XMaterialPixelShaderProgram mShaderProgram; + XString mShaderName; + XMaterialPixelShaderProgram mProgram; }; #endif // XMATERIALPIXERHSHADER_H diff --git a/libs/xassets/xmaterialpixelshaderprogram.cpp b/libs/xassets/xmaterialpixelshaderprogram.cpp index e373024..44eb960 100644 --- a/libs/xassets/xmaterialpixelshaderprogram.cpp +++ b/libs/xassets/xmaterialpixelshaderprogram.cpp @@ -8,11 +8,6 @@ XMaterialPixelShaderProgram::XMaterialPixelShaderProgram() SetName("Material Pixel Shader Program"); } -XMaterialPixelShaderProgram::~XMaterialPixelShaderProgram() -{ - -} - void XMaterialPixelShaderProgram::Clear() { mPixelShader.Clear(); @@ -21,15 +16,25 @@ void XMaterialPixelShaderProgram::Clear() void XMaterialPixelShaderProgram::ParseData(XDataStream *aStream) { - mLoadDef.ParseData(aStream); - mPixelShader.ParseData(aStream); - - if (mLoadDef.GetPhysicalPartSize()) + if (IsDebug()) { - //mPixelShader. + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } - else + + mPixelShader.ParsePtr(aStream, false); + + if (!mPixelShader.GetPtr()) { - //mLoadDef + mLoadDef.ParseData(aStream); } } + +XGfxPixelShaderLoadDef XMaterialPixelShaderProgram::LoadDef() const +{ + return mLoadDef; +} + +void XMaterialPixelShaderProgram::SetLoadDef(const XGfxPixelShaderLoadDef &aLoadDef) +{ + mLoadDef = aLoadDef; +} diff --git a/libs/xassets/xmaterialpixelshaderprogram.h b/libs/xassets/xmaterialpixelshaderprogram.h index b04b5b2..7800b84 100644 --- a/libs/xassets/xmaterialpixelshaderprogram.h +++ b/libs/xassets/xmaterialpixelshaderprogram.h @@ -12,11 +12,14 @@ class XMaterialPixelShaderProgram : public XAsset { public: explicit XMaterialPixelShaderProgram(); - ~XMaterialPixelShaderProgram(); + ~XMaterialPixelShaderProgram() = default; void Clear() override; void ParseData(XDataStream *aStream) override; + XGfxPixelShaderLoadDef LoadDef() const; + void SetLoadDef(const XGfxPixelShaderLoadDef &aLoadDef); + private: XD3DPixelShader mPixelShader; XGfxPixelShaderLoadDef mLoadDef; diff --git a/libs/xassets/xmaterialshaderargument.cpp b/libs/xassets/xmaterialshaderargument.cpp index 3ed1f3f..efce6a9 100644 --- a/libs/xassets/xmaterialshaderargument.cpp +++ b/libs/xassets/xmaterialshaderargument.cpp @@ -18,19 +18,18 @@ void XMaterialShaderArgument::Clear() void XMaterialShaderArgument::ParseData(XDataStream *aStream) { - *aStream - >> mType - >> mDest; + mType = aStream->ParseUInt16(QString("%1 type").arg(GetName())); + mDest = aStream->ParseUInt16(QString("%1 destination").arg(GetName())); mDef.ParseData(aStream); } -quint16 XMaterialShaderArgument::GetType() const +quint16 XMaterialShaderArgument::GetArgType() const { return mType; } -quint16 XMaterialShaderArgument::GetDest() const +quint16 XMaterialShaderArgument::GetArgDest() const { return mDest; } diff --git a/libs/xassets/xmaterialshaderargument.h b/libs/xassets/xmaterialshaderargument.h index 35ba427..f9a331c 100644 --- a/libs/xassets/xmaterialshaderargument.h +++ b/libs/xassets/xmaterialshaderargument.h @@ -12,8 +12,8 @@ public: virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; - quint16 GetType() const; - quint16 GetDest() const; + quint16 GetArgType() const; + quint16 GetArgDest() const; private: quint16 mType; diff --git a/libs/xassets/xmaterialstreamrouting.cpp b/libs/xassets/xmaterialstreamrouting.cpp index 850f622..3baf72d 100644 --- a/libs/xassets/xmaterialstreamrouting.cpp +++ b/libs/xassets/xmaterialstreamrouting.cpp @@ -6,19 +6,14 @@ XMaterialStreamRouting::XMaterialStreamRouting() SetName("Material Stream Routing"); } -XMaterialStreamRouting::~XMaterialStreamRouting() -{ - -} - void XMaterialStreamRouting::Clear() { - + mSource = 0; + mDest = 0; } void XMaterialStreamRouting::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XMaterialStreamRouting::ParseData + mSource = aStream->ParseUInt8(QString("%1 source").arg(GetName())); + mDest = aStream->ParseUInt8(QString("%1 destination").arg(GetName())); } diff --git a/libs/xassets/xmaterialstreamrouting.h b/libs/xassets/xmaterialstreamrouting.h index ebb8664..6b633b0 100644 --- a/libs/xassets/xmaterialstreamrouting.h +++ b/libs/xassets/xmaterialstreamrouting.h @@ -7,7 +7,7 @@ class XMaterialStreamRouting : public XAsset { public: explicit XMaterialStreamRouting(); - ~XMaterialStreamRouting(); + ~XMaterialStreamRouting() = default; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xmaterialtechnique.cpp b/libs/xassets/xmaterialtechnique.cpp index 2e708e8..d919d80 100644 --- a/libs/xassets/xmaterialtechnique.cpp +++ b/libs/xassets/xmaterialtechnique.cpp @@ -2,7 +2,7 @@ XMaterialTechnique::XMaterialTechnique() : XAsset() - , mName() + , mTechniqueName() , mFlags(0) , mPassCount(0) , mPassArray() @@ -10,46 +10,72 @@ XMaterialTechnique::XMaterialTechnique() SetName("Material Technique"); } -XMaterialTechnique::~XMaterialTechnique() -{ - -} - void XMaterialTechnique::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + if (IsDebug()) { - if (IsDebug()) - { - qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); - } - mName.ParsePtr(aStream, false); - - *aStream - >> mFlags - >> mPassCount; - - if (IsDebug()) - { - qDebug() << QString("[%1] mFlags = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mFlags); - qDebug() << QString("[%1] mPassCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPassCount); - } - - mPassArray = QVector(mPassCount); - - for (int i = 0; i < mPassCount; i++) - { - mPassArray[i].ParseData(aStream); - } - - mName.ParseData(aStream); + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } + mTechniqueName.ParsePtr(aStream, false); + + mFlags = aStream->ParseUInt16(QString("%1 flags").arg(GetName())); + mPassCount = aStream->ParseUInt16(QString("%1 pass count").arg(GetName())); + + mPassArray = QVector(mPassCount); + + for (int i = 0; i < mPassCount; i++) + { + mPassArray[i].SetCommonInfo(GetCommonInfo()); + mPassArray[i].ParseData(aStream); + } + + mTechniqueName.ParseDataSafe(aStream); } void XMaterialTechnique::Clear() { - mName.Clear(); + mTechniqueName.Clear(); mFlags = 0; mPassCount = 0; mPassArray.clear(); } + +XString XMaterialTechnique::TechniqueName() const +{ + return mTechniqueName; +} + +void XMaterialTechnique::SetTechniqueName(const XString &aName) +{ + mTechniqueName = aName; +} + +quint16 XMaterialTechnique::Flags() const +{ + return mFlags; +} + +void XMaterialTechnique::SetFlags(quint16 aFlags) +{ + mFlags = aFlags; +} + +quint16 XMaterialTechnique::PassCount() const +{ + return mPassCount; +} + +void XMaterialTechnique::SetPassCount(quint16 aPassCount) +{ + mPassCount = aPassCount; +} + +QVector XMaterialTechnique::PassArray() const +{ + return mPassArray; +} + +void XMaterialTechnique::SetPassArray(const QVector &aPassArray) +{ + mPassArray = aPassArray; +} diff --git a/libs/xassets/xmaterialtechnique.h b/libs/xassets/xmaterialtechnique.h index 060bb4d..a1f6b5f 100644 --- a/libs/xassets/xmaterialtechnique.h +++ b/libs/xassets/xmaterialtechnique.h @@ -11,13 +11,22 @@ class XMaterialTechnique : public XAsset { public: explicit XMaterialTechnique(); - ~XMaterialTechnique(); + ~XMaterialTechnique() = default; virtual void ParseData(XDataStream* aStream) override; virtual void Clear() override; + XString TechniqueName() const; + void SetTechniqueName(const XString &aName); + quint16 Flags() const; + void SetFlags(quint16 aFlags); + quint16 PassCount() const; + void SetPassCount(quint16 aPassCount); + QVector PassArray() const; + void SetPassArray(const QVector &aPassArray); + private: - XString mName; + XString mTechniqueName; quint16 mFlags; quint16 mPassCount; QVector mPassArray; diff --git a/libs/xassets/xmaterialtechniqueset.cpp b/libs/xassets/xmaterialtechniqueset.cpp index fbb5cd4..d07a2bd 100644 --- a/libs/xassets/xmaterialtechniqueset.cpp +++ b/libs/xassets/xmaterialtechniqueset.cpp @@ -2,10 +2,9 @@ XMaterialTechniqueSet::XMaterialTechniqueSet() : XAsset() - , mName() + , mTechniqueSetName() , mWorldVertFormat(0) - , mRemappedTechniqueSet() - , mTechniques(26) + , mTechniques() { SetType(ASSET_TYPE_TECHNIQUE_SET); SetName("Material Technique Set"); @@ -13,60 +12,153 @@ XMaterialTechniqueSet::XMaterialTechniqueSet() XMaterialTechniqueSet::~XMaterialTechniqueSet() { - + } void XMaterialTechniqueSet::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + if (IsDebug()) + { + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); + } + mTechniqueSetName.ParsePtr(aStream, false); + + mWorldVertFormat = aStream->ParseUInt8(QString("%1 world vertex format").arg(GetName())); + mHasBeenUploaded = aStream->ParseUInt8(QString("%1 has been uploaded").arg(GetName())); + + aStream->skipRawData(2 + 4); + + if (IsDebug()) + { + qDebug() << QString("Parsing techniques."); + } + + for (int i = 0; i < GetMaxTechniqueCount(); i++) + { + XMaterialTechnique newTechnique; + newTechnique.SetCommonInfo(GetCommonInfo()); + newTechnique.ParsePtr(aStream, false); + mTechniques.push_back(newTechnique); + + if (IsDebug()) + { + qDebug() << QString("[%1] material technique ptr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(newTechnique.GetPtr()); + } + } + + mTechniqueSetName.SetRemoveString(","); + mTechniqueSetName.ParseDataSafe(aStream); + SetDisplayName(mTechniqueSetName.GetString()); + AddSubAsset(&mTechniqueSetName); + + if (IsDebug()) + { + qDebug() << QString("[%1] technique set name = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTechniqueSetName.GetString()); + } + + for (int i = 0; i < mTechniques.size(); i++) { if (IsDebug()) { - qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); - } - mName.ParsePtr(aStream, false); - - *aStream >> mWorldVertFormat; - if (IsDebug()) - { - qDebug() << QString("[%1] mWorldVertFormat = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mWorldVertFormat); - } - - aStream->skipRawData(3); - - qint32 remappedPtr; - *aStream >> remappedPtr; - if (IsDebug()) - { - qDebug() << QString("[%1] remappedPtr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(remappedPtr); - - qDebug() << QString("Parsing techniques."); - } - for (int i = 0; i < 26; i++) - { - XMaterialTechnique newTechnique; - newTechnique.ParsePtr(aStream, false); - mTechniques.append(newTechnique); - } - - mName.SetRemoveString(","); - mName.ParseData(aStream); - - for (int i = 0; i < 26; i++) - { - mTechniques[i].ParseData(aStream); + qDebug() << QString("Parsing technique: %1").arg(i); } + mTechniques[i].SetCommonInfo(GetCommonInfo()); + mTechniques[i].ParseDataSafe(aStream); + AddSubAsset(&mTechniques[i]); } } void XMaterialTechniqueSet::Clear() { - mName.Clear(); + mTechniqueSetName.Clear(); mWorldVertFormat = 0; - delete mRemappedTechniqueSet; - mRemappedTechniqueSet = new XMaterialTechniqueSet(); - mTechniques.clear(); - mTechniques = QVector(26); + mTechniques = QVector(GetMaxTechniqueCount()); +} + +quint32 XMaterialTechniqueSet::GetMaxTechniqueCount() const +{ + if (GetCommonInfo()->GetPlatform() == PLATFORM_PS3) { + if (GetCommonInfo()->GetGame() == GAME_COD4) { + return 26; + } else if (GetCommonInfo()->GetGame() == GAME_COD5) { + return 51; + } else if (GetCommonInfo()->GetGame() == GAME_COD6) { + return 37; + } else if (GetCommonInfo()->GetGame() == GAME_COD7) { + return 71; + } else if (GetCommonInfo()->GetGame() == GAME_COD8) { + return 41; + } else if (GetCommonInfo()->GetGame() == GAME_COD10) { + return 39; + } + } else if (GetCommonInfo()->GetPlatform() == PLATFORM_XBOX) { + if (GetCommonInfo()->GetGame() == GAME_COD4) { + return 26; + } else if (GetCommonInfo()->GetGame() == GAME_COD5) { + return 51; + } else if (GetCommonInfo()->GetGame() == GAME_COD6) { + return 33; + } else if (GetCommonInfo()->GetGame() == GAME_COD7) { + return 71; + } else if (GetCommonInfo()->GetGame() == GAME_COD8) { + return 37; + } else if (GetCommonInfo()->GetGame() == GAME_COD10) { + return 36; + } + } else if (GetCommonInfo()->GetPlatform() == PLATFORM_PC) { + if (GetCommonInfo()->GetGame() == GAME_COD4) { + return 34; + } else if (GetCommonInfo()->GetGame() == GAME_COD5) { + return 59; + } else if (GetCommonInfo()->GetGame() == GAME_COD6) { + return 48; + } else if (GetCommonInfo()->GetGame() == GAME_COD7) { + return 130; + } else if (GetCommonInfo()->GetGame() == GAME_COD8) { + return 54; + } + } + return 0; +} + +XString XMaterialTechniqueSet::TechniqueSetName() const +{ + return mTechniqueSetName; +} + +void XMaterialTechniqueSet::SetTechniqueSetName(const XString &aName) +{ + mTechniqueSetName = aName; +} + +quint8 XMaterialTechniqueSet::WorldVertFormat() const +{ + return mWorldVertFormat; +} + +void XMaterialTechniqueSet::SetWorldVertFormat(quint8 aWorldVertFormat) +{ + mWorldVertFormat = aWorldVertFormat; +} + +bool XMaterialTechniqueSet::HasBeenUploaded() const +{ + return mHasBeenUploaded; +} + +void XMaterialTechniqueSet::SetHasBeenUploaded(bool aHasBeenUploaded) +{ + mHasBeenUploaded = aHasBeenUploaded; +} + +QVector XMaterialTechniqueSet::Techniques() const +{ + return mTechniques; +} + +void XMaterialTechniqueSet::SetTechniques(const QVector &aTechniques) +{ + mTechniques = aTechniques; } diff --git a/libs/xassets/xmaterialtechniqueset.h b/libs/xassets/xmaterialtechniqueset.h index c98a8dc..843939e 100644 --- a/libs/xassets/xmaterialtechniqueset.h +++ b/libs/xassets/xmaterialtechniqueset.h @@ -14,10 +14,21 @@ public: void ParseData(XDataStream *aStream) override; void Clear() override; + quint32 GetMaxTechniqueCount() const; + + XString TechniqueSetName() const; + void SetTechniqueSetName(const XString &aName); + quint8 WorldVertFormat() const; + void SetWorldVertFormat(quint8 aWorldVertFormat); + bool HasBeenUploaded() const; + void SetHasBeenUploaded(bool aHasBeenUploaded); + QVector Techniques() const; + void SetTechniques(const QVector &aTechniques); + private: - XString mName; + XString mTechniqueSetName; quint8 mWorldVertFormat; - XMaterialTechniqueSet* mRemappedTechniqueSet; + bool mHasBeenUploaded; QVector mTechniques; }; diff --git a/libs/xassets/xmaterialtexturedef.cpp b/libs/xassets/xmaterialtexturedef.cpp index c5fb2f8..cdcb36f 100644 --- a/libs/xassets/xmaterialtexturedef.cpp +++ b/libs/xassets/xmaterialtexturedef.cpp @@ -5,7 +5,7 @@ XMaterialTextureDef::XMaterialTextureDef() , mNameHash(0) , mNameStart(0) , mNameEnd(0) - , mSamplerState(0) + , mSamplerState() , mSemantic(0) , mDefInfo(*this) { @@ -26,23 +26,17 @@ void XMaterialTextureDef::ParseData(XDataStream *aStream) { if (GetPtr() == -1) { + char tempSamplerState; *aStream >> mNameHash >> mNameStart >> mNameEnd - >> mSamplerState + >> tempSamplerState >> mSemantic; + // TODO: Convert tempSamplerState to mSamplerState + mDefInfo.SetCommonInfo(GetCommonInfo()); mDefInfo.ParseData(aStream); - - if (mSemantic == 11) - { - - } - else - { - - } } } @@ -51,7 +45,6 @@ void XMaterialTextureDef::Clear() mNameHash = 0; mNameStart = 0; mNameEnd = 0; - mSamplerState = 0; mSemantic = 0; mDefInfo.Clear(); } diff --git a/libs/xassets/xmaterialtexturedef.h b/libs/xassets/xmaterialtexturedef.h index 63df5e7..fb83885 100644 --- a/libs/xassets/xmaterialtexturedef.h +++ b/libs/xassets/xmaterialtexturedef.h @@ -3,6 +3,7 @@ #include "xasset.h" #include "xmaterialtexturedefinfo.h" +#include "xmaterialtexturedefsamplerstate.h" class XMaterialTextureDef : public XAsset { @@ -19,7 +20,7 @@ private: quint32 mNameHash; char mNameStart; char mNameEnd; - quint8 mSamplerState; + XMaterialTextureDefSamplerState mSamplerState; quint8 mSemantic; XMaterialTextureDefInfo mDefInfo; }; diff --git a/libs/xassets/xmaterialtexturedefinfo.cpp b/libs/xassets/xmaterialtexturedefinfo.cpp index f11f0fb..0116a63 100644 --- a/libs/xassets/xmaterialtexturedefinfo.cpp +++ b/libs/xassets/xmaterialtexturedefinfo.cpp @@ -26,17 +26,14 @@ XMaterialTextureDefInfo::~XMaterialTextureDefInfo() void XMaterialTextureDefInfo::ParseData(XDataStream *aStream) { - mImage.ParsePtr(aStream, false); - - if (aParent->GetSemantic() == 11) { - if (mImage.GetPtr() == -1) - { - mWater.ParseData(aStream); - } + if (aParent && aParent->GetSemantic() == 11) { + mWater.SetCommonInfo(GetCommonInfo()); + mWater.ParsePtr(aStream); } else { - mImage.ParseData(aStream); + mImage.SetCommonInfo(GetCommonInfo()); + mImage.ParsePtr(aStream); } } diff --git a/libs/xassets/xmaterialtexturedefsamplerstate.h b/libs/xassets/xmaterialtexturedefsamplerstate.h new file mode 100644 index 0000000..ef35238 --- /dev/null +++ b/libs/xassets/xmaterialtexturedefsamplerstate.h @@ -0,0 +1,13 @@ +#ifndef XMATERIALTEXTUREDEFSAMPLERSTATE_H +#define XMATERIALTEXTUREDEFSAMPLERSTATE_H + +struct XMaterialTextureDefSamplerState +{ + unsigned char filter : 3; + unsigned char mipMap : 2; + unsigned char clampU : 1; + unsigned char clampV : 1; + unsigned char clampW : 1; +}; + +#endif // XMATERIALTEXTUREDEFSAMPLERSTATE_H diff --git a/libs/xassets/xmaterialvertexdeclaration.cpp b/libs/xassets/xmaterialvertexdeclaration.cpp index 1102e9a..94798e4 100644 --- a/libs/xassets/xmaterialvertexdeclaration.cpp +++ b/libs/xassets/xmaterialvertexdeclaration.cpp @@ -4,6 +4,7 @@ XMaterialVertexDeclaration::XMaterialVertexDeclaration() : XAsset() , mStreamCount(0) , mHasOptionalSource(false) + , mIsLoaded(false) , mRouting() { SetName("Material Vertex Declaration"); @@ -11,26 +12,23 @@ XMaterialVertexDeclaration::XMaterialVertexDeclaration() void XMaterialVertexDeclaration::Clear() { - + mStreamCount = 0; + mHasOptionalSource = false; + mIsLoaded = false; + mRouting.Clear(); } void XMaterialVertexDeclaration::ParseData(XDataStream *aStream) { if (IsDebug()) { - qDebug() << QString("[%1]").arg(aStream->device()->pos(), 10, 10, QChar('0')) << "Parsing data for " << XAssetTypeToString(GetType()); + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } - if (GetPtr() == -1) - { - *aStream - >> mStreamCount - >> mHasOptionalSource; - if (IsDebug()) - { - qDebug() << QString("[%1]").arg(aStream->device()->pos(), 10, 10, QChar('0')) << " mStreamCount = " << mStreamCount; - qDebug() << QString("[%1]").arg(aStream->device()->pos(), 10, 10, QChar('0')) << " mHasOptionalSource = " << mHasOptionalSource; - } + mStreamCount = aStream->ParseUInt8(QString("%1 stream count").arg(GetName())); + mHasOptionalSource = aStream->ParseUInt8(QString("%1 has optional source").arg(GetName())); + mIsLoaded = aStream->ParseUInt8(QString("%1 is loaded").arg(GetName())); - mRouting.ParseData(aStream); - } + aStream->skipRawData(1); + + mRouting.ParseData(aStream); } diff --git a/libs/xassets/xmaterialvertexdeclaration.h b/libs/xassets/xmaterialvertexdeclaration.h index 8eed9d1..7ed9850 100644 --- a/libs/xassets/xmaterialvertexdeclaration.h +++ b/libs/xassets/xmaterialvertexdeclaration.h @@ -13,8 +13,9 @@ public: virtual void ParseData(XDataStream *aStream) override; private: - int mStreamCount; + quint8 mStreamCount; bool mHasOptionalSource; + bool mIsLoaded; XMaterialVertexStreamRouting mRouting; }; diff --git a/libs/xassets/xmaterialvertexshader.cpp b/libs/xassets/xmaterialvertexshader.cpp index a12f1cd..544aada 100644 --- a/libs/xassets/xmaterialvertexshader.cpp +++ b/libs/xassets/xmaterialvertexshader.cpp @@ -3,29 +3,48 @@ XMaterialVertexShader::XMaterialVertexShader() : XAsset() - , mName() + , mShaderName() , mProgram() { + SetType(ASSET_TYPE_VERTEXSHADER); SetName("Material Vertex Shader"); } void XMaterialVertexShader::Clear() { - + mShaderName.Clear(); + mProgram.Clear(); } void XMaterialVertexShader::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + if (IsDebug()) { - if (IsDebug()) - { - qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); - } - mName.ParsePtr(aStream, false); - mProgram.ParseData(aStream); - - mName.ParseData(aStream); - mProgram.ParseData(aStream); + qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } + mShaderName.ParsePtr(aStream, false); + mProgram.ParseData(aStream); + + mShaderName.ParseDataSafe(aStream); + mProgram.LoadDef().ParseProgram(aStream); +} + +XString XMaterialVertexShader::ShaderName() const +{ + return mShaderName; +} + +void XMaterialVertexShader::SetShaderName(const XString &aName) +{ + mShaderName = aName; +} + +XMaterialVertexShaderProgram XMaterialVertexShader::Program() const +{ + return mProgram; +} + +void XMaterialVertexShader::SetProgram(const XMaterialVertexShaderProgram &aProgram) +{ + mProgram = aProgram; } diff --git a/libs/xassets/xmaterialvertexshader.h b/libs/xassets/xmaterialvertexshader.h index 5e1afdc..862187f 100644 --- a/libs/xassets/xmaterialvertexshader.h +++ b/libs/xassets/xmaterialvertexshader.h @@ -11,12 +11,18 @@ class XMaterialVertexShader : public XAsset { public: explicit XMaterialVertexShader(); + ~XMaterialVertexShader() = default; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; + XString ShaderName() const; + void SetShaderName(const XString &aName); + XMaterialVertexShaderProgram Program() const; + void SetProgram(const XMaterialVertexShaderProgram &aProgram); + private: - XString mName; + XString mShaderName; XMaterialVertexShaderProgram mProgram; }; diff --git a/libs/xassets/xmaterialvertexshaderprogram.cpp b/libs/xassets/xmaterialvertexshaderprogram.cpp index 9224bb7..4b3ae49 100644 --- a/libs/xassets/xmaterialvertexshaderprogram.cpp +++ b/libs/xassets/xmaterialvertexshaderprogram.cpp @@ -2,20 +2,15 @@ XMaterialVertexShaderProgram::XMaterialVertexShaderProgram() : XAsset() - //, mVertexShader() + , mVertexShader() , mLoadDef() { SetName("Material Vertex Shader Program"); } -XMaterialVertexShaderProgram::~XMaterialVertexShaderProgram() -{ - -} - void XMaterialVertexShaderProgram::Clear() { - //mVertexShader.Clear(); + mVertexShader.Clear(); mLoadDef.Clear(); } @@ -25,5 +20,21 @@ void XMaterialVertexShaderProgram::ParseData(XDataStream *aStream) { qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } - mLoadDef.ParseData(aStream); + + mVertexShader.ParsePtr(aStream, false); + + if (!mVertexShader.GetPtr()) + { + mLoadDef.ParseData(aStream); + } +} + +XGfxVertexShaderLoadDef XMaterialVertexShaderProgram::LoadDef() const +{ + return mLoadDef; +} + +void XMaterialVertexShaderProgram::SetLoadDef(const XGfxVertexShaderLoadDef &aLoadDef) +{ + mLoadDef = aLoadDef; } diff --git a/libs/xassets/xmaterialvertexshaderprogram.h b/libs/xassets/xmaterialvertexshaderprogram.h index 7bfdb15..7eb3eab 100644 --- a/libs/xassets/xmaterialvertexshaderprogram.h +++ b/libs/xassets/xmaterialvertexshaderprogram.h @@ -2,19 +2,23 @@ #define XMATERIALVERTEXSHADERPROGRAM_H #include "xasset.h" +#include "xd3dvertexshader.h" #include "xgfxvertexshaderloaddef.h" class XMaterialVertexShaderProgram : public XAsset { public: XMaterialVertexShaderProgram(); - ~XMaterialVertexShaderProgram(); + ~XMaterialVertexShaderProgram() = default; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; + XGfxVertexShaderLoadDef LoadDef() const; + void SetLoadDef(const XGfxVertexShaderLoadDef &aLoadDef); + private: - //XD3DVertexShader mVertexShader; + XD3DVertexShader mVertexShader; XGfxVertexShaderLoadDef mLoadDef; }; diff --git a/libs/xassets/xmaterialvertexstreamrouting.cpp b/libs/xassets/xmaterialvertexstreamrouting.cpp index 2a9bc6d..14af964 100644 --- a/libs/xassets/xmaterialvertexstreamrouting.cpp +++ b/libs/xassets/xmaterialvertexstreamrouting.cpp @@ -3,14 +3,15 @@ XMaterialVertexStreamRouting::XMaterialVertexStreamRouting() : XAsset() , mData(16) - , mDecl(15) + , mDecl(16) { SetName("Material Vertex Stream Routing"); } void XMaterialVertexStreamRouting::Clear() { - + mData.clear(); + mDecl.clear(); } void XMaterialVertexStreamRouting::ParseData(XDataStream *aStream) @@ -19,7 +20,11 @@ void XMaterialVertexStreamRouting::ParseData(XDataStream *aStream) { qDebug() << QString("[%1] Parsing data for %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(GetName()); } - for (int i = 0; i < 15; i++) + for (int i = 0; i < 16; i++) + { + mData[i].ParseData(aStream); + } + for (int i = 0; i < 16; i++) { mDecl[i].ParsePtr(aStream, false); } diff --git a/libs/xassets/xmenudef.cpp b/libs/xassets/xmenudef.cpp index 2a4475e..45f36f5 100644 --- a/libs/xassets/xmenudef.cpp +++ b/libs/xassets/xmenudef.cpp @@ -8,7 +8,7 @@ XMenuDef::XMenuDef() , mFullScreen(0) , mItemCount(0) , mFontIndex(0) - , mCursorItem(4) + , mCursorItem() , mFadeCycle(0) , mFadeClamp(0.0f) , mFadeAmount(0.0f) @@ -32,11 +32,6 @@ XMenuDef::XMenuDef() SetName("Menu Definition"); } -XMenuDef::~XMenuDef() -{ - -} - void XMenuDef::Clear() { @@ -48,14 +43,13 @@ void XMenuDef::ParseData(XDataStream *aStream) mFont.ParsePtr(aStream, false); - *aStream - >> mFullScreen - >> mItemCount - >> mFontIndex; + mFullScreen = aStream->ParseInt32(QString("%1 fullscreen").arg(GetName())); + mItemCount = aStream->ParseInt32(QString("%1 item count").arg(GetName())); + mFontIndex = aStream->ParseInt32(QString("%1 font index").arg(GetName())); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 1; i++) { - *aStream >> mCursorItem[i]; + mCursorItem.push_back(aStream->ParseInt32(QString("%1 cursor item %2").arg(GetName()).arg(i))); } mFadeCycle = aStream->ParseInt32(QString("%1 fade cycle").arg(GetName())); @@ -74,45 +68,79 @@ void XMenuDef::ParseData(XDataStream *aStream) mAllowedBinding.ParsePtr(aStream, false); mSoundName.ParsePtr(aStream, false); - *aStream >> mImageTrack; + mImageTrack = aStream->ParseInt32(QString("%1 image track").arg(GetName())); float focusR = aStream->ParseSingle(QString("%1 focus color r").arg(GetName())); float focusG = aStream->ParseSingle(QString("%1 focus color g").arg(GetName())); float focusB = aStream->ParseSingle(QString("%1 focus color b").arg(GetName())); float focusA = aStream->ParseSingle(QString("%1 focus color a").arg(GetName())); + mFocusColor = QColor::fromRgbF(focusR, focusG, focusB, focusA); float disableR = aStream->ParseSingle(QString("%1 disable color r").arg(GetName())); float disableG = aStream->ParseSingle(QString("%1 disable color g").arg(GetName())); float disableB = aStream->ParseSingle(QString("%1 disable color b").arg(GetName())); float disableA = aStream->ParseSingle(QString("%1 disable color a").arg(GetName())); - - mFocusColor = QColor::fromRgbF(focusR, focusG, focusB, focusA); mDisableColor = QColor::fromRgbF(disableR, disableG, disableB, disableA); mRectXExp.ParseData(aStream); mRectYExp.ParseData(aStream); - qint32 itemsPtr; - *aStream >> itemsPtr; + qint32 itemsPtr = aStream->ParseInt32(QString("%1 items ptr").arg(GetName())); - mFont.ParseData(aStream); - mOnOpen.ParseData(aStream); - mOnClose.ParseData(aStream); - mOnESC.ParseData(aStream); - mOnKey.ParseData(aStream); - mVisibleExp.ParseData(aStream); - mAllowedBinding.ParseData(aStream); - mSoundName.ParseData(aStream); - mRectXExp.ParseData(aStream); - mRectYExp.ParseData(aStream); + mWindow.WindowName().ParseDataSafe(aStream); + mWindow.Group().ParseDataSafe(aStream); + mWindow.Background().ParseDataSafe(aStream); + + mFont.ParseDataSafe(aStream); + mOnOpen.ParseDataSafe(aStream); + mOnClose.ParseDataSafe(aStream); + mOnESC.ParseDataSafe(aStream); + mOnKey.ParseDataSafe(aStream); + + if (mVisibleExp.EntriesPtr()) + { + for (int i = 0; i < mVisibleExp.NumEntries(); i++) + { + XExpressionEntry newEntry; + newEntry.ParsePtr(aStream); + mVisibleExp.AddEntry(newEntry); + } + } + + mAllowedBinding.ParseDataSafe(aStream); + mSoundName.ParseDataSafe(aStream); + + if (mRectXExp.EntriesPtr()) + { + for (int i = 0; i < mRectXExp.NumEntries(); i++) + { + XExpressionEntry newEntry; + newEntry.ParsePtr(aStream); + mRectXExp.AddEntry(newEntry); + } + } + if (mRectYExp.EntriesPtr()) + { + for (int i = 0; i < mRectYExp.NumEntries(); i++) + { + XExpressionEntry newEntry; + newEntry.ParsePtr(aStream); + mRectYExp.AddEntry(newEntry); + } + } if (itemsPtr) { for (int i = 0; i < mItemCount; i++) { XItemDef newItemDef; - newItemDef.ParsePtr(aStream); - mItems.append(newItemDef); + newItemDef.SetCommonInfo(GetCommonInfo()); + newItemDef.ParsePtr(aStream, false); + mItems.push_back(newItemDef); + } + for (int i = 0; i < mItems.size(); i++) + { + mItems[i].ParseDataSafe(aStream); } } } diff --git a/libs/xassets/xmenudef.h b/libs/xassets/xmenudef.h index 0d05750..fb86dd9 100644 --- a/libs/xassets/xmenudef.h +++ b/libs/xassets/xmenudef.h @@ -7,14 +7,13 @@ #include "xstatement.h" #include "xstring.h" #include "xwindowdef.h" - -class XItemDef; +#include "xitemdef.h" class XMenuDef : public XAsset { public: explicit XMenuDef(); - ~XMenuDef(); + ~XMenuDef() = default; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; diff --git a/libs/xassets/xmenulist.cpp b/libs/xassets/xmenulist.cpp index efcc98a..969f334 100644 --- a/libs/xassets/xmenulist.cpp +++ b/libs/xassets/xmenulist.cpp @@ -2,30 +2,25 @@ XMenuList::XMenuList() : XAsset() - , mName(new XString()) + , mName() , mMenuCount(0) - , mMenus(QVector()) + , mMenus() { SetType(ASSET_TYPE_MENULIST); - XAsset::SetName("Menu List"); + SetName("Menu List"); } XMenuList::~XMenuList() { - for (int i = 0; i < mMenus.size(); i++) - { - delete mMenus[i]; - } - - delete mName; + mMenus.clear(); } -void XMenuList::SetName(XString *aName) +void XMenuList::SetMenuListName(XString aName) { mName = aName; } -XString *XMenuList::GetName() const +XString XMenuList::MenuListName() const { return mName; } @@ -35,37 +30,47 @@ int XMenuList::GetMenuCount() const return mMenuCount; } -void XMenuList::SetMenuEntry(int aIndex, XMenuDef *aMenuDef) +void XMenuList::SetMenuEntry(int aIndex, XMenuDef aMenuDef) { mMenus[aIndex] = aMenuDef; } -XMenuDef *XMenuList::GetMenuEntry(int aIndex) const +XMenuDef XMenuList::GetMenuEntry(int aIndex) const { return mMenus[aIndex]; } void XMenuList::Clear() { - for (int i = 0; i < mMenus.size(); i++) - { - delete mMenus[i]; - } - - mName->Clear(); + mName.Clear(); mMenuCount = 0; mMenus.clear(); } void XMenuList::ParseData(XDataStream *aStream) { - mName->ParsePtr(aStream, false); + mName.ParsePtr(aStream, false); - *aStream - >> mMenuCount; + mMenuCount = aStream->ParseUInt32(QString("%1 menu count").arg(GetName())); - for (int i = 0; i < mMenuCount; i++) + qint32 menusPtr = aStream->ParseInt32(QString("%1 menus ptr").arg(GetName())); + + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); + + if (menusPtr) { - //XMenuDef* newMenu = new XMenuDef(); + for (uint i = 0; i < mMenuCount; i++) + { + XMenuDef newMenu; + newMenu.SetCommonInfo(GetCommonInfo()); + newMenu.ParsePtr(aStream, false); + mMenus.push_back(newMenu); + } + + for (uint i = 0; i < mMenus.size(); i++) + { + mMenus[i].ParseDataSafe(aStream); + } } } diff --git a/libs/xassets/xmenulist.h b/libs/xassets/xmenulist.h index 8b78bb3..51c2fc5 100644 --- a/libs/xassets/xmenulist.h +++ b/libs/xassets/xmenulist.h @@ -10,21 +10,21 @@ public: XMenuList(); ~XMenuList(); - void SetName(XString* aName); - XString* GetName() const; + void SetMenuListName(XString aName); + XString MenuListName() const; int GetMenuCount() const; - void SetMenuEntry(int aIndex, XMenuDef* aMenuDef); - XMenuDef* GetMenuEntry(int aIndex) const; + void SetMenuEntry(int aIndex, XMenuDef aMenuDef); + XMenuDef GetMenuEntry(int aIndex) const; virtual void Clear() override; virtual void ParseData(XDataStream *aStream) override; private: - XString* mName; - int mMenuCount; - QVector mMenus; + XString mName; + quint32 mMenuCount; + QVector mMenus; }; #endif // XMENULIST_H diff --git a/libs/xassets/xmodel.cpp b/libs/xassets/xmodel.cpp index 7472fd7..6dbfcbf 100644 --- a/libs/xassets/xmodel.cpp +++ b/libs/xassets/xmodel.cpp @@ -29,6 +29,7 @@ XModel::XModel() , mStreamInfo() , mMemUsage(0) , mFlags(0) + , mBad(false) , mPhysPreset() , mPhysGeoms() { @@ -85,20 +86,22 @@ void XModel::ParseData(XDataStream *aStream) { mMaxs.setY(aStream->ParseSingle(QString("%1 maxs y").arg(GetName()))); mMaxs.setZ(aStream->ParseSingle(QString("%1 maxs z").arg(GetName()))); - mNumLods = aStream->ParseInt16(QString("%1 num lods").arg(GetName())); + mNumLods = aStream->ParseUInt16(QString("%1 num lods").arg(GetName())); mCollLod = aStream->ParseInt16(QString("%1 coll lod").arg(GetName())); - mStreamInfo.ParsePtr(aStream, false); + mStreamInfo.ParseData(aStream); mMemUsage = aStream->ParseInt32(QString("%1 mem usage").arg(GetName())); mFlags = aStream->ParseUInt8(QString("%1 flags").arg(GetName())); + mBad = aStream->ParseUInt8(QString("%1 bad").arg(GetName())); - aStream->skipRawData(3); + aStream->skipRawData(2); mPhysPreset.ParsePtr(aStream, false); mPhysGeoms.ParsePtr(aStream, false); - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); if (boneNamesPtr == -1) { for (int i = 0; i < mNumBones; i++) { @@ -116,8 +119,10 @@ void XModel::ParseData(XDataStream *aStream) { if (quatsPtr == -1) { for (int i = 0; i < 8 * (mNumBones - mNumRootBones); i++) { - quint8 quat = aStream->ParseUInt8(QString("%1 quat %2").arg(GetName()).arg(i)); - mQuats.append(quat); + + XModelQuat newQuat; + newQuat.ParseData(aStream); + mQuats.append(newQuat); } } @@ -148,6 +153,7 @@ void XModel::ParseData(XDataStream *aStream) { if (matHandlesPtr == -1) { for (int i = 0; i < mNumSurfs; i++) { XMaterial newMaterial; + newMaterial.SetCommonInfo(GetCommonInfo()); newMaterial.ParseData(aStream); mMaterialHandles.append(newMaterial); } diff --git a/libs/xassets/xmodel.h b/libs/xassets/xmodel.h index 86c495b..011dc84 100644 --- a/libs/xassets/xmodel.h +++ b/libs/xassets/xmodel.h @@ -2,6 +2,7 @@ #define XMODEL_H #include "xasset.h" +#include "xmodelquat.h" #include "xmodelstreaminfo.h" #include "xphysgeomlist.h" #include "xphyspreset.h" @@ -29,7 +30,7 @@ private: quint8 mLodRampType; QVector mBoneNames; QVector mParentList; - QVector mQuats; + QVector mQuats; QVector mTrans; QVector mPartClassification; XDObjAnimMat mBaseMat; @@ -48,6 +49,7 @@ private: XModelStreamInfo mStreamInfo; qint32 mMemUsage; quint8 mFlags; + bool mBad; XPhysPreset mPhysPreset; XPhysGeomList mPhysGeoms; }; diff --git a/libs/xassets/xmodellodinfo.cpp b/libs/xassets/xmodellodinfo.cpp index 843e22d..8cbab73 100644 --- a/libs/xassets/xmodellodinfo.cpp +++ b/libs/xassets/xmodellodinfo.cpp @@ -5,56 +5,27 @@ XModelLodInfo::XModelLodInfo() , mDist(0) , mNumSurfs(0) , mSurfIndex(0) - , mPartBits(4) + , mPartBits() + , mLod(0) + , mSmcIndexPlusOne(0) + , mSmcAllocBits(0) { SetName("Model LOD Info"); } -XModelLodInfo::~XModelLodInfo() -{ - -} - void XModelLodInfo::ParseData(XDataStream *aStream) { - quint32 rawDist; - *aStream >> rawDist; - memcpy(&mDist, &rawDist, sizeof(mDist)); - - if (IsDebug()) + mDist = aStream->ParseSingle(QString("%1 distance").arg(GetName())); + mNumSurfs = aStream->ParseUInt16(QString("%1 number surfaces").arg(GetName())); + mSurfIndex = aStream->ParseUInt16(QString("%1 surface index").arg(GetName())); + for (int i = 0; i < 4; i++) { - qDebug() << QString("[%1] mDist = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mDist); - } - *aStream >> mNumSurfs; - if (IsDebug()) - { - qDebug() << QString("[%1] mNumSurfs = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mNumSurfs); - } - *aStream >> mSurfIndex; - if (IsDebug()) - { - qDebug() << QString("[%1] mSurfIndex = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mSurfIndex); - } - *aStream >> mPartBits[0]; - if (IsDebug()) - { - qDebug() << QString("[%1] mPartBits[0] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPartBits[0]); - } - *aStream >> mPartBits[1]; - if (IsDebug()) - { - qDebug() << QString("[%1] mPartBits[1] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPartBits[1]); - } - *aStream >> mPartBits[2]; - if (IsDebug()) - { - qDebug() << QString("[%1] mPartBits[2] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPartBits[2]); - } - *aStream >> mPartBits[3]; - if (IsDebug()) - { - qDebug() << QString("[%1] mPartBits[3] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPartBits[3]); + mPartBits.push_back(aStream->ParseInt32(QString("%1 part bit %2").arg(GetName()).arg(i))); } + mLod = aStream->ParseUInt8(QString("%1 level of detail").arg(GetName())); + mSmcIndexPlusOne = aStream->ParseUInt8(QString("%1 smc index plus one").arg(GetName())); + mSmcAllocBits = aStream->ParseUInt8(QString("%1 smc alloc bits").arg(GetName())); + aStream->skipRawData(1); } void XModelLodInfo::Clear() @@ -63,4 +34,7 @@ void XModelLodInfo::Clear() mNumSurfs = 0; mSurfIndex = 0; mPartBits.clear(); + mLod = 0; + mSmcIndexPlusOne = 0; + mSmcAllocBits = 0; } diff --git a/libs/xassets/xmodellodinfo.h b/libs/xassets/xmodellodinfo.h index 47fe375..1c66c54 100644 --- a/libs/xassets/xmodellodinfo.h +++ b/libs/xassets/xmodellodinfo.h @@ -8,8 +8,8 @@ class XModelLodInfo : public XAsset { public: - XModelLodInfo(); - ~XModelLodInfo(); + explicit XModelLodInfo(); + ~XModelLodInfo() = default; virtual void ParseData(XDataStream* aStream) override; virtual void Clear() override; @@ -19,6 +19,9 @@ private: quint16 mNumSurfs; quint16 mSurfIndex; QVector mPartBits; + quint8 mLod; + quint8 mSmcIndexPlusOne; + quint8 mSmcAllocBits; }; #endif // XMODELLODINFO_H diff --git a/libs/xassets/xmodelpieces.cpp b/libs/xassets/xmodelpieces.cpp index d1676bd..25acd73 100644 --- a/libs/xassets/xmodelpieces.cpp +++ b/libs/xassets/xmodelpieces.cpp @@ -26,7 +26,7 @@ void XModelPieces::ParseData(XDataStream *aStream) >> mNumPieces >> piecesPtr; - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); if (piecesPtr) { diff --git a/libs/xassets/xmodelquat.cpp b/libs/xassets/xmodelquat.cpp new file mode 100644 index 0000000..094f95f --- /dev/null +++ b/libs/xassets/xmodelquat.cpp @@ -0,0 +1,31 @@ +#include "xmodelquat.h" + +XModelQuat::XModelQuat() + : XAsset() + , mQuatElements(4) +{ + +} + +void XModelQuat::ParseData(XDataStream *aStream) +{ + for (int i = 0; i < 4; i++) + { + mQuatElements[i] = aStream->ParseUInt8(QString("%1 quad element %2").arg(GetName()).arg(i + 1)); + } +} + +void XModelQuat::Clear() +{ + mQuatElements.clear(); +} + +QVector XModelQuat::QuatElements() const +{ + return mQuatElements; +} + +void XModelQuat::SetQuatElements(const QVector &aQuatElements) +{ + mQuatElements = aQuatElements; +} diff --git a/libs/xassets/xmodelquat.h b/libs/xassets/xmodelquat.h new file mode 100644 index 0000000..637efd1 --- /dev/null +++ b/libs/xassets/xmodelquat.h @@ -0,0 +1,21 @@ +#ifndef XMODELQUAT_H +#define XMODELQUAT_H + +#include "xasset.h" + +class XModelQuat : public XAsset +{ +public: + XModelQuat(); + + void ParseData(XDataStream *aStream) override; + void Clear() override; + + QVector QuatElements() const; + void SetQuatElements(const QVector &aQuatElements); + +private: + QVector mQuatElements; +}; + +#endif // XMODELQUAT_H diff --git a/libs/xassets/xmultidef.cpp b/libs/xassets/xmultidef.cpp index 60bf486..2db33ec 100644 --- a/libs/xassets/xmultidef.cpp +++ b/libs/xassets/xmultidef.cpp @@ -2,9 +2,7 @@ XMultiDef::XMultiDef() : XAsset() - , mDvarListPtrs() , mDvarList() - , mDvarStrPtrs() , mDvarStr() , mDvarValue() , mCount(0) @@ -13,23 +11,41 @@ XMultiDef::XMultiDef() SetName("Multi Definition"); } -XMultiDef::~XMultiDef() -{ - -} - void XMultiDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); + for (int i = 0; i < 32; i++) + { + XString newListDvar; + newListDvar.ParsePtr(aStream, false); + mDvarList.push_back(newListDvar); + } + for (int i = 0; i < 32; i++) + { + XString newListStr; + newListStr.ParsePtr(aStream, false); + mDvarStr.push_back(newListStr); + } + for (int i = 0; i < 32; i++) + { + mDvarValue.push_back(aStream->ParseSingle(QString("%1 dvar value %2").arg(GetName()).arg(i))); + } + mCount = aStream->ParseInt32(QString("%1 count").arg(GetName())); + mStrDef = aStream->ParseInt32(QString("%1 string def").arg(GetName())); + + for (int i = 0; i < mDvarList.size(); i++) + { + mDvarList[i].ParseDataSafe(aStream); + } + for (int i = 0; i < mDvarStr.size(); i++) + { + mDvarStr[i].ParseDataSafe(aStream); + } - // TODO: Fill in XMultiDef::ParseData } void XMultiDef::Clear() { - mDvarListPtrs.clear(); mDvarList.clear(); - mDvarStrPtrs.clear(); mDvarStr.clear(); mDvarValue.clear(); mCount = 0; diff --git a/libs/xassets/xmultidef.h b/libs/xassets/xmultidef.h index 03b0441..5e0fed7 100644 --- a/libs/xassets/xmultidef.h +++ b/libs/xassets/xmultidef.h @@ -2,6 +2,7 @@ #define XMULTIDEF_H #include "xasset.h" +#include "xstring.h" #include @@ -9,19 +10,17 @@ class XMultiDef : public XAsset { public: explicit XMultiDef(); - ~XMultiDef(); + ~XMultiDef() = default; void ParseData(XDataStream *aStream) override; void Clear() override; private: - QVector mDvarListPtrs; - QStringList mDvarList; - QVector mDvarStrPtrs; - QStringList mDvarStr; + QVector mDvarList; + QVector mDvarStr; QVector mDvarValue; - int mCount; - int mStrDef; + qint32 mCount; + qint32 mStrDef; }; #endif // XMULTIDEF_H diff --git a/libs/xassets/xoperand.cpp b/libs/xassets/xoperand.cpp index 30dd407..24e72f9 100644 --- a/libs/xassets/xoperand.cpp +++ b/libs/xassets/xoperand.cpp @@ -15,9 +15,8 @@ XOperand::~XOperand() void XOperand::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - // TODO: Fill in XOperand::ParseData + mDataType = (XExpDataType)aStream->ParseUInt32(QString("%1 data type").arg(GetName())); + mInternals.ParseData(aStream, mDataType); } void XOperand::Clear() diff --git a/libs/xassets/xoperandinternaldataunion.cpp b/libs/xassets/xoperandinternaldataunion.cpp index 931f22f..cf4fcad 100644 --- a/libs/xassets/xoperandinternaldataunion.cpp +++ b/libs/xassets/xoperandinternaldataunion.cpp @@ -4,7 +4,7 @@ XOperandInternalDataUnion::XOperandInternalDataUnion() : XAsset() , mIntVal(0) , mFloatVal(0.0f) - , mString("") + , mString() { SetName("Operand Internal Data Union"); } @@ -19,9 +19,25 @@ void XOperandInternalDataUnion::ParseData(XDataStream *aStream) aStream->ParseSingle(QString("%1 center of mass x").arg(GetName())); } +void XOperandInternalDataUnion::ParseData(XDataStream *aStream, XExpDataType aDataType) +{ + if (aDataType == VAL_INT) + { + mIntVal = aStream->ParseInt32(QString("%1 int val").arg(GetName())); + } + else if (aDataType == VAL_FLOAT) + { + mFloatVal = aStream->ParseSingle(QString("%1 float val").arg(GetName())); + } + else if (aDataType == VAL_STRING) + { + mString.ParseData(aStream); + } +} + void XOperandInternalDataUnion::Clear() { mIntVal = 0; mFloatVal = 0; - mString.clear(); + mString.Clear(); } diff --git a/libs/xassets/xoperandinternaldataunion.h b/libs/xassets/xoperandinternaldataunion.h index aaae84c..04a68eb 100644 --- a/libs/xassets/xoperandinternaldataunion.h +++ b/libs/xassets/xoperandinternaldataunion.h @@ -2,6 +2,8 @@ #define XOPERANDINTERNALDATAUNION_H #include "xasset.h" +#include "xmenuenums.h" +#include "xstring.h" #include @@ -12,12 +14,13 @@ public: ~XOperandInternalDataUnion(); void ParseData(XDataStream *aStream) override; + void ParseData(XDataStream *aStream, XExpDataType aDataType); void Clear() override; private: int mIntVal; float mFloatVal; - QString mString; + XString mString; }; #endif // XOPERANDINTERNALDATAUNION_H diff --git a/libs/xassets/xpackedtexcoords.cpp b/libs/xassets/xpackedtexcoords.cpp index f8bc4f0..e360550 100644 --- a/libs/xassets/xpackedtexcoords.cpp +++ b/libs/xassets/xpackedtexcoords.cpp @@ -9,14 +9,10 @@ XPackedTexCoords::XPackedTexCoords() void XPackedTexCoords::ParseData(XDataStream *aStream) { - *aStream >> mPacked; - if (IsDebug()) - { - qDebug() << QString("[%1] mPacked = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPacked); - } + mPacked = aStream->ParseUInt32(QString("%1 packed").arg(GetName())); } void XPackedTexCoords::Clear() { - + mPacked = 0; } diff --git a/libs/xassets/xpackedunitvec.cpp b/libs/xassets/xpackedunitvec.cpp index d503448..7430f6b 100644 --- a/libs/xassets/xpackedunitvec.cpp +++ b/libs/xassets/xpackedunitvec.cpp @@ -2,21 +2,20 @@ XPackedUnitVec::XPackedUnitVec() : XAsset() - , mPacked(0) + , mArray() { SetName("Packed Unit Vec"); } void XPackedUnitVec::ParseData(XDataStream *aStream) { - *aStream >> mPacked; - if (IsDebug()) + for (int i = 0; i < 4; i++) { - qDebug() << QString("[%1] mPacked = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mPacked); + mArray.push_back(aStream->ParseInt8(QString("%1 array %2").arg(GetName()).arg(i))); } } void XPackedUnitVec::Clear() { - + mArray.clear(); } diff --git a/libs/xassets/xpackedunitvec.h b/libs/xassets/xpackedunitvec.h index 97db0ae..c64f826 100644 --- a/libs/xassets/xpackedunitvec.h +++ b/libs/xassets/xpackedunitvec.h @@ -12,7 +12,7 @@ public: void Clear() override; private: - quint32 mPacked; + QVector mArray; }; #endif // XPACKEDUNITVEC_H diff --git a/libs/xassets/xphyspreset.cpp b/libs/xassets/xphyspreset.cpp index a839d54..219974c 100644 --- a/libs/xassets/xphyspreset.cpp +++ b/libs/xassets/xphyspreset.cpp @@ -54,7 +54,8 @@ void XPhysPreset::ParseData(XDataStream *aStream) *aStream >> mTempDefaultToCylinder; - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); mSndAliasPrefix.ParseData(aStream); } } diff --git a/libs/xassets/xpicmip.cpp b/libs/xassets/xpicmip.cpp new file mode 100644 index 0000000..a1ed048 --- /dev/null +++ b/libs/xassets/xpicmip.cpp @@ -0,0 +1,28 @@ +#include "xpicmip.h" + +XPicmip::XPicmip() + : mPlatform(2) +{ + +} + +void XPicmip::ParseData(XDataStream *aStream) +{ + mPlatform[0] = aStream->ParseUInt8(QString("%1 platform 1").arg(GetName())); + mPlatform[1] = aStream->ParseUInt8(QString("%1 platform 2").arg(GetName())); +} + +void XPicmip::Clear() +{ + mPlatform.clear(); +} + +QVector XPicmip::Platform() const +{ + return mPlatform; +} + +void XPicmip::SetPlatform(const QVector &aPlatform) +{ + mPlatform = aPlatform; +} diff --git a/libs/xassets/xpicmip.h b/libs/xassets/xpicmip.h new file mode 100644 index 0000000..a0b4be8 --- /dev/null +++ b/libs/xassets/xpicmip.h @@ -0,0 +1,21 @@ +#ifndef XPICMIP_H +#define XPICMIP_H + +#include "xasset.h" + +class XPicmip : public XAsset +{ +public: + XPicmip(); + + virtual void ParseData(XDataStream* aStream) override; + virtual void Clear() override; + + QVector Platform() const; + void SetPlatform(const QVector &aPlatform); + +private: + QVector mPlatform; +}; + +#endif // XPICMIP_H diff --git a/libs/xassets/xplatform.h b/libs/xassets/xplatform.h index 6f38a1a..bd8b586 100644 --- a/libs/xassets/xplatform.h +++ b/libs/xassets/xplatform.h @@ -5,12 +5,12 @@ enum XPlatform { - PLATFORM_NONE = 0x00, // No platform - PLATFORM_XBOX = 0x01, // Xbox 360 - PLATFORM_PS3 = 0x02, // Playstation 3 - PLATFORM_PC = 0x03, // PC - PLATFORM_WII = 0x04, // WII - PLATFORM_WIIU = 0x05 // WII U + PLATFORM_NONE = 0, // No platform + PLATFORM_XBOX = 1, // Xbox 360 + PLATFORM_PS3 = 2, // Playstation 3 + PLATFORM_PC = 3, // PC + PLATFORM_WII = 4, // WII + PLATFORM_WIIU = 5 // WII U }; #endif // XPLATFORM_H diff --git a/libs/xassets/xrawfile.cpp b/libs/xassets/xrawfile.cpp index cbe5b8e..dfc54b6 100644 --- a/libs/xassets/xrawfile.cpp +++ b/libs/xassets/xrawfile.cpp @@ -2,7 +2,7 @@ XRawFile::XRawFile() : XAsset() - , mName(new XString()) + , mName() , mLength(0) , mBuffer() { @@ -10,31 +10,16 @@ XRawFile::XRawFile() SetName("Raw File"); } -XRawFile::~XRawFile() +void XRawFile::SetRawFileName(const XString& aName) { - delete mName; -} - -void XRawFile::SetName(XString* aName) -{ - if (aName == nullptr) - { - return; - } - mName = aName; } -void XRawFile::SetName(const QString& aName) +void XRawFile::SetRawFileName(const QString& aName) { - if (mName == nullptr) - { - mName = new XString(); - } - - mName->SetString(aName); + mName.SetString(aName); } -XString* XRawFile::Name() const +XString XRawFile::GetRawFileName() const { return mName; } @@ -63,7 +48,7 @@ QByteArray XRawFile::Buffer() const void XRawFile::Clear() { - mName->Clear(); + mName.Clear(); mLength = 0; mBuffer = QByteArray(); @@ -72,18 +57,15 @@ void XRawFile::Clear() void XRawFile::ParseData(XDataStream *aStream) { - mName->ParsePtr(aStream, false); + mName.ParsePtr(aStream, false); qint32 bufferPtr; *aStream >> mLength >> bufferPtr; - if (mName == nullptr) - { - mName = new XString(); - } - mName->ParseData(aStream); + mName.ParseDataSafe(aStream); + SetDisplayName(mName.GetString()); if (bufferPtr) { diff --git a/libs/xassets/xrawfile.h b/libs/xassets/xrawfile.h index 9b11916..fa8a39e 100644 --- a/libs/xassets/xrawfile.h +++ b/libs/xassets/xrawfile.h @@ -8,11 +8,10 @@ class XRawFile : public XAsset { public: XRawFile(); - ~XRawFile(); - void SetName(XString* aName = nullptr); - void SetName(const QString& aName); - XString* Name() const; + void SetRawFileName(const XString& aName); + void SetRawFileName(const QString& aName); + XString GetRawFileName() const; void SetLength(int aLength); int Length() const; @@ -24,7 +23,7 @@ public: virtual void ParseData(XDataStream *aStream) override; private: - XString* mName; + XString mName; quint32 mLength; QByteArray mBuffer; }; diff --git a/libs/xassets/xrigidvertlist.cpp b/libs/xassets/xrigidvertlist.cpp index 8345854..8cbe481 100644 --- a/libs/xassets/xrigidvertlist.cpp +++ b/libs/xassets/xrigidvertlist.cpp @@ -11,41 +11,72 @@ XRigidVertList::XRigidVertList() SetName("Rigid Vertex List"); } -XRigidVertList::~XRigidVertList() -{ - -} - void XRigidVertList::ParseData(XDataStream *aStream) { - *aStream >> mBoneOffset; - if (IsDebug()) - { - qDebug() << QString("[%1] mBoneOffset = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mBoneOffset); - } + mBoneOffset = aStream->ParseUInt16(QString("%1 bone offset").arg(GetName())); + mVertCount = aStream->ParseUInt16(QString("%1 vertex count").arg(GetName())); + mTriOffset = aStream->ParseUInt16(QString("%1 tri offset").arg(GetName())); + mTriCount = aStream->ParseUInt16(QString("%1 tri count").arg(GetName())); - *aStream >> mVertCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mVertCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertCount); - } - - *aStream >> mTriOffset; - if (IsDebug()) - { - qDebug() << QString("[%1] mTriOffset = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTriOffset); - } - - *aStream >> mTriCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mTriCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTriCount); - } - - mCollisionTree.ParsePtr(aStream); + mCollisionTree.ParsePtr(aStream, false); } void XRigidVertList::Clear() { - + mBoneOffset = 0; + mVertCount = 0; + mTriOffset = 0; + mTriCount = 0; + + mCollisionTree.Clear(); +} + +quint16 XRigidVertList::BoneOffset() const +{ + return mBoneOffset; +} + +void XRigidVertList::SetBoneOffset(quint16 aBoneOffset) +{ + mBoneOffset = aBoneOffset; +} + +quint16 XRigidVertList::VertCount() const +{ + return mVertCount; +} + +void XRigidVertList::SetVertCount(quint16 aVertCount) +{ + mVertCount = aVertCount; +} + +quint16 XRigidVertList::TriOffset() const +{ + return mTriOffset; +} + +void XRigidVertList::SetTriOffset(quint16 aTriOffset) +{ + mTriOffset = aTriOffset; +} + +quint16 XRigidVertList::TriCount() const +{ + return mTriCount; +} + +void XRigidVertList::SetTriCount(quint16 aTriCount) +{ + mTriCount = aTriCount; +} + +XSurfaceCollisionTree XRigidVertList::CollisionTree() const +{ + return mCollisionTree; +} + +void XRigidVertList::SetCollisionTree(const XSurfaceCollisionTree &aCollisionTree) +{ + mCollisionTree = aCollisionTree; } diff --git a/libs/xassets/xrigidvertlist.h b/libs/xassets/xrigidvertlist.h index 1588866..721dfc4 100644 --- a/libs/xassets/xrigidvertlist.h +++ b/libs/xassets/xrigidvertlist.h @@ -7,12 +7,22 @@ class XRigidVertList : public XAsset { public: - explicit XRigidVertList(); - ~XRigidVertList(); + explicit XRigidVertList();; void ParseData(XDataStream *aStream) override; void Clear() override; + quint16 BoneOffset() const; + void SetBoneOffset(quint16 aBoneOffset); + quint16 VertCount() const; + void SetVertCount(quint16 aVertCount); + quint16 TriOffset() const; + void SetTriOffset(quint16 aTriOffset); + quint16 TriCount() const; + void SetTriCount(quint16 aTriCount); + XSurfaceCollisionTree CollisionTree() const; + void SetCollisionTree(const XSurfaceCollisionTree &aCollisionTree); + private: quint16 mBoneOffset; quint16 mVertCount; diff --git a/libs/xassets/xscriptstringlist.cpp b/libs/xassets/xscriptstringlist.cpp index 6558cbb..b76797d 100644 --- a/libs/xassets/xscriptstringlist.cpp +++ b/libs/xassets/xscriptstringlist.cpp @@ -48,6 +48,9 @@ void XScriptStringList::ParsePtr(XDataStream *aStream, bool aDataFlag) *aStream >> mCount >> stringsPtr; + + mCount--; + if (mDebug) { // Always treat as unsigned when displaying in hex @@ -68,3 +71,23 @@ void XScriptStringList::ParsePtr(XDataStream *aStream, bool aDataFlag) ParseData(aStream); } } + +int XScriptStringList::Count() const +{ + return mCount; +} + +void XScriptStringList::SetCount(int aCount) +{ + mCount = aCount; +} + +QVector XScriptStringList::ScriptStrings() const +{ + return mScriptStrings; +} + +void XScriptStringList::SetScriptStrings(const QVector &aScriptStrings) +{ + mScriptStrings = aScriptStrings; +} diff --git a/libs/xassets/xscriptstringlist.h b/libs/xassets/xscriptstringlist.h index ab23a51..ee4ee87 100644 --- a/libs/xassets/xscriptstringlist.h +++ b/libs/xassets/xscriptstringlist.h @@ -17,6 +17,11 @@ public: virtual void ParseData(XDataStream *aStream) override; virtual void ParsePtr(XDataStream *aStream, bool aDataFlag = true) override; + int Count() const; + void SetCount(int aCount); + QVector ScriptStrings() const; + void SetScriptStrings(const QVector &aScriptStrings); + private: int mCount; QVector mScriptStrings; diff --git a/libs/xassets/xsoundaliaslist.cpp b/libs/xassets/xsoundaliaslist.cpp index 9002120..5e0c84e 100644 --- a/libs/xassets/xsoundaliaslist.cpp +++ b/libs/xassets/xsoundaliaslist.cpp @@ -10,11 +10,6 @@ XSoundAliasList::XSoundAliasList() SetName("Sound Alias List"); } -XSoundAliasList::~XSoundAliasList() -{ - -} - void XSoundAliasList::Clear() { mAliasName.Clear(); diff --git a/libs/xassets/xsoundaliaslist.h b/libs/xassets/xsoundaliaslist.h index f574848..cdda7a5 100644 --- a/libs/xassets/xsoundaliaslist.h +++ b/libs/xassets/xsoundaliaslist.h @@ -8,7 +8,7 @@ class XSoundAliasList : public XAsset { public: explicit XSoundAliasList(); - ~XSoundAliasList(); + ~XSoundAliasList() = default; virtual void Clear() override; virtual void ParseData(XDataStream* aStream) override; diff --git a/libs/xassets/xsoundcurve.cpp b/libs/xassets/xsoundcurve.cpp index 5f20a7c..44cd668 100644 --- a/libs/xassets/xsoundcurve.cpp +++ b/libs/xassets/xsoundcurve.cpp @@ -57,12 +57,13 @@ void XSoundCurve::ParseData(XDataStream *aStream) for (int i = 0; i < 8; i++) { + mKnots.push_back(QVector()); for (int j = 0; j < 2; j++) { float knot; *aStream >> knot; - mKnots[i][j] = knot; + mKnots[i].push_back(knot); } } } diff --git a/libs/xassets/xsounddriverglobals.cpp b/libs/xassets/xsounddriverglobals.cpp index e0995ba..99f0cec 100644 --- a/libs/xassets/xsounddriverglobals.cpp +++ b/libs/xassets/xsounddriverglobals.cpp @@ -30,5 +30,6 @@ void XSoundDriverGlobals::ParseData(XDataStream* aStream) mAudioReverbSettings->ParseData(aStream); mName->ParseData(aStream); + SetDisplayName(mName->GetString()); } } diff --git a/libs/xassets/xstatement.cpp b/libs/xassets/xstatement.cpp index 38c82d4..4509f05 100644 --- a/libs/xassets/xstatement.cpp +++ b/libs/xassets/xstatement.cpp @@ -11,18 +11,7 @@ XStatement::XStatement() void XStatement::ParseData(XDataStream *aStream) { mNumEntries = aStream->ParseInt32(QString("%1 # entries").arg(GetName())); - - qint32 entriesPtr; - entriesPtr = aStream->ParseInt32(QString("%1 entries ptr").arg(GetName())); - if (entriesPtr) - { - for (int i = 0; i < mNumEntries; i++) - { - XExpressionEntry newEntry; - newEntry.ParsePtr(aStream); - mEntries.append(newEntry); - } - } + mEntriesPtr = aStream->ParseInt32(QString("%1 entries ptr").arg(GetName())); } void XStatement::Clear() @@ -30,3 +19,38 @@ void XStatement::Clear() mNumEntries = 0; mEntries.clear(); } + +qint32 XStatement::NumEntries() const +{ + return mNumEntries; +} + +void XStatement::SetNumEntries(qint32 aNumEntries) +{ + mNumEntries = aNumEntries; +} + +qint32 XStatement::EntriesPtr() const +{ + return mEntriesPtr; +} + +void XStatement::SetEntriesPtr(qint32 aEntriesPtr) +{ + mEntriesPtr = aEntriesPtr; +} + +QVector XStatement::Entries() const +{ + return mEntries; +} + +void XStatement::AddEntry(const XExpressionEntry& aEntry) +{ + mEntries.push_back(aEntry); +} + +void XStatement::SetEntries(const QVector &aEntries) +{ + mEntries = aEntries; +} diff --git a/libs/xassets/xstatement.h b/libs/xassets/xstatement.h index c75b61b..674bb73 100644 --- a/libs/xassets/xstatement.h +++ b/libs/xassets/xstatement.h @@ -15,8 +15,17 @@ public: void ParseData(XDataStream *aStream) override; void Clear() override; + qint32 NumEntries() const; + void SetNumEntries(qint32 aNumEntries); + qint32 EntriesPtr() const; + void SetEntriesPtr(qint32 aEntriesPtr); + QVector Entries() const; + void SetEntries(const QVector &aEntries); + + void AddEntry(const XExpressionEntry &aEntry); private: qint32 mNumEntries; + qint32 mEntriesPtr; QVector mEntries; }; diff --git a/libs/xassets/xstreamfilenameraw.cpp b/libs/xassets/xstreamfilenameraw.cpp index 5530a73..66712fe 100644 --- a/libs/xassets/xstreamfilenameraw.cpp +++ b/libs/xassets/xstreamfilenameraw.cpp @@ -14,7 +14,7 @@ void XStreamFileNameRaw::ParseData(XDataStream *aStream) mName.ParsePtr(aStream, false); mDir.ParseData(aStream); - mName.ParseData(aStream); + mName.ParseDataSafe(aStream); } void XStreamFileNameRaw::Clear() diff --git a/libs/xassets/xstring.cpp b/libs/xassets/xstring.cpp index 2507d6f..16f7025 100644 --- a/libs/xassets/xstring.cpp +++ b/libs/xassets/xstring.cpp @@ -21,11 +21,6 @@ XString::XString(const QString aString) SetName("String"); } -XString::~XString() -{ - -} - QString XString::GetString() const { return mString; @@ -83,27 +78,24 @@ void XString::Clear() void XString::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + if (mContentLength == -1) { - if (mContentLength == -1) - { - mString = ParseCustom(aStream); - } - else if (mContentLength != 0) - { - QByteArray rawString(mContentLength, Qt::Uninitialized); - aStream->readRawData(rawString.data(), mContentLength); - mString = QString::fromUtf8(rawString); - } + mString = ParseCustom(aStream); + } + else if (mContentLength != 0) + { + QByteArray rawString(mContentLength, Qt::Uninitialized); + aStream->readRawData(rawString.data(), mContentLength); + mString = QString::fromUtf8(rawString); + } - if (!mRemoveString.isEmpty()) - { - mString = mString.replace(mRemoveString, ""); - } + if (!mRemoveString.isEmpty()) + { + mString = mString.replace(mRemoveString, ""); + } - if (IsDebug()) - { - qDebug() << QString("[%1] mString = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mString); - } + if (IsDebug()) + { + qDebug() << QString("[%1] mString = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mString); } } diff --git a/libs/xassets/xstring.h b/libs/xassets/xstring.h index efd2ef9..129e71e 100644 --- a/libs/xassets/xstring.h +++ b/libs/xassets/xstring.h @@ -12,7 +12,7 @@ class XString : public XAsset public: XString(); XString(const QString aString); - virtual ~XString() override; + ~XString() = default; void SetString(const QString& aString); QString GetString() const; diff --git a/libs/xassets/xstringtable.cpp b/libs/xassets/xstringtable.cpp index 8747aac..e28234b 100644 --- a/libs/xassets/xstringtable.cpp +++ b/libs/xassets/xstringtable.cpp @@ -22,7 +22,7 @@ XStringTable::~XStringTable() } } -void XStringTable::SetName(XString *aName) { +void XStringTable::SetStringTableName(XString *aName) { if (aName == nullptr) { return; @@ -31,11 +31,11 @@ void XStringTable::SetName(XString *aName) { mName = aName; } -void XStringTable::SetName(const QString aName) { +void XStringTable::SetStringTableName(const QString aName) { mName->SetString(aName); } -XString *XStringTable::GetName() const { +XString *XStringTable::StringTableName() const { return mName; } @@ -90,6 +90,7 @@ void XStringTable::ParseData(XDataStream *aStream) { >> valuesPtr; mName->ParseData(aStream); + SetDisplayName(mName->GetString()); if (valuesPtr) { mValues = XString::ParseArray(aStream, mRowCount * mColumnCount); diff --git a/libs/xassets/xstringtable.h b/libs/xassets/xstringtable.h index 515e2a0..26954f5 100644 --- a/libs/xassets/xstringtable.h +++ b/libs/xassets/xstringtable.h @@ -10,7 +10,7 @@ public: explicit XStringTable(); ~XStringTable(); - XString* GetName() const; + XString* StringTableName() const; XStringArray* GetValues() const; int GetColumnCount() const; int GetRowCount() const; @@ -19,8 +19,8 @@ public: virtual void Clear() override; public slots: - void SetName(QString aName); - void SetName(XString* aName); + void SetStringTableName(QString aName); + void SetStringTableName(XString* aName); void SetValues(XStringArray *aValues); void SetColumnCount(int aColumnCount); void SetRowCount(int aRowCount); diff --git a/libs/xassets/xsunflare.cpp b/libs/xassets/xsunflare.cpp index 0d31c82..c52145a 100644 --- a/libs/xassets/xsunflare.cpp +++ b/libs/xassets/xsunflare.cpp @@ -35,39 +35,44 @@ XSunFlare::~XSunFlare() void XSunFlare::ParseData(XDataStream *aStream) { - *aStream - >> mHasValidData; + mHasValidData = aStream->ParseUInt8(QString("%1 has valid data").arg(GetName())); aStream->skipRawData(3); mSpriteMaterial.ParsePtr(aStream, false); mFlareMaterial.ParsePtr(aStream, false); - *aStream - >> mSpriteSize - >> mFlareMinSize - >> mFlareMinDot - >> mFlareMaxSize - >> mFlareMaxDot - >> mFlareMaxAlpha - >> mFlareFadeInTime - >> mFlareFadeOutTime - >> mBlindMinDot - >> mBlindMaxDot - >> mBlindMaxDarken - >> mBlindFadeInTime - >> mBlindFadeOutTime - >> mGlareMinDot - >> mGlareMaxDot - >> mGlareMaxLighten - >> mGlareFadeInTime - >> mGlareFadeOutTime - >> mSunFxPosition[0] - >> mSunFxPosition[1] - >> mSunFxPosition[2]; + mSpriteSize = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mFlareMinSize = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mFlareMinDot = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mFlareMaxSize = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mFlareMaxDot = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mFlareMaxAlpha = aStream->ParseSingle(QString("%1 radius").arg(GetName())); - mSpriteMaterial.ParseData(aStream); - mFlareMaterial.ParseData(aStream); + mFlareFadeInTime = aStream->ParseInt32(QString("%1 radius").arg(GetName())); + mFlareFadeOutTime = aStream->ParseInt32(QString("%1 radius").arg(GetName())); + + mBlindMinDot = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mBlindMaxDot = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mBlindMaxDarken = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + + mBlindFadeInTime = aStream->ParseInt32(QString("%1 radius").arg(GetName())); + mBlindFadeInTime = aStream->ParseInt32(QString("%1 radius").arg(GetName())); + + mGlareMinDot = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mGlareMaxDot = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + mGlareMaxLighten = aStream->ParseSingle(QString("%1 radius").arg(GetName())); + + mGlareFadeInTime = aStream->ParseInt32(QString("%1 radius").arg(GetName())); + mGlareFadeOutTime = aStream->ParseInt32(QString("%1 radius").arg(GetName())); + + for (int i = 0; i < 3; i++) + { + mSunFxPosition[i] = aStream->ParseSingle(QString("%1 sun fx position %2").arg(GetName()).arg(i)); + } + + mSpriteMaterial.ParseDataSafe(aStream); + mFlareMaterial.ParseDataSafe(aStream); } void XSunFlare::Clear() diff --git a/libs/xassets/xsunflare.h b/libs/xassets/xsunflare.h index d5c42e4..d35b84d 100644 --- a/libs/xassets/xsunflare.h +++ b/libs/xassets/xsunflare.h @@ -25,18 +25,18 @@ private: float mFlareMaxSize; float mFlareMaxDot; float mFlareMaxAlpha; - int mFlareFadeInTime; - int mFlareFadeOutTime; + qint32 mFlareFadeInTime; + qint32 mFlareFadeOutTime; float mBlindMinDot; float mBlindMaxDot; float mBlindMaxDarken; - int mBlindFadeInTime; - int mBlindFadeOutTime; + qint32 mBlindFadeInTime; + qint32 mBlindFadeOutTime; float mGlareMinDot; float mGlareMaxDot; float mGlareMaxLighten; - int mGlareFadeInTime; - int mGlareFadeOutTime; + qint32 mGlareFadeInTime; + qint32 mGlareFadeOutTime; QVector3D mSunFxPosition; }; diff --git a/libs/xassets/xsurface.cpp b/libs/xassets/xsurface.cpp index 7db1fb3..3d16d5e 100644 --- a/libs/xassets/xsurface.cpp +++ b/libs/xassets/xsurface.cpp @@ -6,103 +6,79 @@ XSurface::XSurface() , mDeformed(false) , mVertCount(0) , mTriCount(0) - , mTriIndices(0) + , mTriIndices() , mVertInfo() , mVert() - , mVertBuffer() , mVertListCount(0) , mVertList() - , mIndexBuffer() - , mPartBits(4) + , mPartBits() { SetName("Surface"); } -XSurface::~XSurface() -{ - -} - void XSurface::ParseData(XDataStream *aStream) { - *aStream >> mTileMode; - if (IsDebug()) - { - qDebug() << QString("[%1] mTileMode = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTileMode); - } + mTileMode = aStream->ParseUInt8(QString("%1 tile mode").arg(GetName())); + mDeformed = aStream->ParseUInt8(QString("%1 deformed").arg(GetName())); - *aStream >> mDeformed; - if (IsDebug()) - { - qDebug() << QString("[%1] mDeformed = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mDeformed); - } + mVertCount = aStream->ParseUInt16(QString("%1 vertex count").arg(GetName())); + mTriCount = aStream->ParseUInt16(QString("%1 tri count").arg(GetName())); - *aStream >> mVertCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mVertCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertCount); - } + mZoneHandle = aStream->ParseInt8(QString("%1 zone handle").arg(GetName())); - *aStream >> mTriCount; - if (IsDebug()) - { - qDebug() << QString("[%1] mTriCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mTriCount); - } + aStream->skipRawData(1); - aStream->skipRawData(2); + mBaseTriIndex = aStream->ParseUInt16(QString("%1 base tri index").arg(GetName())); + mBaseVertIndex = aStream->ParseUInt16(QString("%1 base vertex index").arg(GetName())); - qint32 triIndicesPtr; - *aStream >> triIndicesPtr; - if (IsDebug()) - { - qDebug() << QString("[%1] triIndicesPtr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(triIndicesPtr); - } + mTriIndices.ParsePtr(aStream, false); - mVertInfo.SetPtr(-1); mVertInfo.ParseData(aStream); mVert.ParsePtr(aStream, false); - mVertBuffer.ParseData(aStream); - *aStream >> mVertListCount; - if (IsDebug()) + mVertListCount = aStream->ParseUInt32(QString("%1 vertex list count").arg(GetName())); + + qint32 vertListPtr = aStream->ParseInt32(QString("%1 vert list ptr").arg(GetName())); + + for (int i = 0; i < 4; i++) { - qDebug() << QString("[%1] mVertListCount = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertListCount); + mPartBits.push_back(aStream->ParseInt32(QString("%1 part bits %2").arg(GetName()).arg(i))); } - mVertList.ParseData(aStream); - mIndexBuffer.ParseData(aStream); + mVert.ParseDataSafe(aStream); - *aStream - >> mPartBits[0] - >> mPartBits[1] - >> mPartBits[2] - >> mPartBits[3]; - if (IsDebug()) + if (vertListPtr == -1) { - qDebug() << QString("[%1] mPartBits = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(*mPartBits.data()); - } - - //mVertInfo.ParseData(aStream); - mVert.ParseData(aStream); - mVertBuffer.ParseData(aStream); - //mVertList.ParseData(aStream); - - if (triIndicesPtr == -1) - { - for (int i = 0; i < mTriCount; i++) + for (int i = 0; i < mVertListCount; i++) { - quint16 newTri; - *aStream >> newTri; - if (IsDebug()) - { - qDebug() << QString("[%1] newTri = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(newTri); - } - mTriIndices.append(newTri); + XRigidVertList newVertList; + newVertList.ParseData(aStream); + mVertList.push_back(newVertList); + } + for (int i = 0; i < mVertList.size(); i++) + { + auto collTree = mVertList[i].CollisionTree(); + collTree.ParseDataSafe(aStream); + mVertList[i].SetCollisionTree(collTree); } } + + mTriIndices.ParseDataSafe(aStream); } void XSurface::Clear() { - + mTileMode = 0; + mDeformed = false; + mVertCount = 0; + mTriCount = 0; + mZoneHandle = 0; + mBaseTriIndex = 0; + mBaseVertIndex = 0; + mTriIndices.Clear(); + mVertInfo.Clear(); + mVert.Clear(); + mVertListCount = 0; + mVertList.clear(); + mPartBits.clear(); } diff --git a/libs/xassets/xsurface.h b/libs/xassets/xsurface.h index 1d957cf..6297cd9 100644 --- a/libs/xassets/xsurface.h +++ b/libs/xassets/xsurface.h @@ -2,17 +2,15 @@ #define XSURFACE_H #include "xasset.h" -#include "xd3dindexbuffer.h" #include "xrigidvertlist.h" +#include "xsurfacetri.h" #include "xsurfacevertexinfo.h" #include "xgfxpackedvertex.h" -#include "xd3dvertexbuffer.h" class XSurface : public XAsset { public: explicit XSurface(); - ~XSurface(); void ParseData(XDataStream *aStream) override; void Clear() override; @@ -22,14 +20,15 @@ private: bool mDeformed; quint16 mVertCount; quint16 mTriCount; - QVector mTriIndices; + qint8 mZoneHandle; + quint16 mBaseTriIndex; + quint16 mBaseVertIndex; + XSurfaceTri mTriIndices; XSurfaceVertexInfo mVertInfo; XGfxPackedVertex mVert; - XD3DVertexBuffer mVertBuffer; quint32 mVertListCount; - XRigidVertList mVertList; - XD3DIndexBuffer mIndexBuffer; - QVector mPartBits; + QVector mVertList; + QVector mPartBits; }; #endif // XSURFACE_H diff --git a/libs/xassets/xsurfacecollisionaabb.cpp b/libs/xassets/xsurfacecollisionaabb.cpp index 4d6973b..f94dc57 100644 --- a/libs/xassets/xsurfacecollisionaabb.cpp +++ b/libs/xassets/xsurfacecollisionaabb.cpp @@ -2,24 +2,26 @@ XSurfaceCollisionAabb::XSurfaceCollisionAabb() : XAsset() - , mMins(3) - , mMaxs(3) + , mMins(0) + , mMaxs(0) { SetName("Surface Collision AABB"); } void XSurfaceCollisionAabb::ParseData(XDataStream *aStream) { - *aStream - >> mMins[0] - >> mMins[1] - >> mMins[2] - >> mMaxs[0] - >> mMaxs[1] - >> mMaxs[2]; + for (int i = 0; i < 3; i++) + { + mMins.push_back(aStream->ParseUInt16(QString("%1 min %2").arg(GetName()).arg(i))); + } + for (int i = 0; i < 3; i++) + { + mMaxs.push_back(aStream->ParseUInt16(QString("%1 max %2").arg(GetName()).arg(i))); + } } void XSurfaceCollisionAabb::Clear() { - + mMins.clear(); + mMaxs.clear(); } diff --git a/libs/xassets/xsurfacecollisionleaf.cpp b/libs/xassets/xsurfacecollisionleaf.cpp index e8a14e0..34f33dc 100644 --- a/libs/xassets/xsurfacecollisionleaf.cpp +++ b/libs/xassets/xsurfacecollisionleaf.cpp @@ -9,7 +9,7 @@ XSurfaceCollisionLeaf::XSurfaceCollisionLeaf() void XSurfaceCollisionLeaf::ParseData(XDataStream *aStream) { - *aStream >> mTriangleBeginIndex; + mTriangleBeginIndex = aStream->ParseUInt16(QString("%1 triangle collision leaf").arg(GetName())); } void XSurfaceCollisionLeaf::Clear() diff --git a/libs/xassets/xsurfacecollisionnode.cpp b/libs/xassets/xsurfacecollisionnode.cpp index 764efe7..de4637b 100644 --- a/libs/xassets/xsurfacecollisionnode.cpp +++ b/libs/xassets/xsurfacecollisionnode.cpp @@ -13,9 +13,8 @@ void XSurfaceCollisionNode::ParseData(XDataStream *aStream) { mAABB.ParseData(aStream); - *aStream - >> mChildBeginIndex - >> mChildCount; + mChildBeginIndex = aStream->ParseUInt16(QString("%1 child begin index").arg(GetName())); + mChildCount = aStream->ParseUInt16(QString("%1 child count").arg(GetName())); } void XSurfaceCollisionNode::Clear() diff --git a/libs/xassets/xsurfacecollisiontree.cpp b/libs/xassets/xsurfacecollisiontree.cpp index 3dedccd..9c052b7 100644 --- a/libs/xassets/xsurfacecollisiontree.cpp +++ b/libs/xassets/xsurfacecollisiontree.cpp @@ -14,28 +14,18 @@ XSurfaceCollisionTree::XSurfaceCollisionTree() void XSurfaceCollisionTree::ParseData(XDataStream *aStream) { - quint32 rawTrans; - *aStream >> rawTrans; - memcpy(&mTrans[0], &rawTrans, sizeof(mTrans[0])); - *aStream >> rawTrans; - memcpy(&mTrans[1], &rawTrans, sizeof(mTrans[1])); - *aStream >> rawTrans; - memcpy(&mTrans[2], &rawTrans, sizeof(mTrans[2])); + mTrans.setX(aStream->ParseSingle(QString("%1 transformation x").arg(GetName()))); + mTrans.setY(aStream->ParseSingle(QString("%1 transformation y").arg(GetName()))); + mTrans.setZ(aStream->ParseSingle(QString("%1 transformation z").arg(GetName()))); - quint32 rawScale; - *aStream >> rawScale; - memcpy(&mScale[0], &rawScale, sizeof(mScale[0])); - *aStream >> rawScale; - memcpy(&mScale[1], &rawScale, sizeof(mScale[1])); - *aStream >> rawScale; - memcpy(&mScale[2], &rawScale, sizeof(mScale[2])); + mScale.setX(aStream->ParseSingle(QString("%1 scale x").arg(GetName()))); + mScale.setY(aStream->ParseSingle(QString("%1 scale y").arg(GetName()))); + mScale.setZ(aStream->ParseSingle(QString("%1 scale z").arg(GetName()))); - qint32 nodesPtr, leafsPtr; - *aStream - >> mNodeCount - >> nodesPtr - >> mLeafCount - >> leafsPtr; + mNodeCount = aStream->ParseUInt32(QString("%1 node count").arg(GetName())); + qint32 nodesPtr = aStream->ParseInt32(QString("%1 nodes ptr").arg(GetName())); + mLeafCount = aStream->ParseUInt32(QString("%1 leaf count").arg(GetName())); + qint32 leafsPtr = aStream->ParseInt32(QString("%1 leafs ptr").arg(GetName())); if (nodesPtr) { @@ -43,7 +33,7 @@ void XSurfaceCollisionTree::ParseData(XDataStream *aStream) { XSurfaceCollisionNode newNode; newNode.ParseData(aStream); - mNodes.append(newNode); + mNodes.push_back(newNode); } } if (leafsPtr) @@ -52,12 +42,23 @@ void XSurfaceCollisionTree::ParseData(XDataStream *aStream) { XSurfaceCollisionLeaf newLeaf; newLeaf.ParseData(aStream); - mLeafs.append(newLeaf); + mLeafs.push_back(newLeaf); + } + + // TODO: Figure out if this is necessary + if (mLeafCount % 2 != 0) + { + //aStream->skipRawData(2); } } } void XSurfaceCollisionTree::Clear() { - + mTrans = QVector3D(); + mScale = QVector3D(); + mNodeCount = 0; + mNodes.clear(); + mLeafCount = 0; + mLeafs.clear(); } diff --git a/libs/xassets/xsurfacetri.cpp b/libs/xassets/xsurfacetri.cpp new file mode 100644 index 0000000..bb0e895 --- /dev/null +++ b/libs/xassets/xsurfacetri.cpp @@ -0,0 +1,21 @@ +#include "xsurfacetri.h" + +XSurfaceTri::XSurfaceTri() + : XAsset() + , mData() +{ + SetName("Surface Triangle"); +} + +void XSurfaceTri::ParseData(XDataStream *aStream) +{ + for (int i = 0; i < 3; i++) + { + mData.push_back(aStream->ParseUInt16(QString("%1 surface tri %2").arg(GetName()).arg(i))); + } +} + +void XSurfaceTri::Clear() +{ + mData.clear(); +} diff --git a/libs/xassets/xsurfacetri.h b/libs/xassets/xsurfacetri.h new file mode 100644 index 0000000..f27eb72 --- /dev/null +++ b/libs/xassets/xsurfacetri.h @@ -0,0 +1,18 @@ +#ifndef XSURFACETRI_H +#define XSURFACETRI_H + +#include "xasset.h" + +class XSurfaceTri : public XAsset +{ +public: + explicit XSurfaceTri(); + + void ParseData(XDataStream *aStream) override; + void Clear() override; + +private: + QVector mData; +}; + +#endif // XSURFACETRI_H diff --git a/libs/xassets/xsurfacevertexinfo.cpp b/libs/xassets/xsurfacevertexinfo.cpp index 7968b63..62a8f47 100644 --- a/libs/xassets/xsurfacevertexinfo.cpp +++ b/libs/xassets/xsurfacevertexinfo.cpp @@ -2,7 +2,7 @@ XSurfaceVertexInfo::XSurfaceVertexInfo() : XAsset() - , mVertCount(4) + , mVertCount() , mVertsBlend() { SetName("Surface Vertex Info"); @@ -10,54 +10,27 @@ XSurfaceVertexInfo::XSurfaceVertexInfo() void XSurfaceVertexInfo::ParseData(XDataStream *aStream) { - if (GetPtr() == -1) + for (int i = 0; i < 4; i++) { - *aStream >> mVertCount[0]; + mVertCount.push_back(aStream->ParseInt16(QString("%1 vertex count %2").arg(GetName()).arg(i))); + } + + qint32 vertsBlendPtr = aStream->ParseInt32(QString("%1 vertices blend ptr").arg(GetName())); + if (vertsBlendPtr == -1) + { + int vertBlendSize = 2 * (mVertCount[0] + 3 * mVertCount[1] + 5 * mVertCount[2] + 7 * mVertCount[3]); + mVertsBlend = QByteArray(vertBlendSize, Qt::Uninitialized); + aStream->readRawData(mVertsBlend.data(), vertBlendSize); + if (IsDebug()) { - qDebug() << QString("[%1] mVertCount[0] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertCount[0]); - } - - *aStream >> mVertCount[1]; - if (IsDebug()) - { - qDebug() << QString("[%1] mVertCount[1] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertCount[1]); - } - - *aStream >> mVertCount[2]; - if (IsDebug()) - { - qDebug() << QString("[%1] mVertCount[2] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertCount[2]); - } - - *aStream >> mVertCount[3]; - if (IsDebug()) - { - qDebug() << QString("[%1] mVertCount[3] = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertCount[3]); - } - - qint32 vertsBlendPtr; - *aStream >> vertsBlendPtr; - if (IsDebug()) - { - qDebug() << QString("[%1] vertsBlendPtr = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(vertsBlendPtr); - } - - - if (vertsBlendPtr == -1) - { - aStream->readRawData(mVertsBlend.data(), 2 * (mVertCount[0] + 3 * mVertCount[1] + 5 * mVertCount[2] + 7 * mVertCount[3])); - - if (IsDebug()) - { - qDebug() << QString("[%1] mVertsBlend = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertsBlend); - } - + qDebug() << QString("[%1] vertices blend = %2").arg(aStream->device()->pos(), 10, 10, QChar('0')).arg(mVertsBlend); } } } void XSurfaceVertexInfo::Clear() { - + mVertCount.clear(); + mVertsBlend.clear(); } diff --git a/libs/xassets/xweapondef.cpp b/libs/xassets/xweapondef.cpp index 8861085..0e9d596 100644 --- a/libs/xassets/xweapondef.cpp +++ b/libs/xassets/xweapondef.cpp @@ -17,6 +17,8 @@ void XWeaponDef::ParseData(XDataStream *aStream) { mInternalName = XString::ParseCustom(aStream); mDisplayName = XString::ParseCustom(aStream); mOverlayName = XString::ParseCustom(aStream); + + SetDisplayName(mInternalName); } } diff --git a/libs/xassets/xwindowdef.cpp b/libs/xassets/xwindowdef.cpp index 077fdba..4961855 100644 --- a/libs/xassets/xwindowdef.cpp +++ b/libs/xassets/xwindowdef.cpp @@ -2,7 +2,7 @@ XWindowDef::XWindowDef() : XAsset() - , mName() + , mWindowName() , mRect() , mRectClient() , mGroup() @@ -12,7 +12,7 @@ XWindowDef::XWindowDef() , mOwnerDrawFlags(0) , mBorderSize(0.0f) , mStaticFlags(0) - , mDynamicFlags(4) + , mDynamicFlags() , mNextTime(0) , mForeColor() , mBackColor() @@ -30,9 +30,7 @@ XWindowDef::~XWindowDef() void XWindowDef::ParseData(XDataStream *aStream) { - Q_UNUSED(aStream); - - mName.ParsePtr(aStream, false); + mWindowName.ParsePtr(aStream, false); mRect.ParseData(aStream); mRectClient.ParseData(aStream); @@ -46,9 +44,9 @@ void XWindowDef::ParseData(XDataStream *aStream) mBorderSize = aStream->ParseSingle(QString("%1 border size").arg(GetName())); mStaticFlags = aStream->ParseInt32(QString("%1 static flags").arg(GetName())); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 1; i++) { - mDynamicFlags[i] = aStream->ParseInt32(QString("%1 dynamic flag %2").arg(GetName()).arg(i)); + mDynamicFlags.push_back(aStream->ParseInt32(QString("%1 dynamic flag %2").arg(GetName()).arg(i))); } mNextTime = aStream->ParseInt32(QString("%1 next time").arg(GetName())); @@ -79,16 +77,13 @@ void XWindowDef::ParseData(XDataStream *aStream) a = aStream->ParseSingle(QString("%1 outline alpha").arg(GetName())); mOutlineColor = QColor(r, g, b, a); + mBackground.SetCommonInfo(GetCommonInfo()); mBackground.ParsePtr(aStream, false); - - mName.ParseData(aStream); - mGroup.ParseData(aStream); - mBackground.ParseData(aStream); } void XWindowDef::Clear() { - mName.Clear(); + mWindowName.Clear(); mRect.Clear(); mRectClient.Clear(); mGroup.Clear(); @@ -106,3 +101,173 @@ void XWindowDef::Clear() mOutlineColor = QColor(); mBackground.Clear(); } + +XString XWindowDef::WindowName() const +{ + return mWindowName; +} + +void XWindowDef::SetWindowName(const XString &aWindowName) +{ + mWindowName = aWindowName; +} + +XRectDef XWindowDef::Rect() const +{ + return mRect; +} + +void XWindowDef::SetRect(const XRectDef &aRect) +{ + mRect = aRect; +} + +XRectDef XWindowDef::RectClient() const +{ + return mRectClient; +} + +void XWindowDef::SetRectClient(const XRectDef &aRectClient) +{ + mRectClient = aRectClient; +} + +XString XWindowDef::Group() const +{ + return mGroup; +} + +void XWindowDef::SetGroup(const XString &aGroup) +{ + mGroup = aGroup; +} + +int XWindowDef::Style() const +{ + return mStyle; +} + +void XWindowDef::SetStyle(int aStyle) +{ + mStyle = aStyle; +} + +int XWindowDef::Border() const +{ + return mBorder; +} + +void XWindowDef::SetBorder(int aBorder) +{ + mBorder = aBorder; +} + +int XWindowDef::OwnerDraw() const +{ + return mOwnerDraw; +} + +void XWindowDef::SetOwnerDraw(int aOwnerDraw) +{ + mOwnerDraw = aOwnerDraw; +} + +int XWindowDef::OwnerDrawFlags() const +{ + return mOwnerDrawFlags; +} + +void XWindowDef::SetOwnerDrawFlags(int aOwnerDrawFlags) +{ + mOwnerDrawFlags = aOwnerDrawFlags; +} + +float XWindowDef::BorderSize() const +{ + return mBorderSize; +} + +void XWindowDef::SetBorderSize(float aBorderSize) +{ + mBorderSize = aBorderSize; +} + +int XWindowDef::StaticFlags() const +{ + return mStaticFlags; +} + +void XWindowDef::SetStaticFlags(int aStaticFlags) +{ + mStaticFlags = aStaticFlags; +} + +QVector XWindowDef::DynamicFlags() const +{ + return mDynamicFlags; +} + +void XWindowDef::SetDynamicFlags(const QVector &aDynamicFlags) +{ + mDynamicFlags = aDynamicFlags; +} + +int XWindowDef::NextTime() const +{ + return mNextTime; +} + +void XWindowDef::SetNextTime(int aNextTime) +{ + mNextTime = aNextTime; +} + +QColor XWindowDef::ForeColor() const +{ + return mForeColor; +} + +void XWindowDef::SetForeColor(const QColor &aForeColor) +{ + mForeColor = aForeColor; +} + +QColor XWindowDef::BackColor() const +{ + return mBackColor; +} + +void XWindowDef::SetBackColor(const QColor &aBackColor) +{ + mBackColor = aBackColor; +} + +QColor XWindowDef::BorderColor() const +{ + return mBorderColor; +} + +void XWindowDef::SetBorderColor(const QColor &aBorderColor) +{ + mBorderColor = aBorderColor; +} + +QColor XWindowDef::OutlineColor() const +{ + return mOutlineColor; +} + +void XWindowDef::SetOutlineColor(const QColor &aOutlineColor) +{ + mOutlineColor = aOutlineColor; +} + +XMaterial XWindowDef::Background() const +{ + return mBackground; +} + +void XWindowDef::SetBackground(const XMaterial &aBackground) +{ + mBackground = aBackground; +} diff --git a/libs/xassets/xwindowdef.h b/libs/xassets/xwindowdef.h index 3685a72..f1b66a9 100644 --- a/libs/xassets/xwindowdef.h +++ b/libs/xassets/xwindowdef.h @@ -16,8 +16,43 @@ public: void ParseData(XDataStream *aStream) override; void Clear() override; + XString WindowName() const; + void SetWindowName(const XString &aWindowName); + XRectDef Rect() const; + void SetRect(const XRectDef &aRect); + XRectDef RectClient() const; + void SetRectClient(const XRectDef &aRectClient); + XString Group() const; + void SetGroup(const XString &aGroup); + int Style() const; + void SetStyle(int aStyle); + int Border() const; + void SetBorder(int aBorder); + int OwnerDraw() const; + void SetOwnerDraw(int aOwnerDraw); + int OwnerDrawFlags() const; + void SetOwnerDrawFlags(int aOwnerDrawFlags); + float BorderSize() const; + void SetBorderSize(float aBorderSize); + int StaticFlags() const; + void SetStaticFlags(int aStaticFlags); + QVector DynamicFlags() const; + void SetDynamicFlags(const QVector &aDynamicFlags); + int NextTime() const; + void SetNextTime(int aNextTime); + QColor ForeColor() const; + void SetForeColor(const QColor &aForeColor); + QColor BackColor() const; + void SetBackColor(const QColor &aBackColor); + QColor BorderColor() const; + void SetBorderColor(const QColor &aBorderColor); + QColor OutlineColor() const; + void SetOutlineColor(const QColor &aOutlineColor); + XMaterial Background() const; + void SetBackground(const XMaterial &aBackground); + private: - XString mName; + XString mWindowName; XRectDef mRect; XRectDef mRectClient; XString mGroup; diff --git a/libs/zonefile/360/zonefile_cod10_360.cpp b/libs/zonefile/360/zonefile_cod10_360.cpp index ab79c9a..c9572f1 100644 --- a/libs/zonefile/360/zonefile_cod10_360.cpp +++ b/libs/zonefile/360/zonefile_cod10_360.cpp @@ -13,7 +13,7 @@ ZoneFile_COD10_360::ZoneFile_COD10_360() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/360/zonefile_cod2_360.cpp b/libs/zonefile/360/zonefile_cod2_360.cpp index 8931e4c..7e6a4ec 100644 --- a/libs/zonefile/360/zonefile_cod2_360.cpp +++ b/libs/zonefile/360/zonefile_cod2_360.cpp @@ -15,7 +15,7 @@ ZoneFile_COD2_360::ZoneFile_COD2_360() //pSetType(-1, ASSET_TYPE_FX); //pSetType(-1, ASSET_TYPE_SOUND); //pSetType(-1, ASSET_TYPE_XANIMPARTS); - //pSetType(-1, ASSET_TYPE_COLLISION_MAP); + //pSetType(-1, ASSET_TYPE_COL_MAP_MP); //pSetType(-1, ASSET_TYPE_STRINGTABLE); //pSetType(-1, ASSET_TYPE_MENU); //pSetType(-1, ASSET_TYPE_TECHNIQUE_SET); diff --git a/libs/zonefile/360/zonefile_cod5_360.cpp b/libs/zonefile/360/zonefile_cod5_360.cpp index 5c4fb92..17c5a9b 100644 --- a/libs/zonefile/360/zonefile_cod5_360.cpp +++ b/libs/zonefile/360/zonefile_cod5_360.cpp @@ -15,7 +15,7 @@ ZoneFile_COD5_360::ZoneFile_COD5_360() pSetType(8, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/360/zonefile_cod6_360.cpp b/libs/zonefile/360/zonefile_cod6_360.cpp index 3cb6a29..cefce63 100644 --- a/libs/zonefile/360/zonefile_cod6_360.cpp +++ b/libs/zonefile/360/zonefile_cod6_360.cpp @@ -279,7 +279,7 @@ bool ZoneFile_COD6_360::Load(const QByteArray aFileData) { // result.images << pParseASSET_TYPE_IMAGE(aZoneFileStream); // } else if (assetType == ASSET_TYPE_SOUND) { // loaded_sound // result.sounds << pParseASSET_TYPE_SOUND(aZoneFileStream); -// } else if (assetType == ASSET_TYPE_COLLISION_MAP) { // col_map_mp +// } else if (assetType == ASSET_TYPE_COL_MAP_MP) { // col_map_mp // pParseAsset_ColMapMP(aZoneFileStream); // } else if (assetType == ASSET_MP_MAP) { // game_map_sp // pParseAsset_GameMapSP(aZoneFileStream); diff --git a/libs/zonefile/360/zonefile_cod9_360.cpp b/libs/zonefile/360/zonefile_cod9_360.cpp index df8452f..a73f9cb 100644 --- a/libs/zonefile/360/zonefile_cod9_360.cpp +++ b/libs/zonefile/360/zonefile_cod9_360.cpp @@ -13,7 +13,7 @@ ZoneFile_COD9_360::ZoneFile_COD9_360() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/PC/zonefile_cod10_pc.cpp b/libs/zonefile/PC/zonefile_cod10_pc.cpp index e99eeb3..d41fda2 100644 --- a/libs/zonefile/PC/zonefile_cod10_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod10_pc.cpp @@ -9,7 +9,7 @@ ZoneFile_COD10_PC::ZoneFile_COD10_PC() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/PC/zonefile_cod11_pc.cpp b/libs/zonefile/PC/zonefile_cod11_pc.cpp index 904e5ca..571d552 100644 --- a/libs/zonefile/PC/zonefile_cod11_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod11_pc.cpp @@ -9,7 +9,7 @@ ZoneFile_COD11_PC::ZoneFile_COD11_PC() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/PC/zonefile_cod21_pc.cpp b/libs/zonefile/PC/zonefile_cod21_pc.cpp new file mode 100644 index 0000000..5d54929 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod21_pc.cpp @@ -0,0 +1,81 @@ +#include "zonefile_cod21_pc.h" + +ZoneFile_COD21_PC::ZoneFile_COD21_PC() + : ZoneFile() +{ + pSetType(0, ASSET_TYPE_PHYSPRESET); + pSetType(1, ASSET_TYPE_PHYS_CONSTRAINTS); + pSetType(2, ASSET_TYPE_DESTRUCTIBLE_DEF); + pSetType(3, ASSET_TYPE_XANIMPARTS); + pSetType(4, ASSET_TYPE_XMODEL); + pSetType(5, ASSET_TYPE_XMODEL_MESH); + pSetType(6, ASSET_TYPE_MATERIAL); + pSetType(7, ASSET_TYPE_COMPUTE_SHADER_SET); + pSetType(8, ASSET_TYPE_TECHNIQUE_SET); + pSetType(9, ASSET_TYPE_IMAGE); + pSetType(10, ASSET_TYPE_SOUND); + pSetType(17, ASSET_TYPE_LIGHT_DEF); + pSetType(21, ASSET_TYPE_FONT_ICON); + pSetType(23, ASSET_TYPE_WEAPON); + pSetType(27, ASSET_TYPE_CG_MEDIA_TABLE); + pSetType(28, ASSET_TYPE_PLAYER_SOUNDS_TABLE); + pSetType(29, ASSET_TYPE_PLAYER_FX_TABLE); + pSetType(30, ASSET_TYPE_SHARED_WEAPON_SOUNDS); + pSetType(31, ASSET_TYPE_ATTACHMENT); + pSetType(32, ASSET_TYPE_ATTACHMENT_UNIQUE); + pSetType(33, ASSET_TYPE_WEAPON_CAMO); + pSetType(34, ASSET_TYPE_CUSTOMIZATION_TABLE); + pSetType(35, ASSET_TYPE_CUSTOMIZATION_TABLE_FEIMAGES); + pSetType(36, ASSET_TYPE_CUSTOMIZATION_TABLE_COLOR); + pSetType(38, ASSET_TYPE_FX); + pSetType(47, ASSET_TYPE_RAWFILE); + pSetType(48, ASSET_TYPE_STRINGTABLE); + pSetType(49, ASSET_TYPE_STRUCTURED_TABLE); + pSetType(50, ASSET_TYPE_LEADERBOARD_DEF); + pSetType(51, ASSET_TYPE_DDL); + pSetType(54, ASSET_TYPE_SCRIPT_PARSE_TREE); + pSetType(55, ASSET_TYPE_KEY_VALUE_PAIRS); + pSetType(56, ASSET_TYPE_VEHICLE); + pSetType(58, ASSET_TYPE_VEHICLE_TRACER); + pSetType(60, ASSET_TYPE_SURFACE_FX_TABLE); + pSetType(61, ASSET_TYPE_SURFACE_SOUND_DEF); + pSetType(62, ASSET_TYPE_FOOTSTEP_TABLE); + pSetType(63, ASSET_TYPE_ENTITY_FX_IMPACTS); + pSetType(64, ASSET_TYPE_ENTITY_SOUND_IMPACTS); + pSetType(66, ASSET_TYPE_VEHICLE_FX_DEF); + pSetType(67, ASSET_TYPE_VEHICLE_SOUND_DEF); + pSetType(69, ASSET_TYPE_SCRIPT_BUNDLE); + pSetType(70, ASSET_TYPE_SCRIPT_BUNDLE_LIST); + pSetType(71, ASSET_TYPE_RUMBLE); + pSetType(74, ASSET_TYPE_AIM_TABLE); + pSetType(75, ASSET_TYPE_ANIM_SELECTOR_TABLE); + pSetType(76, ASSET_TYPE_ANIM_MAPPING_TABLE); + pSetType(77, ASSET_TYPE_ANIM_STATE_MACHINE); + pSetType(78, ASSET_TYPE_BEHAVIOR_TREE); + pSetType(79, ASSET_TYPE_BEHAVIOR_STATE_MACHINE); + pSetType(81, ASSET_TYPE_S_ANIM); + pSetType(82, ASSET_TYPE_LIGHT_DEF); + pSetType(83, ASSET_TYPE_BIT_FIELD); + pSetType(84, ASSET_TYPE_SURFACE_SOUND_DEF); + pSetType(85, ASSET_TYPE_SURFACE_FX_TABLE); + pSetType(86, ASSET_TYPE_RUMBLE); + pSetType(89, ASSET_TYPE_AIM_TABLE); + pSetType(90, ASSET_TYPE_MAP_TABLE); + pSetType(91, ASSET_TYPE_MAP_TABLE_LOADING_IMAGES); + pSetType(92, ASSET_TYPE_MEDAL); + pSetType(93, ASSET_TYPE_MEDAL_TABLE); + pSetType(94, ASSET_TYPE_OBJECTIVE); + pSetType(95, ASSET_TYPE_OBJECTIVE_LIST); + pSetType(100, ASSET_TYPE_LASER); + pSetType(101, ASSET_TYPE_BEAM); + pSetType(102, ASSET_TYPE_STREAMER_HINT); +} + +ZoneFile_COD21_PC::~ZoneFile_COD21_PC() +{ + +} + +bool ZoneFile_COD21_PC::Load(const QByteArray aFileData) { + return true;//ZoneFile::Load(aFileData); +} diff --git a/libs/zonefile/PC/zonefile_cod21_pc.h b/libs/zonefile/PC/zonefile_cod21_pc.h new file mode 100644 index 0000000..c98d864 --- /dev/null +++ b/libs/zonefile/PC/zonefile_cod21_pc.h @@ -0,0 +1,16 @@ +#ifndef ZONEFILE_COD21_PC_H +#define ZONEFILE_COD21_PC_H + +#include "zonefile.h" + +class ZoneFile_COD21_PC : public ZoneFile +{ +public: + ZoneFile_COD21_PC(); + ~ZoneFile_COD21_PC(); + + bool Load(const QByteArray aFileData) override; + +}; + +#endif // ZONEFILE_COD21_PC_H diff --git a/libs/zonefile/PC/zonefile_cod4_pc.cpp b/libs/zonefile/PC/zonefile_cod4_pc.cpp index 6565b40..a4e1c2b 100644 --- a/libs/zonefile/PC/zonefile_cod4_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod4_pc.cpp @@ -3,29 +3,38 @@ ZoneFile_COD4_PC::ZoneFile_COD4_PC() : ZoneFile() { + pSetType(0, ASSET_TYPE_XMODELPIECES); pSetType(1, ASSET_TYPE_PHYSPRESET); pSetType(2, ASSET_TYPE_XANIMPARTS); pSetType(3, ASSET_TYPE_XMODEL); - pSetType(5, ASSET_TYPE_DESTRUCTIBLE); + pSetType(4, ASSET_TYPE_MATERIAL); + pSetType(5, ASSET_TYPE_TECHNIQUE_SET); pSetType(6, ASSET_TYPE_IMAGE); - pSetType(7, ASSET_TYPE_TECHNIQUE_SET); - pSetType(10, ASSET_TYPE_COL_MAP_SP); - pSetType(11, ASSET_TYPE_COLLISION_MAP); - pSetType(12, ASSET_TYPE_D3DBSP); - pSetType(13, ASSET_TYPE_GAME_MAP_SP); - pSetType(16, ASSET_TYPE_GFX_MAP); - pSetType(18, ASSET_TYPE_LIGHT_DEF); - pSetType(20, ASSET_TYPE_MENU); - pSetType(21, ASSET_TYPE_FONT); - pSetType(22, ASSET_TYPE_SOUND); - pSetType(23, ASSET_TYPE_WEAPON); - pSetType(24, ASSET_TYPE_LOCALIZE_ENTRY); - pSetType(25, ASSET_TYPE_FX); - pSetType(26, ASSET_TYPE_UI_MAP); - pSetType(31, ASSET_TYPE_RAWFILE); - pSetType(32, ASSET_TYPE_SCRIPT_PARSE_TREE); - pSetType(33, ASSET_TYPE_STRINGTABLE); - + pSetType(7, ASSET_TYPE_PIXELSHADER); + pSetType(8, ASSET_TYPE_SOUND_CURVE); + pSetType(9, ASSET_TYPE_LOADED_SOUND); + pSetType(0xA, ASSET_TYPE_COL_MAP_MP); + pSetType(0xB, ASSET_TYPE_COL_MAP_SP); + pSetType(0xC, ASSET_TYPE_COM_MAP); + pSetType(0xD, ASSET_TYPE_GAME_MAP_SP); + pSetType(0xE, ASSET_TYPE_GAME_MAP_MP); + pSetType(0xF, ASSET_TYPE_MAP_ENTS); + pSetType(0x10, ASSET_TYPE_GFX_MAP); + pSetType(0x11, ASSET_TYPE_LIGHT_DEF); + pSetType(0x12, ASSET_TYPE_UI_MAP); + pSetType(0x13, ASSET_TYPE_FONT); + pSetType(0x14, ASSET_TYPE_MENULIST); + pSetType(0x15, ASSET_TYPE_MENU); + pSetType(0x16, ASSET_TYPE_LOCALIZE_ENTRY); + pSetType(0x17, ASSET_TYPE_WEAPON); + pSetType(0x18, ASSET_TYPE_SNDDRIVER_GLOBALS); + pSetType(0x19, ASSET_TYPE_IMPACT_FX); + pSetType(0x1A, ASSET_TYPE_AITYPE); + pSetType(0x1B, ASSET_TYPE_MPTYPE); + pSetType(0x1C, ASSET_TYPE_CHARACTER); + pSetType(0x1D, ASSET_TYPE_XMODELALIAS); + pSetType(0x1F, ASSET_TYPE_RAWFILE); + pSetType(0x20, ASSET_TYPE_STRINGTABLE); } ZoneFile_COD4_PC::~ZoneFile_COD4_PC() { @@ -33,5 +42,5 @@ ZoneFile_COD4_PC::~ZoneFile_COD4_PC() { } bool ZoneFile_COD4_PC::Load(const QByteArray aFileData) { - return true; + return ZoneFile::Load(aFileData); } diff --git a/libs/zonefile/PC/zonefile_cod5_pc.cpp b/libs/zonefile/PC/zonefile_cod5_pc.cpp index e28dc8c..9ea734d 100644 --- a/libs/zonefile/PC/zonefile_cod5_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod5_pc.cpp @@ -7,11 +7,11 @@ ZoneFile_COD5_PC::ZoneFile_COD5_PC() pSetType(3, ASSET_TYPE_DESTRUCTIBLE); pSetType(4, ASSET_TYPE_XANIMPARTS); pSetType(5, ASSET_TYPE_XMODEL); - pSetType(6, ASSET_TYPE_IMAGE); + pSetType(6, ASSET_TYPE_MATERIAL); pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); @@ -31,5 +31,5 @@ ZoneFile_COD5_PC::~ZoneFile_COD5_PC() { } bool ZoneFile_COD5_PC::Load(const QByteArray aFileData) { - return true; + return ZoneFile::Load(aFileData); } diff --git a/libs/zonefile/PC/zonefile_cod6_pc.cpp b/libs/zonefile/PC/zonefile_cod6_pc.cpp index 2f05c08..0a3cac4 100644 --- a/libs/zonefile/PC/zonefile_cod6_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod6_pc.cpp @@ -11,7 +11,7 @@ ZoneFile_COD6_PC::ZoneFile_COD6_PC() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/PC/zonefile_cod7_pc.cpp b/libs/zonefile/PC/zonefile_cod7_pc.cpp index cc32880..ddd9eff 100644 --- a/libs/zonefile/PC/zonefile_cod7_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod7_pc.cpp @@ -48,12 +48,6 @@ ZoneFile_COD7_PC::ZoneFile_COD7_PC() pSetType(42, ASSET_TYPE_EMBLEMSET); pSetType(43, ASSET_TYPE_COUNT); pSetType(44, ASSET_TYPE_ASSETLIST); - -} - -ZoneFile_COD7_PC::~ZoneFile_COD7_PC() -{ - } bool ZoneFile_COD7_PC::Load(const QByteArray aFileData) { diff --git a/libs/zonefile/PC/zonefile_cod7_pc.h b/libs/zonefile/PC/zonefile_cod7_pc.h index 6293c04..5fc5f82 100644 --- a/libs/zonefile/PC/zonefile_cod7_pc.h +++ b/libs/zonefile/PC/zonefile_cod7_pc.h @@ -7,10 +7,9 @@ class ZoneFile_COD7_PC : public ZoneFile { public: ZoneFile_COD7_PC(); - ~ZoneFile_COD7_PC(); + ~ZoneFile_COD7_PC() = default; bool Load(const QByteArray aFileData) override; - }; #endif // ZONEFILE_COD7_PC_H diff --git a/libs/zonefile/PC/zonefile_cod8_pc.cpp b/libs/zonefile/PC/zonefile_cod8_pc.cpp index 16bf686..b3bc9c8 100644 --- a/libs/zonefile/PC/zonefile_cod8_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod8_pc.cpp @@ -9,7 +9,7 @@ ZoneFile_COD8_PC::ZoneFile_COD8_PC() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/PC/zonefile_cod9_pc.cpp b/libs/zonefile/PC/zonefile_cod9_pc.cpp index 75b4e4d..67c4682 100644 --- a/libs/zonefile/PC/zonefile_cod9_pc.cpp +++ b/libs/zonefile/PC/zonefile_cod9_pc.cpp @@ -9,7 +9,7 @@ ZoneFile_COD9_PC::ZoneFile_COD9_PC() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(17, ASSET_TYPE_GFX_MAP); diff --git a/libs/zonefile/PS3/zonefile_cod10_ps3.cpp b/libs/zonefile/PS3/zonefile_cod10_ps3.cpp index 0cc8dd5..a9a0976 100644 --- a/libs/zonefile/PS3/zonefile_cod10_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod10_ps3.cpp @@ -13,7 +13,7 @@ ZoneFile_COD10_PS3::ZoneFile_COD10_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod11_ps3.cpp b/libs/zonefile/PS3/zonefile_cod11_ps3.cpp index cf8a138..4cec463 100644 --- a/libs/zonefile/PS3/zonefile_cod11_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod11_ps3.cpp @@ -13,7 +13,7 @@ ZoneFile_COD11_PS3::ZoneFile_COD11_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod12_ps3.cpp b/libs/zonefile/PS3/zonefile_cod12_ps3.cpp index 5bd0d9f..7386009 100644 --- a/libs/zonefile/PS3/zonefile_cod12_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod12_ps3.cpp @@ -13,7 +13,7 @@ ZoneFile_COD12_PS3::ZoneFile_COD12_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod5_ps3.cpp b/libs/zonefile/PS3/zonefile_cod5_ps3.cpp index f048241..d1d0479 100644 --- a/libs/zonefile/PS3/zonefile_cod5_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod5_ps3.cpp @@ -15,7 +15,7 @@ ZoneFile_COD5_PS3::ZoneFile_COD5_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod6_ps3.cpp b/libs/zonefile/PS3/zonefile_cod6_ps3.cpp index dc3654c..c845bac 100644 --- a/libs/zonefile/PS3/zonefile_cod6_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod6_ps3.cpp @@ -11,7 +11,7 @@ ZoneFile_COD6_PS3::ZoneFile_COD6_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod7_ps3.cpp b/libs/zonefile/PS3/zonefile_cod7_ps3.cpp index f3ed648..eacf36e 100644 --- a/libs/zonefile/PS3/zonefile_cod7_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod7_ps3.cpp @@ -13,7 +13,7 @@ ZoneFile_COD7_PS3::ZoneFile_COD7_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod8_ps3.cpp b/libs/zonefile/PS3/zonefile_cod8_ps3.cpp index bc278c3..93b81a6 100644 --- a/libs/zonefile/PS3/zonefile_cod8_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod8_ps3.cpp @@ -13,7 +13,7 @@ ZoneFile_COD8_PS3::ZoneFile_COD8_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/PS3/zonefile_cod9_ps3.cpp b/libs/zonefile/PS3/zonefile_cod9_ps3.cpp index 0336b94..c2828ca 100644 --- a/libs/zonefile/PS3/zonefile_cod9_ps3.cpp +++ b/libs/zonefile/PS3/zonefile_cod9_ps3.cpp @@ -12,7 +12,7 @@ ZoneFile_COD9_PS3::ZoneFile_COD9_PS3() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/Wii/zonefile_cod4_wii.cpp b/libs/zonefile/Wii/zonefile_cod4_wii.cpp index 50f9d30..ea7471e 100644 --- a/libs/zonefile/Wii/zonefile_cod4_wii.cpp +++ b/libs/zonefile/Wii/zonefile_cod4_wii.cpp @@ -13,7 +13,7 @@ ZoneFile_COD4_Wii::ZoneFile_COD4_Wii() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/Wii/zonefile_cod7_wii.cpp b/libs/zonefile/Wii/zonefile_cod7_wii.cpp index d0ca04a..04e0d3b 100644 --- a/libs/zonefile/Wii/zonefile_cod7_wii.cpp +++ b/libs/zonefile/Wii/zonefile_cod7_wii.cpp @@ -13,7 +13,7 @@ ZoneFile_COD7_Wii::ZoneFile_COD7_Wii() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/Wii/zonefile_cod8_wii.cpp b/libs/zonefile/Wii/zonefile_cod8_wii.cpp index 0cd4b3a..05d00ea 100644 --- a/libs/zonefile/Wii/zonefile_cod8_wii.cpp +++ b/libs/zonefile/Wii/zonefile_cod8_wii.cpp @@ -13,7 +13,7 @@ ZoneFile_COD8_Wii::ZoneFile_COD8_Wii() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp b/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp index ee3912f..d9ddc2c 100644 --- a/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp +++ b/libs/zonefile/WiiU/zonefile_cod10_wiiu.cpp @@ -13,7 +13,7 @@ ZoneFile_COD10_WiiU::ZoneFile_COD10_WiiU() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp b/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp index f96505a..5d583e1 100644 --- a/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp +++ b/libs/zonefile/WiiU/zonefile_cod9_wiiu.cpp @@ -13,7 +13,7 @@ ZoneFile_COD9_WiiU::ZoneFile_COD9_WiiU() pSetType(7, ASSET_TYPE_TECHNIQUE_SET); pSetType(9, ASSET_TYPE_SOUND); pSetType(11, ASSET_TYPE_COL_MAP_SP); - pSetType(12, ASSET_TYPE_COLLISION_MAP); + pSetType(12, ASSET_TYPE_COL_MAP_MP); pSetType(13, ASSET_TYPE_D3DBSP); pSetType(14, ASSET_TYPE_GAME_MAP_SP); pSetType(15, ASSET_TYPE_MENU); diff --git a/libs/zonefile/zonefile.cpp b/libs/zonefile/zonefile.cpp index 4ad7392..0bd60e8 100644 --- a/libs/zonefile/zonefile.cpp +++ b/libs/zonefile/zonefile.cpp @@ -1,52 +1,59 @@ #include "zonefile.h" #include "xassetlist.h" #include "xfile.h" +#include "xdatastream.h" +#include "xcommoninfo.h" #include -#include "xdatastream.h" #include -ZoneFile::ZoneFile() : - mStem(), - mSize(), - mTagCount(), - mTags(), - mRecordCount(), - mRecords(), - mPlatform(), - mGame(), - mTypeMap(), - mHeaderData(), - mAssetList(this) +ZoneFile::ZoneFile() + : mStem() + , mSize() + , mTagCount() + , mTags() + , mRecordCount() + , mRecords() + , mCommonInfo(nullptr) + , mTypeMap() + , mHeaderData() + , mAssetList(this) + , mDebug(false) { } -ZoneFile::~ZoneFile() { +ZoneFile::ZoneFile(const ZoneFile &aZoneFile) + : mStem(aZoneFile.mStem) + , mSize(aZoneFile.mSize) + , mTagCount(aZoneFile.mTagCount) + , mTags(aZoneFile.mTags) + , mRecordCount(aZoneFile.mRecordCount) + , mRecords(aZoneFile.mRecords) + , mAssetTypes(aZoneFile.mAssetTypes) + , mCommonInfo(aZoneFile.mCommonInfo) + , mTypeMap(aZoneFile.mTypeMap) + , mHeaderData(aZoneFile.mHeaderData) + , mAssetList(aZoneFile.mAssetList) +{ } -ZoneFile::ZoneFile(const ZoneFile &aZoneFile) { - mStem = aZoneFile.mStem; - mSize = aZoneFile.mSize; - mTagCount = aZoneFile.mTagCount; - mTags = aZoneFile.mTags; - mRecordCount = aZoneFile.mRecordCount; - mRecords = aZoneFile.mRecords; - mAssetList = aZoneFile.mAssetList; - mHeaderData = aZoneFile.mHeaderData; -} - -ZoneFile &ZoneFile::operator=(const ZoneFile &other) { - if (this != &other) { - mStem = other.mStem; - mSize = other.mSize; - mTagCount = other.mTagCount; - mTags = other.mTags; +ZoneFile &ZoneFile::operator=(const ZoneFile &other) +{ + if (this != &other) + { + mStem = other.mStem; + mSize = other.mSize; + mTagCount = other.mTagCount; + mTags = other.mTags; mRecordCount = other.mRecordCount; - mRecords = other.mRecords; - mAssetList = other.mAssetList; - mHeaderData = other.mHeaderData; + mRecords = other.mRecords; + mAssetTypes = other.mAssetTypes; + mCommonInfo = other.mCommonInfo; + mTypeMap = other.mTypeMap; + mHeaderData = other.mHeaderData; + mAssetList = other.mAssetList; } return *this; } @@ -54,9 +61,17 @@ ZoneFile &ZoneFile::operator=(const ZoneFile &other) { bool ZoneFile::Load(const QByteArray aFileData) { XDataStream zoneStream(aFileData); - zoneStream.SetDebug(); + zoneStream.SetDebug(mDebug); + if (GetCommonInfo()->GetPlatform() == PLATFORM_PC) + { + zoneStream.setByteOrder(QDataStream::LittleEndian); + } + + mHeaderData.SetCommonInfo(mCommonInfo); mHeaderData.ParseData(&zoneStream); + + mAssetList.SetCommonInfo(mCommonInfo); mAssetList.ParseData(&zoneStream); return true; @@ -173,3 +188,58 @@ void ZoneFile::pSetType(quint32 aRawType, XAssetType aType) { mTypeMap[aRawType] = aType; } + +quint32 ZoneFile::RecordCount() const +{ + return mRecordCount; +} + +QStringList ZoneFile::Records() const +{ + return mRecords; +} + +QVector ZoneFile::AssetTypes() const +{ + return mAssetTypes; +} + +void ZoneFile::SetAssetTypes(const QVector &aAssetTypes) +{ + mAssetTypes = aAssetTypes; +} + +QMap ZoneFile::TypeMap() const +{ + return mTypeMap; +} + +void ZoneFile::SetTypeMap(const QMap &aTypeMap) +{ + mTypeMap = aTypeMap; +} + +XFile ZoneFile::HeaderData() const +{ + return mHeaderData; +} + +bool ZoneFile::Debug() const +{ + return mDebug; +} + +void ZoneFile::SetDebug(bool aDebug) +{ + mDebug = aDebug; +} + +const XCommonInfo *ZoneFile::GetCommonInfo() const +{ + return mCommonInfo; +} + +void ZoneFile::SetCommonInfo(const XCommonInfo *newCommonInfo) +{ + mCommonInfo = newCommonInfo; +} diff --git a/libs/zonefile/zonefile.h b/libs/zonefile/zonefile.h index ed1012c..0716dc7 100644 --- a/libs/zonefile/zonefile.h +++ b/libs/zonefile/zonefile.h @@ -13,7 +13,7 @@ class ZoneFile { public: ZoneFile(); - ~ZoneFile(); + virtual ~ZoneFile() = default; ZoneFile(const ZoneFile &aZoneFile); ZoneFile &operator=(const ZoneFile &other); @@ -40,6 +40,19 @@ public: void SetAssetList(XAssetList aAssetList); XAssetType GetType(quint32 aRawType) const; + const XCommonInfo *GetCommonInfo() const; + void SetCommonInfo(const XCommonInfo *newCommonInfo); + + quint32 RecordCount() const; + QStringList Records() const; + QVector AssetTypes() const; + void SetAssetTypes(const QVector &aAssetTypes); + QMap TypeMap() const; + void SetTypeMap(const QMap &aTypeMap); + XFile HeaderData() const; + bool Debug() const; + void SetDebug(bool aDebug); + protected: void pSetType(quint32 aRawType, XAssetType aType); @@ -51,13 +64,14 @@ private: quint32 mRecordCount; QStringList mRecords; QVector mAssetTypes; - QString mPlatform; - QString mGame; + const XCommonInfo* mCommonInfo; QMap mTypeMap; XFile mHeaderData; XAssetList mAssetList; + + bool mDebug; }; #endif // ZONEFILE_H diff --git a/third_party/oodle_lib/dll/oo2core_8_win64.dll b/third_party/oodle_lib/dll/oo2core_8_win64.dll new file mode 100644 index 0000000000000000000000000000000000000000..68548cfe5cc633904f400a43bdb00845915b16ba GIT binary patch literal 972792 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℘m})df|GsQS81B(_SNVSJYyD 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

  • DQm&QxTMTubt|DCF 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 literal 0 HcmV?d00001 diff --git a/tools/asset_assess/mainwindow.cpp b/tools/asset_assess/mainwindow.cpp index 34ec669..f3e7300 100644 --- a/tools/asset_assess/mainwindow.cpp +++ b/tools/asset_assess/mainwindow.cpp @@ -29,7 +29,8 @@ void MainWindow::LogLine(const QString &aLogText) if (mTextEdit->toPlainText().isEmpty()) { mTextEdit->setPlainText(aLogText); } else { - mTextEdit->setPlainText(mTextEdit->toPlainText() + "\r\n" + aLogText); + mTextEdit->setPlainText(mTextEdit->toPlainText() + " +" + aLogText); } }
  • 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%0DN!6KFry4nGXa1NE?i47?Y}M)hy;{psP*e09 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·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