From f5c895f380a4ba7b6271c76dd067bb439ec1a3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Xenxo=20Espasand=C3=ADn?= Date: Sun, 3 Nov 2024 13:11:37 +0100 Subject: [PATCH] fix(arc): decompile original bugs & early return (#229) --- README.md | 1 + include/xsk/arc/common/types.hpp | 1 + src/arc/compiler.cpp | 2 +- src/arc/decompiler.cpp | 40 ++++++++++++++++++++++---------- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2d066c53..b8422248 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ A utility to compile & decompile IW engine game scripts. - **T7** *(Call of Duty: Black Ops III)* `PC` *(Decompiler)* - **T8** *(Call of Duty: Black Ops 4)* ***\*WIP\**** - **T9** *(Call of Duty: Black Ops Cold War)* ***\*WIP\**** +- **T10** *(Call of Duty: Black Ops 6)* ***\*WIP\**** - **JUP** *(Call of Duty: Modern Warfare III (2023)* ***\*WIP\**** ## Usage diff --git a/include/xsk/arc/common/types.hpp b/include/xsk/arc/common/types.hpp index 3233e2bb..48fcae0c 100644 --- a/include/xsk/arc/common/types.hpp +++ b/include/xsk/arc/common/types.hpp @@ -119,6 +119,7 @@ struct locjmp std::string cnt; std::string brk; bool is_dev; + bool is_switch; }; // fordward decl for modules ref diff --git a/src/arc/compiler.cpp b/src/arc/compiler.cpp index 23c6ff91..27f2df98 100644 --- a/src/arc/compiler.cpp +++ b/src/arc/compiler.cpp @@ -128,7 +128,7 @@ auto compiler::emit_decl_function(decl_function const& func) -> void emit_expr_parameters(*func.params); emit_stmt_comp(*func.body); - if (scopes_.back().abort == scope::abort_none) + if (scopes_.back().abort == scope::abort_none || function_->labels.find(index_) != function_->labels.end()) emit_opcode(opcode::OP_End); scopes_.pop_back(); diff --git a/src/arc/decompiler.cpp b/src/arc/decompiler.cpp index 34bf4b92..b17af04e 100644 --- a/src/arc/decompiler.cpp +++ b/src/arc/decompiler.cpp @@ -1381,7 +1381,15 @@ auto decompiler::decompile_ifelses(stmt_list& stm) -> void } else { - decompile_ifelse(stm, i, j); + // fix treyarch compiler bug: breaks outside loops or switches + auto out_of_scope = stm.list.at(stm.list.size() - 1)->loc().begin.line < std::stol(stm.list.at(j)->as().value.substr(4), 0, 16); + + if (locs_.brk == "" && out_of_scope) + decompile_if(stm, i, j); + else + decompile_ifelse(stm, i, j); + + //decompile_ifelse(stm, i, j); } } else @@ -1413,19 +1421,26 @@ auto decompiler::decompile_aborts(stmt_list& stm) -> void } else { - // fix for treyarch compiler bug: nested switch break locs are not preserved - if (jmp != locs_.end) + // fix treyarch compiler bug: breaks outside loops or switches + if (locs_.brk == "") { - auto j = find_location_index(stm, jmp); - - if (stm.list.at(j)->is()) - { - stm.list.erase(stm.list.begin() + i); - stm.list.insert(stm.list.begin() + i, stmt_break::make(loc)); - - continue; - } + stm.list.erase(stm.list.begin() + i); + stm.list.insert(stm.list.begin() + i, stmt_break::make(loc)); + } + // fix treyarch compiler bug: nested switch break locs are not preserved + else if (jmp != locs_.end && stm.list.at(find_location_index(stm, jmp))->is()) + { + stm.list.erase(stm.list.begin() + i); + stm.list.insert(stm.list.begin() + i, stmt_break::make(loc)); + continue; } + else if (locs_.is_switch && stm.list.at(stm.list.size() - 1)->is()) + { + stm.list.erase(stm.list.begin() + i); + stm.list.insert(stm.list.begin() + i, stmt_break::make(loc)); + continue; + } + std::cout << "WARNING: unresolved jump to '" + jmp + "', maybe incomplete for loop\n"; } } @@ -1853,6 +1868,7 @@ auto decompiler::decompile_switch(stmt_list& stm, usize begin, usize end) -> voi auto save = locs_; locs_.brk = last_location_index(stm, end) ? locs_.end : stm.list[end + 1]->label(); locs_.end = stm.list[begin]->as().value; + locs_.is_switch = true; auto loc = stm.list[begin]->loc(); auto test = std::move(stm.list[begin]->as().test);