From ce69051956aac9ff09666bb861e2b5851af0d66b Mon Sep 17 00:00:00 2001 From: xensik Date: Wed, 16 Nov 2022 18:23:30 +0100 Subject: [PATCH] iw9: impl hashing & missing opcodes --- src/iw9/xsk/decompiler.cpp | 14 ++- src/iw9/xsk/disassembler.cpp | 36 ++++++-- src/iw9/xsk/resolver.cpp | 163 +++++++++++++---------------------- src/iw9/xsk/resolver.hpp | 3 + 4 files changed, 97 insertions(+), 119 deletions(-) diff --git a/src/iw9/xsk/decompiler.cpp b/src/iw9/xsk/decompiler.cpp index 6fa9a2ab..38308308 100644 --- a/src/iw9/xsk/decompiler.cpp +++ b/src/iw9/xsk/decompiler.cpp @@ -1330,7 +1330,7 @@ void decompiler::decompile_instruction(const instruction::ptr& inst) for (auto i = 1; i <= count; i++) { - func_->params->list.push_back(std::make_unique(loc, "var_" + inst->data[i])); + func_->params->list.push_back(std::make_unique(loc, inst->data[i])); } break; } @@ -2625,8 +2625,7 @@ void decompiler::process_stmt_for(const ast::stmt_for::ptr& stmt, const block::p for (const auto& index : stmt->vars) { - auto var = utils::string::va("var_%d", std::stoi(index)); - blk->local_vars.push_back({ var, static_cast(std::stoi(index)), true }); + blk->local_vars.push_back({ index, static_cast(blk->local_vars_create_count), true }); blk->local_vars_create_count++; } @@ -2654,8 +2653,7 @@ void decompiler::process_stmt_foreach(const ast::stmt_foreach::ptr& stmt, const for (const auto& index : stmt->vars) { - auto var1 = utils::string::va("var_%d", std::stoi(index)); - blk->local_vars.push_back({ var1, static_cast(std::stoi(index)), true }); + blk->local_vars.push_back({ index, static_cast(blk->local_vars_create_count), true }); blk->local_vars_create_count++; } @@ -3079,7 +3077,7 @@ void decompiler::process_var_create(ast::expr& expr, const block::ptr& blk, bool { if (fromstmt) { - auto var = utils::string::va("var_%s", expr.as_asm_create->index.data()); + auto var = expr.as_asm_create->index; blk->local_vars.push_back({ var, static_cast(blk->local_vars_create_count), true }); blk->local_vars_create_count++; } @@ -3087,11 +3085,11 @@ void decompiler::process_var_create(ast::expr& expr, const block::ptr& blk, bool { for (const auto& entry : expr.as_asm_create->vars) { - blk->local_vars.push_back({ utils::string::va("var_%s", entry.data()), static_cast(blk->local_vars_create_count), true }); + blk->local_vars.push_back({ entry, static_cast(blk->local_vars_create_count), true }); blk->local_vars_create_count++; } - auto var = utils::string::va("var_%s", expr.as_asm_create->index.data()); + auto var = expr.as_asm_create->index; blk->local_vars.push_back({ var, static_cast(blk->local_vars_create_count), true }); blk->local_vars_create_count++; diff --git a/src/iw9/xsk/disassembler.cpp b/src/iw9/xsk/disassembler.cpp index 3a64adab..1ace6d54 100644 --- a/src/iw9/xsk/disassembler.cpp +++ b/src/iw9/xsk/disassembler.cpp @@ -50,7 +50,7 @@ void disassembler::disassemble(const std::string& file, std::vectorindex = static_cast(script_->pos()); func->size = stack_->read(); - func->name = utils::string::va("id_%016llX", stack_->read()); + func->name = resolver::hash_name(stack_->read()); dissasemble_function(func); @@ -215,13 +215,13 @@ void disassembler::dissasemble_instruction(const instruction::ptr& inst) case opcode::OP_EvalFieldVariableRef: case opcode::OP_EvalLevelFieldVariable: case opcode::OP_EvalAnimFieldVariableRef: - inst->data.push_back(utils::string::va("id_%016llX", script_->read())); + inst->data.push_back(resolver::hash_name(script_->read())); break; case opcode::OP_CreateLocalVariable: case opcode::OP_EvalNewLocalArrayRefCached0: case opcode::OP_SafeCreateVariableFieldCached: case opcode::OP_SetNewLocalVariableFieldCached0: - inst->data.push_back(utils::string::va("%016llX", script_->read())); + inst->data.push_back(resolver::hash_name(script_->read())); break; case opcode::OP_SetLocalVariableFieldCached: case opcode::OP_RemoveLocalVariables: @@ -311,6 +311,16 @@ void disassembler::dissasemble_instruction(const instruction::ptr& inst) case opcode::OP_FormalParams_Precompiled: disassemble_formal_params(inst); break; + case opcode::OP_unk_134: + case opcode::OP_unk_137: + script_->seek(4); + break; + case opcode::OP_unk_133: // eval something + case opcode::OP_unk_135: + case opcode::OP_unk_136: + case opcode::OP_unk_138: + inst->data.push_back(resolver::hash_name(script_->read())); + break; default: throw disasm_error(utils::string::va("unhandled opcode 0x%X at index '%04X'!", inst->opcode, inst->index)); } @@ -326,12 +336,24 @@ void disassembler::disassemble_builtin_call(const instruction::ptr& inst, bool m if (method) // TODO { auto str = stack_->read_c_string(); + + if (str.starts_with("#xS")) + { + str = resolver::hash_name(std::stoull(str.substr(3), 0 ,16)); + } + script_->seek(2); inst->data.emplace(inst->data.begin(), str); } else { auto str = stack_->read_c_string(); + + if (str.starts_with("#xS")) + { + str = resolver::hash_name(std::stoull(str.substr(3), 0 ,16)); + } + script_->seek(2); inst->data.emplace(inst->data.begin(), str); } @@ -369,8 +391,8 @@ void disassembler::disassemble_far_call(const instruction::ptr& inst, bool threa } else { - inst->data.emplace(inst->data.begin(), utils::string::va("id_%016llX", file)); - inst->data.emplace(inst->data.begin(), utils::string::va("id_%016llX", name)); + inst->data.emplace(inst->data.begin(), resolver::hash_name(file)); + inst->data.emplace(inst->data.begin(), resolver::hash_name(name)); } } @@ -433,7 +455,7 @@ void disassembler::disassemble_end_switch(const instruction::ptr& inst) void disassembler::disassemble_field_variable(const instruction::ptr& inst) { - inst->data.push_back(utils::string::va("id_%016llX", script_->read())); + inst->data.push_back(resolver::hash_name(script_->read())); } void disassembler::disassemble_formal_params(const instruction::ptr& inst) @@ -445,7 +467,7 @@ void disassembler::disassemble_formal_params(const instruction::ptr& inst) for (auto i = 0u; i < count; i++) { - inst->data.push_back(utils::string::va("%016llX", script_->read())); + inst->data.push_back(resolver::hash_name(script_->read())); } } diff --git a/src/iw9/xsk/resolver.cpp b/src/iw9/xsk/resolver.cpp index 492d3023..d1d424bc 100644 --- a/src/iw9/xsk/resolver.cpp +++ b/src/iw9/xsk/resolver.cpp @@ -14,14 +14,9 @@ namespace xsk::gsc::iw9 { +std::unordered_map hash_map; std::unordered_map opcode_map; -std::unordered_map function_map; -std::unordered_map method_map; -std::unordered_map token_map; std::unordered_map opcode_map_rev; -std::unordered_map function_map_rev; -std::unordered_map method_map_rev; -std::unordered_map token_map_rev; std::unordered_map> files; read_cb_type read_callback = nullptr; std::set string_map; @@ -62,88 +57,31 @@ auto resolver::opcode_name(std::uint8_t id) -> std::string auto resolver::function_id(const std::string& name) -> std::uint16_t { - if (name.starts_with("_func_")) - { - return static_cast(std::stoul(name.substr(6), nullptr, 16)); - } - - const auto itr = function_map_rev.find(name); - - if (itr != function_map_rev.end()) - { - return itr->second; - } - throw error(utils::string::va("couldn't resolve builtin function id for name '%s'!", name.data())); } auto resolver::function_name(std::uint16_t id) -> std::string { - const auto itr = function_map.find(id); - - if (itr != function_map.end()) - { - return std::string(itr->second); - } - return utils::string::va("_func_%04X", id); } auto resolver::method_id(const std::string& name) -> std::uint16_t { - if (name.starts_with("_meth_")) - { - return static_cast(std::stoul(name.substr(6), nullptr, 16)); - } - - const auto itr = method_map_rev.find(name); - - if (itr != method_map_rev.end()) - { - return itr->second; - } - throw error(utils::string::va("couldn't resolve builtin method id for name '%s'!", name.data())); } auto resolver::method_name(std::uint16_t id) -> std::string { - const auto itr = method_map.find(id); - - if (itr != method_map.end()) - { - return std::string(itr->second); - } - return utils::string::va("_meth_%04X", id); } -auto resolver::token_id(const std::string& name) -> std::uint32_t +auto resolver::token_id(const std::string&) -> std::uint32_t { - if (name.starts_with("_id_")) - { - return static_cast(std::stoul(name.substr(4), nullptr, 16)); - } - - const auto itr = token_map_rev.find(name); - - if (itr != token_map_rev.end()) - { - return itr->second; - } - return 0; } auto resolver::token_name(std::uint32_t id) -> std::string { - const auto itr = token_map.find(id); - - if (itr != token_map.end()) - { - return std::string(itr->second); - } - return utils::string::va("_id_%04X", id); } @@ -151,12 +89,12 @@ auto resolver::find_function(const std::string& name) -> bool { if (name.starts_with("_func_")) return true; - const auto itr = function_map_rev.find(name); + /* const auto itr = function_map_rev.find(name); if (itr != function_map_rev.end()) { return true; - } + }*/ return false; } @@ -165,19 +103,19 @@ auto resolver::find_method(const std::string& name) -> bool { if (name.starts_with("_meth_")) return true; - const auto itr = method_map_rev.find(name); + /*const auto itr = method_map_rev.find(name); if (itr != method_map_rev.end()) { return true; - } + }*/ return false; } -void resolver::add_function(const std::string& name, std::uint16_t id) +void resolver::add_function(const std::string& , std::uint16_t ) { - const auto itr = function_map_rev.find(name); + /*const auto itr = function_map_rev.find(name); if (itr != function_map_rev.end()) { @@ -200,12 +138,12 @@ void resolver::add_function(const std::string& name, std::uint16_t id) function_map.insert({ id, *ins.first }); function_map_rev.insert({ *ins.first, id }); } - } + }*/ } -void resolver::add_method(const std::string& name, std::uint16_t id) +void resolver::add_method(const std::string& , std::uint16_t ) { - const auto itr = method_map_rev.find(name); + /*const auto itr = method_map_rev.find(name); if (itr != method_map_rev.end()) { @@ -228,7 +166,7 @@ void resolver::add_method(const std::string& name, std::uint16_t id) method_map.insert({ id, *ins.first }); method_map_rev.insert({ *ins.first, id }); } - } + }*/ } auto resolver::make_token(std::string_view str) -> std::string @@ -295,6 +233,45 @@ auto resolver::fs_to_game_path(const std::filesystem::path& file) -> std::filesy return result.empty() ? file : result; } +auto resolver::hash_id(const std::string& name) -> std::uint64_t +{ + if (name.starts_with("id_")) + { + return static_cast(std::stoull(name.substr(3), nullptr, 16)); + } + + const char* str = name.data(); + uint64_t hash = 0x79D6530B0BB9B5D1; + + while ( *str ) + { + uint8_t byte = *str++; + + if (static_cast(byte - 65) <= 25) + { + byte += 32; + } + + printf("%c", byte); + + hash = (uint64_t)0x10000000233 * ((uint64_t)byte ^ hash); + } + + return hash; +} + +auto resolver::hash_name(std::uint64_t id) -> std::string +{ + const auto itr = hash_map.find(id); + + if (itr != hash_map.end()) + { + return std::string(itr->second); + } + + return utils::string::va("id_%016llX", id); +} + const std::array, 167> opcode_list {{ { 0x00, "OP_CastFieldObject" }, @@ -466,16 +443,12 @@ const std::array, 167> opcode_list { 0xA6, "OP_unk_166" }, }}; -const std::array, 0> function_list -{{ -}}; - -const std::array, 0> method_list -{{ -}}; - -const std::array, 0> token_list +const std::array, 4> hash_list {{ + { 0xC92DD50E8E081414, "main" }, + { 0xAD3D69B62BC6FB2F, "init" }, + { 0x4CCFEE6F73819653, "getfirstarraykey" }, + { 0x6DB433AE7304A362, "getnextarraykey" }, }}; struct __init__ @@ -488,12 +461,7 @@ struct __init__ opcode_map.reserve(opcode_list.size()); opcode_map_rev.reserve(opcode_list.size()); - function_map.reserve(function_list.size()); - function_map_rev.reserve(function_list.size()); - method_map.reserve(method_list.size()); - method_map_rev.reserve(method_list.size()); - token_map.reserve(token_list.size()); - token_map_rev.reserve(token_list.size()); + hash_map.reserve(hash_list.size()); for (const auto& entry : opcode_list) { @@ -501,22 +469,9 @@ struct __init__ opcode_map_rev.insert({ entry.second, entry.first }); } - for (const auto& entry : function_list) + for (const auto& entry : hash_list) { - function_map.insert({ entry.first, entry.second }); - function_map_rev.insert({ entry.second, entry.first }); - } - - for (const auto& entry : method_list) - { - method_map.insert({ entry.first, entry.second }); - method_map_rev.insert({ entry.second, entry.first }); - } - - for (const auto& entry : token_list) - { - token_map.insert({ entry.first, entry.second }); - token_map_rev.insert({ entry.second, entry.first }); + hash_map.insert({ entry.first, entry.second }); } } }; diff --git a/src/iw9/xsk/resolver.hpp b/src/iw9/xsk/resolver.hpp index b6bbd853..6bc9566d 100644 --- a/src/iw9/xsk/resolver.hpp +++ b/src/iw9/xsk/resolver.hpp @@ -26,6 +26,9 @@ public: static auto token_id(const std::string& name) -> std::uint32_t; static auto token_name(std::uint32_t id) -> std::string; + static auto hash_id(const std::string& name) -> std::uint64_t; + static auto hash_name(std::uint64_t id) -> std::string; + static auto find_function(const std::string& name) -> bool; static auto find_method(const std::string& name) -> bool;