Ejemplo n.º 1
0
/**
 * @brief Write the properties definitions stored in the object.
 * @param object Object containing the properties definitions.
 * @param pex Binary to decompile.
 */
void Decompiler::PscCoder::writeProperties(const Pex::Object &object, const Pex::Binary &pex)
{
    bool foundInfo = false;
    if (pex.getDebugInfo().getPropertyGroups().size()) {
        size_t totalProperties = 0;
        // If we have debug info, we have information on the order
        // they were in the original source file, so use that order.
        for (auto& propGroup : pex.getDebugInfo().getPropertyGroups()) {
            if (propGroup.getObjectName() == object.getName()) {
                totalProperties += propGroup.getNames().size();
            }
        }

        if (totalProperties == object.getProperties().size()) {
            foundInfo = true;

            for (auto& propGroup : pex.getDebugInfo().getPropertyGroups()) {
                if (propGroup.getObjectName() == object.getName()) {
                    int propertyIndent = 0;
                    if (!propGroup.getGroupName().asString().empty()) {
                        auto stream = indent(0);
                        stream << "Group " << propGroup.getGroupName();
                        writeUserFlag(stream, propGroup, pex);
                        write(stream);
                        writeDocString(0, propGroup);
                        propertyIndent = 1;
                    }

                    for (auto& propName : propGroup.getNames()) {
                        for (auto& prop : object.getProperties()) {
                            if (prop.getName() == propName) {
                                writeProperty(propertyIndent, prop, object, pex);
                                goto ContinueOrder;
                            }
                        }
                        // If we get here, then we failed to find the struct
                        // member in the debug info :(
                        throw std::runtime_error("Unable to locate the property by the name of '" + propName.asString() + "' referenced in the debug info");
ContinueOrder:
                        continue;
                    }

                    if (!propGroup.getGroupName().asString().empty()) {
                        write(indent(0) << "EndGroup");
                        write("");
                    }
                }
            }
        }
    }

    if (!foundInfo) {
        for (auto& prop : object.getProperties())
            writeProperty(0, prop, object, pex);
    }
}
Ejemplo n.º 2
0
/**
* @brief Write the struct member passed in.
* @param member The member to output.
* @param pex Binary to decompile.
*/
void Decompiler::PscCoder::writeStructMember(const Pex::StructInfo::Member& member, const Pex::Binary& pex)
{
    auto stream = indent(1);
    stream << mapType(member.getTypeName().asString()) << " " << member.getName();

    if (member.getValue().getType() != Pex::ValueType::None) {
        stream << " = " << member.getValue().toString();
    }
    writeUserFlag(stream, member, pex);
    if (member.getConstFlag())
        stream << " Const";
    write(stream);
    writeDocString(1, member);
}
Ejemplo n.º 3
0
/**
* @brief Write the property definition.
* @param i The indent level.
* @param prop The property to write.
* @param object Object containing the properties definitions.
* @param pex Binary to decompile.
*/
void Decompiler::PscCoder::writeProperty(int i, const Pex::Property& prop, const Pex::Object &object, const Pex::Binary& pex)
{
    auto stream = indent(i);
    auto isAutoReadOnly = !prop.hasAutoVar() &&
                          prop.isReadable() &&
                          !prop.isWritable() &&
                          prop.getReadFunction().getInstructions().size() == 1 &&
                          prop.getReadFunction().getInstructions()[0].getOpCode() == Pex::OpCode::RETURN &&
                          prop.getReadFunction().getInstructions()[0].getArgs().size() == 1;
    stream << mapType(prop.getTypeName().asString()) << " Property " << prop.getName();
    if (prop.hasAutoVar()) {
        auto var = object.getVariables().findByName(prop.getAutoVarName());
        if (var == nullptr)
            throw std::runtime_error("Auto variable for property not found");

        auto initialValue = var->getDefaultValue();
        if (initialValue.getType() != Pex::ValueType::None)
            stream << " = " << initialValue.toString();
        stream << " Auto";

        // The flags defined on the variable must be set on the property
        writeUserFlag(stream, *var, pex);
        if (var->getConstFlag())
            stream << " Const";
    } else if (isAutoReadOnly) {
        stream << " = " << prop.getReadFunction().getInstructions()[0].getArgs()[0].toString();
        stream << " AutoReadOnly";
    }
    writeUserFlag(stream, prop, pex);
    write(stream);
    writeDocString(i, prop);

    if (!prop.hasAutoVar() && !isAutoReadOnly) {
        if (prop.isReadable())
            writeFunction(i + 1, prop.getReadFunction(), object, pex, "Get");
        if (prop.isWritable())
            writeFunction(i + 1, prop.getWriteFunction(), object, pex, "Set");
        write(indent(i) << "EndProperty");
    }
}
Ejemplo n.º 4
0
/**
 * @brief Write an object contained in the binary.
 * @param object Object to decompile
 * @param pex Binary to decompile.
 */
