add treyarch animtrees & fix nested switches

This commit is contained in:
xensik 2022-10-14 18:47:38 +02:00 committed by Xenxo Espasandín
parent 5093173549
commit d433fd7d7b
12 changed files with 2205 additions and 1969 deletions

View File

@ -56,6 +56,7 @@ xsk::arc::t6::parser::symbol_type T6lex(xsk::arc::t6::lexer& lexer);
%token INLINE "#inline"
%token INCLUDE "#include"
%token USINGTREE "#using_animtree"
%token ANIMTREE "#animtree"
%token ENDON "endon"
%token NOTIFY "notify"
%token WAIT "wait"
@ -243,6 +244,7 @@ xsk::arc::t6::parser::symbol_type T6lex(xsk::arc::t6::lexer& lexer);
%type <ast::expr_anim::ptr> expr_anim
%type <ast::expr_level::ptr> expr_level
%type <ast::expr_animation::ptr> expr_animation
%type <ast::expr_animtree::ptr> expr_animtree
%type <ast::expr_identifier::ptr> expr_identifier_nosize
%type <ast::expr_identifier::ptr> expr_identifier
%type <ast::expr_path::ptr> expr_path
@ -661,6 +663,7 @@ expr_primitive
| expr_anim { $$.as_node = std::move($1); }
| expr_level { $$.as_node = std::move($1); }
| expr_animation { $$.as_node = std::move($1); }
| expr_animtree { $$.as_node = std::move($1); }
| expr_identifier { $$.as_node = std::move($1); }
| expr_istring { $$.as_node = std::move($1); }
| expr_string { $$.as_node = std::move($1); }
@ -926,6 +929,11 @@ expr_animation
{ $$ = std::make_unique<ast::expr_animation>(@$, $2); };
;
expr_animtree
: ANIMTREE
{ $$ = std::make_unique<ast::expr_animtree>(@$); };
;
expr_identifier_nosize
: IDENTIFIER
{ $$ = std::make_unique<ast::expr_identifier>(@$, $1); };

View File

@ -324,7 +324,7 @@ void assembler::assemble_instruction(const instruction::ptr& inst)
break;
case opcode::OP_GetInteger:
script_->align(4);
script_->write<std::int32_t>(std::stoi(inst->data[0]));
script_->write<std::int32_t>((inst->data.size() == 2) ? -1 : std::stoi(inst->data[0]));
break;
case opcode::OP_GetFloat:
script_->align(4);
@ -579,6 +579,8 @@ void assembler::align_instruction(const instruction::ptr& inst)
break;
case opcode::OP_GetInteger:
inst->size += script_->align(4);
if (inst->data.size() == 2)
add_anim_reference(inst->data, script_->pos());
script_->seek(4);
break;
case opcode::OP_GetFloat:
@ -849,14 +851,28 @@ void assembler::add_anim_reference(const std::vector<std::string>& data, std::ui
{
if (entry.name == data[0])
{
entry.anims.push_back({ data[1], ref });
if (data[1] == "-1")
{
entry.refs.push_back(ref);
}
else
{
entry.anims.push_back({ data[1], ref });
}
return;
}
}
animtree_ref new_entry;
new_entry.name = data[0];
new_entry.anims.push_back({ data[1], ref });
if (data[1] == "-1")
{
new_entry.refs.push_back(ref);
}
else
{
new_entry.anims.push_back({ data[1], ref });
}
animtrees_.push_back(std::move(new_entry));
}

View File

