diff --git a/Decompiler/PscCoder.cpp b/Decompiler/PscCoder.cpp index ed458a0..1466bb0 100644 --- a/Decompiler/PscCoder.cpp +++ b/Decompiler/PscCoder.cpp @@ -183,6 +183,12 @@ void Decompiler::PscCoder::writeObject(const Pex::Object &object, const Pex::Bin writeVariables(object, pex); } + if (object.getGuards().size()) { + write(""); + write(";-- Guards ------------------------------------------"); + writeGuards(object, pex); + } + if (object.getProperties().size()) { write(""); write(";-- Properties --------------------------------------"); @@ -406,6 +412,17 @@ void Decompiler::PscCoder::writeVariables(const Pex::Object &object, const Pex:: } } +/** + * @brief Write the guards contained in the object. + * @param object Object containing the guards. + * @param pex Binary to decompile. + */ +void Decompiler::PscCoder::writeGuards(const Pex::Object& object, const Pex::Binary& pex) { + for (auto& guard : object.getGuards()) { + auto name = guard.getName().asString(); + write("Guard " + name); + } +} /** * @brief Write the states contained in the object. diff --git a/Decompiler/PscCoder.hpp b/Decompiler/PscCoder.hpp index d785440..daa8f86 100644 --- a/Decompiler/PscCoder.hpp +++ b/Decompiler/PscCoder.hpp @@ -30,6 +30,7 @@ class PscCoder : void writeProperties(const Pex::Object& object, const Pex::Binary& pex); void writeProperty(int i, const Pex::Property& prop, const Pex::Object &object, const Pex::Binary& pex); void writeVariables(const Pex::Object& object, const Pex::Binary& pex); + void writeGuards(const Pex::Object& object, const Pex::Binary& pex); void writeStates(const Pex::Object& object, const Pex::Binary& pex); void writeFunctions(int i, const Pex::State& state, const Pex::Object &object, const Pex::Binary& pex); void writeFunction(int i, const Pex::Function& function, const Pex::Object &object, const Pex::Binary& pex, const std::string& name = ""); diff --git a/Decompiler/PscDecompiler.cpp b/Decompiler/PscDecompiler.cpp index 64b3992..e1d6c6f 100644 --- a/Decompiler/PscDecompiler.cpp +++ b/Decompiler/PscDecompiler.cpp @@ -115,6 +115,9 @@ Decompiler::PscDecompiler::PscDecompiler( const Pex::Function &function, m_TempTable.push_back("remove"); m_TempTable.push_back("clear"); m_TempTable.push_back("getallmatchingstructs"); + m_TempTable.push_back("lock"); + m_TempTable.push_back("unlock"); + m_TempTable.push_back("trylock"); //findReplacedVars(); findVarTypes(); @@ -403,8 +406,7 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) auto& varargs = ins.getVarArgs(); Node::BasePtr node; - switch(ins.getOpCode()) - { + switch (ins.getOpCode()) { case Pex::OpCode::NOP: //do nothing break; @@ -456,15 +458,11 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) } case Pex::OpCode::CAST: { - if(args[1].getType() == Pex::ValueType::None) - { + if (args[1].getType() == Pex::ValueType::None) { node = std::make_shared(ip, args[0].getId(), fromValue(ip, args[1])); - } - else if (args[1].getType() != Pex::ValueType::Identifier || (typeOfVar(args[0].getId()) != typeOfVar(args[1].getId()) && args[1].getId() != m_NoneVar) ) - { + } else if (args[1].getType() != Pex::ValueType::Identifier || (typeOfVar(args[0].getId()) != typeOfVar(args[1].getId()) && args[1].getId() != m_NoneVar)) { node = std::make_shared(ip, args[0].getId(), fromValue(ip, args[1]), typeOfVar(args[0].getId())); - } - else // two variables of the same type, equivalent to an assign + } else // two variables of the same type, equivalent to an assign { node = std::make_shared(ip, args[0].getId(), fromValue(ip, args[1])); } @@ -504,10 +502,9 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) { auto callNode = std::make_shared(ip, args[2].getId(), fromValue(ip, args[1]), args[0].getId()); auto argNode = callNode->getParameters(); - for (auto varg : varargs) - { + for (auto varg : varargs) { *argNode << fromValue(ip, varg); - } + } node = callNode; break; } @@ -515,8 +512,7 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) { auto callNode = std::make_shared(ip, args[1].getId(), std::make_shared(ip, "Parent"), args[0].getId()); auto argNode = callNode->getParameters(); - for (auto varg : varargs) - { + for (auto varg : varargs) { *argNode << fromValue(ip, varg); } node = callNode; @@ -526,8 +522,7 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) { auto callNode = std::make_shared(ip, args[2].getId(), fromValue(ip, args[0]), args[1].getId()); auto argNode = callNode->getParameters(); - for (auto varg : varargs) - { + for (auto varg : varargs) { *argNode << fromValue(ip, varg); } node = callNode; @@ -535,12 +530,9 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) } case Pex::OpCode::RETURN: { - if(m_ReturnNone) - { + if (m_ReturnNone) { node = std::make_shared(ip, nullptr); - } - else - { + } else { node = std::make_shared(ip, fromValue(ip, args[0])); } break; @@ -693,7 +685,40 @@ void Decompiler::PscDecompiler::createNodesForBlocks(size_t block) node = callNode; break; } - + case Pex::OpCode::LOCK_GUARDS: + { + auto callNode = std::make_shared(ip, Pex::StringTable::Index(), std::make_shared(ip, "lfunc"), m_TempTable.findIdentifier("lock")); + auto argNode = callNode->getParameters(); + for (auto varg : varargs) { + *argNode << fromValue(ip, varg); + } + node = callNode; + break; + } + case Pex::OpCode::UNLOCK_GUARDS: + { + auto callNode = std::make_shared(ip, Pex::StringTable::Index(), std::make_shared(ip, "lfunc"), m_TempTable.findIdentifier("unlock")); + auto argNode = callNode->getParameters(); + for (auto varg : varargs) { + *argNode << fromValue(ip, varg); + } + node = callNode; + break; + } + case Pex::OpCode::TRY_LOCK_GUARDS: + { + auto callNode = std::make_shared(ip, args[0].getId(), std::make_shared(ip, "lfunc"), m_TempTable.findIdentifier("trylock")); + auto argNode = callNode->getParameters(); + for (auto varg : varargs) { + *argNode << fromValue(ip, varg); + } + node = callNode; + break; + } + default: + { + throw std::exception("Unsupported opcode"); + } } if (node) { diff --git a/Pex/FileReader.cpp b/Pex/FileReader.cpp index 301b7d5..78cddca 100644 --- a/Pex/FileReader.cpp +++ b/Pex/FileReader.cpp @@ -62,7 +62,7 @@ void Pex::FileReader::read(Pex::Binary &binary) m_StringTable = & binary.getStringTable(); read(binary.getDebugInfo()); read(binary.getUserFlags()); - read(binary.getObjects()); + read(binary.getHeader(), binary.getObjects()); } /** @@ -88,7 +88,6 @@ void Pex::FileReader::readHeader(Pex::Header &header) } else { m_endianness = LITTLE_ENDIAN; } - header.setMajorVersion(getUint8()); header.setMinorVersion(getUint8()); header.setGameID(getUint16()); @@ -201,7 +200,7 @@ void Pex::FileReader::read(Pex::UserFlags &userFlags) * @brief Reads the Objects definitions from the file. * @param[in] objects Object collection to fill in. */ -void Pex::FileReader::read(Pex::Objects &objects) +void Pex::FileReader::read(const Pex::Header &header, Pex::Objects &objects) { auto count = getUint16(); objects.resize(count); @@ -224,6 +223,9 @@ void Pex::FileReader::read(Pex::Objects &objects) read(object.getStructInfos()); } read(object.getVariables()); + if (header.getMajorVersion() > 3 || (header.getMajorVersion() == 3 && header.getMinorVersion() >= 12)) { + read(object.getGuards()); + } read(object.getProperties()); read(object.getStates()); } @@ -326,6 +328,18 @@ void Pex::FileReader::read(Pex::States &states) } } +/** + * @brief Reads the Guards definition for an object + * @param[in] guards collection to fill in. + */ +void Pex::FileReader::read(Pex::Guards& guards) { + auto guardCount = getUint16(); + guards.resize(guardCount); + for (auto& guard : guards) { + guard.setName(getStringIndex()); + } +} + /** * @brief Reads the Functions definition for a state * @param[in] functions collection to fill in. diff --git a/Pex/FileReader.hpp b/Pex/FileReader.hpp index 1c37b66..3e60484 100644 --- a/Pex/FileReader.hpp +++ b/Pex/FileReader.hpp @@ -35,11 +35,12 @@ class FileReader void read(StringTable& stringTable); void read(DebugInfo& debugInfo); void read(UserFlags& userFlags); - void read(Objects& objects); + void read(const Pex::Header& header, Objects& objects); void read(StructInfos& structInfos); void read(Variables& variables); void read(Properties& properties); void read(States& states); + void read(Guards& guards); void read(Functions& functions); void read(Function& function); void read(TypedNames& typednames); diff --git a/Pex/Guard.hpp b/Pex/Guard.hpp new file mode 100644 index 0000000..8a962fa --- /dev/null +++ b/Pex/Guard.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +#include "StringTable.hpp" +#include "NamedItem.hpp" + +namespace Pex { + +/** + * @brief Guard definition + * + * This class contains the names guard. + * + */ +class Guard : + public NamedItem { +public: + Guard() = default; + ~Guard() = default; +}; + +typedef std::vector Guards; +} diff --git a/Pex/Instruction.cpp b/Pex/Instruction.cpp index 9d3c119..d0611e5 100644 --- a/Pex/Instruction.cpp +++ b/Pex/Instruction.cpp @@ -73,7 +73,10 @@ static const OpCodeInfo OPCODES[int(Pex::OpCode::MAX_OPCODE)] = { {"array_removelast", 1, false}, {"array_remove", 3, false}, {"array_clear", 1, false}, - {"array_getallmatchingstructs", 6, false}, + {"array_getallmatchingstructs", 6, false}, + {"lock_guards", 0, true}, + {"unlock_guards", 0, true}, + {"try_lock_guards", 1, true}, }; /** diff --git a/Pex/Instruction.hpp b/Pex/Instruction.hpp index d8620c7..ffc2b63 100644 --- a/Pex/Instruction.hpp +++ b/Pex/Instruction.hpp @@ -58,8 +58,12 @@ enum class OpCode { ARRAY_REMOVELAST, ARRAY_REMOVE, ARRAY_CLEAR, - //New in Fallout 76 + // New in Fallout 76 ARRAY_GETALLMATCHINGSTRUCTS, + // New in Starfield + LOCK_GUARDS, + UNLOCK_GUARDS, + TRY_LOCK_GUARDS, MAX_OPCODE }; diff --git a/Pex/Object.cpp b/Pex/Object.cpp index 848c3ef..c484367 100644 --- a/Pex/Object.cpp +++ b/Pex/Object.cpp @@ -111,3 +111,19 @@ Pex::States &Pex::Object::getStates() { return m_States; } + +/** + * @brief Get the guards list + * @return The const guards list + */ +const Pex::Guards& Pex::Object::getGuards() const { + return m_Guards; +} + +/** + * @brief Get the guards list + * @return The const guards list + */ +Pex::Guards& Pex::Object::getGuards() { + return m_Guards; +} \ No newline at end of file diff --git a/Pex/Object.hpp b/Pex/Object.hpp index 80c69be..ffcca57 100644 --- a/Pex/Object.hpp +++ b/Pex/Object.hpp @@ -11,6 +11,7 @@ #include "Variable.hpp" #include "Property.hpp" #include "State.hpp" +#include "Guard.hpp" namespace Pex { @@ -52,6 +53,9 @@ class Object : const States& getStates() const; States& getStates(); + const Guards& getGuards() const; + Guards& getGuards(); + private: StringTable::Index m_ParentClassName; StringTable::Index m_AutoStateName; @@ -61,7 +65,7 @@ class Object : Variables m_Variables; Properties m_Properties; States m_States; - + Guards m_Guards; }; typedef std::vector Objects;