mirror of
https://github.com/redstrate/Novus.git
synced 2025-05-01 15:57:45 +00:00
Decompile Lua bytecode in Data Explorer
The game has *tons* of Lua scripts for event scripting, and are very interesting to explore. I had to do manually call luadec before, but now it should be much easier by automatically decompiling Lua scripts in the Data Explorer.
This commit is contained in:
parent
365d75c754
commit
dab4a698b2
11 changed files with 126 additions and 5 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,3 +4,6 @@
|
|||
[submodule "extern/dxbc"]
|
||||
path = extern/dxbc
|
||||
url = ../dxbc
|
||||
[submodule "extern/luadec51"]
|
||||
path = extern/luadec51
|
||||
url = ../luadec51
|
||||
|
|
|
@ -45,6 +45,7 @@ target_link_libraries(novus-sagasu
|
|||
Novus::TexPart
|
||||
Novus::DicPart
|
||||
Novus::MtrlPart
|
||||
Novus::LuabPart
|
||||
Physis::Logger
|
||||
Qt6::Concurrent
|
||||
Qt6::Network)
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "filepropertieswindow.h"
|
||||
#include "filetypes.h"
|
||||
#include "hexpart.h"
|
||||
#include "luabpart.h"
|
||||
#include "mdlpart.h"
|
||||
#include "mtrlpart.h"
|
||||
#include "shpkpart.h"
|
||||
|
@ -173,6 +174,11 @@ void MainWindow::refreshParts(const QString &path)
|
|||
mtrlWidget->load(physis_material_parse(file));
|
||||
partHolder->addTab(mtrlWidget, i18nc("@title:tab", "Material"));
|
||||
} break;
|
||||
case FileType::LuaBytecode: {
|
||||
auto luabWidget = new LuabPart();
|
||||
luabWidget->load(file);
|
||||
partHolder->addTab(luabWidget, i18nc("@title:tab", "Lua"));
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,20 @@
|
|||
|
||||
#include "novuscommon_export.h"
|
||||
|
||||
enum class FileType { Unknown, ExcelList, ExcelHeader, ExcelData, Model, Texture, ShaderPackage, CharaMakeParams, Skeleton, Dictionary, Material };
|
||||
enum class FileType {
|
||||
Unknown,
|
||||
ExcelList,
|
||||
ExcelHeader,
|
||||
ExcelData,
|
||||
Model,
|
||||
Texture,
|
||||
ShaderPackage,
|
||||
CharaMakeParams,
|
||||
Skeleton,
|
||||
Dictionary,
|
||||
Material,
|
||||
LuaBytecode
|
||||
};
|
||||
|
||||
class NOVUSCOMMON_EXPORT FileTypes
|
||||
{
|
||||
|
|
|
@ -15,7 +15,8 @@ const static QMap<QString, FileType> extensionToType{{QStringLiteral("exl"), Fil
|
|||
{QStringLiteral("cmp"), FileType::CharaMakeParams},
|
||||
{QStringLiteral("sklb"), FileType::Skeleton},
|
||||
{QStringLiteral("dic"), FileType::Dictionary},
|
||||
{QStringLiteral("mtrl"), FileType::Material}};
|
||||
{QStringLiteral("mtrl"), FileType::Material},
|
||||
{QStringLiteral("luab"), FileType::LuaBytecode}};
|
||||
|
||||
const static QMap<FileType, QString> typeToName{{FileType::Unknown, i18n("Unknown")},
|
||||
{FileType::ExcelList, i18n("Excel List")},
|
||||
|
@ -27,7 +28,8 @@ const static QMap<FileType, QString> typeToName{{FileType::Unknown, i18n("Unknow
|
|||
{FileType::CharaMakeParams, i18n("Chara Make Params")},
|
||||
{FileType::Skeleton, i18n("Skeleton")},
|
||||
{FileType::Dictionary, i18n("Dictionary")},
|
||||
{FileType::Material, i18n("Material")}};
|
||||
{FileType::Material, i18n("Material")},
|
||||
{FileType::LuaBytecode, i18n("Lua Bytecode")}};
|
||||
|
||||
const static QMap<FileType, QString> typeToIcon{{FileType::Unknown, QStringLiteral("unknown")},
|
||||
{FileType::ExcelList, QStringLiteral("x-office-spreadsheet")},
|
||||
|
@ -39,7 +41,8 @@ const static QMap<FileType, QString> typeToIcon{{FileType::Unknown, QStringLiter
|
|||
{FileType::CharaMakeParams, QStringLiteral("step_object_SoftBody-symbolic")},
|
||||
{FileType::Skeleton, QStringLiteral("user-symbolic")},
|
||||
{FileType::Dictionary, QStringLiteral("accessories-dictionary-symbolic")},
|
||||
{FileType::Material, QStringLiteral("map-globe-symbolic")}};
|
||||
{FileType::Material, QStringLiteral("map-globe-symbolic")},
|
||||
{FileType::LuaBytecode, QStringLiteral("text-x-lua")}};
|
||||
|
||||
FileType FileTypes::getFileType(const QString &extension)
|
||||
{
|
||||
|
|
5
extern/CMakeLists.txt
vendored
5
extern/CMakeLists.txt
vendored
|
@ -23,3 +23,8 @@ add_subdirectory(magic_enum EXCLUDE_FROM_ALL)
|
|||
add_subdirectory(tinygltf EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(imgui EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(dxbc EXCLUDE_FROM_ALL)
|
||||
|
||||
# For some reason, FFXIV uses a *32-bit* Lua compiler. We have to build it as 32-bit or else loading the bytecode fails.
|
||||
add_compile_options(-m32)
|
||||
add_link_options(-m32)
|
||||
add_subdirectory(luadec51 EXCLUDE_FROM_ALL)
|
1
extern/luadec51
vendored
Submodule
1
extern/luadec51
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 94a5e2b8e08b2c0fdbefc46239b92f1bdcdac303
|
|
@ -11,3 +11,4 @@ add_subdirectory(mtrl)
|
|||
add_subdirectory(shpk)
|
||||
add_subdirectory(sklb)
|
||||
add_subdirectory(tex)
|
||||
add_subdirectory(luab)
|
16
parts/luab/CMakeLists.txt
Normal file
16
parts/luab/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
|||
# SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
add_library(luabpart STATIC)
|
||||
target_sources(luabpart PRIVATE luabpart.cpp)
|
||||
target_link_libraries(luabpart
|
||||
PUBLIC
|
||||
KF6::I18n
|
||||
Physis::Physis
|
||||
Qt6::Core
|
||||
Qt6::Widgets)
|
||||
target_include_directories(luabpart PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_compile_definitions(luabpart PRIVATE TRANSLATION_DOMAIN="novus")
|
||||
add_dependencies(luabpart luadec)
|
||||
|
||||
add_library(Novus::LuabPart ALIAS luabpart)
|
48
parts/luab/luabpart.cpp
Normal file
48
parts/luab/luabpart.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "luabpart.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QProcess>
|
||||
#include <QTemporaryFile>
|
||||
#include <QTextEdit>
|
||||
#include <QVBoxLayout>
|
||||
#include <physis.hpp>
|
||||
|
||||
LuabPart::LuabPart(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
m_codeEdit = new QTextEdit();
|
||||
m_codeEdit->setReadOnly(true);
|
||||
layout->addWidget(m_codeEdit);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void LuabPart::load(physis_Buffer buffer)
|
||||
{
|
||||
QTemporaryFile temporaryFile;
|
||||
if (temporaryFile.open()) {
|
||||
QFile file(temporaryFile.fileName());
|
||||
file.open(QIODevice::WriteOnly);
|
||||
file.write(reinterpret_cast<const char *>(buffer.data), buffer.size);
|
||||
file.close();
|
||||
|
||||
QProcess luaDecProcess;
|
||||
luaDecProcess.setProgram(QStringLiteral("./luadec"));
|
||||
luaDecProcess.setArguments({temporaryFile.fileName()});
|
||||
luaDecProcess.start();
|
||||
luaDecProcess.waitForFinished();
|
||||
|
||||
m_codeEdit->setText(QString::fromUtf8(luaDecProcess.readAllStandardOutput()));
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_luabpart.cpp"
|
24
parts/luab/luabpart.h
Normal file
24
parts/luab/luabpart.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
// SPDX-FileCopyrightText: 2025 Joshua Goins <josh@redstrate.com>
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QTableWidget>
|
||||
#include <QWidget>
|
||||
#include <physis.hpp>
|
||||
|
||||
class QTextEdit;
|
||||
|
||||
class LuabPart : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LuabPart(QWidget *parent = nullptr);
|
||||
|
||||
void load(physis_Buffer file);
|
||||
|
||||
private:
|
||||
GameData *data = nullptr;
|
||||
QTextEdit *m_codeEdit = nullptr;
|
||||
};
|
Loading…
Add table
Reference in a new issue