@ -914,6 +914,9 @@ void compiler::emit_expr(const ast::expr& expr)
case ast::kind::expr_animation:
emit_expr_animation(expr.as_animation);
break;
case ast::kind::expr_animtree:
emit_expr_animtree(expr.as_animtree);
break;
case ast::kind::expr_identifier:
emit_expr_local(expr.as_identifier);
break;
@ -1874,6 +1877,16 @@ void compiler::emit_expr_animation(const ast::expr_animation::ptr& expr)
emit_opcode(opcode::OP_GetAnimation, { animtrees_.back(), expr->value });
}
void compiler::emit_expr_animtree(const ast::expr_animtree::ptr& expr)
{
if (animtrees_.size() == 0)
{
throw comp_error( expr->loc(), "trying to use animtree without specified using animtree");
}
emit_opcode(opcode::OP_GetInteger, { animtrees_.back(), "-1" });
}
void compiler::emit_expr_istring(const ast::expr_istring::ptr& expr)
{
emit_opcode(opcode::OP_GetIString, expr->value);

View File

@ -123,6 +123,7 @@ private:
void emit_expr_object(const ast::expr& expr);
void emit_expr_vector(const ast::expr_vector::ptr& expr);
void emit_expr_animation(const ast::expr_animation::ptr& expr);
void emit_expr_animtree(const ast::expr_animtree::ptr& expr);
void emit_expr_istring(const ast::expr_istring::ptr& expr);
void emit_expr_string(const ast::expr_string::ptr& expr);
void emit_expr_hash(const ast::expr_hash::ptr& expr);

View File

@ -145,7 +145,6 @@ void decompiler::decompile_instruction(const instruction::ptr& inst, bool last)
}
case opcode::OP_GetByte:
case opcode::OP_GetUnsignedShort:
case opcode::OP_GetInteger:
{
auto node = std::make_unique<ast::expr_integer>(loc, inst->data[0]);
stack_.push(std::move(node));
@ -158,6 +157,43 @@ void decompiler::decompile_instruction(const instruction::ptr& inst, bool last)
stack_.push(std::move(node));
break;
}
case opcode::OP_GetInteger:
{
if (inst->data.size() == 2)
{
bool found = false;
//for (const auto& entry : program_->declarations) TODO: C++20 reverse_view
for (auto i = program_->declarations.rbegin(); i != program_->declarations.rend(); ++i)
{
if (*i == ast::kind::decl_usingtree)
{
if (i->as_usingtree->name->value == inst->data[0])
found = true;
else
found = false;
break;
}
}
if (!found)
{
auto tree = std::make_unique<ast::expr_string>(loc, inst->data[0]);
auto decl = std::make_unique<ast::decl_usingtree>(loc, std::move(tree));
program_->declarations.push_back(ast::decl(std::move(decl)));
}
auto node = std::make_unique<ast::expr_animtree>(loc);
stack_.push(std::move(node));
}
else
{
auto node = std::make_unique<ast::expr_integer>(loc, inst->data[0]);
stack_.push(std::move(node));
}
break;
}
case opcode::OP_GetFloat:
{
auto node = std::make_unique<ast::expr_float>(loc, inst->data[0]);
@ -217,14 +253,17 @@ void decompiler::decompile_instruction(const instruction::ptr& inst, bool last)
{
bool found = false;
for (const auto& entry : program_->declarations)
//for (const auto& entry : program_->declarations) TODO: C++20 reverse_view
for (auto i = program_->declarations.rbegin(); i != program_->declarations.rend(); ++i)
{
if (entry == ast::kind::decl_usingtree)
if (*i == ast::kind::decl_usingtree)
{
if (entry.as_usingtree->name->value == inst->data[0])
if (i->as_usingtree->name->value == inst->data[0])
found = true;
else
found = false;
break;
}
}
@ -1426,27 +1465,42 @@ void decompiler::decompile_ifelses(const ast::stmt_list::ptr& stmt)
void decompiler::decompile_aborts(const ast::stmt_list::ptr& stmt)
{
for (auto i = 0u; i < stmt->list.size(); i++)
for (auto i = static_cast<std::make_signed_t<std::size_t>>(stmt->list.size() - 1); i >= 0; i--)
//for (auto i = 0u; i < stmt->list.size(); i++)
{
if (stmt->list.at(i) == ast::kind::asm_jump)
{
auto loc = stmt->list.at(i).loc();
auto jump_loc = stmt->list.at(i).as_jump->value;
if (jump_loc == blocks_.back().loc_continue)
{
stmt->list.erase(stmt->list.begin() + i);
auto new_stmt = ast::stmt(std::make_unique<ast::stmt_continue>(loc));
stmt->list.insert(stmt->list.begin() + i, std::move(new_stmt));
}
else if (jump_loc == blocks_.back().loc_break)
if (jump_loc == blocks_.back().loc_break)
{
stmt->list.erase(stmt->list.begin() + i);
auto new_stmt = ast::stmt(std::make_unique<ast::stmt_break>(loc));
stmt->list.insert(stmt->list.begin() + i, std::move(new_stmt));
}
else if (jump_loc == blocks_.back().loc_continue)
{
stmt->list.erase(stmt->list.begin() + i);
auto new_stmt = ast::stmt(std::make_unique<ast::stmt_continue>(loc));
stmt->list.insert(stmt->list.begin() + i, std::move(new_stmt));
}
else
{
// fix for treyarch compiler bug: nested switch break locs are not preserved
if (jump_loc != blocks_.back().loc_end)
{
auto j = find_location_index(stmt, jump_loc);
if (stmt->list.at(j).as_node->kind() == ast::kind::stmt_break)
{
stmt->list.erase(stmt->list.begin() + i);
auto new_stmt = ast::stmt(std::make_unique<ast::stmt_break>(loc));
stmt->list.insert(stmt->list.begin() + i, std::move(new_stmt));
continue;
}
}
std::cout << "WARNING: unresolved jump to '" + jump_loc + "', maybe incomplete for loop\n";
}
}

View File

@ -108,7 +108,9 @@ void disassembler::disassemble(const std::string& file, std::vector<std::uint8_t
for (auto j = 0; j < ref_count; j++)
{
entry->refs.push_back(script_->read<std::uint32_t>());
auto ref = script_->read<std::uint32_t>();
entry->refs.push_back(ref);
anim_refs_.insert({ ref, entry });
}
for (auto k = 0; k < anim_count; k++)
@ -367,6 +369,7 @@ void disassembler::disassemble_instruction(const instruction::ptr& inst)
break;
case opcode::OP_GetInteger:
inst->size += script_->align(4);
disassemble_animtree(inst);
inst->data.push_back(utils::string::va("%i", script_->read<std::int32_t>()));
break;
case opcode::OP_GetFloat:
@ -465,6 +468,19 @@ void disassembler::disassemble_string(const instruction::ptr& inst)
throw disasm_error(utils::string::va("string reference not found at index '%04X'!", inst->index));
}
void disassembler::disassemble_animtree(const instruction::ptr& inst)
{
// GetInteger(-1) push animtree name if ref found
const auto ref = script_->pos();
const auto entry = anim_refs_.find(ref);
if (entry != anim_refs_.end())
{
inst->data.push_back(entry->second->name);
}
}
void disassembler::disassemble_animation(const instruction::ptr& inst)
{
inst->size += script_->align(4);

View File

@ -34,6 +34,7 @@ private:
void disassemble_function(const function::ptr& func);
void disassemble_instruction(const instruction::ptr& inst);
void disassemble_string(const instruction::ptr& inst);
void disassemble_animtree(const instruction::ptr& inst);
void disassemble_animation(const instruction::ptr& inst);
void disassemble_localvars(const instruction::ptr& inst);
void disassemble_import(const instruction::ptr& inst);

View File

@ -29,6 +29,7 @@ const std::unordered_map<std::string_view, parser::token::token_kind_type> keywo
{ "#inline", parser::token::INLINE },
{ "#include", parser::token::INCLUDE },
{ "#using_animtree", parser::token::USINGTREE },
{ "#animtree", parser::token::ANIMTREE },
{ "endon", parser::token::ENDON },
{ "notify", parser::token::NOTIFY },
{ "wait", parser::token::WAIT },

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -178,6 +178,9 @@ expr_path::expr_path(const location& loc, const std::string& value) : node(kind:
expr_identifier::expr_identifier(const std::string& value) : node(kind::expr_identifier), value(value) {}
expr_identifier::expr_identifier(const location& loc, const std::string& value) : node(kind::expr_identifier, loc), value(value) {}
expr_animtree::expr_animtree() : node(kind::expr_animtree) {}
expr_animtree::expr_animtree(const location& loc) : node(kind::expr_animtree, loc) {}
expr_animation::expr_animation(const std::string& value) : node(kind::expr_animation), value(value) {}
expr_animation::expr_animation(const location& loc, const std::string& value) : node(kind::expr_animation, loc), value(value) {}
@ -590,6 +593,11 @@ auto expr_identifier::print() const -> std::string
return value;
}
auto expr_animtree::print() const -> std::string
{
return "#animtree";
}
auto expr_animation::print() const -> std::string
{
return "%"s += value;
@ -1535,6 +1543,11 @@ bool operator==(const expr_identifier& lhs, const expr_identifier& rhs)
return lhs.value == rhs.value;
}
bool operator==(const expr_animtree&, const expr_animtree&)
{
return true;
}
bool operator==(const expr_animation& lhs, const expr_animation& rhs)
{
return lhs.value == rhs.value;
@ -1664,6 +1677,7 @@ expr::~expr()
case kind::expr_istring: as_istring.~unique_ptr(); return;
case kind::expr_path: as_path.~unique_ptr(); return;
case kind::expr_identifier: as_identifier.~unique_ptr(); return;
case kind::expr_animtree: as_animtree.~unique_ptr(); return;
case kind::expr_animation: as_animation.~unique_ptr(); return;
case kind::expr_level: as_level.~unique_ptr(); return;
case kind::expr_anim: as_anim.~unique_ptr(); return;
@ -1766,6 +1780,7 @@ bool operator==(const expr& lhs, const expr& rhs)
case kind::expr_istring: return *lhs.as_istring == *rhs.as_istring;
case kind::expr_path: return *lhs.as_path == *rhs.as_path;
case kind::expr_identifier: return *lhs.as_identifier == *rhs.as_identifier;
case kind::expr_animtree: return *lhs.as_animtree == *rhs.as_animtree;
case kind::expr_animation: return *lhs.as_animation == *rhs.as_animation;
case kind::expr_level: return *lhs.as_level == *rhs.as_level;
case kind::expr_anim: return *lhs.as_anim == *rhs.as_anim;

View File

@ -21,6 +21,7 @@ enum class kind
expr_istring,
expr_path,
expr_identifier,
expr_animtree,
expr_animation,
expr_level,
expr_anim,
@ -152,6 +153,7 @@ struct expr_string;
struct expr_istring;
struct expr_path;
struct expr_identifier;
struct expr_animtree;
struct expr_animation;
struct expr_level;
struct expr_anim;
@ -305,6 +307,7 @@ union expr
std::unique_ptr<expr_istring> as_istring;
std::unique_ptr<expr_path> as_path;
std::unique_ptr<expr_identifier> as_identifier;
std::unique_ptr<expr_animtree> as_animtree;
std::unique_ptr<expr_animation> as_animation;
std::unique_ptr<expr_level> as_level;
std::unique_ptr<expr_anim> as_anim;
@ -627,6 +630,16 @@ struct expr_identifier : public node
friend bool operator==(const expr_identifier& lhs, const expr_identifier& rhs);
};
struct expr_animtree : public node
{
using ptr = std::unique_ptr<expr_animtree>;
expr_animtree();
expr_animtree(const location& loc);
auto print() const -> std::string override;
friend bool operator==(const expr_animtree& lhs, const expr_animtree& rhs);
};
struct expr_animation : public node
{
using ptr = std::unique_ptr<expr_animation>;