void Decompiler::PscCoder::writeObject(const Pex::Object &object, const Pex::Binary &pex)
{
    auto stream = indent(0);
    stream <<"ScriptName " << object.getName().asString();
    if (! object.getParentClassName().asString().empty())
    {
        stream << " extends " << object.getParentClassName().asString();
    }
    if (object.getConstFlag())
        stream << " Const";

    writeUserFlag(stream, object, pex);
    write(stream);

    writeDocString(0, object);

    if (object.getStructInfos().size()) {
        write("");
        write(";-- Structs -----------------------------------------");
        writeStructs(object, pex);
    }

    if (object.getProperties().size()) {
        write("");
        write(";-- Properties --------------------------------------");
        writeProperties(object, pex);
    }

    if (object.getVariables().size()) {
        write("");
        write(";-- Variables ---------------------------------------");
        writeVariables(object, pex);
    }

    writeStates(object, pex);
}
Ejemplo n.º 5
0
void 
DOMWriter::visitText(Text * node)
{
  writeDocString(node->getNodeValue());
}
Ejemplo n.º 6
0
/**
 * @brief Decompile a function.
 * @param i The indentation level.
 * @param function The function to decompile.
 * @param object The Object containing the function.
 * @param pex Binary to decompile.
 * @param name Name of the function. This parameter override the name stored in the function object.
 */
void Decompiler::PscCoder::writeFunction(int i, const Pex::Function &function, const Pex::Object& object, const Pex::Binary &pex, const std::string &name)
{
    std::string functionName = name;

    if (functionName.empty())
    {
        functionName = function.getName().asString();
    }

    bool isEvent = functionName.size() > 2 && !_stricmp(functionName.substr(0, 2).c_str(), "on");
    if (functionName.size() > 9 && !_stricmp(functionName.substr(0, 9).c_str(), "::remote_")) {
        isEvent = true;
        functionName = functionName.substr(9);
        functionName[function.getParams()[0].getTypeName().asString().size()] = '.';
    }

    if (functionName != "GetState" && functionName != "GotoState")
    {
        auto stream = indent(i);
        if (_stricmp(function.getReturnTypeName().asString().c_str(), "none") != 0)
            stream << mapType(function.getReturnTypeName().asString()) << " ";

        if (isEvent)
            stream << "Event ";
        else
            stream << "Function ";
        stream << functionName << "(";

        auto first = true;
        for (auto& param : function.getParams())
        {
            if (first)
            {
                first = false;
            }
            else
            {
                stream << ", ";
            }
            stream << mapType(param.getTypeName().asString()) << " " << param.getName();
        }
        stream << ")";

        if (function.isGlobal())
        {
            stream << " global";
        }
        if (function.isNative())
        {
            stream << " native";
        }
        writeUserFlag(stream, function, pex);
        write(stream);

        writeDocString(i, function);

        if (! function.isNative())
        {
            for (auto& line : PscDecompiler(function, object, m_CommentAsm))
            {
                write(indent(i+1) << line);
            }
            if (isEvent)
                write(indent(i) << "EndEvent");
            else
                write(indent(i) << "EndFunction");
        }
    }
    else
    {
        write(indent(i) << "; Skipped compiler generated " << functionName);
    }
}