Skip to content

Commit

Permalink
do not shutdown decompiler after bad opcode
Browse files Browse the repository at this point in the history
  • Loading branch information
ate47 committed Oct 26, 2024
1 parent b9733dd commit b6269c5
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 24 deletions.
4 changes: 3 additions & 1 deletion src/acts/tools/gsc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ namespace tool::gsc {
enum ASMContextNodeType : UINT {
TYPE_BLOCK,
TYPE_STATEMENT,
TYPE_COMMENT,
TYPE_DO_WHILE,
TYPE_WHILE,
TYPE_FOR,
Expand Down Expand Up @@ -585,8 +586,9 @@ namespace tool::gsc {

/*
* Complete any statement on the ASCM stack
* @param resetLoc reset the location after the statement
*/
void CompleteStatement();
void CompleteStatement(bool resetLoc = true);

/*
* Compute the default param value from the function block
Expand Down
84 changes: 61 additions & 23 deletions src/acts/tools/gsc_opcodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace tool::gsc::opcode {
if (!_strcmpi("pc", name)) {
return PLATFORM_PC;
}
if (!_strcmpi("pc_alpha", name) || !_strcmpi("pca", name)) {
if (!_strcmpi("pc_alpha", name) || !_strcmpi("pca", name) || !_strcmpi("alpha", name) || !_strcmpi("a", name)) {
return PLATFORM_PC_ALPHA;
}
if (!_strcmpi("xbox", name) || !_strcmpi("xb", name)) {
Expand Down Expand Up @@ -140,7 +140,7 @@ namespace tool::gsc::opcode {
case PLATFORM_PC: return "PC";
case PLATFORM_XBOX: return "Xbox";
case PLATFORM_PLAYSTATION: return "PlayStation";
case PLATFORM_PC_ALPHA: return "PC Alpha";
case PLATFORM_PC_ALPHA: return "Alpha";
default: return "Unknown";
}
}
Expand Down Expand Up @@ -576,8 +576,6 @@ class OPCodeInfounknown : public OPCodeInfo {
using OPCodeInfo::OPCodeInfo;

int Dump(std::ostream& out, uint16_t value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override {

context.DisableDecompiler(std::format("Unknown operator 0x{:x} ({}/{})", value, context.m_objctx.m_vmInfo->codeName, PlatformName(context.m_platform)));
out << "Unknown operator: " << std::hex << value << "\n";

byte* oldBcl = context.m_bcl;
Expand Down Expand Up @@ -641,8 +639,29 @@ class OPCodeInfounknown : public OPCodeInfo {
}
}
}
if (context.m_opt.m_dcomp) {
ASMContextNodeMultOp* op = new ASMContextNodeMultOp("InvalidOpCode", false);
op->AddParam(new ASMContextNodeValue<uint16_t>(value, TYPE_VALUE, true, false, true));

// add params
while (context.m_stack.size() && context.PeekASMCNode()->m_type != TYPE_PRECODEPOS) {
op->AddParam(context.PopASMCNode());
}
op->m_priority = PRIORITY_INST;
context.PushASMCNode(op);
context.CompleteStatement(false);

ASMContextNodeMultOp* op2 = new ASMContextNodeMultOp("Unknown operator ", false, TYPE_COMMENT);
op2->AddParam(new ASMContextNodeValue<uint16_t>(value, TYPE_VALUE, true, false, true));
op2->AddParam(new ASMContextNodeValue<const char*>(context.m_objctx.m_vmInfo->codeName, TYPE_VALUE));
op2->AddParam(new ASMContextNodeValue<const char*>(PlatformName(context.m_platform), TYPE_VALUE));
context.PushASMCNode(op2);
context.CompleteStatement();
//context.DisableDecompiler(std::format("Unknown operator 0x{:x} ({}/{})", value, context.m_objctx.m_vmInfo->codeName, PlatformName(context.m_platform)));
}


return -1;
return -2;
}
int Skip(uint16_t value, ASMSkipContext& ctx) const override {
ctx.m_error = std::format("Unknown operator: {:x}", value);
Expand Down Expand Up @@ -1776,21 +1795,31 @@ class OPCodeInfoSetWaittillVariableFieldCached : public OPCodeInfo {
out << std::endl;

if (context.m_runDecompiler) {
ASMContextNode* prev = context.PopASMCNode();
ASMContextNode* prev = context.PeekASMCNode();

if (prev->m_type != TYPE_WAITTILL) {
prev = context.PopASMCNode();
ASMContextNode* node;
if (prev->m_type == TYPE_WAITTILL_SET) {
auto* lro = reinterpret_cast<ASMContextNodeLeftRightOperator*>(prev);
lro->m_left = new ASMContextNodeLeftRightOperator(lro->m_left, new ASMContextNodeIdentifier(name), ", ", PRIORITY_SET, TYPE_WAITTILL_SET);
node = lro;
}
else {
node = new ASMContextNodeLeftRightOperator(
new ASMContextNodeIdentifier(name), prev, " = ", PRIORITY_SET, TYPE_WAITTILL_SET);
}

ASMContextNode* node;
if (prev->m_type == TYPE_WAITTILL_SET) {
auto* lro = reinterpret_cast<ASMContextNodeLeftRightOperator*>(prev);
lro->m_left = new ASMContextNodeLeftRightOperator(lro->m_left, new ASMContextNodeIdentifier(name), ", ", PRIORITY_SET, TYPE_WAITTILL_SET);
node = lro;
context.SetFieldIdASMCNode(node->Clone());
context.PushASMCNode(node);
}
else {
node = new ASMContextNodeLeftRightOperator(
new ASMContextNodeIdentifier(name), prev, " = ", PRIORITY_SET, TYPE_WAITTILL_SET);
ASMContextNodeMultOp* wtop = reinterpret_cast<ASMContextNodeMultOp*>(prev);
ASMContextNode* idf = new ASMContextNodeIdentifier(name);
wtop->AddParam(idf);
context.SetFieldIdASMCNode(idf->Clone());
}

context.SetFieldIdASMCNode(node->Clone());
context.PushASMCNode(node);
}

return 0;
Expand Down Expand Up @@ -4598,8 +4627,9 @@ class OPCodeInfoSingle : public OPCodeInfo {
unsigned int m_count;
unsigned int m_delta;
bool m_hasCaller;
OPCodeInfoSingle(OPCode id, const char* name, const char* op, bool pushReturn, unsigned int count = 1, unsigned int delta = 0, bool hasCaller = true) : OPCodeInfo(id, name),
m_op(op), m_pushReturn(pushReturn), m_count(count), m_delta(delta), m_hasCaller(hasCaller) {
ASMContextNodeType m_type = TYPE_STATEMENT;
OPCodeInfoSingle(OPCode id, const char* name, const char* op, bool pushReturn, unsigned int count = 1, unsigned int delta = 0, bool hasCaller = true, ASMContextNodeType type = TYPE_STATEMENT)
: OPCodeInfo(id, name), m_op(op), m_pushReturn(pushReturn), m_count(count), m_delta(delta), m_hasCaller(hasCaller), m_type(type) {
}

int Dump(std::ostream& out, uint16_t value, ASMContext& context, tool::gsc::T8GSCOBJContext& objctx) const override {
Expand All @@ -4613,7 +4643,7 @@ class OPCodeInfoSingle : public OPCodeInfo {
out << "\n";

if (context.m_runDecompiler) {
ASMContextNodeMultOp* node = new ASMContextNodeMultOp(m_op, m_hasCaller);
ASMContextNodeMultOp* node = new ASMContextNodeMultOp(m_op, m_hasCaller, m_type);

// self
if (m_hasCaller) {
Expand Down Expand Up @@ -5288,7 +5318,7 @@ namespace tool::gsc::opcode {
RegisterOpCodeHandler(new OPCodeInfoFuncGet(OPCODE_IW_GetBuiltinFunction, "GetBuiltinFunction", 2));
RegisterOpCodeHandler(new OPCodeInfoFuncGet(OPCODE_IW_GetBuiltinMethod, "GetBuiltinMethod", 2));
RegisterOpCodeHandler(new OPCodeInfoSingle(OPCODE_IW_SingleEndon, "Endon", "endon", false));
RegisterOpCodeHandler(new OPCodeInfoSingle(OPCODE_IW_SingleWaitTill, "WaitTill", "waittill", true));
RegisterOpCodeHandler(new OPCodeInfoSingle(OPCODE_IW_SingleWaitTill, "WaitTill", "waittill", true, 1, 0, true, TYPE_WAITTILL));
RegisterOpCodeHandler(new OPCodeInfoSingleFunc(OPCODE_IW_IsTrue, "IsTrue", "istrue", true, true));
RegisterOpCodeHandler(new OPCodeInfoGetGlobal(OPCODE_IW_GetLevel, "GetLevel", GGGT_PUSH, "level"));
RegisterOpCodeHandler(new OPCodeInfoGetGlobal(OPCODE_IW_GetLevelGRef, "GetLevelGRef", GGGT_GLOBAL, "level"));
Expand Down Expand Up @@ -5319,7 +5349,7 @@ namespace tool::gsc::opcode {

RegisterOpCodeHandler(new OPCodeInfoStatement(OPCODE_IW_WaitFrame, "WaitSingleFrame", "waitframe()"));
RegisterOpCodeHandler(new OPCodeInfoGetConstant(OPCODE_IW_GetThread, "GetThread", "getthread()"));
RegisterOpCodeHandler(new OPCodeInfoSingle(OPCODE_IW_WaitTillMatch, "WaitTillMatch", "waittillmatch", true, 2, 2));
RegisterOpCodeHandler(new OPCodeInfoSingle(OPCODE_IW_WaitTillMatch, "WaitTillMatch", "waittillmatch", true, 2, 2, true, TYPE_WAITTILL));
// scripts\asm\asm::asm_getanim()'s assertmsg lol
RegisterOpCodeHandler(new OPCodeInfoSingle(OPCODE_T10_FlatArgs, "FlatArgs", "flat_args", true, 2, 0, false));
RegisterOpCodeHandler(new OPCodeInfoGetPositionRef());
Expand Down Expand Up @@ -5689,7 +5719,7 @@ ASMContextNode* ASMContext::PeekASMCNode() {
return m_stack[m_stack.size() - 1];
}

void ASMContext::CompleteStatement() {
void ASMContext::CompleteStatement(bool resetLoc) {
if (m_stack.size() && m_lastOpCodeBase != -1) { // empty func tests
//if (m_fieldId) {
// delete m_fieldId;
Expand All @@ -5703,7 +5733,9 @@ void ASMContext::CompleteStatement() {
auto* loc = &m_locs[m_lastOpCodeBase];

m_funcBlock.m_statements.push_back({ node, loc});
m_lastOpCodeBase = -1;
if (resetLoc) {
m_lastOpCodeBase = -1;
}
//// clear stack
//for (auto& n : m_stack) {
// delete n;
Expand Down Expand Up @@ -5849,10 +5881,16 @@ void ASMContextNodeBlock::Dump(std::ostream& out, DecompContext& ctx) const {
if (hide && ref.node->m_type != TYPE_PRECODEPOS) {
out << "<END DETECTED> ";
}
if (ref.node->m_type == TYPE_COMMENT) {
out << "// ";
}
ref.node->Dump(out, ctx);

if (ref.node->m_renderSemicolon) {
out << ";\n";
if (ref.node->m_type != TYPE_COMMENT) {
out << ";";
}
out << "\n";
}
if (ref.node->m_type == TYPE_JUMP || ref.node->m_type == TYPE_RETURN) {
hide = true;
Expand Down
12 changes: 12 additions & 0 deletions src/acts/tools/gsc_opcodes_load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1055,6 +1055,9 @@ namespace tool::gsc::opcode {
RegisterVMHashOPCode(VM_MW23, '&', OPCODE_GetHash, 8, [](const char* str) { return hashutils::HashJupScr(str); });
RegisterDevCall(VM_MW23, "assert", "assertmsg", "assertex", "println");
RegisterDatatype(VM_MW23, "builtinfunction", "builtinmethod", "function", "string", "istring", "struct", "int", "float", "vector");
RegisterOpCode(VM_MW23, PLATFORM_PC, OPCODE_CheckClearParams, 0x43);
RegisterOpCode(VM_MW23, PLATFORM_PC, OPCODE_SafeCreateLocalVariables, 0x98);
RegisterOpCode(VM_MW23, PLATFORM_PC, OPCODE_IW_RegisterVariable, 0x2B, 0xA4);

RegisterVM(VM_MW23B, "Call of Duty: Modern Warfare III (8B)", "jup8b", "mwiii", VmFlags::VMF_CRC_DUMP | VmFlags::VMF_FOREACH_IW | VmFlags::VMF_HASH64 | VmFlags::VMF_NO_PARAM_FLAGS | VmFlags::VMF_FULL_FILE_NAMESPACE | VmFlags::VMF_HASH_IW | VmFlags::VMF_CALL_NO_PARAMS | VmFlags::VMF_IW_CALLS);
RegisterVmName(VM_MW23B, "jup", "s5", "mwiii", "modernwarfareiii", "mw23");
Expand All @@ -1078,6 +1081,9 @@ namespace tool::gsc::opcode {
RegisterVMHashOPCode(VM_MW23B, '&', OPCODE_GetHash, 8, [](const char* str) { return hashutils::HashJupScr(str); });
RegisterDevCall(VM_MW23B, "assert", "assertmsg", "assertex", "println");
RegisterDatatype(VM_MW23B, "builtinfunction", "builtinmethod", "function", "string", "istring", "struct", "int", "float", "vector");
RegisterOpCode(VM_MW23B, PLATFORM_PC, OPCODE_CheckClearParams, 0x39);
RegisterOpCode(VM_MW23B, PLATFORM_PC, OPCODE_SafeCreateLocalVariables, 0x4d);
RegisterOpCode(VM_MW23B, PLATFORM_PC, OPCODE_IW_RegisterMultipleVariables, 0x79);

RegisterVM(VM_BO6_06, "Call of Duty: Black Ops 6 (06)", "t10_6", "bo6_6", VmFlags::VMF_EXPORT_NOCHECKSUM | VmFlags::VMF_CRC_DUMP | VmFlags::VMF_FOREACH_IW | VmFlags::VMF_HASH64 | VmFlags::VMF_FULL_FILE_NAMESPACE | VmFlags::VMF_HASH_CER | VmFlags::VMF_CALL_NO_PARAMS); // VmFlags::VMF_IW_CALLS | VmFlags::VMF_NO_PARAM_FLAGS
RegisterVmName(VM_BO6_06, "cer6", "t10_6", "blackops6_6");
Expand Down Expand Up @@ -1248,6 +1254,9 @@ namespace tool::gsc::opcode {
RegisterOpCode(VM_BO6_07, PLATFORM_PC, OPCODE_Nop, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf);
RegisterOpCode(VM_BO6_07, PLATFORM_PC, OPCODE_Nop, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef);
RegisterOpCode(VM_BO6_07, PLATFORM_PC, OPCODE_Nop, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff);
RegisterOpCode(VM_BO6_07, PLATFORM_PC, OPCODE_CheckClearParams, 0x4d);
RegisterOpCode(VM_BO6_07, PLATFORM_PC, OPCODE_SafeCreateLocalVariables, 0x5a);
RegisterOpCode(VM_BO6_07, PLATFORM_PC, OPCODE_IW_RegisterMultipleVariables, 0x53);

RegisterVM(VM_BO6_0C, "Call of Duty: Black Ops 6", "t10", "bo6", VmFlags::VMF_CRC_DUMP | VmFlags::VMF_FOREACH_IW | VmFlags::VMF_EXPORT_CRC32 | VmFlags::VMF_HASH64 | VmFlags::VMF_FULL_FILE_NAMESPACE | VmFlags::VMF_HASH_CER | VmFlags::VMF_CALL_NO_PARAMS); // VmFlags::VMF_IW_CALLS | VmFlags::VMF_NO_PARAM_FLAGS
RegisterVmName(VM_BO6_0C, "cer", "t10", "blackops6");
Expand All @@ -1273,6 +1282,9 @@ namespace tool::gsc::opcode {
RegisterVMHashOPCode(VM_BO6_0C, '&', OPCODE_T10_GetScrHash, 8, [](const char* str) { return hashutils::HashT10Scr(str); });
RegisterDevCall(VM_BO6_0C, "assert", "assertmsg", "assertex", "println");
RegisterDatatype(VM_BO6_0C, "builtinfunction", "builtinmethod", "function", "string", "istring", "struct", "int", "float", "vector");
RegisterOpCode(VM_BO6_0C, PLATFORM_PC, OPCODE_CheckClearParams, 0x24);
RegisterOpCode(VM_BO6_0C, PLATFORM_PC, OPCODE_SafeCreateLocalVariables, 0x20);
RegisterOpCode(VM_BO6_0C, PLATFORM_PC, OPCODE_IW_RegisterMultipleVariables, 0x93);

RegisterVM(VM_T7, "Call of Duty: Black ops 3", "t7", "bo3", VmFlags::VMF_CLIENT_VM | VmFlags::VMF_NO_FILE_NAMESPACE | VmFlags::VMF_OPCODE_U16 | VmFlags::VMF_ALIGN | VmFlags::VMF_ANIMTREE_T7 | VmFlags::VMF_HASH_T7);
RegisterVmName(VM_T7, "t7", "blackops3");
Expand Down

0 comments on commit b6269c5

Please sign in to comment.