add treyarch animtrees & fix nested switches
This commit is contained in:
parent
b0ed15dc6c
commit
4e4480792a
@ -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); };
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
@ -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;
|
||||
|
@ -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>;
|
||||
|
Loading…
Reference in New Issue
Block a user