pattern/pex: Added formatter for opcode and some other name cleanups (#371)

This commit is contained in:
Jonathan Ostrus
2025-05-10 02:51:43 -07:00
committed by GitHub
parent b6df1742b6
commit e7d366571d

View File

@@ -50,6 +50,10 @@ namespace formatter {
(_): return "Unknown type"; (_): return "Unknown type";
} }
}; };
fn vartypestruct(ref auto data) {
return formatter::vartype(data.varType);
};
fn arraycount(ref auto data) { fn arraycount(ref auto data) {
return std::format("[{}]", data.count); return std::format("[{}]", data.count);
@@ -63,6 +67,69 @@ namespace formatter {
(3): std::assert(true, "Unknown function type"); (3): std::assert(true, "Unknown function type");
} }
}; };
fn resolveop(u8 op) {
match (op)
{
(0x00): return "nop";
(0x01): return "iadd";
(0x02): return "fadd";
(0x03): return "isub";
(0x04): return "fsub";
(0x05): return "imul";
(0x06): return "fmul";
(0x07): return "idiv";
(0x08): return "fdiv";
(0x09): return "imod";
(0x0A): return "not";
(0x0B): return "ineg";
(0x0C): return "fneg";
(0x0D): return "assign";
(0x0E): return "cast";
(0x0F): return "cmp_eq";
(0x10): return "cmp_lt";
(0x11): return "cmp_lte";
(0x12): return "cmp_gt";
(0x13): return "comp_gte";
(0x14): return "jmp";
(0x15): return "jmpt";
(0x16): return "jmpf";
(0x17): return "callmethod";
(0x18): return "callparent";
(0x19): return "callstatic";
(0x1A): return "return";
(0x1B): return "strcat";
(0x1C): return "propget";
(0x1D): return "propset";
(0x1E): return "array_create";
(0x1F): return "array_length";
(0x20): return "array_getlement";
(0x21): return "array_setelement";
(0x22): return "array_findelement";
(0x23): return "array_rfindelement";
(0x24): return "is";
(0x25): return "struct_create";
(0x26): return "struct_get";
(0x27): return "struct_set";
(0x28): return "array_findstruct";
(0x29): return "array_rfindstruct";
(0x2A): return "array_add";
(0x2B): return "array_insert";
(0x2C): return "array_removelast";
(0x2D): return "array_remove";
(0x2E): return "array_clear";
(0x2F): return "array_getallmatchingstructs";
(0x30): return "lock_guards";
(0x31): return "unlock_guards";
(0x32): return "try_lock_guards";
(_): return "Unknown";
}
};
fn resolveopstruct(auto data) {
return formatter::resolveop(data.op);
};
} }
fn StringLookup(u16 idx) { fn StringLookup(u16 idx) {
@@ -72,11 +139,9 @@ fn StringLookup(u16 idx) {
struct PexVersion { struct PexVersion {
u8 MajorVersion; u8 MajorVersion;
u8 MinorVersion; u8 MinorVersion;
}[[sealed, format("formatter::pexversion")]]; } [[sealed, format("formatter::pexversion")]];
struct StringReference { using StringReference = u16 [[format("StringLookup")]];
u16 name;
} [[sealed, format("formatter::structname")]];
// Dynamic array of strings // Dynamic array of strings
struct StringsTable { struct StringsTable {
@@ -87,25 +152,25 @@ struct StringsTable {
struct Time { struct Time {
u64 Time; u64 Time;
}[[sealed, format("formatter::time")]]; } [[sealed, format("formatter::time")]];
struct VariableData { struct VariableData {
u8 varType [[format("formatter::vartype")]]; u8 varType [[format("formatter::vartype")]];
match (varType) match (varType)
{ {
(0x0): {} // object pointer (0x0): {} // object pointer
(0x1): u16 stringVal [[format("StringLookup")]]; // identifier (0x1): StringReference stringVal; // identifier
(0x2): u16 stringVal [[format("StringLookup")]]; // string (0x2): StringReference stringVal; // string
(0x3): s32 intVal; // integer (0x3): s32 intVal; // integer
(0x4): float floatVal; (0x4): float floatVal;
(0x5): bool boolVal; (0x5): bool boolVal;
(_): std::assert(false, "Unknown type for variable data"); (_): std::assert(false, "Unknown type for variable data");
} }
}; } [[format("formatter::vartypestruct")]];
struct VariableType { struct VariableType {
u16 name [[format("StringLookup")]]; StringReference name;
u16 varType [[format("StringLookup")]]; StringReference varType;
}; };
struct VariableTypes { struct VariableTypes {
@@ -115,7 +180,7 @@ struct VariableTypes {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct Instruction { struct Instruction {
u8 op; u8 op [[format("formatter::resolveop")]];
match (op) match (op)
{ {
( (
@@ -147,18 +212,18 @@ struct Instruction {
0x2A | // array_add 0x2A | // array_add
0x2B | // array_insert 0x2B | // array_insert
0x2D // array_remove 0x2D // array_remove
): VariableData argument[3]; ): VariableData arguments[3];
( (
0x22 | // array_findelement 0x22 | // array_findelement
0x23 // array_rfindelement 0x23 // array_rfindelement
): VariableData argument[4]; ): VariableData arguments[4];
( (
0x14 | // jmp 0x14 | // jmp
0x1A | // return 0x1A | // return
0x25 | // struct_create 0x25 | // struct_create
0x2C | // array_removelast 0x2C | // array_removelast
0x2E // array_clear 0x2E // array_clear
): VariableData argument[1]; ): VariableData arguments[1];
( (
0x0A | // not 0x0A | // not
0x0B | // ineg 0x0B | // ineg
@@ -169,55 +234,54 @@ struct Instruction {
0x16 | // jmpf 0x16 | // jmpf
0x1E | // array_create 0x1E | // array_create
0x1F // array_length 0x1F // array_length
): VariableData argument[2]; ): VariableData arguments[2];
( (
0x28 | // array_findstruct 0x28 | // array_findstruct
0x29 // array_rfindstruct 0x29 // array_rfindstruct
): VariableData argument[5]; ): VariableData arguments[5];
( (
0x2F // array_getallmatchingstructs 0x2F // array_getallmatchingstructs
): VariableData argument[6]; ): VariableData arguments[6];
( (
0x17 | // callmethod 0x17 | // callmethod
0x19 // callstatic 0x19 // callstatic
): { ): {
VariableData argument[4]; VariableData arguments[4];
std::assert(argument[3].varType == 0x3, "VarArgs not integer"); std::assert(arguments[3].varType == 0x3, "VarArgs not integer");
if (argument[3].intVal > 0) if (arguments[3].intVal > 0)
VariableData varArgument[argument[3].intVal]; VariableData vararguments[arguments[3].intVal];
} }
( (
0x18 // callparent 0x18 // callparent
): { ): {
VariableData argument[3]; VariableData arguments[3];
std::assert(argument[2].varType == 0x3, "VarArgs not integer"); std::assert(arguments[2].varType == 0x3, "VarArgs not integer");
if (argument[2].intVal > 0) if (arguments[2].intVal > 0)
VariableData varArgument[argument[2].intVal]; VariableData vararguments[arguments[2].intVal];
} }
( (
0x30 | // lock_guards 0x30 | // lock_guards
0x31 // unlock_guards 0x31 // unlock_guards
): { ): {
VariableData argument[1]; VariableData arguments[1];
std::assert(argument[0].varType == 0x3, "VarArgs not integer"); std::assert(arguments[0].varType == 0x3, "VarArgs not integer");
if (argument[0].intVal > 0) if (arguments[0].intVal > 0)
VariableData varArgument[argument[0].intVal]; VariableData vararguments[arguments[0].intVal];
} }
( (
0x32 // try_lock_guards 0x32 // try_lock_guards
): { ): {
VariableData argument[2]; VariableData arguments[2];
std::assert(argument[1].varType == 0x3, "VarArgs not integer"); std::assert(arguments[1].varType == 0x3, "VarArgs not integer");
if (argument[1].intVal > 0) if (arguments[1].intVal > 0)
VariableData varArgument[argument[1].intVal]; VariableData vararguments[arguments[1].intVal];
} }
(_): { (_): {
Printf("Invalid opcode: %Xh\n", op); std::print("Invalid opcode: {:02x}", op);
std::assert(false, "Invalid opcode"); std::assert(false, "Invalid opcode");
} }
} }
} [[format("formatter::resolveopstruct")]];;
};
struct Instructions { struct Instructions {
u16 count; u16 count;
@@ -225,9 +289,15 @@ struct Instructions {
Instruction instruction[count] [[inline]]; Instruction instruction[count] [[inline]];
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct Function { /*
u16 returnType [[format("StringLookup")]];
u16 docString [[format("StringLookup")]]; this "BaseFunction" struct is used by the Papyrus struct property
getter and setter functions, and by regular named functions.
*/
struct BaseFunction {
StringReference returnType;
StringReference docString;
u32 userFlags; u32 userFlags;
u8 flags; u8 flags;
VariableTypes arguments; VariableTypes arguments;
@@ -236,8 +306,8 @@ struct Function {
}; };
struct NamedFunction { struct NamedFunction {
u16 name [[format("StringLookup")]]; StringReference name;
Function function [[inline]]; BaseFunction function [[inline]];
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
struct NamedFunctions { struct NamedFunctions {
@@ -247,10 +317,16 @@ struct NamedFunctions {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct State { struct State {
u16 name [[format("StringLookup")]]; StringReference name;
NamedFunctions functions; NamedFunctions functions;
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
struct SyncStates {
u16 count;
if (count > 0)
StringReference names[count] [[inline]];
} [[format("formatter::arraycount")]];
struct States { struct States {
u16 count; u16 count;
if (count > 0) if (count > 0)
@@ -258,18 +334,18 @@ struct States {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct Property { struct Property {
u16 name [[format("StringLookup")]]; StringReference name;
u16 typeName [[format("StringLookup")]]; StringReference typeName;
u16 docString [[format("StringLookup")]]; StringReference docString;
u32 userFlags; u32 userFlags;
u8 flags; u8 flags;
if ((flags & 0x4) != 0) if ((flags & 0x4) != 0)
u16 autoVarName [[format("StringLookup")]]; StringReference autoVarName;
else { else {
if ((flags & 0x1) != 0) if ((flags & 0x1) != 0)
Function readHandler; BaseFunction readHandler;
if ((flags & 0x2) != 0) if ((flags & 0x2) != 0)
Function writeHandler; BaseFunction writeHandler;
} }
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
@@ -280,8 +356,8 @@ struct Properties {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct Variable { struct Variable {
u16 name [[format("StringLookup")]]; StringReference name;
u16 typeName [[format("StringLookup")]]; StringReference typeName;
u32 userFlags; u32 userFlags;
VariableData data; VariableData data;
if (g_GameId >= GAMEID::GAME_Fallout4) if (g_GameId >= GAMEID::GAME_Fallout4)
@@ -295,12 +371,12 @@ struct Variables {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct ObjectStructMember { struct ObjectStructMember {
u16 name [[format("StringLookup")]]; StringReference name;
u16 typeName [[format("StringLookup")]]; StringReference typeName;
u32 userFlags; u32 userFlags;
VariableData data; VariableData data;
u8 constFlag; u8 constFlag;
u16 docString [[format("StringLookup")]]; StringReference docString;
} [[format("formatter::typedstructname")]]; } [[format("formatter::typedstructname")]];
struct ObjectStructMembers { struct ObjectStructMembers {
@@ -310,7 +386,7 @@ struct ObjectStructMembers {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct ObjectStruct { struct ObjectStruct {
u16 name [[format("StringLookup")]]; StringReference name;
ObjectStructMembers members; ObjectStructMembers members;
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
@@ -327,12 +403,12 @@ struct Guards {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct ScriptObjectData { struct ScriptObjectData {
u16 parentClassName [[format("StringLookup")]]; StringReference parentClassName;
u16 docString [[format("StringLookup")]]; StringReference docString;
if (g_GameId >= GAMEID::GAME_Fallout4) if (g_GameId >= GAMEID::GAME_Fallout4)
u8 constFlag; u8 constFlag;
u32 userFlags; u32 userFlags;
u16 autoStateName [[format("StringLookup")]]; StringReference autoStateName;
if (g_GameId >= GAMEID::GAME_Fallout4) if (g_GameId >= GAMEID::GAME_Fallout4)
ObjectStructs structs; ObjectStructs structs;
Variables variables; Variables variables;
@@ -341,11 +417,11 @@ struct ScriptObjectData {
Properties properties; Properties properties;
States states; States states;
if (g_GameId == GAMEID::GAME_Fallout76) if (g_GameId == GAMEID::GAME_Fallout76)
u16 unknown; SyncStates syncStates;
}; };
struct ScriptObject { struct ScriptObject {
u16 name [[format("StringLookup")]]; StringReference name;
u32 length; u32 length;
ScriptObjectData data; ScriptObjectData data;
@@ -363,7 +439,7 @@ struct ScriptObjects {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct UserFlag { struct UserFlag {
u16 name [[format("StringLookup")]]; StringReference name;
u8 flagIndex; u8 flagIndex;
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
@@ -380,9 +456,9 @@ struct StringMembers {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct DebugPropertyGroup { struct DebugPropertyGroup {
u16 objectName [[format("StringLookup")]]; StringReference objectName;
u16 name [[format("StringLookup")]]; StringReference name;
u16 docString [[format("StringLookup")]]; StringReference docString;
u32 userFlags; u32 userFlags;
StringMembers members; StringMembers members;
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
@@ -394,18 +470,18 @@ struct DebugInstructions {
} [[format("formatter::arraycount")]]; } [[format("formatter::arraycount")]];
struct DebugFunction { struct DebugFunction {
u16 objectName [[format("StringLookup")]]; StringReference objectName;
u16 stateName [[format("StringLookup")]]; StringReference stateName;
u16 name [[format("StringLookup")]]; StringReference name;
u8 functionType [[format("formatter::functiontype")]]; u8 functionType [[format("formatter::functiontype")]];
DebugInstructions instructions; DebugInstructions instructions;
} [[format("formatter::structname")]]; } [[format("formatter::structname")]];
struct DebugStruct { struct DebugStruct {
u16 name [[format("StringLookup")]]; StringReference parentName;
u16 orderName [[format("StringLookup")]]; StringReference name;
StringMembers members; StringMembers members;
}; } [[format("formatter::structname")]];
struct DebugFunctions { struct DebugFunctions {
u16 count; u16 count;