From dc6d1d523104d23a6734d547989cca88a70856d2 Mon Sep 17 00:00:00 2001 From: xensik Date: Tue, 16 Nov 2021 15:06:56 +0100 Subject: [PATCH] add missing decompiler opcodes --- src/h1/xsk/decompiler.cpp | 10 +++ src/h2/xsk/decompiler.cpp | 10 +++ src/iw5/xsk/decompiler.cpp | 127 ++++++++++++++++++++++++++++++++++++- src/iw6/xsk/decompiler.cpp | 10 +++ src/iw7/xsk/decompiler.cpp | 10 +++ src/iw8/xsk/decompiler.cpp | 10 +++ src/s1/xsk/decompiler.cpp | 10 +++ src/s2/xsk/decompiler.cpp | 10 +++ src/s4/xsk/decompiler.cpp | 10 +++ 9 files changed, 205 insertions(+), 2 deletions(-) diff --git a/src/h1/xsk/decompiler.cpp b/src/h1/xsk/decompiler.cpp index b5274d1c..ab0a685e 100644 --- a/src/h1/xsk/decompiler.cpp +++ b/src/h1/xsk/decompiler.cpp @@ -1650,6 +1650,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/h2/xsk/decompiler.cpp b/src/h2/xsk/decompiler.cpp index 67c10808..8e8325c5 100644 --- a/src/h2/xsk/decompiler.cpp +++ b/src/h2/xsk/decompiler.cpp @@ -1650,6 +1650,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/iw5/xsk/decompiler.cpp b/src/iw5/xsk/decompiler.cpp index 97fd3b47..bb61f4ed 100644 --- a/src/iw5/xsk/decompiler.cpp +++ b/src/iw5/xsk/decompiler.cpp @@ -1644,6 +1644,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); @@ -2038,6 +2048,8 @@ void decompiler::decompile_search_ifelse(const gsc::stmt_list_ptr& block) if(stmt.as_node->type == gsc::node_t::asm_jump_cond) { std::uint32_t end; + auto last_loc = blocks_.back().loc_end; + if(stmt.as_cond->value == blocks_.back().loc_end) { end = block->stmts.size() - 1; @@ -2046,8 +2058,119 @@ void decompiler::decompile_search_ifelse(const gsc::stmt_list_ptr& block) { end = find_location_index(block, stmt.as_cond->value) - 1; } - - auto last_loc = blocks_.back().loc_end; +/* + // normal block + if(blocks_.back().loc_break == "" && blocks_.back().loc_continue == "") + { + if(block->stmts.at(end).as_node->type == gsc::node_t::asm_jump) + { +normal_block: if(block->stmts.at(end).as_jump->value == stmt.as_cond->value) + { + // check if inside there is another if that jumps to cond->value + bool checked = false; + for(auto j = index + 1; j < end; j++) + { + auto& stmt2 = block->stmts.at(j); + if(stmt2.as_node->type == gsc::node_t::asm_jump_cond) + { + auto value = stmt2.as_cond->value; + if(std::stoi(value.substr(4), 0, 16) > block->stmts.at(end).as_jump->loc.begin.line) + { + checked = true; + } + } + } + + if(checked) + { + // if with if/else inside with empty else + decompile_if(block, index, end); + } + else + { + // if/else with empty else + decompile_ifelse(block, index, end); + } + } + else + { + // normal if/else not empty + decompile_ifelse(block, index, end); + } + } + else if(block->stmts.at(end).as_node->type == gsc::node_t::stmt_return + && block->stmts.at(end).as_return->expr.as_node->type == gsc::node_t::null) + { + if(end - index == 1) + { + decompile_if(block, index, end); // only one explicit return + } + else if(block->stmts.back().as_node->type != gsc::node_t::stmt_return) + { + decompile_if(block, index, end); // block end is not a last return + } + else if(blocks_.back().is_last && block->stmts.back().as_node->type != gsc::node_t::stmt_return) + { + decompile_if(block, index, end); // inside a last block but is not and inner last + } + else if(find_location_reference(block, end, block->stmts.size(), last_loc)) + { + decompile_if(block, index, end); // reference to func end after the if + } + else if(blocks_.size() > 1 && !blocks_.back().is_last) + { + decompile_if(block, index, end); // fake last ifelse + } + else + { + decompile_last_ifelse(block, index, end); // special case + } + } + else + { + decompile_if(block, index, end); + } + } + else // loop block + { + if(block->stmts.at(end).as_node->type == gsc::node_t::asm_jump) + { + // if block is a loop check break, continue + if(block->stmts.at(end).as_jump->value == blocks_.back().loc_continue) + { + if(end - index == 1) + { + decompile_if(block, index, end); + } + else + { + decompile_ifelse(block, index, end); + } + } + else if(block->stmts.at(end).as_jump->value == blocks_.back().loc_break) + { + decompile_if(block, index, end); + } + else if(block->stmts.at(end).as_jump->value == blocks_.back().loc_end) + { + decompile_ifelse(block, index, end); + } + else + { + goto normal_block; + } + } + else if(block->stmts.at(end).as_node->type == gsc::node_t::stmt_return + && block->stmts.at(end).as_return->expr.as_node->type == gsc::node_t::null) + { + decompile_if(block, index, end); + } + else + { + decompile_if(block, index, end); + } + } +*/ if(block->stmts.at(end).as_node->type == gsc::node_t::asm_jump) { diff --git a/src/iw6/xsk/decompiler.cpp b/src/iw6/xsk/decompiler.cpp index a27db380..edd081f6 100644 --- a/src/iw6/xsk/decompiler.cpp +++ b/src/iw6/xsk/decompiler.cpp @@ -1644,6 +1644,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/iw7/xsk/decompiler.cpp b/src/iw7/xsk/decompiler.cpp index cdb31519..f1d6d0aa 100644 --- a/src/iw7/xsk/decompiler.cpp +++ b/src/iw7/xsk/decompiler.cpp @@ -1644,6 +1644,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/iw8/xsk/decompiler.cpp b/src/iw8/xsk/decompiler.cpp index 65dd3dcf..072def4f 100644 --- a/src/iw8/xsk/decompiler.cpp +++ b/src/iw8/xsk/decompiler.cpp @@ -1651,6 +1651,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/s1/xsk/decompiler.cpp b/src/s1/xsk/decompiler.cpp index 88529179..5c244cee 100644 --- a/src/s1/xsk/decompiler.cpp +++ b/src/s1/xsk/decompiler.cpp @@ -1650,6 +1650,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/s2/xsk/decompiler.cpp b/src/s2/xsk/decompiler.cpp index 5a4c6997..aa00af94 100644 --- a/src/s2/xsk/decompiler.cpp +++ b/src/s2/xsk/decompiler.cpp @@ -1650,6 +1650,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0"); diff --git a/src/s4/xsk/decompiler.cpp b/src/s4/xsk/decompiler.cpp index 7de79000..8a426f22 100644 --- a/src/s4/xsk/decompiler.cpp +++ b/src/s4/xsk/decompiler.cpp @@ -1651,6 +1651,16 @@ void decompiler::decompile_statements(const gsc::function_ptr& func) } } break; + case opcode::OP_SafeSetVariableFieldCached0: + { + func_->params->list.push_back(std::make_unique(loc, "var_0")); + } + break; + case opcode::OP_SafeSetVariableFieldCached: + { + func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[0])); + } + break; case opcode::OP_EvalLocalVariableRefCached0: { auto node = std::make_unique(loc, "0");