From 3a066354b463370430eec37b17669147509832c6 Mon Sep 17 00:00:00 2001 From: xensik Date: Tue, 12 Nov 2024 23:39:05 +0100 Subject: [PATCH] refactor usize --- include/xsk/gsc/assembler.hpp | 19 +- include/xsk/gsc/common/assembly.hpp | 10 +- include/xsk/gsc/compiler.hpp | 4 +- include/xsk/gsc/context.hpp | 2 +- include/xsk/gsc/decompiler.hpp | 2 +- include/xsk/utils/reader.hpp | 8 +- include/xsk/utils/writer.hpp | 21 +- src/gsc/assembler.cpp | 398 ++++++++++++---------------- src/gsc/compiler.cpp | 34 +-- src/gsc/context.cpp | 2 +- src/gsc/decompiler.cpp | 4 +- src/gsc/disassembler.cpp | 4 +- src/gsc/source.cpp | 6 +- src/utils/reader.cpp | 8 +- src/utils/writer.cpp | 37 ++- 15 files changed, 250 insertions(+), 309 deletions(-) diff --git a/include/xsk/gsc/assembler.hpp b/include/xsk/gsc/assembler.hpp index 1ba9f84c..2b306b55 100644 --- a/include/xsk/gsc/assembler.hpp +++ b/include/xsk/gsc/assembler.hpp @@ -28,17 +28,18 @@ class assembler private: auto assemble_function(function const& func) -> void; auto assemble_instruction(instruction const& inst) -> void; - auto assemble_builtin_call(instruction const& inst, bool method, bool args) -> void; - auto assemble_local_call(instruction const& inst, bool thread) -> void; - auto assemble_far_call(instruction const& inst, bool thread) -> void; - auto assemble_switch(instruction const& inst) -> void; - auto assemble_end_switch(instruction const& inst) -> void; - auto assemble_field_variable(instruction const& inst) -> void; - auto assemble_formal_params(instruction const& inst) -> void; + auto assemble_field(instruction const& inst) -> void; + auto assemble_params(instruction const& inst) -> void; + auto assemble_call_far(instruction const& inst, bool thread) -> void; + auto assemble_call_far2(instruction const& inst, bool thread) -> void; + auto assemble_call_local(instruction const& inst, bool thread) -> void; + auto assemble_call_builtin(instruction const& inst, bool method, bool args) -> void; auto assemble_jump(instruction const& inst, bool expr, bool back) -> void; + auto assemble_switch(instruction const& inst) -> void; + auto assemble_switch_table(instruction const& inst) -> void; auto assemble_offset(i32 offs) -> void; - auto resolve_function(std::string const& name) -> i32; - auto resolve_label(std::string const& name) -> i32; + auto resolve_function(std::string const& name) -> usize; + auto resolve_label(std::string const& name) -> usize; auto encrypt_string(std::string const& str) -> std::string; }; diff --git a/include/xsk/gsc/common/assembly.hpp b/include/xsk/gsc/common/assembly.hpp index 973ddf51..702646a2 100644 --- a/include/xsk/gsc/common/assembly.hpp +++ b/include/xsk/gsc/common/assembly.hpp @@ -230,8 +230,8 @@ struct instruction { using ptr = std::unique_ptr; - u32 index; - u32 size; + usize index; + usize size; sourcepos pos; opcode opcode; std::vector data; @@ -246,12 +246,12 @@ struct function { using ptr = std::unique_ptr; - u32 index; - u32 size; + usize index; + usize size; u32 id; std::string name; std::vector instructions; - std::unordered_map labels; + std::unordered_map labels; static auto make() -> function::ptr { diff --git a/include/xsk/gsc/compiler.hpp b/include/xsk/gsc/compiler.hpp index 3522ca86..2bc0ebf4 100644 --- a/include/xsk/gsc/compiler.hpp +++ b/include/xsk/gsc/compiler.hpp @@ -23,8 +23,8 @@ class compiler std::vector continue_blks_; std::string animname_; sourcepos debug_pos_; - u32 index_; - u32 label_idx_; + usize index_; + usize label_idx_; bool can_break_; bool can_continue_; bool developer_thread_; diff --git a/include/xsk/gsc/context.hpp b/include/xsk/gsc/context.hpp index f8249f05..e21c4054 100644 --- a/include/xsk/gsc/context.hpp +++ b/include/xsk/gsc/context.hpp @@ -55,7 +55,7 @@ class context auto engine_name() const -> std::string_view; - auto opcode_size(opcode op) const -> u32; + auto opcode_size(opcode op) const -> usize; auto opcode_id(opcode op) const -> u8; diff --git a/include/xsk/gsc/decompiler.hpp b/include/xsk/gsc/decompiler.hpp index 41adb94e..511d5057 100644 --- a/include/xsk/gsc/decompiler.hpp +++ b/include/xsk/gsc/decompiler.hpp @@ -15,7 +15,7 @@ class decompiler context const* ctx_; program::ptr program_; decl_function::ptr func_; - std::unordered_map labels_; + std::unordered_map labels_; std::vector expr_labels_; std::vector tern_labels_; std::stack stack_; diff --git a/include/xsk/utils/reader.hpp b/include/xsk/utils/reader.hpp index 763e2e39..5b8b5fe1 100644 --- a/include/xsk/utils/reader.hpp +++ b/include/xsk/utils/reader.hpp @@ -27,11 +27,11 @@ struct reader auto read() -> T; auto read_i24() -> i32; auto read_cstr() -> std::string; - auto read_bytes(u32 pos, u32 count) -> std::string; + auto read_bytes(usize pos, usize count) -> std::string; auto is_avail() const -> bool; - auto seek(u32 size) -> void; - auto seek_neg(u32 size) -> void; - auto align(u32 size) -> u32; + auto seek(usize size) -> void; + auto seek_neg(usize size) -> void; + auto align(usize size) -> usize; auto data() const -> u8 const*; auto size() const -> usize; auto pos() const -> usize; diff --git a/include/xsk/utils/writer.hpp b/include/xsk/utils/writer.hpp index c2ed782a..616f831f 100644 --- a/include/xsk/utils/writer.hpp +++ b/include/xsk/utils/writer.hpp @@ -14,10 +14,10 @@ struct writer using error = std::runtime_error; private: - static constexpr u32 default_size = 0x100000; + static constexpr usize default_size = 0x100000; u8* data_; - u32 size_; - u32 pos_ = 0; + usize size_; + usize pos_ = 0; bool swap_; public: @@ -26,21 +26,22 @@ struct writer auto operator=(writer const&) -> writer& = delete; auto operator=(writer&&) -> writer& = delete; explicit writer(bool swap = false); - writer(u32 size, bool swap = false); + writer(usize size, bool swap = false); ~writer(); auto clear() -> void; template auto write(T data) -> void; + auto write_i24(i32 data) -> void; auto write_string(std::string const& data) -> void; auto write_cstr(std::string const& data) -> void; auto is_avail() const -> bool; - auto seek(u32 size) -> void; - auto seek_neg(u32 size) -> void; - auto align(u32 size) -> u32; + auto seek(usize size) -> void; + auto seek_neg(usize size) -> void; + auto align(usize size) -> usize; auto data() const -> u8 const*; - auto size() const -> u32; - auto pos() const -> u32; - auto pos(u32 pos) -> void; + auto size() const -> usize; + auto pos() const -> usize; + auto pos(usize pos) -> void; }; } // namespace xsk::utils diff --git a/src/gsc/assembler.cpp b/src/gsc/assembler.cpp index 4ab0dd47..92b3ee4d 100644 --- a/src/gsc/assembler.cpp +++ b/src/gsc/assembler.cpp @@ -30,10 +30,10 @@ auto assembler::assemble(assembly const& data) -> std::tuple(devmap_count_); - devmap_.pos(dev_endpos); + devmap_.pos(save); return { buffer{ script_.data(), script_.pos() }, buffer{ stack_.data(), stack_.pos() }, buffer{ devmap_.data(), devmap_.pos() } }; } @@ -42,7 +42,7 @@ auto assembler::assemble_function(function const& func) -> void { func_ = &func; - stack_.write(func.size); + stack_.write(static_cast(func.size)); if (ctx_->props() & props::hash) { @@ -73,7 +73,7 @@ auto assembler::assemble_instruction(instruction const& inst) -> void if ((ctx_->build() & build::dev_maps) != build::prod) { - devmap_.write(script_.pos()); + devmap_.write(static_cast(script_.pos())); devmap_.write(static_cast(inst.pos.line)); devmap_.write(static_cast(inst.pos.column)); devmap_count_++; @@ -246,7 +246,7 @@ auto assembler::assemble_instruction(instruction const& inst) -> void case opcode::OP_EvalLevelFieldVariableRef: case opcode::OP_EvalAnimFieldVariable: case opcode::OP_EvalSelfFieldVariableRef: - assemble_field_variable(inst); + assemble_field(inst); break; case opcode::OP_CallBuiltinPointer: case opcode::OP_CallBuiltinMethodPointer: @@ -260,31 +260,31 @@ auto assembler::assemble_instruction(instruction const& inst) -> void case opcode::OP_ScriptLocalFunctionCall2: case opcode::OP_ScriptLocalFunctionCall: case opcode::OP_ScriptLocalMethodCall: - assemble_local_call(inst, false); + assemble_call_local(inst, false); break; case opcode::OP_ScriptLocalThreadCall: case opcode::OP_ScriptLocalChildThreadCall: case opcode::OP_ScriptLocalMethodThreadCall: case opcode::OP_ScriptLocalMethodChildThreadCall: - assemble_local_call(inst, true); + assemble_call_local(inst, true); break; case opcode::OP_GetFarFunction: case opcode::OP_ScriptFarFunctionCall2: case opcode::OP_ScriptFarFunctionCall: case opcode::OP_ScriptFarMethodCall: - assemble_far_call(inst, false); + assemble_call_far(inst, false); break; case opcode::OP_ScriptFarThreadCall: case opcode::OP_ScriptFarChildThreadCall: case opcode::OP_ScriptFarMethodThreadCall: case opcode::OP_ScriptFarMethodChildThreadCall: - assemble_far_call(inst, true); + assemble_call_far(inst, true); break; case opcode::OP_CallBuiltin: - assemble_builtin_call(inst, false, true); + assemble_call_builtin(inst, false, true); break; case opcode::OP_CallBuiltinMethod: - assemble_builtin_call(inst, true, true); + assemble_call_builtin(inst, true, true); break; case opcode::OP_GetBuiltinFunction: case opcode::OP_CallBuiltin0: @@ -293,7 +293,7 @@ auto assembler::assemble_instruction(instruction const& inst) -> void case opcode::OP_CallBuiltin3: case opcode::OP_CallBuiltin4: case opcode::OP_CallBuiltin5: - assemble_builtin_call(inst, false, false); + assemble_call_builtin(inst, false, false); break; case opcode::OP_GetBuiltinMethod: case opcode::OP_CallBuiltinMethod0: @@ -302,7 +302,7 @@ auto assembler::assemble_instruction(instruction const& inst) -> void case opcode::OP_CallBuiltinMethod3: case opcode::OP_CallBuiltinMethod4: case opcode::OP_CallBuiltinMethod5: - assemble_builtin_call(inst, true, false); + assemble_call_builtin(inst, true, false); break; case opcode::OP_JumpOnFalseExpr: case opcode::OP_JumpOnTrueExpr: @@ -320,296 +320,242 @@ auto assembler::assemble_instruction(instruction const& inst) -> void assemble_switch(inst); break; case opcode::OP_endswitch: - assemble_end_switch(inst); + assemble_switch_table(inst); break; case opcode::OP_FormalParams: - assemble_formal_params(inst); + assemble_params(inst); break; default: throw asm_error(std::format("unhandled opcode {} at index {:04X}", ctx_->opcode_name(inst.opcode), inst.index)); } } -auto assembler::assemble_builtin_call(instruction const& inst, bool method, bool args) -> void +auto assembler::assemble_field(instruction const& inst) -> void { - if (args) - { - script_.write(static_cast(std::stoi(inst.data[1]))); - } - if (ctx_->props() & props::hash) { - stack_.write_cstr(std::format("#xS{:x}", ctx_->hash_id(inst.data[0]))); - script_.write(0); + return script_.write(ctx_->hash_id(inst.data[0])); } + + auto id = ctx_->token_id(inst.data[0]); + + if (id == 0) id = 0xFFFFFFFF; + + if (ctx_->props() & props::tok4) + script_.write(id); else + script_.write(static_cast(id)); + + if (id > ctx_->str_count()) { - auto const id = method ? ctx_->meth_id(inst.data[0]) : ctx_->func_id(inst.data[0]); + if (ctx_->props() & props::tok4) + stack_.write(0); + else + stack_.write(0); - script_.write(id); + stack_.write_cstr(encrypt_string(inst.data[0])); } } -auto assembler::assemble_local_call(instruction const& inst, bool thread) -> void +auto assembler::assemble_params(instruction const& inst) -> void { - auto const addr = resolve_function(inst.data[0]); - auto const offset = static_cast(addr - inst.index - 1); + auto count = std::stoul(inst.data[0]); - assemble_offset(offset); + script_.write(static_cast(count)); - if (thread) + for (auto i = 1u; i <= count; i++) { - script_.write(static_cast(std::stoi(inst.data[1]))); + if (ctx_->props() & props::hash) + script_.write(ctx_->hash_id(inst.data[i])); + else + script_.write(static_cast(std::stoi(inst.data[i]))); } } -auto assembler::assemble_far_call(instruction const& inst, bool thread) -> void +auto assembler::assemble_call_far(instruction const& inst, bool thread) -> void { if (ctx_->props() & props::farcall) { - if (inst.data[0].empty()) - { - auto const addr = resolve_function(inst.data[1]); - auto const offset = static_cast(addr - inst.index - 1); + return assemble_call_far2(inst, thread); + } - script_.write(static_cast(offset)); // unsigned? - stack_.write(0); - stack_.write(0); - } - else - { - auto path = inst.data[0]; - if (!path.starts_with("_id_")) - path.append(ctx_->instance() == instance::server ? ".gsc" : ".csc"); + auto file_id = ctx_->token_id(inst.data[0]); + auto func_id = ctx_->token_id(inst.data[1]); - script_.write(0); - stack_.write(ctx_->path_id(path)); - stack_.write(ctx_->hash_id(inst.data[1])); - } + if (ctx_->props() & props::tok4) + stack_.write(file_id); + else + stack_.write(static_cast(file_id)); - if (thread) - { - script_.write(static_cast(std::stoi(inst.data[2]))); - } - } + if (file_id == 0) + stack_.write_cstr(encrypt_string(inst.data[0])); + + if (ctx_->props() & props::tok4) + stack_.write(func_id); else + stack_.write(static_cast(func_id)); + + if (func_id == 0) + stack_.write_cstr(encrypt_string(inst.data[1])); + + script_.write(0); + script_.write(0); + + if (thread) { - script_.write(0); - script_.write(0); + script_.write(static_cast(std::stoi(inst.data[2]))); + } +} - if (thread) - { - script_.write(static_cast(std::stoi(inst.data[2]))); - } +auto assembler::assemble_call_far2(instruction const& inst, bool thread) -> void +{ + if (inst.data[0].empty()) + { + script_.write(static_cast(resolve_function(inst.data[1]) - inst.index - 1)); + stack_.write(0); + stack_.write(0); + } + else + { + auto path = inst.data[0]; - auto const file_id = ctx_->token_id(inst.data[0]); - auto const func_id = ctx_->token_id(inst.data[1]); + if (!path.starts_with("_id_")) + path.append(ctx_->instance() == instance::server ? ".gsc" : ".csc"); - if (ctx_->props() & props::tok4) - stack_.write(file_id); - else - stack_.write(static_cast(file_id)); + script_.write(0); + stack_.write(ctx_->path_id(path)); + stack_.write(ctx_->hash_id(inst.data[1])); + } - if (file_id == 0) - stack_.write_cstr(encrypt_string(inst.data[0])); + if (thread) + { + script_.write(static_cast(std::stoi(inst.data[2]))); + } +} - if (ctx_->props() & props::tok4) - stack_.write(func_id); - else - stack_.write(static_cast(func_id)); +auto assembler::assemble_call_local(instruction const& inst, bool thread) -> void +{ + assemble_offset(static_cast(resolve_function(inst.data[0]) - inst.index - 1)); - if (func_id == 0) - stack_.write_cstr(encrypt_string(inst.data[1])); + if (thread) + { + script_.write(static_cast(std::stoi(inst.data[1]))); } } -auto assembler::assemble_switch(instruction const& inst) -> void +auto assembler::assemble_call_builtin(instruction const& inst, bool method, bool args) -> void { - auto const addr = resolve_label(inst.data[0]); + if (args) + { + script_.write(static_cast(std::stoi(inst.data[1]))); + } - script_.write(addr - inst.index - 4); + if (ctx_->props() & props::hash) + { + stack_.write_cstr(std::format("#xS{:x}", ctx_->hash_id(inst.data[0]))); + script_.write(0); + } + else + { + script_.write(method ? ctx_->meth_id(inst.data[0]) : ctx_->func_id(inst.data[0])); + } } -auto assembler::assemble_end_switch(instruction const& inst) -> void +auto assembler::assemble_jump(instruction const& inst, bool expr, bool back) -> void { - auto const count = std::stoul(inst.data[0]); + if (expr) + { + script_.write(static_cast(resolve_label(inst.data[0]) - inst.index - 3)); + } + else if (back) + { + script_.write(static_cast((inst.index + 3) - resolve_label(inst.data[0]))); + } + else + { + script_.write(static_cast(resolve_label(inst.data[0]) - inst.index - 5)); + } +} - script_.write(static_cast(count)); +auto assembler::assemble_switch(instruction const& inst) -> void +{ + script_.write(resolve_label(inst.data[0]) - inst.index - 4); +} - auto type = static_cast(std::stoul(inst.data.back())); +auto assembler::assemble_switch_table(instruction const& inst) -> void +{ + auto count = std::stoul(inst.data[0]); auto index = inst.index + 3u; + script_.write(static_cast(count)); + for (auto i = 0u; i < count; i++) { - if (ctx_->engine() == engine::iw9) + if (inst.data[1 + (4 * i)] == "case") { - if (inst.data[1 + (4 * i)] == "case") - { - type = static_cast(std::stoul(inst.data[1 + (4 * i) + 1])); + auto type = static_cast(std::stoul(inst.data[1 + (4 * i) + 1])); - if (type == switch_type::integer) - { + if (type == switch_type::integer) + { + if (ctx_->engine() == engine::iw9) script_.write(std::stoi(inst.data[1 + (4 * i) + 2])); //signed? - } else - { - script_.write(0); - stack_.write_cstr(inst.data[1 + (4 * i) + 2]); - } - - auto const addr = resolve_label(inst.data[1 + (4 * i) + 3]); - - script_.write(static_cast(addr - index - 4)); - script_.write(0); - script_.write(static_cast(type)); - - index += 8; + script_.write((std::stoi(inst.data[1 + (4 * i) + 2]) & 0xFFFFFF) + 0x800000); } - else if (inst.data[1 + (4 * i)] == "default") + else { - auto const addr = resolve_label(inst.data[1 + (4 * i) + 1]); + script_.write((ctx_->engine() == engine::iw9) ? 0 : i + 1); + stack_.write_cstr(encrypt_string(inst.data[1 + (4 * i) + 2])); + } - script_.write(0); - script_.write(static_cast(addr - index - 4)); - script_.write(0); + auto addr = resolve_label(inst.data[1 + (4 * i) + 3]); + if (ctx_->engine() == engine::iw9) + { + script_.write(static_cast(addr - index - 4)); + script_.write(0xFF); + script_.write(static_cast(type)); index += 8; } else { - throw asm_error(std::format("invalid switch case {}", inst.data[1 + (4 * i)])); + assemble_offset(addr - index - 4); + index += 7; } } - else + else if (inst.data[1 + (4 * i)] == "default") { - if (inst.data[1 + (3 * i)] == "case") - { - if (type == switch_type::integer) - { - script_.write((std::stoi(inst.data[1 + (3 * i) + 1]) & 0xFFFFFF) + 0x800000); - } - else - { - script_.write(i + 1); - stack_.write_cstr(encrypt_string(inst.data[1 + (3 * i) + 1])); - } + auto addr = resolve_label(inst.data[1 + (4 * i) + 1]); - auto const addr = resolve_label(inst.data[1 + (3 * i) + 2]); - - assemble_offset(addr - index - 4); - - index += 7; + if (ctx_->engine() == engine::iw9) + { + script_.write(0); + script_.write(static_cast(addr - index - 4)); + script_.write(0xFF); + script_.write(0); + index += 8; } - else if (inst.data[1 + (3 * i)] == "default") + else { script_.write(0); stack_.write_cstr("\x01"); - - auto const addr = resolve_label(inst.data[1 + (3 * i) + 1]); - assemble_offset(addr - index - 4); - index += 7; } - else - { - throw asm_error(std::format("invalid switch case {}", inst.data[1 + (3 * i)])); - } - } - } -} - -auto assembler::assemble_field_variable(instruction const& inst) -> void -{ - if (ctx_->props() & props::hash) - { - script_.write(ctx_->hash_id(inst.data[0])); - } - else - { - auto id = ctx_->token_id(inst.data[0]); - - if (id == 0) id = 0xFFFFFFFF; - - if (ctx_->props() & props::tok4) - script_.write(id); - else - script_.write(static_cast(id)); - - if (id > ctx_->str_count()) - { - if (ctx_->props() & props::tok4) - stack_.write(0); - else - stack_.write(0); - - stack_.write_cstr(encrypt_string(inst.data[0])); - } - } -} - -auto assembler::assemble_formal_params(instruction const& inst) -> void -{ - auto const count = std::stoul(inst.data[0]); - - script_.write(static_cast(count)); - - for (auto i = 1u; i <= count; i++) - { - if (ctx_->props() & props::hash) - { - script_.write(ctx_->hash_id(inst.data[i])); } else { - script_.write(static_cast(std::stoi(inst.data[i]))); + throw asm_error("malformed switch table"); } } } -auto assembler::assemble_jump(instruction const& inst, bool expr, bool back) -> void -{ - auto const addr = resolve_label(inst.data[0]); - - if (expr) - { - script_.write(static_cast(addr - inst.index - 3)); - } - else if (back) - { - script_.write(static_cast((inst.index + 3) - addr)); - } - else - { - script_.write(static_cast(addr - inst.index - 5)); - } -} - auto assembler::assemble_offset(i32 offs) -> void { - auto bytes = std::array{}; - - auto const shift = (ctx_->props() & props::offs8) ? 8 : (ctx_->props() & props::offs9) ? 9 : 10; - - offs = (offs << shift) >> 8; - - *reinterpret_cast(bytes.data()) = offs; - - if (ctx_->endian() == endian::little) - { - script_.write(bytes[0]); - script_.write(bytes[1]); - script_.write(bytes[2]); - } - else - { - script_.write(bytes[2]); - script_.write(bytes[1]); - script_.write(bytes[0]); - } + script_.write_i24((offs << ((ctx_->props() & props::offs8) ? 8 : (ctx_->props() & props::offs9) ? 9 : 10)) >> 8); } -auto assembler::resolve_function(std::string const& name) -> std::int32_t +auto assembler::resolve_function(std::string const& name) -> usize { for (auto const& entry : assembly_->functions) { @@ -622,7 +568,7 @@ auto assembler::resolve_function(std::string const& name) -> std::int32_t throw asm_error(std::format("couldn't resolve local function address of {}", name)); } -auto assembler::resolve_label(std::string const& name) -> std::int32_t +auto assembler::resolve_label(std::string const& name) -> usize { for (auto const& entry : func_->labels) { @@ -637,21 +583,21 @@ auto assembler::resolve_label(std::string const& name) -> std::int32_t auto assembler::encrypt_string(std::string const& str) -> std::string { - if (str.starts_with("_encstr_") && str.size() % 2 == 0) + if (!str.starts_with("_encstr_") || str.size() % 2 != 0) { - auto data = std::string{}; + return str; + } - data.reserve(str.size() / 2); + auto data = ""s; - for (auto i = 8u; i < str.size(); i += 2) - { - data += static_cast(std::stoul(str.substr(i, 2), 0, 16)); - } + data.reserve(str.size() / 2); - return data; + for (auto i = 8u; i < str.size(); i += 2) + { + data += static_cast(std::stoul(str.substr(i, 2), 0, 16)); } - return str; + return data; } } // namespace xsk::gsc diff --git a/src/gsc/compiler.cpp b/src/gsc/compiler.cpp index c9593dab..e49f05c1 100644 --- a/src/gsc/compiler.cpp +++ b/src/gsc/compiler.cpp @@ -736,7 +736,6 @@ auto compiler::emit_stmt_switch(stmt_switch const& stm, scope& scp) -> void auto data = std::vector{}; data.push_back(std::format("{}", stm.body->block->list.size())); - auto type = switch_type::none; auto loc_default = std::string{}; auto has_default = false; scope* default_ctx = nullptr; @@ -751,39 +750,13 @@ auto compiler::emit_stmt_switch(stmt_switch const& stm, scope& scp) -> void if (entry->as().value->is()) { - if (ctx_->engine() == engine::iw9) - { - data.push_back(std::format("{}", static_cast>(switch_type::integer))); - } - else - { - if (type == switch_type::string) - { - throw comp_error(entry->loc(), "switch cases with different types"); - } - - type = switch_type::integer; - } - + data.push_back(std::format("{}", static_cast(switch_type::integer))); data.push_back(entry->as().value->as().value); data.push_back(insert_label()); } else if (entry->as().value->is()) { - if (ctx_->engine() == engine::iw9) - { - data.push_back(std::format("{}", static_cast>(switch_type::string))); - } - else - { - if (type == switch_type::integer) - { - throw comp_error(entry->loc(), "switch cases with different types"); - } - - type = switch_type::string; - } - + data.push_back(std::format("{}", static_cast>(switch_type::string))); data.push_back(entry->as().value->as().value); data.push_back(insert_label()); } @@ -834,10 +807,7 @@ auto compiler::emit_stmt_switch(stmt_switch const& stm, scope& scp) -> void scp.init(break_blks_); } - data.push_back(std::format("{}", static_cast>(type))); - insert_label(table_loc); - emit_opcode(opcode::OP_endswitch, data); auto offset = static_cast(((ctx_->engine() == engine::iw9) ? 8 : 7) * stm.body->block->list.size()); diff --git a/src/gsc/context.cpp b/src/gsc/context.cpp index 4efe871c..c9933056 100644 --- a/src/gsc/context.cpp +++ b/src/gsc/context.cpp @@ -57,7 +57,7 @@ auto context::engine_name() const -> std::string_view return ""; } -auto context::opcode_size(opcode op) const -> u32 +auto context::opcode_size(opcode op) const -> usize { switch (op) { diff --git a/src/gsc/decompiler.cpp b/src/gsc/decompiler.cpp index 5e268ef4..c020a749 100644 --- a/src/gsc/decompiler.cpp +++ b/src/gsc/decompiler.cpp @@ -36,7 +36,7 @@ auto decompiler::decompile_function(function const& func) -> void locs_ = {}; stack_ = {}; - auto loc = location{ nullptr, static_cast(func.index) }; + auto loc = location{ nullptr, static_cast(func.index) }; auto name = expr_identifier::make(loc, func.name); auto prms = expr_parameters::make(loc); auto body = stmt_comp::make(loc, stmt_list::make(loc)); @@ -67,7 +67,7 @@ auto decompiler::decompile_instruction(instruction const& inst) -> void { decompile_expressions(inst); - auto loc = location{ nullptr, static_cast(inst.index) }; + auto loc = location{ nullptr, static_cast(inst.index) }; switch (inst.opcode) { diff --git a/src/gsc/disassembler.cpp b/src/gsc/disassembler.cpp index 1a8bec1e..5a8a3c5a 100644 --- a/src/gsc/disassembler.cpp +++ b/src/gsc/disassembler.cpp @@ -475,7 +475,7 @@ auto disassembler::disassemble_switch_table(instruction& inst) -> void inst.data.push_back(std::format("{}", count)); - for (auto i = count; i > 0; i--) + for (auto i = 0u; i < count; i++) { auto data = script_.read(); auto offs = (ctx_->engine() == engine::iw9) ? script_.read() : disassemble_offset(); @@ -577,7 +577,7 @@ auto disassembler::resolve_functions() -> void auto disassembler::resolve_function(std::string const& index) -> std::string { - auto addr = static_cast(std::stoul(index)); + auto addr = std::stoul(index); for (auto const& func : assembly_->functions) { diff --git a/src/gsc/source.cpp b/src/gsc/source.cpp index 7d70eb00..3065353a 100644 --- a/src/gsc/source.cpp +++ b/src/gsc/source.cpp @@ -32,7 +32,7 @@ auto source::parse_assembly(u8 const* data, usize size) -> assembly::ptr auto lines = utils::string::clean_buffer_lines(data, size); auto assembly = assembly::make(); auto func = function::ptr{ nullptr }; - auto index = u32{ 1 }; + auto index = usize{ 1 }; auto count = u16{ 0 }; for (auto& line : lines) @@ -93,6 +93,10 @@ auto source::parse_assembly(u8 const* data, usize size) -> assembly::ptr count = static_cast(std::stoul(inst->data[0])); inst->size += 7 * count; break; + case opcode::OP_FormalParams: + count = static_cast(std::stoul(inst->data[0])); + inst->size += (ctx_->props() & props::hash) ? count * 8 : count; + break; default: break; } diff --git a/src/utils/reader.cpp b/src/utils/reader.cpp index 540dc4ed..000f86f6 100644 --- a/src/utils/reader.cpp +++ b/src/utils/reader.cpp @@ -219,7 +219,7 @@ auto reader::read_cstr() -> std::string return ret; } -auto reader::read_bytes(u32 pos, u32 count) -> std::string +auto reader::read_bytes(usize pos, usize count) -> std::string { auto data = std::string{}; @@ -240,17 +240,17 @@ auto reader::is_avail() const -> bool return pos_ < size_; } -auto reader::seek(u32 size) -> void +auto reader::seek(usize size) -> void { if (pos_ + size <= size_) pos_ += size; } -auto reader::seek_neg(u32 size) -> void +auto reader::seek_neg(usize size) -> void { if (pos_ >= size) pos_ -= size; } -auto reader::align(u32 size) -> u32 +auto reader::align(usize size) -> usize { auto pos = pos_; diff --git a/src/utils/writer.cpp b/src/utils/writer.cpp index 1127bdfe..1021859d 100644 --- a/src/utils/writer.cpp +++ b/src/utils/writer.cpp @@ -14,7 +14,7 @@ writer::writer(bool swap) : size_{ default_size }, swap_{ swap } data_ = new u8[size_](); } -writer::writer(u32 size, bool swap) : size_{ size }, swap_{ swap } +writer::writer(usize size, bool swap) : size_{ size }, swap_{ swap } { data_ = new u8[size_](); } @@ -192,13 +192,32 @@ template<> auto writer::write(f32 data) -> void pos_ += 4; } +auto writer::write_i24(i32 data) -> void +{ + if (pos_ + 3 > size_) + throw error("writer: out of bounds"); + + if (!swap_) + { + *reinterpret_cast(data_ + pos_) = data & 0xFFFFFF; + } + else + { + (data_ + pos_)[0] = reinterpret_cast(&data)[2]; + (data_ + pos_)[1] = reinterpret_cast(&data)[1]; + (data_ + pos_)[2] = reinterpret_cast(&data)[0]; + } + + pos_ += 3; +} + auto writer::write_string(std::string const& data) -> void { if (pos_ + data.size() > size_) throw error("writer: out of bounds"); std::memcpy(reinterpret_cast(data_ + pos_), data.data(), data.size()); - pos_ += static_cast(data.size()); + pos_ += data.size(); } auto writer::write_cstr(std::string const& data) -> void @@ -207,7 +226,7 @@ auto writer::write_cstr(std::string const& data) -> void throw error("writer: out of bounds"); std::memcpy(reinterpret_cast(data_ + pos_), data.data(), data.size()); - pos_ += static_cast(data.size() + 1); + pos_ += data.size() + 1; } auto writer::is_avail() const -> bool @@ -215,17 +234,17 @@ auto writer::is_avail() const -> bool return pos_ < size_; } -auto writer::seek(u32 size) -> void +auto writer::seek(usize size) -> void { if (pos_ + size <= size_) pos_ += size; } -auto writer::seek_neg(u32 size) -> void +auto writer::seek_neg(usize size) -> void { if (pos_ >= size) pos_ -= size; } -auto writer::align(u32 size) -> u32 +auto writer::align(usize size) -> usize { auto pos = pos_; @@ -239,17 +258,17 @@ auto writer::data() const -> const u8* return data_; } -auto writer::size() const -> u32 +auto writer::size() const -> usize { return size_; } -auto writer::pos() const -> u32 +auto writer::pos() const -> usize { return pos_; } -auto writer::pos(u32 pos) -> void +auto writer::pos(usize pos) -> void { if (pos <= size_) pos_ = pos; }