From 5ec9a91eb92beeaa561d5bbb78852be819152bb8 Mon Sep 17 00:00:00 2001 From: water111 <48171810+water111@users.noreply.github.com> Date: Mon, 22 Feb 2021 09:36:30 -0500 Subject: [PATCH] Decompiler fixes + decompiling (#276) * decomp pad * more decompilation * update * fix test name --- common/type_system/Type.cpp | 54 +- common/type_system/Type.h | 15 +- common/type_system/TypeSystem.cpp | 12 +- common/type_system/deftype.cpp | 19 +- decompiler/IR2/AtomicOpForm.cpp | 2 +- decompiler/IR2/AtomicOpTypeAnalysis.cpp | 6 +- decompiler/IR2/Form.cpp | 9 + decompiler/IR2/Form.h | 6 + decompiler/IR2/FormExpressionAnalysis.cpp | 162 +++-- decompiler/IR2/FormStack.cpp | 80 ++- decompiler/IR2/FormStack.h | 10 +- decompiler/IR2/GenericElementMatcher.cpp | 32 + decompiler/IR2/GenericElementMatcher.h | 4 + decompiler/IR2/IR2_common.h | 3 + decompiler/analysis/atomic_op_builder.cpp | 20 +- decompiler/analysis/cfg_builder.cpp | 4 +- decompiler/analysis/expression_build.cpp | 4 +- decompiler/analysis/final_output.cpp | 11 +- decompiler/config/all-types.gc | 581 ++++++++++++------ .../jak1_ntsc_black_label/label_types.jsonc | 11 + .../jak1_ntsc_black_label/type_hints.jsonc | 12 + .../jak1_ntsc_black_label/var_names.jsonc | 41 ++ doc/code_status.md | 21 +- game/CMakeLists.txt | 1 + game/kernel/kmachine.cpp | 1 + game/sce/libpad.cpp | 12 + game/sce/libpad.h | 7 + game/sce/stubs.cpp | 7 - game/sce/stubs.h | 8 - goal_src/engine/dma/dma-buffer.gc | 2 +- goal_src/engine/dma/dma-disasm.gc | 179 ++++++ goal_src/engine/dma/dma-h.gc | 3 +- goal_src/engine/gfx/hw/display-h.gc | 183 ++++++ goal_src/engine/gfx/hw/gs.gc | 518 ++++++++++++++++ goal_src/engine/load/file-io.gc | 202 +++--- goal_src/engine/load/loader-h.gc | 181 ++++++ goal_src/engine/ps2/pad.gc | 312 ++++++++++ goal_src/goos-lib.gs | 10 +- goal_src/kernel-defs.gc | 4 +- goalc/compiler/compilation/Type.cpp | 6 +- scripts/decomp_progress.py | 16 +- test/decompiler/test_AtomicOpBuilder.cpp | 20 +- .../decompiler/test_FormBeforeExpressions.cpp | 4 +- test/decompiler/test_FormExpressionBuild.cpp | 40 +- .../test_FormExpressionBuildLong.cpp | 87 ++- test/decompiler/test_gkernel_decomp.cpp | 101 ++- .../with_game/inlined-packed-basics.gc | 63 ++ test/goalc/test_with_game.cpp | 11 + 48 files changed, 2567 insertions(+), 530 deletions(-) create mode 100644 game/sce/libpad.cpp create mode 100644 game/sce/libpad.h create mode 100644 test/goalc/source_templates/with_game/inlined-packed-basics.gc diff --git a/common/type_system/Type.cpp b/common/type_system/Type.cpp index 216fbf5586..414b3324f7 100644 --- a/common/type_system/Type.cpp +++ b/common/type_system/Type.cpp @@ -280,8 +280,12 @@ int NullType::get_in_memory_alignment() const { throw std::runtime_error("get_in_memory_alignment called on NullType"); } -int NullType::get_inline_array_alignment() const { - throw std::runtime_error("get_inline_array_alignment called on NullType"); +int NullType::get_inline_array_start_alignment() const { + throw std::runtime_error("get_inline_array_start_alignment called on NullType"); +} + +int NullType::get_inline_array_stride_alignment() const { + throw std::runtime_error("get_inline_array_stride_alignment called on NullType"); } std::string NullType::print() const { @@ -372,7 +376,11 @@ int ValueType::get_in_memory_alignment() const { return m_size; } -int ValueType::get_inline_array_alignment() const { +int ValueType::get_inline_array_stride_alignment() const { + return m_size; +} + +int ValueType::get_inline_array_start_alignment() const { return m_size; } @@ -528,7 +536,13 @@ int StructureType::get_in_memory_alignment() const { return STRUCTURE_ALIGNMENT; } -int StructureType::get_inline_array_alignment() const { +// So the GOAL compiler was weird here. +// It seems like there were two states: +// - don't care about alignment of both the first element and the later +// - don't care about the alignment, but pad the stride. +// so you end up with a misaligned array of padded structures which seems very stupid. + +int StructureType::get_inline_array_stride_alignment() const { if (m_pack) { // make elements of inline array the minimum allowable alignment. int alignment = 1; @@ -544,6 +558,22 @@ int StructureType::get_inline_array_alignment() const { } } +int StructureType::get_inline_array_start_alignment() const { + if (m_pack || m_allow_misalign) { + // make elements of inline array the minimum allowable alignment. + int alignment = 1; + // TODO - I don't know if GOAL actually did this check, maybe packed inline arrays could + // violate these? + for (const auto& field : m_fields) { + alignment = std::max(alignment, field.alignment()); + } + return alignment; + } else { + // make elements of inline array properly aligned structures + return STRUCTURE_ALIGNMENT; + } +} + bool StructureType::lookup_field(const std::string& name, Field* out) { for (auto& x : m_fields) { if (x.name() == name) { @@ -580,6 +610,22 @@ int BasicType::get_offset() const { return BASIC_OFFSET; } +int BasicType::get_inline_array_start_alignment() const { + if (m_pack) { + // make elements of inline array the minimum allowable alignment. + int alignment = 8; + // TODO - I don't know if GOAL actually did this check, maybe packed inline arrays could + // violate these? + for (const auto& field : m_fields) { + alignment = std::max(alignment, field.alignment()); + } + return alignment; + } else { + // make elements of inline array properly aligned structures + return STRUCTURE_ALIGNMENT; + } +} + ///////////////// // Bitfield ///////////////// diff --git a/common/type_system/Type.h b/common/type_system/Type.h index d9e16bfb8b..65439afc93 100644 --- a/common/type_system/Type.h +++ b/common/type_system/Type.h @@ -52,7 +52,8 @@ class Type { // get the alignment for the "size in memory" data. virtual int get_in_memory_alignment() const = 0; - virtual int get_inline_array_alignment() const = 0; + virtual int get_inline_array_stride_alignment() const = 0; + virtual int get_inline_array_start_alignment() const = 0; virtual bool operator==(const Type& other) const = 0; @@ -115,7 +116,8 @@ class NullType : public Type { int get_load_size() const override; bool get_load_signed() const override; int get_size_in_memory() const override; - int get_inline_array_alignment() const override; + int get_inline_array_stride_alignment() const override; + int get_inline_array_start_alignment() const override; RegClass get_preferred_reg_class() const override; int get_offset() const override; int get_in_memory_alignment() const override; @@ -143,7 +145,8 @@ class ValueType : public Type { RegClass get_preferred_reg_class() const override; int get_offset() const override; int get_in_memory_alignment() const override; - int get_inline_array_alignment() const override; + int get_inline_array_stride_alignment() const override; + int get_inline_array_start_alignment() const override; std::string print() const override; bool operator==(const Type& other) const override; ~ValueType() = default; @@ -231,11 +234,13 @@ class StructureType : public ReferenceType { int get_size_in_memory() const override; int get_offset() const override; int get_in_memory_alignment() const override; - int get_inline_array_alignment() const override; + int get_inline_array_stride_alignment() const override; + int get_inline_array_start_alignment() const override; bool lookup_field(const std::string& name, Field* out); bool is_dynamic() const { return m_dynamic; } ~StructureType() = default; void set_pack(bool pack) { m_pack = pack; } + void set_allow_misalign(bool misalign) { m_allow_misalign = misalign; } protected: friend class TypeSystem; @@ -254,6 +259,7 @@ class StructureType : public ReferenceType { bool m_dynamic = false; int m_size_in_mem = 0; bool m_pack = false; + bool m_allow_misalign = false; int m_offset = 0; size_t m_idx_of_first_unique_field = 0; }; @@ -262,6 +268,7 @@ class BasicType : public StructureType { public: BasicType(std::string parent, std::string name, bool dynamic = false); int get_offset() const override; + int get_inline_array_start_alignment() const override; std::string print() const override; ~BasicType() = default; }; diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index a54a26af66..1e2b7411d2 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -147,8 +147,8 @@ DerefInfo TypeSystem::get_deref_info(const TypeSpec& ts) const { info.sign_extend = false; // not applicable anyway if (result_type->is_reference()) { - info.stride = - align(result_type->get_size_in_memory(), result_type->get_inline_array_alignment()); + info.stride = align(result_type->get_size_in_memory(), + result_type->get_inline_array_stride_alignment()); } else { // can't have an inline array of value types! assert(false); @@ -886,11 +886,11 @@ int TypeSystem::get_alignment_in_type(const Field& field) { if (field.is_array()) { // TODO - is this actually correct? or do we use in_memory for the first element and // inline_array for the ones that follow? - return field_type->get_inline_array_alignment(); + return field_type->get_inline_array_start_alignment(); } else { // it is an inlined field, so return the alignment in memory // TODO - for inline, but not inline array, do we use structure alignment always? - return field_type->get_inline_array_alignment(); + return field_type->get_inline_array_start_alignment(); } } @@ -929,8 +929,8 @@ int TypeSystem::get_size_in_type(const Field& field) const { throw std::runtime_error("bad get size in type"); } assert(field_type->is_reference()); - return field.array_size() * - align(field_type->get_size_in_memory(), field_type->get_inline_array_alignment()); + return field.array_size() * align(field_type->get_size_in_memory(), + field_type->get_inline_array_stride_alignment()); } else { if (field_type->is_reference()) { return field.array_size() * POINTER_SIZE; diff --git a/common/type_system/deftype.cpp b/common/type_system/deftype.cpp index 1dd840d969..b1bc118cef 100644 --- a/common/type_system/deftype.cpp +++ b/common/type_system/deftype.cpp @@ -225,6 +225,7 @@ struct StructureDefResult { TypeFlags flags; bool generate_runtime_type = true; bool pack_me = false; + bool allow_misaligned = false; }; StructureDefResult parse_structure_def(StructureType* type, @@ -286,9 +287,9 @@ StructureDefResult parse_structure_def(StructureType* type, u16 hb = get_int(car(rest)); rest = cdr(rest); flags.heap_base = hb; - } - - else { + } else if (opt_name == ":allow-misaligned") { + result.allow_misaligned = true; + } else { throw std::runtime_error("Invalid option in field specification: " + opt_name); } } @@ -459,8 +460,13 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { result.flags = sr.flags; result.create_runtime_type = sr.generate_runtime_type; if (sr.pack_me) { - fmt::print("[TypeSystem] :pack-me was set on {}, which is a basic and cannot be packed.", - name); + new_type->set_pack(true); + } + if (sr.allow_misaligned) { + fmt::print( + "[TypeSystem] :allow-misaligned was set on {}, which is a basic and cannot " + "be misaligned\n", + name); throw std::runtime_error("invalid pack option on basic"); } ts->add_type(name, std::move(new_type)); @@ -476,6 +482,9 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { if (sr.pack_me) { new_type->set_pack(true); } + if (sr.allow_misaligned) { + new_type->set_allow_misalign(true); + } ts->add_type(name, std::move(new_type)); } else if (is_type("integer", parent_type, ts)) { auto pto = ts->lookup_type(parent_type); diff --git a/decompiler/IR2/AtomicOpForm.cpp b/decompiler/IR2/AtomicOpForm.cpp index d6a9a919a9..81fc9fb436 100644 --- a/decompiler/IR2/AtomicOpForm.cpp +++ b/decompiler/IR2/AtomicOpForm.cpp @@ -81,7 +81,7 @@ FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const { result->mark_as_dead_set(); // fmt::print("marked {} as dead set\n", to_string(env)); } - } else if (m_src.get_arg(0).is_sym_ptr() && m_src.get_arg(0).get_str() == "#f") { + } else if (m_src.get_arg(0).is_sym_val() && m_src.get_arg(0).get_str() == "#f") { auto& ri = env.reg_use().op.at(m_my_idx); if (ri.written_and_unused.find(dst().reg()) != ri.written_and_unused.end()) { result->mark_as_dead_false(); diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 778a376cb4..ba418e5f25 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -12,7 +12,7 @@ bool tc(const DecompilerTypeSystem& dts, const TypeSpec& expected, const TP_Type } bool is_int_or_uint(const DecompilerTypeSystem& dts, const TP_Type& type) { - return tc(dts, TypeSpec("int"), type) || tc(dts, TypeSpec("uint"), type); + return tc(dts, TypeSpec("integer"), type) || tc(dts, TypeSpec("uint"), type); } bool is_signed(const DecompilerTypeSystem& dts, const TP_Type& type) { @@ -534,7 +534,6 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input, IR2_RegOffset ro; if (get_as_reg_offset(m_src, &ro)) { auto& input_type = input.get(ro.reg); - if ((input_type.kind == TP_Type::Kind::TYPE_OF_TYPE_OR_CHILD || input_type.kind == TP_Type::Kind::TYPE_OF_TYPE_NO_VIRTUAL) && ro.offset >= 16 && (ro.offset & 3) == 0 && m_size == 4 && m_kind == Kind::UNSIGNED) { @@ -568,7 +567,8 @@ TP_Type LoadVarOp::get_src_type(const TypeState& input, } } - if (input_type.typespec() == TypeSpec("pointer")) { + if (input_type.typespec() == TypeSpec("pointer") && + input_type.kind != TP_Type::Kind::OBJECT_PLUS_PRODUCT_WITH_CONSTANT) { // we got a plain pointer. let's just assume we're loading an integer. // perhaps we should disable this feature by default on 4-byte loads if we're getting // lots of false positives for loading pointers from plain pointers. diff --git a/decompiler/IR2/Form.cpp b/decompiler/IR2/Form.cpp index 76a7683c70..a374945ae2 100644 --- a/decompiler/IR2/Form.cpp +++ b/decompiler/IR2/Form.cpp @@ -302,6 +302,9 @@ bool SetVarElement::is_sequence_point() const { } void SetVarElement::collect_vars(VariableSet& vars) const { + if (m_var_info.is_dead_set || m_var_info.is_dead_false) { + return; + } vars.insert(m_dst); m_src->collect_vars(vars); } @@ -1160,6 +1163,12 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) { return "/"; case FixedOperatorKind::ADDITION: return "+"; + case FixedOperatorKind::ADDITION_IN_PLACE: + return "+!"; + case FixedOperatorKind::ADDITION_PTR: + return "&+"; + case FixedOperatorKind::ADDITION_PTR_IN_PLACE: + return "&+!"; case FixedOperatorKind::SUBTRACTION: return "-"; case FixedOperatorKind::MULTIPLICATION: diff --git a/decompiler/IR2/Form.h b/decompiler/IR2/Form.h index edd3dbf06f..6e15c7461e 100644 --- a/decompiler/IR2/Form.h +++ b/decompiler/IR2/Form.h @@ -177,6 +177,7 @@ class StoreElement : public FormElement { void apply_form(const std::function& f) override; void collect_vars(VariableSet& vars) const override; void get_modified_regs(RegSet& regs) const override; + void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override; private: // todo - we may eventually want to use a different representation for more @@ -407,6 +408,11 @@ class ConditionElement : public FormElement { const std::vector& source_forms, const std::vector& types); + FormElement* make_zero_check_generic(const Env& env, + FormPool& pool, + const std::vector& source_forms, + const std::vector& types); + private: IR2_Condition::Kind m_kind; std::optional m_src[2]; diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index 4128ece7dd..369b843632 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -72,6 +72,18 @@ bool FormElement::has_side_effects() { namespace { +bool is_power_of_two(int in, int* out) { + int x = 1; + for (int i = 0; i < 32; i++) { + if (x == in) { + *out = i; + return true; + } + x = x * 2; + } + return false; +} + /*! * Create a form which represents a variable. */ @@ -222,6 +234,11 @@ bool is_uint_type(const Env& env, int my_idx, Variable var) { auto type = env.get_types_before_op(my_idx).get(var.reg()).typespec(); return type == TypeSpec("uint"); } + +bool is_ptr_or_child(const Env& env, int my_idx, Variable var) { + auto type = env.get_types_before_op(my_idx).get(var.reg()).typespec().base_type(); + return type == "pointer"; +} } // namespace /*! @@ -456,6 +473,7 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env, bool allow_side_effects) { auto arg0_i = is_int_type(env, m_my_idx, m_expr.get_arg(0).var()); auto arg0_u = is_uint_type(env, m_my_idx, m_expr.get_arg(0).var()); + bool arg0_ptr = is_ptr_or_child(env, m_my_idx, m_expr.get_arg(0).var()); bool arg1_reg = m_expr.get_arg(1).is_var(); bool arg1_i = true; @@ -523,28 +541,60 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env, if (out.success) { // it is. now we have to modify things // first, look for the index - auto arg0_matcher = - Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION), - {Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::MULTIPLICATION), - {Matcher::integer(input.stride), Matcher::any(0)}), - Matcher::integer(input.offset)}); - auto match_result = match(arg0_matcher, args.at(0)); - if (match_result.matched) { - bool used_index = false; - std::vector tokens; - for (auto& tok : out.tokens) { - if (tok.kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX) { - assert(!used_index); - used_index = true; - tokens.push_back(DerefToken::make_int_expr(match_result.maps.forms.at(0))); - } else { - tokens.push_back(to_token(tok)); + int p2; + if (is_power_of_two(input.stride, &p2)) { + // (+ (shl (-> a0-0 reg-count) 3) 28) + auto arg0_matcher = + Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION), + {Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL), + {Matcher::any(0), Matcher::integer(p2)}), + Matcher::integer(input.offset)}); + auto match_result = match(arg0_matcher, args.at(0)); + if (match_result.matched) { + bool used_index = false; + std::vector tokens; + for (auto& tok : out.tokens) { + if (tok.kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX) { + assert(!used_index); + used_index = true; + tokens.push_back(DerefToken::make_int_expr(match_result.maps.forms.at(0))); + } else { + tokens.push_back(to_token(tok)); + } } + result->push_back(pool.alloc_element(args.at(1), out.addr_of, tokens)); + return; + } else { + throw std::runtime_error( + fmt::format("Failed to match for stride (power 2 {}) with add: {}", input.stride, + args.at(0)->to_string(env))); } - result->push_back(pool.alloc_element(args.at(1), out.addr_of, tokens)); - return; } else { - throw std::runtime_error("Failed to match for stride (non power 2) with add"); + auto arg0_matcher = + Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION), + {Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::MULTIPLICATION), + {Matcher::integer(input.stride), Matcher::any(0)}), + Matcher::integer(input.offset)}); + auto match_result = match(arg0_matcher, args.at(0)); + if (match_result.matched) { + bool used_index = false; + std::vector tokens; + for (auto& tok : out.tokens) { + if (tok.kind == FieldReverseLookupOutput::Token::Kind::VAR_IDX) { + assert(!used_index); + used_index = true; + tokens.push_back(DerefToken::make_int_expr(match_result.maps.forms.at(0))); + } else { + tokens.push_back(to_token(tok)); + } + } + result->push_back(pool.alloc_element(args.at(1), out.addr_of, tokens)); + return; + } else { + throw std::runtime_error( + fmt::format("Failed to match for stride (non power 2 {}) with add: {}", + input.stride, args.at(0)->to_string(env))); + } } } } @@ -554,6 +604,10 @@ void SimpleExpressionElement::update_from_stack_add_i(const Env& env, auto new_form = pool.alloc_element( GenericOperator::make_fixed(FixedOperatorKind::ADDITION), args.at(0), args.at(1)); result->push_back(new_form); + } else if (arg0_ptr) { + auto new_form = pool.alloc_element( + GenericOperator::make_fixed(FixedOperatorKind::ADDITION_PTR), args.at(0), args.at(1)); + result->push_back(new_form); } else { auto cast = pool.alloc_single_element_form( nullptr, TypeSpec(arg0_i ? "int" : "uint"), args.at(1)); @@ -1459,7 +1513,7 @@ void UntilElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stac for (auto& entry : form->elts()) { entry->push_to_stack(env, pool, temp_stack); } - auto new_entries = temp_stack.rewrite(pool); + auto new_entries = temp_stack.rewrite(pool, env); form->clear(); for (auto e : new_entries) { form->push_back(e); @@ -1478,7 +1532,7 @@ void WhileElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stac for (auto& entry : form->elts()) { entry->push_to_stack(env, pool, temp_stack); } - auto new_entries = temp_stack.rewrite(pool); + auto new_entries = temp_stack.rewrite(pool, env); form->clear(); for (auto e : new_entries) { form->push_back(e); @@ -1517,9 +1571,9 @@ void CondNoElseElement::push_to_stack(const Env& env, FormPool& pool, FormStack& std::vector new_entries; if (form == entry.body && used_as_value) { - new_entries = rewrite_to_get_var(temp_stack, pool, final_destination); + new_entries = rewrite_to_get_var(temp_stack, pool, final_destination, env); } else { - new_entries = temp_stack.rewrite(pool); + new_entries = temp_stack.rewrite(pool, env); } form->clear(); @@ -1568,7 +1622,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac } std::vector new_entries; - new_entries = temp_stack.rewrite(pool); + new_entries = temp_stack.rewrite(pool, env); form->clear(); for (auto e : new_entries) { @@ -1585,7 +1639,7 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac } std::vector new_entries; - new_entries = temp_stack.rewrite(pool); + new_entries = temp_stack.rewrite(pool, env); else_ir->clear(); for (auto e : new_entries) { @@ -1629,9 +1683,9 @@ void CondWithElseElement::push_to_stack(const Env& env, FormPool& pool, FormStac // rewrite extra sets as needed. if (rewrite_as_set && !set_unused) { for (auto& entry : entries) { - rewrite_to_get_var(entry.body->elts(), pool, *last_var); + rewrite_to_get_var(entry.body->elts(), pool, *last_var, env); } - rewrite_to_get_var(else_ir->elts(), pool, *last_var); + rewrite_to_get_var(else_ir->elts(), pool, *last_var, env); } if (rewrite_as_set) { @@ -1683,9 +1737,9 @@ void ShortCircuitElement::push_to_stack(const Env& env, FormPool& pool, FormStac std::vector new_entries; if (i == int(entries.size()) - 1) { - new_entries = rewrite_to_get_var(temp_stack, pool, final_result); + new_entries = rewrite_to_get_var(temp_stack, pool, final_result, env); } else { - new_entries = temp_stack.rewrite(pool); + new_entries = temp_stack.rewrite(pool, env); } entry.condition->clear(); @@ -1721,9 +1775,9 @@ void ShortCircuitElement::update_from_stack(const Env& env, std::vector new_entries; if (i == int(entries.size()) - 1) { - new_entries = rewrite_to_get_var(temp_stack, pool, final_result); + new_entries = rewrite_to_get_var(temp_stack, pool, final_result, env); } else { - new_entries = temp_stack.rewrite(pool); + new_entries = temp_stack.rewrite(pool, env); } entry.condition->clear(); @@ -1739,13 +1793,34 @@ void ShortCircuitElement::update_from_stack(const Env& env, // ConditionElement /////////////////// -FormElement* ConditionElement::make_generic(const Env&, +FormElement* ConditionElement::make_zero_check_generic(const Env&, + FormPool& pool, + const std::vector& source_forms, + const std::vector&) { + // (zero? (+ thing small-integer)) -> (= thing (- small-integer)) + + auto mr = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION), + {Matcher::any(0), Matcher::any_integer(1)}), + source_forms.at(0)); + if (mr.matched) { + s64 value = -mr.maps.ints.at(1); + auto value_form = pool.alloc_single_element_form( + nullptr, SimpleAtom::make_int_constant(value)); + return pool.alloc_element(GenericOperator::make_fixed(FixedOperatorKind::EQ), + std::vector{mr.maps.forms.at(0), value_form}); + } else { + return pool.alloc_element(GenericOperator::make_compare(m_kind), source_forms); + } +} + +FormElement* ConditionElement::make_generic(const Env& env, FormPool& pool, const std::vector& source_forms, const std::vector& types) { switch (m_kind) { - case IR2_Condition::Kind::TRUTHY: case IR2_Condition::Kind::ZERO: + return make_zero_check_generic(env, pool, source_forms, types); + case IR2_Condition::Kind::TRUTHY: case IR2_Condition::Kind::NONZERO: case IR2_Condition::Kind::FALSE: case IR2_Condition::Kind::IS_PAIR: @@ -1966,7 +2041,7 @@ void ReturnElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta } std::vector new_entries; - new_entries = rewrite_to_get_var(temp_stack, pool, env.end_var()); + new_entries = rewrite_to_get_var(temp_stack, pool, env.end_var(), env); return_code->clear(); for (auto e : new_entries) { @@ -2067,20 +2142,6 @@ void DynamicMethodAccess::update_from_stack(const Env& env, // ArrayFieldAccess //////////////////////// -namespace { -bool is_power_of_two(int in, int* out) { - int x = 1; - for (int i = 0; i < 32; i++) { - if (x == in) { - *out = i; - return true; - } - x = x * 2; - } - return false; -} -} // namespace - void ArrayFieldAccess::update_with_val(Form* new_val, const Env& env, FormPool& pool, @@ -2277,6 +2338,11 @@ void EmptyElement::push_to_stack(const Env&, FormPool&, FormStack& stack) { stack.push_form_element(this, true); } +void StoreElement::push_to_stack(const Env&, FormPool&, FormStack& stack) { + mark_popped(); + stack.push_form_element(this, true); +} + bool is_symbol_true(const Form* form) { auto as_simple = dynamic_cast(form->try_as_single_element()); if (as_simple && as_simple->expr().is_identity() && as_simple->expr().get_arg(0).is_sym_ptr() && diff --git a/decompiler/IR2/FormStack.cpp b/decompiler/IR2/FormStack.cpp index b694795be8..5bcf42956c 100644 --- a/decompiler/IR2/FormStack.cpp +++ b/decompiler/IR2/FormStack.cpp @@ -1,6 +1,7 @@ #include #include "FormStack.h" #include "Form.h" +#include "GenericElementMatcher.h" namespace decompiler { std::string FormStack::StackEntry::print(const Env& env) const { @@ -206,7 +207,68 @@ FormElement* FormStack::pop_back(FormPool& pool) { } } -std::vector FormStack::rewrite(FormPool& pool) { +namespace { +bool is_op_in_place(SetVarElement* elt, + FixedOperatorKind op, + const Env&, + Variable* base_out, + Form** val_out) { + auto matcher = Matcher::op(GenericOpMatcher::fixed(op), {Matcher::any_reg(0), Matcher::any(1)}); + auto result = match(matcher, elt->src()); + if (result.matched) { + auto first = result.maps.regs.at(0); + assert(first.has_value()); + if (first->reg() != elt->dst().reg()) { + return false; + } + + if (first->idx() != elt->dst().idx()) { + return false; + } + + *val_out = result.maps.forms.at(1); + *base_out = first.value(); + return true; + } + return false; +} + +FormElement* rewrite_set_op_in_place_for_kind(SetVarElement* in, + const Env& env, + FormPool& pool, + FixedOperatorKind first_kind, + FixedOperatorKind in_place_kind) { + Form* val = nullptr; + Variable base; + + if (is_op_in_place(in, first_kind, env, &base, &val)) { + return pool.alloc_element( + GenericOperator::make_fixed(in_place_kind), + std::vector{ + pool.alloc_single_element_form(nullptr, SimpleAtom::make_var(base)), + val}); + } + return in; +} + +FormElement* try_rewrites_in_place(SetVarElement* in, const Env& env, FormPool& pool) { + auto out = rewrite_set_op_in_place_for_kind(in, env, pool, FixedOperatorKind::ADDITION, + FixedOperatorKind::ADDITION_IN_PLACE); + if (out != in) { + return out; + } + + out = rewrite_set_op_in_place_for_kind(in, env, pool, FixedOperatorKind::ADDITION_PTR, + FixedOperatorKind::ADDITION_PTR_IN_PLACE); + if (out != in) { + return out; + } + + return in; +} +} // namespace + +std::vector FormStack::rewrite(FormPool& pool, const Env& env) { std::vector result; for (auto& e : m_stack) { @@ -215,10 +277,14 @@ std::vector FormStack::rewrite(FormPool& pool) { } if (e.destination.has_value()) { + // (set! x (+ x y)) -> (+! x y) + auto elt = pool.alloc_element(*e.destination, e.source, e.sequence_point, e.set_info); e.source->parent_element = elt; - result.push_back(elt); + + auto final_elt = try_rewrites_in_place(elt, env, pool); + result.push_back(final_elt); } else { result.push_back(e.elt); } @@ -228,7 +294,8 @@ std::vector FormStack::rewrite(FormPool& pool) { void rewrite_to_get_var(std::vector& default_result, FormPool& pool, - const Variable& var) { + const Variable& var, + const Env&) { auto last_op_as_set = dynamic_cast(default_result.back()); if (last_op_as_set && last_op_as_set->dst().reg() == var.reg()) { default_result.pop_back(); @@ -243,9 +310,10 @@ void rewrite_to_get_var(std::vector& default_result, std::vector rewrite_to_get_var(FormStack& stack, FormPool& pool, - const Variable& var) { - auto default_result = stack.rewrite(pool); - rewrite_to_get_var(default_result, pool, var); + const Variable& var, + const Env& env) { + auto default_result = stack.rewrite(pool, env); + rewrite_to_get_var(default_result, pool, var, env); return default_result; } diff --git a/decompiler/IR2/FormStack.h b/decompiler/IR2/FormStack.h index 0fbe8b8126..c30590006f 100644 --- a/decompiler/IR2/FormStack.h +++ b/decompiler/IR2/FormStack.h @@ -39,7 +39,7 @@ class FormStack { FormElement* pop_back(FormPool& pool); Form* unsafe_peek(Register reg, const Env& env); bool is_single_expression(); - std::vector rewrite(FormPool& pool); + std::vector rewrite(FormPool& pool, const Env& env); std::string print(const Env& env); bool is_root() const { return m_is_root_stack; } @@ -64,6 +64,10 @@ class FormStack { void rewrite_to_get_var(std::vector& default_result, FormPool& pool, - const Variable& var); -std::vector rewrite_to_get_var(FormStack& stack, FormPool& pool, const Variable& var); + const Variable& var, + const Env& env); +std::vector rewrite_to_get_var(FormStack& stack, + FormPool& pool, + const Variable& var, + const Env& env); } // namespace decompiler diff --git a/decompiler/IR2/GenericElementMatcher.cpp b/decompiler/IR2/GenericElementMatcher.cpp index d7f2e76bb3..fe7e919807 100644 --- a/decompiler/IR2/GenericElementMatcher.cpp +++ b/decompiler/IR2/GenericElementMatcher.cpp @@ -68,6 +68,13 @@ Matcher Matcher::integer(std::optional value) { return m; } +Matcher Matcher::any_integer(int match_id) { + Matcher m; + m.m_kind = Kind::ANY_INT; + m.m_int_out_id = match_id; + return m; +} + Matcher Matcher::any_quoted_symbol(int match_id) { Matcher m; m.m_kind = Kind::ANY_QUOTED_SYMBOL; @@ -272,6 +279,31 @@ bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out) const { return false; } break; + case Kind::ANY_INT: { + auto as_simple_atom = dynamic_cast(input->try_as_single_element()); + if (as_simple_atom) { + if (as_simple_atom->atom().is_int()) { + if (m_int_out_id != -1) { + maps_out->ints[m_int_out_id] = as_simple_atom->atom().get_int(); + } + return true; + } + } + + auto as_expr = dynamic_cast(input->try_as_single_element()); + if (as_expr && as_expr->expr().is_identity()) { + auto atom = as_expr->expr().get_arg(0); + if (atom.is_int()) { + if (m_int_out_id != -1) { + maps_out->ints[m_int_out_id] = atom.get_int(); + } + return true; + } + } + + return false; + } break; + case Kind::ANY_QUOTED_SYMBOL: { auto as_simple_atom = dynamic_cast(input->try_as_single_element()); if (as_simple_atom) { diff --git a/decompiler/IR2/GenericElementMatcher.h b/decompiler/IR2/GenericElementMatcher.h index c4a952829a..eb2acbd2e2 100644 --- a/decompiler/IR2/GenericElementMatcher.h +++ b/decompiler/IR2/GenericElementMatcher.h @@ -18,6 +18,7 @@ struct MatchResult { std::unordered_map strings; std::unordered_map forms; std::unordered_map label; + std::unordered_map ints; } maps; }; @@ -33,6 +34,7 @@ class Matcher { static Matcher cast(const std::string& type, Matcher value); static Matcher any(int match_id = -1); static Matcher integer(std::optional value); + static Matcher any_integer(int match_id = -1); static Matcher any_reg_cast_to_int_or_uint(int match_id = -1); static Matcher any_quoted_symbol(int match_id = -1); static Matcher any_symbol(int match_id = -1); @@ -52,6 +54,7 @@ class Matcher { CAST, ANY, INT, + ANY_INT, ANY_QUOTED_SYMBOL, ANY_SYMBOL, DEREF_OP, @@ -74,6 +77,7 @@ class Matcher { int m_string_out_id = -1; int m_form_match = -1; int m_label_out_id = -1; + int m_int_out_id = -1; std::optional m_int_match; std::string m_str; }; diff --git a/decompiler/IR2/IR2_common.h b/decompiler/IR2/IR2_common.h index a9157cdd1e..014a40da4b 100644 --- a/decompiler/IR2/IR2_common.h +++ b/decompiler/IR2/IR2_common.h @@ -93,6 +93,9 @@ enum class FixedOperatorKind { GPR_TO_FPR, DIVISION, ADDITION, + ADDITION_PTR, + ADDITION_IN_PLACE, + ADDITION_PTR_IN_PLACE, SUBTRACTION, MULTIPLICATION, SQRT, diff --git a/decompiler/analysis/atomic_op_builder.cpp b/decompiler/analysis/atomic_op_builder.cpp index db40df6b47..b5920e9580 100644 --- a/decompiler/analysis/atomic_op_builder.cpp +++ b/decompiler/analysis/atomic_op_builder.cpp @@ -66,7 +66,7 @@ SimpleAtom make_src_atom(Register reg, int idx) { } SimpleAtom false_sym() { - return SimpleAtom::make_sym_ptr("#f"); + return SimpleAtom::make_sym_val("#f"); } //////////////////////// @@ -168,7 +168,7 @@ std::unique_ptr make_standard_store(const Instruction& i0, SimpleExpression dst; if (i0.get_src(0).is_reg(rs7())) { assert(!is_float); - val = SimpleAtom::make_sym_ptr("#f"); + val = SimpleAtom::make_sym_val("#f"); } else if (i0.get_src(0).is_reg(rr0())) { assert(!is_float); val = SimpleAtom::make_int_constant(0); @@ -581,7 +581,7 @@ std::unique_ptr convert_sw_1(const Instruction& i0, int idx) { SimpleAtom val; if (i0.get_src(0).is_reg(rs7())) { // store a false - val = SimpleAtom::make_sym_ptr("#f"); + val = SimpleAtom::make_sym_val("#f"); } else if (i0.get_src(0).is_reg(rr0())) { // store a 0 val = SimpleAtom::make_int_constant(0); @@ -648,14 +648,14 @@ std::unique_ptr convert_beql_1(const Instruction& i0, int idx, bool li } else if (i0.get_src(0).is_reg(rs7())) { if (s1 == rs7()) { // (if #f ...) type code? - condition = IR2_Condition(IR2_Condition::Kind::FALSE, SimpleAtom::make_sym_ptr("#f")); + condition = IR2_Condition(IR2_Condition::Kind::FALSE, SimpleAtom::make_sym_val("#f")); } else { condition = IR2_Condition(IR2_Condition::Kind::FALSE, make_src_atom(s1, idx)); } } else if (s1 == rs7()) { // likely a case where somebody wrote (= x #f) or (!= x #f). much rarer than the flipped one condition = IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), - SimpleAtom::make_sym_ptr("#f")); + SimpleAtom::make_sym_val("#f")); } else { condition = IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx)); @@ -676,7 +676,7 @@ std::unique_ptr convert_bnel_1(const Instruction& i0, int idx, bool li } else if (s1 == rs7()) { // likely a case where somebody wrote (= x #f) or (!= x #f). much rarer than the flipped one condition = IR2_Condition(IR2_Condition::Kind::NOT_EQUAL, make_src_atom(s0, idx), - SimpleAtom::make_sym_ptr("#f")); + SimpleAtom::make_sym_val("#f")); } else { condition = IR2_Condition(IR2_Condition::Kind::NOT_EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx)); @@ -855,7 +855,7 @@ std::unique_ptr convert_bne_2(const Instruction& i0, } else if (s1 == rs7()) { // likely a case where somebody wrote (= x #f) or (!= x #f). much rarer than the flipped one condition = IR2_Condition(IR2_Condition::Kind::NOT_EQUAL, make_src_atom(s0, idx), - SimpleAtom::make_sym_ptr("#f")); + SimpleAtom::make_sym_val("#f")); } else { condition = IR2_Condition(IR2_Condition::Kind::NOT_EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx)); @@ -879,14 +879,14 @@ std::unique_ptr convert_beq_2(const Instruction& i0, } else if (i0.get_src(0).is_reg(rs7())) { if (s1 == rs7()) { // (if #f ...) type code? - condition = IR2_Condition(IR2_Condition::Kind::FALSE, SimpleAtom::make_sym_ptr("#f")); + condition = IR2_Condition(IR2_Condition::Kind::FALSE, SimpleAtom::make_sym_val("#f")); } else { condition = IR2_Condition(IR2_Condition::Kind::FALSE, make_src_atom(s1, idx)); } } else if (s1 == rs7()) { // likely a case where somebody wrote (= x #f) or (!= x #f). much rarer than the flipped one condition = IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), - SimpleAtom::make_sym_ptr("#f")); + SimpleAtom::make_sym_val("#f")); } else { condition = IR2_Condition(IR2_Condition::Kind::EQUAL, make_src_atom(s0, idx), make_src_atom(s1, idx)); @@ -1081,7 +1081,7 @@ std::unique_ptr convert_dsubu_3(const Instruction& i0, // some sort of not gone wrong? result = std::make_unique( make_dst_var(dest, idx), - IR2_Condition(kind, make_src_atom(a, idx), SimpleAtom::make_sym_ptr("#f")), idx); + IR2_Condition(kind, make_src_atom(a, idx), SimpleAtom::make_sym_val("#f")), idx); } else if (b == rr0()) { // not the greatest codegen... result = std::make_unique( diff --git a/decompiler/analysis/cfg_builder.cpp b/decompiler/analysis/cfg_builder.cpp index cf9215e20f..3f521b896a 100644 --- a/decompiler/analysis/cfg_builder.cpp +++ b/decompiler/analysis/cfg_builder.cpp @@ -201,7 +201,7 @@ bool delay_slot_sets_false(BranchElement* branch, SetVarOp& delay) { assert(branch->op()->likely()); assert(branch->op()->branch_delay().kind() == IR2_BranchDelay::Kind::NO_DELAY); - if (delay.src().is_identity() && delay.src().get_arg(0).is_sym_ptr() && + if (delay.src().is_identity() && delay.src().get_arg(0).is_sym_val() && delay.src().get_arg(0).get_str() == "#f") { return true; } @@ -517,7 +517,7 @@ void convert_cond_no_else_to_compare(FormPool& pool, auto dst = body->dst(); auto src_atom = get_atom_src(body->src()); assert(src_atom); - assert(src_atom->is_sym_ptr()); + assert(src_atom->is_sym_val()); assert(src_atom->get_str() == "#f"); assert(cne->entries.size() == 1); diff --git a/decompiler/analysis/expression_build.cpp b/decompiler/analysis/expression_build.cpp index ae2837a860..4cbb19150e 100644 --- a/decompiler/analysis/expression_build.cpp +++ b/decompiler/analysis/expression_build.cpp @@ -70,7 +70,7 @@ bool convert_to_expressions(Form* top_level_form, std::vector new_entries; if (f.type.last_arg() != TypeSpec("none")) { auto return_var = f.ir2.atomic_ops->end_op().return_var(); - new_entries = rewrite_to_get_var(stack, pool, return_var); + new_entries = rewrite_to_get_var(stack, pool, return_var, f.ir2.env); auto reg_return_type = f.ir2.env.get_types_after_op(f.ir2.atomic_ops->ops.size() - 1).get(return_var.reg()); if (!dts.ts.typecheck(f.type.last_arg(), reg_return_type.typespec(), "", false, false)) { @@ -82,7 +82,7 @@ bool convert_to_expressions(Form* top_level_form, new_entries.push_back(cast); } } else { - new_entries = stack.rewrite(pool); + new_entries = stack.rewrite(pool, f.ir2.env); } assert(!new_entries.empty()); top_level_form->clear(); diff --git a/decompiler/analysis/final_output.cpp b/decompiler/analysis/final_output.cpp index 63008b80c7..424e061d1a 100644 --- a/decompiler/analysis/final_output.cpp +++ b/decompiler/analysis/final_output.cpp @@ -229,9 +229,14 @@ std::string write_from_top_level(const Function& top_level, auto deftype_match_result = match(deftype_matcher, &f); if (deftype_match_result.matched) { auto& name = deftype_match_result.maps.strings.at(type_name); - result += fmt::format(";; definition of type {}\n", name); - result += dts.ts.generate_deftype(dts.ts.lookup_type(name)); - result += "\n\n"; + if (dts.ts.fully_defined_type_exists(name)) { + result += fmt::format(";; definition of type {}\n", name); + result += dts.ts.generate_deftype(dts.ts.lookup_type(name)); + result += "\n\n"; + } else { + result += + fmt::format(";; type {} defintion, but it is unknown to the decompiler\n\n", name); + } something_matched = true; } } diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index 6c6f96ba20..5f784cdc4c 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -2421,7 +2421,7 @@ ;;(define-extern vif-stcycl-imm object) ;; unknown type ;;(define-extern dma-bank object) ;; unknown type ;;(define-extern flush-cache object) ;; unknown type -;;(define-extern *video-parms* object) ;; unknown type +(define-extern *video-parms* video-parms) ;; unknown type ;;(define-extern video-parms object) ;; unknown type ;;(define-extern generic-bucket-state object) ;; unknown type ;;(define-extern *vu1-enable-user-menu* object) ;; unknown type @@ -2484,7 +2484,7 @@ (deftype dma-buffer (basic) ((allocated-length int32 :offset-assert 4) (base pointer :offset-assert 8) - (end uint32 :offset-assert 12) + (end pointer :offset-assert 12) (data uint64 1 :offset-assert 16) ;; weird, I guess this aligns the data? (data-buffer uint8 :dynamic :offset 16) ) @@ -2515,9 +2515,11 @@ (define-extern dma-buffer-add-buckets (function dma-buffer int none)) (define-extern dma-buffer-patch-buckets (function dma-bucket int int)) -;;;;;;;;;;;;;;; -;; dma-disasm -;;;;;;;;;;;;;;; +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; DMA-DISASM ;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; (deftype vif-disasm-element (structure) @@ -2534,17 +2536,18 @@ ) (define-extern *vif-disasm-table* (array vif-disasm-element)) ;; unknown type -(define-extern disasm-vif-tag function) -(define-extern disasm-dma-tag function) -(define-extern disasm-vif-details (function symbol (pointer uint8) int int int)) +;;(define-extern disasm-vif-tag (function (pointer uint32) int symbol int symbol)) +(define-extern disasm-dma-tag (function uint symbol int)) +(define-extern disasm-vif-details (function symbol (pointer uint8) int int symbol)) (define-extern vif-disasm-element type) ;;(define-extern *dma-disasm* object) ;; unknown type (define-extern disasm-dma-list function) -;;;;;;;;;;;;;;; -;; pad -;;;;;;;;;;;;;;; - +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; PAD ;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; (deftype hw-cpad (basic) ((valid uint8 :offset-assert 4) (status uint8 :offset-assert 5) @@ -2564,9 +2567,9 @@ (deftype cpad-info (hw-cpad) ((number int32 :offset-assert 36) (cpad-file int32 :offset-assert 40) - (button0-abs int32 3 :offset-assert 44) ;; guess - (button0-shadow-abs int32 1 :offset-assert 56) ;; guess - (button0-rel int32 3 :offset-assert 60) ;; guess + (button0-abs uint32 3 :offset-assert 44) ;; guess + (button0-shadow-abs uint32 1 :offset-assert 56) ;; guess + (button0-rel uint32 3 :offset-assert 60) ;; guess (stick0-dir float :offset-assert 72) (stick0-speed float :offset-assert 76) (new-pad int32 :offset-assert 80) @@ -2579,6 +2582,9 @@ (buzz-act int32 :offset-assert 124) (change-time uint64 :offset-assert 128) ) + (:methods + (new (symbol type int) _type_ 0) + ) :method-count-assert 9 :size-assert #x88 :flag-assert #x900000088 @@ -2586,29 +2592,91 @@ (deftype cpad-list (basic) ((num-cpads int32 :offset-assert 4) - (cpads int32 2 :offset-assert 8) ;; guess + (cpads cpad-info 2 :offset-assert 8) ;; guess ) + (:methods + (new (symbol type) _type_ 0)) :method-count-assert 9 :size-assert #x10 :flag-assert #x900000010 ) -;;;;;;;;;;;;;;; -;; gs -;;;;;;;;;;;;;;; +;; display +(define-extern get-current-time (function uint)) +(define-extern get-integral-current-time (function uint)) +;; in the kernel. +(define-extern cpad-open (function cpad-info int cpad-info)) +(define-extern cpad-get-data (function cpad-info cpad-info)) + + +(define-extern cpad-set-buzz! (function cpad-info int int int none)) +(define-extern *cpad-debug* symbol) ;; unknown type +(define-extern analog-input (function int float float float float float)) +(define-extern buzz-stop! (function int none)) +;;(define-extern cpad-info object) ;; unknown type +;;(define-extern hw-cpad object) ;; unknown type +(define-extern cpad-invalid! (function cpad-info cpad-info)) +;;(define-extern cpad-list object) ;; unknown type +;;(define-extern *cheat-mode* object) ;; unknown type +(define-extern *cpad-list* cpad-list) ;; unknown type +(define-extern service-cpads (function cpad-list)) + +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; GS ;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; + +;; L139 - #x900000008 +;; L138 - +;; L137 - + +(deftype gs-pmode (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-smode2 (uint64) + () + :flag-assert #x900000008 + ) + +(define-extern psm-size (function int int)) +(define-extern psm-page-height (function int int)) +(define-extern psm->string (function int string)) + +(deftype gs-display-fb (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-display (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-bgcolor (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-csr (uint64) + () + :flag-assert #x900000008 + ) (deftype gs-bank (structure) - ((pmode uint64 :offset-assert 0) - (smode2 uint64 :offset 32) - (dspfb1 uint64 :offset 112) - (display1 uint64 :offset 128) - (dspfb2 uint64 :offset 144) - (display2 uint64 :offset 160) + ((pmode gs-pmode :offset-assert 0) + (smode2 gs-smode2 :offset 32) + (dspfb1 gs-display-fb :offset 112) + (display1 gs-display :offset 128) + (dspfb2 gs-display-fb :offset 144) + (display2 gs-display :offset 160) (extbuf uint64 :offset 176) (extdata uint64 :offset 192) (extwrite uint64 :offset 208) - (bgcolor uint64 :offset 224) - (csr uint64 :offset 4096) + (bgcolor gs-bgcolor :offset 224) + (csr gs-csr :offset 4096) (imr uint64 :offset 4112) (busdir uint64 :offset 4160) ) @@ -2617,50 +2685,170 @@ :flag-assert #x900001048 ) -; ;; gs -; (deftype gs-alpha (uint64) -; () -; :method-count-assert 9 -; :size-assert #x8 -; :flag-assert #x900000008 -; ;; likely a bitfield type -; ) +(deftype gs-frame (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-zbuf (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-xy-offset (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-scissor (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-prmode-cont (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-color-clamp (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-dthe (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-test (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-prim (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-rgbaq (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-xyz (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-uv (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-st (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-xyzf (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-trxpos (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-trxreg (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-trxdir (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-bitbltbuf (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-tex0 (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-tex1 (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-texa (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-texclut (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-miptbp (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-alpha (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-fog (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-fogcol (uint64) + () + :flag-assert #x900000008 + ) -; ;; gs -; (deftype gs-fog (uint64) -; () -; :method-count-assert 9 -; :size-assert #x8 -; :flag-assert #x900000008 -; ;; likely a bitfield type -; ) - -; ;; gs -; (deftype gs-fogcol (uint64) -; () -; :method-count-assert 9 -; :size-assert #x8 -; :flag-assert #x900000008 -; ;; likely a bitfield type -; ) +(deftype gif-ctrl (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-mode (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-stat (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-cnt (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-p3cnt (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-p3tag (uint32) + () + :flag-assert #x900000004 + ) (deftype gif-bank (structure) - ((ctrl uint32 :offset 0) - (mode uint32 :offset 16) - (stat uint32 :offset 32) + ((ctrl gif-ctrl :offset 0) + (mode gif-mode :offset 16) + (stat gif-stat :offset 32) (tag0 uint32 :offset 64) (tag1 uint32 :offset 80) (tag2 uint32 :offset 96) (tag3 uint32 :offset 112) - (cnt uint32 :offset 128) - (p3cnt uint32 :offset 144) - (p3tag uint32 :offset 160) + (cnt gif-cnt :offset 128) + (p3cnt gif-p3cnt :offset 144) + (p3tag gif-p3tag :offset 160) ) :method-count-assert 9 :size-assert #xa4 :flag-assert #x9000000a4 ) +(deftype gif-tag-prim (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-tag-count (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-tag64 (uint64) + () + :flag-assert #x900000008 + ) +(deftype gif-tag (uint128) + () + :flag-assert #x900000010 + ) + (deftype gs-gif-tag (structure) ((qword uint128 :offset-assert 0) ;; is "qword" and inline? in game (dword uint64 2 :offset 0) @@ -2673,20 +2861,21 @@ :flag-assert #x900000010 ) -; ;; gs -; (deftype gif-tag (uint128) -; () -; :method-count-assert 9 -; :size-assert #x10 -; :flag-assert #x900000010 -; ;; bad type dec string: [~8x] gif-tag~% -; ) +(define-extern *fog-color* int) +(define-extern default-buffer-init (function dma-buffer none)) +(define-extern *default-regs-buffer* dma-buffer) + (deftype gif-packet (basic) ((reg-count int32 :offset-assert 4) (gif-tag0 uint128 :offset-assert 16) + (gif-tag gs-gif-tag :inline :offset 16) ;; note- added (args uint64 1 :offset-assert 32) + ) + (:methods + (new (symbol type int) _type_ 0) + ) :method-count-assert 9 :size-assert #x28 :flag-assert #x900000028 @@ -2700,11 +2889,74 @@ (height int32 :offset-assert 20) (color int32 4 :offset-assert 24) ) + (:methods + (new (symbol type int int int int int) _type_ 0) + ) :method-count-assert 9 :size-assert #x28 :flag-assert #x900000028 ) + +;;(define-extern gs-trxreg object) ;; unknown type +;;(define-extern gif-packet object) ;; unknown type +;;(define-extern gs-fogcol object) ;; unknown type +;;(define-extern gs-zbuf object) ;; unknown type +;;(define-extern gif-bank object) ;; unknown type +;; ;; unknown type +;;(define-extern gs-trxpos object) ;; unknown type +;;(define-extern gs-xy-offset object) ;; unknown type +;;(define-extern gs-tex1 object) ;; unknown type +;;(define-extern gs-prim object) ;; unknown type +;;(define-extern gif-tag object) ;; unknown type +;;(define-extern gs-display object) ;; unknown type +;;(define-extern gs-prmode-cont object) ;; unknown type +;;(define-extern gs-scissor object) ;; unknown type +;;(define-extern gs-st object) ;; unknown type +;;(define-extern gs-smode2 object) ;; unknown type +(define-extern add-reg-gif-packet (function gif-packet int int none)) +;;(define-extern draw-context object) ;; unknown type +;;(define-extern gs-texclut object) ;; unknown type +;;(define-extern gs-bgcolor object) ;; unknown type +(define-extern open-gif-packet (function gif-packet gif-packet)) +;;(define-extern gif-tag-count object) ;; unknown type +;;(define-extern gs-test object) ;; unknown type +;;(define-extern gs-tex0 object) ;; unknown type +;;(define-extern gif-tag64 object) ;; unknown type +;;(define-extern gs-alpha object) ;; unknown type +;;(define-extern gs-miptbp object) ;; unknown type +;;(define-extern gs-color-clamp object) ;; unknown type +;;(define-extern gif-p3cnt object) ;; unknown type +;;(define-extern gs-clamp object) ;; unknown type +;;(define-extern gs-uv object) ;; unknown type +;;(define-extern gif-stat object) ;; unknown type + +;;(define-extern gif-mode object) ;; unknown type + +;;(define-extern gs-trxdir object) ;; unknown type +;;(define-extern gs-xyzf object) ;; unknown type +;;(define-extern gs-csr object) ;; unknown type +(define-extern draw-context-set-xy (function draw-context int int none)) + +;;(define-extern gs-frame object) ;; unknown type +;;(define-extern gs-texa object) ;; unknown type +;;(define-extern gs-bank object) ;; unknown type +;;(define-extern gif-cnt object) ;; unknown type +;;(define-extern gif-ctrl object) ;; unknown type +;;(define-extern gs-gif-tag object) ;; unknown type +;;(define-extern gs-pmode object) ;; unknown type +;;(define-extern gs-dthe object) ;; unknown type +;;(define-extern gs-fog object) ;; unknown type +;;(define-extern gs-xyz object) ;; unknown type + +;;(define-extern gif-tag-prim object) ;; unknown type +;;(define-extern gif-p3tag object) ;; unknown type +(define-extern close-gif-packet (function gif-packet int gif-packet)) +;;(define-extern gs-display-fb object) ;; unknown type +;;(define-extern gs-bitbltbuf object) ;; unknown type +;;(define-extern gs-rgbaq object) ;; unknown type + + ;;;;;;;;;;;;;;; ;; display-h ;;;;;;;;;;;;;;; @@ -2745,6 +2997,16 @@ :flag-assert #x900000080 ) +;;(define-extern display-env object) ;; unknown type +;;(define-extern display-frame object) ;; unknown type +;;(define-extern display object) ;; unknown type +;;(define-extern *post-draw-hook* object) ;; unknown type +;;(define-extern virtual-frame object) ;; unknown type +(define-extern put-draw-env (function dma-packet none)) +;;(define-extern draw-env object) ;; unknown type +;;(define-extern *pre-draw-hook* object) ;; unknown type + + (deftype display-frame (basic) ((buffer int32 11 :offset-assert 4) ;; no idea (calc-buf basic :offset 8) @@ -2754,6 +3016,9 @@ (bucket-group dma-bucket :offset 44) (profile-bar basic 2 :offset 48) (run-time uint64 :offset 56) + ) + (:methods + (new (symbol type) _type_ 0) ) :method-count-assert 9 :size-assert #x40 @@ -2761,13 +3026,14 @@ ) (deftype virtual-frame (structure) - ((display display-env :offset-assert 0) - (display-last display-env :offset-assert 4) - (gif uint32 :offset-assert 8) - (draw draw-env :offset-assert 12) - (frame basic :offset-assert 16) + ((display display-env :offset-assert 0) + (display-last display-env :offset-assert 4) + (gif pointer :offset-assert 8) + (draw draw-env :offset-assert 12) + (frame display-frame :offset-assert 16) ) - :pack-me + + :allow-misaligned :method-count-assert 9 :size-assert #x14 :flag-assert #x900000014 @@ -2786,10 +3052,8 @@ (draw2 draw-env :inline :offset-assert 432) (on-screen int32 :offset-assert 560) (last-screen int32 :offset-assert 564) - ;(frames UNKNOWN 6 :offset-assert 568) - (_frames-pad uint8 196) - ;(bg-clear-color UNKNOWN 4 :offset-assert 760) - (_bg-clear-color-pad uint8 8) + (frames virtual-frame 6 :inline :offset-assert 568) + (bg-clear-color uint32 4 :offset-assert 760) (real-frame-counter uint64 :offset-assert 776) (base-frame-counter uint64 :offset-assert 784) (game-frame-counter uint64 :offset-assert 792) @@ -2816,11 +3080,13 @@ :size-assert #x39c :flag-assert #xa0000039c (:methods + (new (symbol type int int int int int) _type_ 0) (dummy-9 () none 9) ) ) (define-extern *display* display) +(define-extern set-display (function display int int int int int display)) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2947,9 +3213,29 @@ ;; loader-h ;;;;;;;;;;;;;;; +(deftype load-dir (basic) + ((unknown basic) + (string-array (array string)) + (data-array (array basic))) + :flag-assert #xb00000010 + (:methods + (new (symbol type int basic) _type_ 0) + (dummy-9 () none 9) + (dummy-10 () none 10) + ) + ) + +(deftype load-dir-art-group (load-dir) + () + :flag-assert #xb00000010 + (:methods + (new (symbol type int basic) _type_ 0) + ) + ) + (deftype external-art-buffer (basic) ((index int32 :offset-assert 4) - (other basic :offset-assert 8) + (other external-art-buffer :offset-assert 8) (status basic :offset-assert 12) (locked? basic :offset-assert 16) (frame-lock basic :offset-assert 20) @@ -2970,6 +3256,7 @@ :size-assert #x68 :flag-assert #x1000000068 (:methods + (new (symbol type int) _type_) (dummy-9 () none 9) (dummy-10 () none 10) (dummy-11 () none 11) @@ -2989,38 +3276,40 @@ (owner uint64 :offset-assert 32) (command-list basic :offset-assert 40) ) + :pack-me :method-count-assert 9 :size-assert #x2c :flag-assert #x90000002c ) -;; loader-h -;; todo inline basics -; (deftype external-art-control (basic) -; ((buffer basic 2 :offset-assert 4) -; ;(rec UNKNOWN 3 :offset-assert 20) -; (_rec-pad uint8 142) -; (spool-lock uint64 :offset-assert 160) -; (reserve-buffer basic :offset-assert 168) -; (reserve-buffer-count int32 :offset-assert 172) -; (active-stream basic :offset-assert 176) -; (preload-stream spool-anim :inline :offset-assert 188) -; (last-preload-stream spool-anim :inline :offset-assert 236) -; ) -; :method-count-assert 17 -; :size-assert #x118 -; :flag-assert #x1100000118 -; (:methods -; (dummy-9 () none 9) -; (dummy-10 () none 10) -; (dummy-11 () none 11) -; (dummy-12 () none 12) -; (dummy-13 () none 13) -; (dummy-14 () none 14) -; (dummy-15 () none 15) -; (dummy-16 () none 16) -; ) -; ) +; loader-h +; todo inline basics +(deftype external-art-control (basic) + ((buffer external-art-buffer 2 :offset-assert 4) + (rec spool-anim 3 :inline) + (spool-lock uint64 :offset-assert 160) + (reserve-buffer basic :offset-assert 168) + (reserve-buffer-count int32 :offset-assert 172) + (active-stream basic :offset-assert 176) + (preload-stream spool-anim :inline :offset-assert 184) + (last-preload-stream spool-anim :inline :offset-assert 232) + (end-pad uint32) + ) + :method-count-assert 17 + :size-assert #x118 + :flag-assert #x1100000118 + (:methods + (new (symbol type) _type_ 0) + (dummy-9 () none 9) + (dummy-10 () none 10) + (dummy-11 () none 11) + (dummy-12 () none 12) + (dummy-13 () none 13) + (dummy-14 () none 14) + (dummy-15 () none 15) + (dummy-16 () none 16) + ) + ) ;;;;;;;;;;;;;; ;; texture-h @@ -32152,88 +32441,12 @@ ;;(define-extern error object) ;; unknown type ;;(define-extern details object) ;; unknown type -(define-extern cpad-set-buzz! function) -;;(define-extern *cpad-debug* object) ;; unknown type -(define-extern analog-input function) -(define-extern buzz-stop! function) -;;(define-extern cpad-info object) ;; unknown type -;;(define-extern hw-cpad object) ;; unknown type -(define-extern cpad-invalid! function) -;;(define-extern cpad-list object) ;; unknown type -;;(define-extern *cheat-mode* object) ;; unknown type -;;(define-extern *cpad-list* object) ;; unknown type -(define-extern service-cpads function) -(define-extern get-integral-current-time function) -(define-extern get-current-time function) + +(define-extern get-integral-current-time (function uint)) +(define-extern get-current-time (function uint)) ;;(define-extern cpad-get-data object) ;; unknown type ;;(define-extern cpad-open object) ;; unknown type -(define-extern psm->string function) -;;(define-extern gs-trxreg object) ;; unknown type -;;(define-extern gif-packet object) ;; unknown type -;;(define-extern gs-fogcol object) ;; unknown type -;;(define-extern gs-zbuf object) ;; unknown type -;;(define-extern gif-bank object) ;; unknown type -;;(define-extern *fog-color* object) ;; unknown type -;;(define-extern gs-trxpos object) ;; unknown type -;;(define-extern gs-xy-offset object) ;; unknown type -;;(define-extern gs-tex1 object) ;; unknown type -;;(define-extern gs-prim object) ;; unknown type -;;(define-extern gif-tag object) ;; unknown type -;;(define-extern gs-display object) ;; unknown type -;;(define-extern gs-prmode-cont object) ;; unknown type -;;(define-extern gs-scissor object) ;; unknown type -;;(define-extern gs-st object) ;; unknown type -;;(define-extern gs-smode2 object) ;; unknown type -(define-extern add-reg-gif-packet function) -;;(define-extern draw-context object) ;; unknown type -;;(define-extern gs-texclut object) ;; unknown type -;;(define-extern gs-bgcolor object) ;; unknown type -(define-extern open-gif-packet function) -;;(define-extern gif-tag-count object) ;; unknown type -;;(define-extern gs-test object) ;; unknown type -;;(define-extern gs-tex0 object) ;; unknown type -;;(define-extern gif-tag64 object) ;; unknown type -;;(define-extern gs-alpha object) ;; unknown type -;;(define-extern gs-miptbp object) ;; unknown type -;;(define-extern gs-color-clamp object) ;; unknown type -;;(define-extern gif-p3cnt object) ;; unknown type -;;(define-extern gs-clamp object) ;; unknown type -;;(define-extern gs-uv object) ;; unknown type -;;(define-extern gif-stat object) ;; unknown type -(define-extern psm-page-height function) -;;(define-extern gif-mode object) ;; unknown type -(define-extern psm-size function) -;;(define-extern gs-trxdir object) ;; unknown type -;;(define-extern gs-xyzf object) ;; unknown type -;;(define-extern gs-csr object) ;; unknown type -(define-extern draw-context-set-xy function) -;;(define-extern *default-regs-buffer* object) ;; unknown type -;;(define-extern gs-frame object) ;; unknown type -;;(define-extern gs-texa object) ;; unknown type -;;(define-extern gs-bank object) ;; unknown type -;;(define-extern gif-cnt object) ;; unknown type -;;(define-extern gif-ctrl object) ;; unknown type -;;(define-extern gs-gif-tag object) ;; unknown type -;;(define-extern gs-pmode object) ;; unknown type -;;(define-extern gs-dthe object) ;; unknown type -;;(define-extern gs-fog object) ;; unknown type -;;(define-extern gs-xyz object) ;; unknown type -(define-extern default-buffer-init function) -;;(define-extern gif-tag-prim object) ;; unknown type -;;(define-extern gif-p3tag object) ;; unknown type -(define-extern close-gif-packet function) -;;(define-extern gs-display-fb object) ;; unknown type -;;(define-extern gs-bitbltbuf object) ;; unknown type -;;(define-extern gs-rgbaq object) ;; unknown type -;;(define-extern display-env object) ;; unknown type -;;(define-extern display-frame object) ;; unknown type -;;(define-extern display object) ;; unknown type -;;(define-extern *post-draw-hook* object) ;; unknown type -;;(define-extern virtual-frame object) ;; unknown type -(define-extern put-draw-env function) -;;(define-extern draw-env object) ;; unknown type -;;(define-extern *pre-draw-hook* object) ;; unknown type -(define-extern set-display function) + ;;(define-extern *display* object) ;; unknown type diff --git a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc index 6308f8228a..d1342a403c 100644 --- a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc @@ -28,5 +28,16 @@ ["L128", "float", true], ["L110", "float", true], ["L136", "float", true] + ], + + "pad":[ + ["L44", "float", true], + ["L42", "float", true], + ["L43", "float", true], + ["L41", "float", true] + ], + + "loader-h":[ + ["L10", "float", true] ] } \ No newline at end of file diff --git a/decompiler/config/jak1_ntsc_black_label/type_hints.jsonc b/decompiler/config/jak1_ntsc_black_label/type_hints.jsonc index 334f0ac6ee..37838b7645 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_hints.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_hints.jsonc @@ -175,6 +175,18 @@ "dma-bucket-insert-tag":[ [1, ["a0", "uint"]], [2, ["v1", "dma-bucket"]] + ], + + "default-buffer-init":[ + [9, ["a1", "gs-gif-tag"]], + [15, ["a1", "pointer"]], + [16, ["a1", "gs-gif-tag"]], + [19, ["a1", "gs-gif-tag"]], + [24, ["a1", "pointer"]], + [25, ["a1", "gs-gif-tag"]], + [31, ["a1", "(pointer uint64)"]], + [68, ["a0", "gs-gif-tag"]], + [72, ["a0", "pointer"]] ] diff --git a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc index a5d27ce8d0..0ad70fdc58 100644 --- a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc @@ -427,6 +427,47 @@ "disasm-vif-details":{ "args":["stream", "data", "kind", "count"], "vars":{"s4-0":"count2", "s3-0":"data-ptr", "s2-0":"i"} + }, + + "cpad-invalid!":{ + "args":["pad"] + }, + + "(method 0 cpad-info)":{ + "args":["alloction", "type-to-make", "idx"], + "vars":{"s5-0":"obj"} + }, + + "analog-input":{ + "args":["in", "offset", "center-val", "max-val", "out-range"], + "vars":{"f1-1":"offset-in", "f0-3":"magnitude", "v1-0":"max-magnitude"} + }, + + "cpad-set-buzz!":{ + "args":["pad", "buzz-idx", "buzz-amount", "duration"] + }, + + "service-cpads":{ + "vars":{"gp-0":"pad-list", "s5-0":"pad-idx", "s4-0":"pad", "s3-0":"buzz-idx", "v1-29":"current-button0"} + }, + + "default-buffer-init":{ + "args":["buff"], + "vars":{"v1-0":"buff", "v1-1":"buff", "v1-3":"buff", "v1-4":"buff", "a1-4":"tag", "a1-6":"tag2", "a1-8":"data", "a0-1":"tag3", "v1-2":"buff"} + }, + + "add-reg-gif-packet":{ + "args":["packet", "reg-idx", "reg-val"], + "vars":{"v1-0":"tag"} + }, + + "(method 0 draw-context)":{ + "args":["allocation", "type-to-make", "org-x", "org-y", "width", "height", "color-0"] + }, + + "(method 0 display)":{ + "args":["allocation", "type-to-make", "psm", "w", "h", "ztest", "zpsm"], + "vars":{"gp-0":"obj"} } diff --git a/doc/code_status.md b/doc/code_status.md index 650045f02c..a456f54895 100644 --- a/doc/code_status.md +++ b/doc/code_status.md @@ -112,4 +112,23 @@ - The sends won't work on PC, but it should let you build the buffer... ## `dma-bucket`: **Done** -- Could clean up some bitfield access, should probably add some features to the compiler to help here. \ No newline at end of file +- Could clean up some bitfield access, should probably add some features to the compiler to help here. + +## `dma-disasm`: In progress +- Unused, but possibly useful debugging utilities for printing DMA chains. +- Needs stack stuff to do the last two functions +- Needs static data disassembler for a lookup table. + +## `pad`: **Done** + +## `gs`: **Done** +- Missing bitfields + +## `display-h`: **Done** + +## `vector`: asm + +## `fileio`: **Done** + +## `loader-h`: **Done** +- Good one for playing with inlined basics. \ No newline at end of file diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index 10b1c680e6..5f98512988 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -37,6 +37,7 @@ set(RUNTIME_SOURCE sce/libcdvd_ee.cpp sce/libscf.cpp sce/libdma.cpp + sce/libpad.cpp sce/libgraph.cpp sce/deci2.cpp sce/sif_ee.cpp diff --git a/game/kernel/kmachine.cpp b/game/kernel/kmachine.cpp index 0015e0702f..9dd2ff23c2 100644 --- a/game/kernel/kmachine.cpp +++ b/game/kernel/kmachine.cpp @@ -26,6 +26,7 @@ #include "game/sce/stubs.h" #include "game/sce/libdma.h" #include "game/sce/libgraph.h" +#include "game/sce/libpad.h" #include "common/symbols.h" #include "common/log/log.h" using namespace ee; diff --git a/game/sce/libpad.cpp b/game/sce/libpad.cpp new file mode 100644 index 0000000000..a95e7c5ecd --- /dev/null +++ b/game/sce/libpad.cpp @@ -0,0 +1,12 @@ +#include +#include "libpad.h" + +namespace ee { +int scePadPortOpen(int port, int slot, void*) { + // we are expected to return a non-zero file descriptor. + // we return the port + 1 and succeed always. + // the game just opens this once at the beginning, we don't have to implement closing/reopening. + assert(slot == 0); + return port + 1; +} +} // namespace ee diff --git a/game/sce/libpad.h b/game/sce/libpad.h new file mode 100644 index 0000000000..a2c80f60b7 --- /dev/null +++ b/game/sce/libpad.h @@ -0,0 +1,7 @@ +#pragma once + +#define SCE_PAD_DMA_BUFFER_SIZE 0x100 + +namespace ee { +int scePadPortOpen(int port, int slot, void* data); +} \ No newline at end of file diff --git a/game/sce/stubs.cpp b/game/sce/stubs.cpp index 782875b413..4871e78688 100644 --- a/game/sce/stubs.cpp +++ b/game/sce/stubs.cpp @@ -3,13 +3,6 @@ #include "stubs.h" namespace ee { -int scePadPortOpen(int port, int slot, void* data) { - (void)port; - (void)slot; - (void)data; - assert(false); - return 0; -} void sceGsSyncV() { assert(false); diff --git a/game/sce/stubs.h b/game/sce/stubs.h index 86a5bd4492..e07de52d95 100644 --- a/game/sce/stubs.h +++ b/game/sce/stubs.h @@ -1,12 +1,7 @@ #pragma once -#ifndef JAK1_STUBS_H -#define JAK1_STUBS_H - #include "common/common_types.h" -#define SCE_PAD_DMA_BUFFER_SIZE 0x100 - namespace ee { void sceGsSyncV(); void sceGsSyncPath(); @@ -14,7 +9,6 @@ void sceGsPutIMR(); void sceGsGetIMR(); void sceGsExecStoreImage(); void FlushCache(); -int scePadPortOpen(int port, int slot, void* data); } // namespace ee namespace iop { @@ -22,5 +16,3 @@ u32 snd_BankLoadByLoc(u32 sector, u32 unk); u32 snd_GetLastLoadError(); void snd_ResolveBankXREFS(); } // namespace iop - -#endif // JAK1_STUBS_H diff --git a/goal_src/engine/dma/dma-buffer.gc b/goal_src/engine/dma/dma-buffer.gc index 19e4c8667a..76ba1a06f3 100644 --- a/goal_src/engine/dma/dma-buffer.gc +++ b/goal_src/engine/dma/dma-buffer.gc @@ -59,7 +59,7 @@ (deftype dma-buffer (basic) ((allocated-length int32 :offset-assert 4) (base pointer :offset-assert 8) - (end uint32 :offset-assert 12) + (end pointer :offset-assert 12) (data uint64 1 :offset-assert 16) ;; weird, I guess this aligns the data? (data-buffer uint8 :dynamic :offset 16) ) diff --git a/goal_src/engine/dma/dma-disasm.gc b/goal_src/engine/dma/dma-disasm.gc index a3d9a90978..3d3f473364 100644 --- a/goal_src/engine/dma/dma-disasm.gc +++ b/goal_src/engine/dma/dma-disasm.gc @@ -19,3 +19,182 @@ ) +(defun disasm-vif-details ((stream symbol) (data (pointer uint8)) (kind int) (count int)) + (local-vars + (v1-21 uint) + (v1-26 uint) + (a3-7 int) + (i int) + (s2-1 int) + (s2-2 int) + (s2-3 int) + (s2-4 int) + (s2-5 int) + (s2-6 int) + (data-ptr (pointer uint8)) + (s3-1 (pointer uint8)) + (s3-2 (pointer uint8)) + (s3-3 (pointer uint8)) + (s3-4 (pointer uint8)) + (s3-5 (pointer uint8)) + (s3-6 (pointer uint8)) + (count2 int) + ) + (set! count2 count) + (cond + ((= kind 110) + (set! data-ptr (&-> data 4)) + (set! i 0) + (while (< i count2) + (format stream " #x~X: #x~2X #x~2X #x~2X #x~2X~%" + (+ (+ (shl i 2) 4) (the-as int data)) + (-> (the-as (pointer uint8) (&+ data-ptr (shl i 2)))) + (-> (the-as (pointer uint8) (&+ data-ptr (+ (shl i 2) 1)))) + (-> (the-as (pointer uint8) (&+ data-ptr (+ (shl i 2) 2)))) + (-> (the-as (pointer uint8) (&+ data-ptr (+ (shl i 2) 3)))) + ) + (+! i 1) + ) + ) + ((= kind 98) + (set! s3-1 (&-> data 4)) + (set! s2-1 0) + (while (< s2-1 count2) + (format stream " #x~X: #x~2x~%" (+ (+ s2-1 4) (the-as int data)) count) + (set! v1-21 (-> (the-as (pointer uint8) (&+ s3-1 (* 3 s2-1))))) + (set! v1-26 (-> (the-as (pointer uint8) (&+ s3-1 (+ (* 3 s2-1) 1))))) + (+! s2-1 1) + ) + ) + ((= kind 108) + (set! s3-2 (&-> data 4)) + (set! s2-2 0) + (while (< s2-2 count2) + (format stream " #x~X: #x~8x #x~8x #x~8x #x~8x~%" + (+ (+ (shl s2-2 4) 4) (the-as int data)) + (-> (the-as (pointer uint32) (&+ s3-2 (shl (shl s2-2 2) 2)))) + (-> (the-as (pointer uint32) (&+ s3-2 (shl (+ (shl s2-2 2) 1) 2)))) + (-> (the-as (pointer uint32) (&+ s3-2 (shl (+ (shl s2-2 2) 2) 2)))) + (-> (the-as (pointer uint32) (&+ s3-2 (shl (+ (shl s2-2 2) 3) 2)))) + ) + (+! s2-2 1) + ) + ) + ((= kind 109) + (set! s3-3 (&-> data 4)) + (set! s2-3 0) + (while + (< s2-3 count2) + (format stream " #x~X: #x~4x #x~4x #x~4x #x~4x~%" + (+ (+ (shl s2-3 3) 4) (the-as int data)) + (-> (the-as (pointer uint16) (&+ s3-3 (shl (shl s2-3 2) 1)))) + (-> (the-as (pointer uint16) (&+ s3-3 (shl (+ (shl s2-3 2) 1) 1)))) + (-> (the-as (pointer uint16) (&+ s3-3 (shl (+ (shl s2-3 2) 2) 1)))) + (-> (the-as (pointer uint16) (&+ s3-3 (shl (+ (shl s2-3 2) 3) 1)))) + ) + (+! s2-3 1) + ) + ) + ((= kind 104) + (set! s3-4 (&-> data 4)) + (set! s2-4 0) + (while + (< s2-4 count2) + (format stream + " #x~X: #x~8x #x~8x #x~8x~%" + (+ (+ (* 12 s2-4) 4) (the-as int data)) + (-> (the-as (pointer uint32) (&+ s3-4 (* 12 s2-4)))) + (-> (the-as (pointer uint32) (&+ s3-4 (shl (+ (* 3 s2-4) 1) 2)))) + (-> (the-as (pointer uint32) (&+ s3-4 (shl (+ (* 3 s2-4) 2) 2)))) + ) + (+! s2-4 1) + ) + ) + ((= kind 105) + (set! s3-5 (&-> data 4)) + (set! s2-5 0) + (while + (< s2-5 count2) + (format stream + " #x~X: #x~4x #x~4x #x~4x~%" + (+ (+ (* 6 s2-5) 4) (the-as int data)) + (-> (the-as (pointer uint16) (&+ s3-5 (* 6 s2-5)))) + (-> (the-as (pointer uint16) (&+ s3-5 (shl (+ (* 3 s2-5) 1) 1)))) + (-> (the-as (pointer uint16) (&+ s3-5 (shl (+ (* 3 s2-5) 2) 1)))) + ) + (+! s2-5 1) + ) + ) + ((= kind 101) + (set! s3-6 (&-> data 4)) + (set! s2-6 0) + (while + (< s2-6 count2) + (format stream " #x~X: #x~4x #x~4x~%" + (+ (+ (shl s2-6 2) 4) (the-as int data)) + (-> (the-as (pointer uint16) (&+ s3-6 (* 6 s2-6)))) + (-> (the-as (pointer uint16) (&+ s3-6 (shl (+ (* 3 s2-6) 1) 1)))) + ) + (+! s2-6 1) + ) + ) + (else + (set! a3-7 kind) + (format stream + " #x~X: Data format #b~b not yet supported, add it for yourself!~%" + (&-> data 4) + a3-7 + ) + ) + ) + #f + ) + +(defun disasm-dma-tag ((arg0 uint) (arg1 symbol)) + "Print out a dma-tag" + (local-vars + (v1-1 uint) + (v1-15 int) + ) + (format arg1 "(dma-tag ") + + ;; this is a case used by value, which it doesn't like because the temp v1-1 can't be folded into a single + ;; expression. In reality, the game does the following line _after_ the format symbol is loaded, + ;; but this makes no difference and OpenGOAL doesn't have case, so we have to make do with this. + (set! v1-1 (shr (shl arg0 33) 61)) + (format arg1 "~s" + (cond + ((= v1-1 7) "end") + ((= v1-1 6) "ret") + ((= v1-1 5) "call") + ((= v1-1 4) "refs") + ((= v1-1 3) "ref") + ((= v1-1 2) "next") + ((= v1-1 1) "cnt") + ((zero? v1-1) "refe") + (else "*unknown*") + ) + ) + + ;; only print address if nonzero + (if (> (shr (shl arg0 1) 33) 0) + (format arg1 " :addr #x~8x" (shr (shl arg0 1) 33)) + ) + + ;; only print qwc if nonzero + (if (> (shr (shl arg0 48) 48) 0) + (format arg1 " :qwc ~d" (shr (shl arg0 48) 48)) + ) + ;; only print spr if set + (if (> (shr arg0 63) 0) + (format arg1 " :spr ~d" (shr arg0 63))) + ;;(.srl v1-15 arg0 31) + (set! v1-15 (logand #xffffffff (shr arg0 31))) + (when (> (the-as uint v1-15) 0) + (format arg1 " :irq ~d" (logand #xffffffff (shr arg0 31))) + ) + (if (> (shr (shl arg0 36) 62) 0) + (format arg1 " :pce ~d" (shr (shl arg0 36) 62)) + ) + (the-as int (format arg1 ")~%")) + ) diff --git a/goal_src/engine/dma/dma-h.gc b/goal_src/engine/dma/dma-h.gc index 2ea615d466..0a53a981e6 100644 --- a/goal_src/engine/dma/dma-h.gc +++ b/goal_src/engine/dma/dma-h.gc @@ -86,7 +86,8 @@ (defconstant VIF0_DMA_BANK (the dma-bank-vif #x10008000)) (defconstant VIF1_DMA_BANK (the dma-bank-vif #x10009000)) -;; gif, ipuFrom, ipTop, sif0, sif1, sif2 believed unused. +(defconstant GIF_DMA_BANK (the dma-bank #x1000a000)) +;; ipuFrom, ipTop, sif0, sif1, sif2 believed unused. (defconstant SPR_FROM_BANK (the dma-bank-spr #x1000d000)) (defconstant SPR_TO_BANK (the dma-bank-spr #x1000d400)) diff --git a/goal_src/engine/gfx/hw/display-h.gc b/goal_src/engine/gfx/hw/display-h.gc index 0d48df0b56..2eba8b8b64 100644 --- a/goal_src/engine/gfx/hw/display-h.gc +++ b/goal_src/engine/gfx/hw/display-h.gc @@ -5,3 +5,186 @@ ;; name in dgo: display-h ;; dgos: GAME, ENGINE +(declare-type display basic) +(define-extern set-display (function display int int int int int display)) + +(deftype display-env (structure) + ((pmode uint64 :offset-assert 0) + (smode2 uint64 :offset-assert 8) + (dspfb uint64 :offset-assert 16) + (display uint64 :offset-assert 24) + (bgcolor uint64 :offset-assert 32) + ) + :pack-me + :method-count-assert 9 + :size-assert #x28 + :flag-assert #x900000028 + ) + +(deftype draw-env (structure) + ((frame1 uint64 :offset-assert 0) + (frame1addr uint64 :offset-assert 8) + (zbuf1 uint64 :offset-assert 16) + (zbuf1addr uint64 :offset-assert 24) + (xyoffset1 uint64 :offset-assert 32) + (xyoffset1addr uint64 :offset-assert 40) + (scissor1 uint64 :offset-assert 48) + (scissor1addr uint64 :offset-assert 56) + (prmodecont uint64 :offset-assert 64) + (prmodecontaddr uint64 :offset-assert 72) + (colclamp uint64 :offset-assert 80) + (colclampaddr uint64 :offset-assert 88) + (dthe uint64 :offset-assert 96) + (dtheaddr uint64 :offset-assert 104) + (test1 uint64 :offset-assert 112) + (test1addr uint64 :offset-assert 120) + ) + :method-count-assert 9 + :size-assert #x80 + :flag-assert #x900000080 + ) + +(defun put-draw-env ((packet dma-packet)) + "Uses the qwc stored in the packet." + ;; TODO - good spot to patch for PC, or maybe just exclude. + (dma-send GIF_DMA_BANK (the uint packet) (+ (the uint 1) (-> packet dma qwc))) + ) + +(deftype display-frame (basic) + ((buffer int32 11 :offset-assert 4) ;; no idea + (calc-buf basic :offset 8) ;; todo - maybe DMA buffers? + (vu1-buf basic :offset 8) + (debug-buf basic :offset 36) + (global-buf basic :offset 40) + (bucket-group dma-bucket :offset 44) + (profile-bar basic 2 :offset 48) + (run-time uint64 :offset 56) + ) + (:methods + (new (symbol type) _type_ 0) + ) + :method-count-assert 9 + :size-assert #x40 + :flag-assert #x900000040 + ) + +(defmethod new display-frame ((allocation symbol) (type-to-make type)) + "Allocate a new display-frame" + (local-vars (obj display-frame)) + (set! obj (object-new allocation type-to-make (the-as int (-> type-to-make size)))) + (set! (-> obj buffer 1) 0) + (set! (-> obj buffer 9) 0) + (set! (-> obj buffer 8) 0) + (when *debug-segment* + (set! (-> obj profile-bar 0) (new 'debug 'profile-bar)) + (set! (-> obj profile-bar 1) (new 'debug 'profile-bar)) + ) + obj + ) + +(deftype virtual-frame (structure) + ((display display-env :offset-assert 0) + (display-last display-env :offset-assert 4) + (gif pointer :offset-assert 8) + (draw draw-env :offset-assert 12) + (frame display-frame :offset-assert 16) + ) + + :allow-misaligned + :method-count-assert 9 + :size-assert #x14 + :flag-assert #x900000014 + ) + + +(deftype display (basic) + ((display-env0 display-env :inline :offset-assert 8) + (display-env1 display-env :inline :offset-assert 48) + (display-env2 display-env :inline :offset-assert 88) + (gif-tag0 uint128 :offset-assert 128) + (draw0 draw-env :inline :offset-assert 144) + (gif-tag1 uint128 :offset-assert 272) + (draw1 draw-env :inline :offset-assert 288) + (gif-tag2 uint128 :offset-assert 416) + (draw2 draw-env :inline :offset-assert 432) + (on-screen int32 :offset-assert 560) + (last-screen int32 :offset-assert 564) + (frames virtual-frame 6 :inline :offset-assert 568) + (bg-clear-color uint32 4 :offset-assert 760) + (real-frame-counter uint64 :offset-assert 776) + (base-frame-counter uint64 :offset-assert 784) + (game-frame-counter uint64 :offset-assert 792) + (integral-frame-counter uint64 :offset-assert 800) + (real-integral-frame-counter uint64 :offset-assert 808) + (actual-frame-counter uint64 :offset-assert 816) + (real-actual-frame-counter uint64 :offset-assert 824) + (part-frame-counter uint64 :offset-assert 832) + (old-real-frame-counter uint64 :offset-assert 840) + (old-base-frame-counter uint64 :offset-assert 848) + (old-game-frame-counter uint64 :offset-assert 856) + (old-integral-frame-counter uint64 :offset-assert 864) + (old-real-integral-frame-counter uint64 :offset-assert 872) + (old-actual-frame-counter uint64 :offset-assert 880) + (old-real-actual-frame-counter uint64 :offset-assert 888) + (old-part-frame-counter uint64 :offset-assert 896) + (time-ratio float :offset-assert 904) + (seconds-per-frame float :offset-assert 908) + (frames-per-second float :offset-assert 912) + (time-factor float :offset-assert 916) + (time-adjust-ratio float :offset-assert 920) + ) + :method-count-assert 10 + :size-assert #x39c + :flag-assert #xa0000039c + (:methods + (new (symbol type int int int int int) _type_ 0) + (dummy-9 () none 9) + ) + ) + +(defmethod new display ((allocation symbol) (type-to-make type) (psm int) (w int) (h int) (ztest int) (zpsm int)) + (local-vars (obj display)) + (set! obj + (object-new allocation type-to-make (the-as int (-> type-to-make size))) + ) + (set-display obj psm w h ztest zpsm) + (set! (-> obj frames 0 display) (-> obj display-env0)) + (set! (-> obj frames 1 display) (-> obj display-env1)) + (set! (-> obj frames 2 display) (-> obj display-env2)) + (set! (-> obj frames 3 display) (-> obj display-env0)) + (set! (-> obj frames 4 display) (-> obj display-env1)) + (set! (-> obj frames 5 display) (-> obj display-env2)) + (set! (-> obj frames 0 display-last) (-> obj display-env2)) + (set! (-> obj frames 1 display-last) (-> obj display-env0)) + (set! (-> obj frames 2 display-last) (-> obj display-env1)) + (set! (-> obj frames 3 display-last) (-> obj display-env2)) + (set! (-> obj frames 4 display-last) (-> obj display-env0)) + (set! (-> obj frames 5 display-last) (-> obj display-env1)) + (set! (-> obj frames 0 gif) (&-> obj gif-tag0)) + (set! (-> obj frames 1 gif) (&-> obj gif-tag1)) + (set! (-> obj frames 2 gif) (&-> obj gif-tag2)) + (set! (-> obj frames 3 gif) (&-> obj gif-tag0)) + (set! (-> obj frames 4 gif) (&-> obj gif-tag1)) + (set! (-> obj frames 5 gif) (&-> obj gif-tag2)) + (set! (-> obj frames 0 draw) (-> obj draw0)) + (set! (-> obj frames 1 draw) (-> obj draw1)) + (set! (-> obj frames 2 draw) (-> obj draw2)) + (set! (-> obj frames 3 draw) (-> obj draw0)) + (set! (-> obj frames 4 draw) (-> obj draw1)) + (set! (-> obj frames 5 draw) (-> obj draw2)) + (set! (-> obj frames 0 frame) (new 'global 'display-frame)) + (set! (-> obj frames 1 frame) (new 'global 'display-frame)) + (set! (-> obj frames 2 frame) (-> obj frames 0 frame)) + (set! (-> obj frames 3 frame) (-> obj frames 1 frame)) + (set! (-> obj frames 4 frame) (-> obj frames 0 frame)) + (set! (-> obj frames 5 frame) (-> obj frames 1 frame)) + (default-buffer-init *default-regs-buffer*) + (set! (-> obj bg-clear-color 0) #x80808080) + (set! (-> obj bg-clear-color 1) #x80808080) + (set! (-> obj bg-clear-color 2) #x80808080) + (set! (-> obj bg-clear-color 3) #x80808080) + obj + ) + +(define *pre-draw-hook* nothing) +(define *post-draw-hook* nothing) diff --git a/goal_src/engine/gfx/hw/gs.gc b/goal_src/engine/gfx/hw/gs.gc index 37f6c6cd4a..517f69d4e4 100644 --- a/goal_src/engine/gfx/hw/gs.gc +++ b/goal_src/engine/gfx/hw/gs.gc @@ -5,3 +5,521 @@ ;; name in dgo: gs ;; dgos: GAME, ENGINE +(deftype gs-pmode (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-smode2 (uint64) + () + :flag-assert #x900000008 + ) + +;; 19 = PSMT8 +;; 20 = PSMT4 +;; 2 = PSMCT24 +;; 10 = PSMCT16S +;; 50 = PSMZ16 +;; 58 = PSMZ16S + +(defconstant TEX_MZ16S 58) +(defconstant TEX_MZ16 50) +(defconstant TEX_MZ24 49) +(defconstant TEX_MZ32 48) +(defconstant TEX_MT4HH 44) +(defconstant TEX_MT4HL 36) +(defconstant TEX_MT8H 27) +(defconstant TEX_MT4 20) +(defconstant TEX_MT8 19) +(defconstant TEX_CT16S 10) +(defconstant TEX_CT16 2) +(defconstant TEX_CT24 1) +(defconstant TEX_CT32 0) + +(defun psm-size ((arg0 int)) + "Not sure exactly what 'size' means, but this likely takes a texture format as an input." + (cond + ((= arg0 TEX_MT8) 64) + ((= arg0 TEX_MT4) 32) + (else + (if (or (= arg0 TEX_CT16) (= arg0 TEX_CT16S) (= arg0 TEX_MZ16) (= arg0 TEX_MZ16S)) + 128 + 256 + ) + ) + ) + ) + +(defun psm-page-height ((arg0 int)) + "texture format -> page height?" + (cond + ((= arg0 TEX_MT8) 64) + ((= arg0 TEX_MT4) 128) + (else + (if (or (= arg0 TEX_CT16) (= arg0 TEX_CT16S) (= arg0 TEX_MZ16) (= arg0 TEX_MZ16S)) + 64 + 32 + ) + ) + ) + ) + + +(defun psm->string ((arg0 int)) + "Convert texture format to its name" + (local-vars (v1-0 int)) + (set! v1-0 arg0) + (cond + ((= v1-0 TEX_MZ16S) "mz16s") + ((= v1-0 TEX_MZ16) "mz16") + ((= v1-0 TEX_MZ24) "mz24") + ((= v1-0 TEX_MZ32) "mz32") + ((= v1-0 TEX_MT4HH) "mt4hh") + ((= v1-0 TEX_MT4HL) "mt4hl") + ((= v1-0 TEX_MT8H) "mt8h") + ((= v1-0 TEX_MT4) "mt4") + ((= v1-0 TEX_MT8) "mt8") + ((= v1-0 TEX_CT16S) "ct16s") + ((= v1-0 TEX_CT16) "ct16") + ((= v1-0 TEX_CT24) "ct24") + ((zero? v1-0) "ct32") + (else "*unknown*") + ) + ) + +(deftype gs-display-fb (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-display (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-bgcolor (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-csr (uint64) + () + :flag-assert #x900000008 + ) + +(deftype gs-bank (structure) + ((pmode gs-pmode :offset-assert 0) + (smode2 gs-smode2 :offset 32) + (dspfb1 gs-display-fb :offset 112) + (display1 gs-display :offset 128) + (dspfb2 gs-display-fb :offset 144) + (display2 gs-display :offset 160) + (extbuf uint64 :offset 176) + (extdata uint64 :offset 192) + (extwrite uint64 :offset 208) + (bgcolor gs-bgcolor :offset 224) + (csr gs-csr :offset 4096) + (imr uint64 :offset 4112) + (busdir uint64 :offset 4160) + ) + :method-count-assert 9 + :size-assert #x1048 + :flag-assert #x900001048 + ) + +(deftype gs-frame (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-zbuf (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-xy-offset (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-scissor (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-prmode-cont (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-color-clamp (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-dthe (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-test (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-prim (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-rgbaq (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-xyz (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-uv (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-st (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-xyzf (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-trxpos (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-trxreg (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-trxdir (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-bitbltbuf (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-tex0 (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-tex1 (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-texa (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-texclut (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-miptbp (uint64) + () + :flag-assert #x900000008 + ) +(deftype gs-alpha (uint64) + () + :flag-assert #x900000008 + ) + +(defmethod inspect gs-alpha ((obj gs-alpha)) + (format #t "[~8x] ~A~%" obj 'gs-alpha) + (format #t "~Ta: ~D~%" (shr (shl (the-as int obj) 62) 62)) + (format #t "~Tb: ~D~%" (shr (shl (the-as int obj) 60) 62)) + (format #t "~Tc: ~D~%" (shr (shl (the-as int obj) 58) 62)) + (format #t "~Td: ~D~%" (shr (shl (the-as int obj) 56) 62)) + (format #t "~Tfix: ~D~%" (shr (shl (the-as int obj) 24) 56)) + obj + ) + +(deftype gs-fog (uint64) + () + :flag-assert #x900000008 + ) + +(defmethod inspect gs-fog ((obj gs-fog)) + (format #t "[~8x] ~A~%" obj 'gs-fog) + (format #t "~Tf: ~D~%" (shr (the-as int obj) 56)) + obj + ) + +(deftype gs-fogcol (uint64) + () + :flag-assert #x900000008 + ) + +(defmethod inspect gs-fogcol ((obj gs-fogcol)) + (format #t "[~8x] ~A~%" obj 'gs-fogcol) + (format #t "~Tr: ~D~%" (shr (shl (the-as int obj) 56) 56)) + (format #t "~Tg: ~D~%" (shr (shl (the-as int obj) 48) 56)) + (format #t "~Tb: ~D~%" (shr (shl (the-as int obj) 40) 56)) + obj + ) + +(deftype gif-ctrl (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-mode (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-stat (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-cnt (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-p3cnt (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-p3tag (uint32) + () + :flag-assert #x900000004 + ) + +(deftype gif-bank (structure) + ((ctrl gif-ctrl :offset 0) + (mode gif-mode :offset 16) + (stat gif-stat :offset 32) + (tag0 uint32 :offset 64) + (tag1 uint32 :offset 80) + (tag2 uint32 :offset 96) + (tag3 uint32 :offset 112) + (cnt gif-cnt :offset 128) + (p3cnt gif-p3cnt :offset 144) + (p3tag gif-p3tag :offset 160) + ) + :method-count-assert 9 + :size-assert #xa4 + :flag-assert #x9000000a4 + ) + +(deftype gif-tag-prim (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-tag-count (uint32) + () + :flag-assert #x900000004 + ) +(deftype gif-tag64 (uint64) + () + :flag-assert #x900000008 + ) +(deftype gif-tag (uint128) + () + :flag-assert #x900000010 + ) + +(deftype gs-gif-tag (structure) + ((qword uint128 :offset-assert 0) ;; is "qword" and inline? in game + (dword uint64 2 :offset 0) + (word uint32 4 :offset 0) + (tag uint64 :offset 0) + (regs uint64 :offset 8) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; Note - there was an inspect method for the uint128-based gif-tag, but it is being left out. + +;; no idea what format this is stored in. Looks like a nasty orange? +(define *fog-color* #xc88029) + +;; set up a DMA buffer. This will hold a message to set the GS state to normal. +;; these regs are NOT the ones mapped in the EE memory, but other internal GS registers. +(define *default-regs-buffer* (new 'global 'dma-buffer 1024)) + +(defun default-buffer-init ((buff dma-buffer)) + "Puts some currently unknown gif tags in the buffer." + (local-vars + (tag3 gs-gif-tag) + (tag gs-gif-tag) + (tag2 gs-gif-tag) + (data (pointer uint64)) + ) + ;; reset the buffer base and end. + (set! (-> buff base) (-> buff data)) + (set! (-> buff end) (&-> buff data-buffer (-> buff allocated-length))) + + ;; make a tag (maybe this is actually a dma/vif tag?) + (set! tag (the gs-gif-tag (-> buff base))) + (set! (-> tag dword 0) #x1000000a) + (set! (-> tag word 2) #x13000000) + (set! (-> tag word 3) #x5000000a) + (set! (-> buff base) (&+ (the-as pointer tag) 16)) + + ;; make another tag. + (set! tag2 (the gs-gif-tag (-> buff base))) + ;; no idea what this is about, it doesn't matter. + ;;(set! a2-3 (l.d L53)) + ;;(.pcpyld a2-4 r0-0 a2-3) + (set! (-> tag2 dword 0) #x9000000000008001) + (set! (-> tag2 dword 1) #xeeeeeeeeeeeeeeee) + (set! (-> buff base) (&+ (the-as pointer tag2) 16)) + + ;; now some payload. + (set! data (the (pointer uint64) (-> buff base))) + (set! (-> data 0) 68) + (set! (-> data 1) 66) + (set! (-> data 2) #x10001c0) + (set! (-> data 3) 78) + (set! (-> data 4) #x5000e) + (set! (-> data 5) 71) + (set! (-> data 6) 0) + (set! (-> data 7) 73) + (set! (-> data 8) 5) + (set! (-> data 9) 8) + (set! (-> data 10) 96) + (set! (-> data 11) 20) + (set! (-> data 12) (shl 128 32)) + (set! (-> data 13) 59) + (set! (-> data 14) 4) + (set! (-> data 15) 28) + (set! (-> data 16) *fog-color*) + (set! (-> data 17) 61) + (set! (-> buff base) (&-> data 18)) + + ;; and a final tag. + (set! tag3 (the gs-gif-tag (-> buff base))) + (set! (-> tag3 dword 0) #x60000000) + (set! (-> tag3 word 2) 0) + (set! (-> tag3 word 3) 0) + (set! (-> buff base) (&+ (the-as pointer tag3) 16)) + (none) + ) + +(default-buffer-init *default-regs-buffer*) + +;; This isn't a dynamic type in the type system, but it's used as one. +;; the array at the end is used as a dynamic array. +;; NOTE - this gif-packet stuff seems unused. Instead dma-gif-packet is used. +;; this seems to use 128-bit integer values, but the compiler gets confused sometimes?? + +;; This stuff could be used like this: +;; - new gif-packet +;; - open-gif-packet +;; - add-reg-gif-packet to add a register +;; - close-gif-packet +;; now you have a reglist gs packet. + +(deftype gif-packet (basic) + ((reg-count int32 :offset-assert 4) + (gif-tag0 uint128 :offset-assert 16) + (gif-tag gs-gif-tag :inline :offset 16) + (args uint64 1 :offset-assert 32) ;; there's one here already. + ) + (:methods + (new (symbol type int) _type_ 0) + ) + :method-count-assert 9 + :size-assert #x28 + :flag-assert #x900000028 + ) + +(defmethod new gif-packet ((allocation symbol) (type-to-make type) (arg0 int)) + "Make a new gif packet with enough room for arg0 64-bit args" + (object-new allocation type-to-make + (the-as int (+ (-> type-to-make size) (shl (+ arg0 -1) 3))) + ) + ) + +(defun open-gif-packet ((arg0 gif-packet)) + "Initialize a gif packet" + (set! (-> arg0 reg-count) 0) + (set! (-> arg0 gif-tag dword 1) 0) + arg0 + ) + +(defun add-reg-gif-packet ((packet gif-packet) (reg-idx int) (reg-val int)) + "Adds a register to reglist packet." + (local-vars (tag gs-gif-tag)) + (set! tag (-> packet gif-tag)) + ;; dword 1 contains the list of registers to set. each is 4-bits. + (set! (-> tag dword 1) + (logior (-> tag dword 1) + (the-as uint (ash reg-idx (shl (-> packet reg-count) 2))) ;; shift to the correct spot + ) + ) + ;; ?? (-> packet args (-> packet reg-count)) + ;; store the value for the register. + (set! (-> (&-> packet args (-> packet reg-count)) 0) reg-val) + ;; increment the reg we're on. + (set! (-> packet reg-count) (+ (-> packet reg-count) 1)) + (none) + ) + +(defun close-gif-packet ((arg0 gif-packet) (arg1 int)) + "Sets the lower dword of the giftag for reglist" + (local-vars (v1-2 int) (v1-3 int)) + (set! v1-2 + (logior (logior #x400000000000001 (the-as uint (shl (-> arg0 reg-count) 60))) + (the-as uint (shr (shl arg1 63) 48)) + ) + ) + ;;(.pcpyld v1-3 r0-0 v1-2)?? GOAL compiler is confused. + (set! (-> arg0 gif-tag dword 0) v1-2) + arg0 + ) + + +(deftype draw-context (basic) + ((orgx int32 :offset-assert 4) + (orgy int32 :offset-assert 8) + (orgz int32 :offset-assert 12) + (width int32 :offset-assert 16) + (height int32 :offset-assert 20) + (color int32 4 :offset-assert 24) + ) + (:methods + (new (symbol type int int int int int) _type_ 0) + ) + :method-count-assert 9 + :size-assert #x28 + :flag-assert #x900000028 + ) + +(defmethod new draw-context ((allocation symbol) + (type-to-make type) + (org-x int) + (org-y int) + (width int) + (height int) + (color-0 int) + ) + "Allocate and initialize a draw-context" + (local-vars (v0-0 draw-context) (v1-3 int) (a0-2 int)) + (set! v0-0 + (object-new allocation type-to-make (the-as int (-> type-to-make size))) + ) + (set! v1-3 + (the int (* (the float org-y) (-> *video-parms* relative-y-scale))) + ) + (set! a0-2 + (the int (* (the float height) (-> *video-parms* relative-y-scale))) + ) + (set! (-> v0-0 orgx) org-x) + (set! (-> v0-0 orgy) v1-3) + (set! (-> v0-0 orgz) #xffffff) + (set! (-> v0-0 width) width) + (set! (-> v0-0 height) a0-2) + (set! (-> v0-0 color 0) color-0) + v0-0 + ) + +(defun draw-context-set-xy ((arg0 draw-context) (x int) (y int)) + "Set the origin of the draw context, scaling by relative-y-scale as needed." + (local-vars (v0-0 int)) + (set! v0-0 (the int (* (the float y) (-> *video-parms* relative-y-scale)))) + (set! (-> arg0 orgx) x) + (set! (-> arg0 orgy) v0-0) + (none) + ) diff --git a/goal_src/engine/load/file-io.gc b/goal_src/engine/load/file-io.gc index 2c6f9d51ec..3c51f69ca5 100644 --- a/goal_src/engine/load/file-io.gc +++ b/goal_src/engine/load/file-io.gc @@ -19,8 +19,8 @@ (file uint32 :offset-assert 16) ) (:methods - (new ((allocation symbol) (type-to-make type) (name string) (mode basic)) _type_) - ) + (new ((allocation symbol) (type-to-make type) (name string) (mode basic)) _type_) + ) :method-count-assert 9 :size-assert #x14 :flag-assert #x900000014 @@ -28,26 +28,26 @@ (defmethod new file-stream ((allocation symbol) (type-to-make type) (name string) (mode basic)) - "Allocate a file-stream and open it." - (let ((stream (object-new allocation type-to-make))) - (file-stream-open stream name mode) - stream - ) - ) + "Allocate a file-stream and open it." + (let ((stream (object-new allocation type-to-make))) + (file-stream-open stream name mode) + stream + ) + ) ;; we already have a length method for a file-stream defined in C. ;; just store that in the method table. (set! (-> file-stream method-table 4) file-stream-length) (defun file-stream-read-string ((stream file-stream) (str string)) - "Fill a string with data from a file stream. + "Fill a string with data from a file stream. Note: this function does not work." - ;; makes the length of the string 0. - (clear str) - ;; so this will read nothing. - (file-stream-read stream (-> str data) (length str)) - str - ) + ;; makes the length of the string 0. + (clear str) + ;; so this will read nothing. + (file-stream-read stream (-> str data) (length str)) + str + ) ;; A common file header found in GOAL files. @@ -66,63 +66,77 @@ ) (defmethod print file-info ((obj file-info)) - "Print information about a file" - (format #t "#<~A ~A :version ~D.~D @ #x~X>" - (-> obj type) (-> obj file-name) (-> obj major-version) (-> obj minor-version) obj) - obj - ) + "Print information about a file" + (format #t "#<~A ~A :version ~D.~D @ #x~X>" + (-> obj type) (-> obj file-name) (-> obj major-version) (-> obj minor-version) obj) + obj + ) ;; allocate a temporary string (define *file-temp-string* (new 'global 'string 128 (the string #f))) +(defconstant LEVEL_BT_FILE 0) ;; aka bsp-header +(defconstant LEVEL_BT_FILE_VERSION 30) +(defconstant ART_GROUP_FILE 1) +(defconstant ART_GROUP_FILE_VERSION 6) +(defconstant TPAGE_FILE 2) +(defconstant TPAGE_FILE_VERSION 7) ;; also used for dir +(defconstant DIR_TPAGE_FILE 3) +(defconstant LEVEL_VS_FILE 4) +(defconstant LEVEL_VS_FILE_VERSION 30) +(defconstant TX_FILE 5) +(defconstant TX_FILE_VERSION 1) +(defconstant VIS_FILE 6) + + (defun make-file-name ((kind int) (name string) (art-group-version int)) - "Make a file name. Similar to MakeFileName in C. + "Make a file name. Similar to MakeFileName in C. Note: file type enum is different between C and GOAL. File versions should match those in versions.h. Uses a single *file-temp-string* buffer, shared with make-vfile-name." - (clear *file-temp-string*) - (cond - ((= kind 3) - (format *file-temp-string* "texture-page~D/dir-tpages" 7)) - ((= kind 2) - (format *file-temp-string* "texture-page~D/tpage-~S" 7 name)) - ((zero? kind) - (format *file-temp-string* "level~D/~S-bt" 30 name)) - ((= kind 5) - (format *file-temp-string* "res~D/~S-tx" 1 name)) - ((= kind 4) - (format *file-temp-string* "level~D/~S-vs" 30 name)) - ((= kind 6) - (format *file-temp-string* "~S.VIS" name)) - ((= kind 1) - (format *file-temp-string* "art-group~D/~S-ag" - (if (> art-group-version 0) art-group-version 6) - name - ) - ) - ) - *file-temp-string* - ) + (clear *file-temp-string*) + (cond + ((= kind DIR_TPAGE_FILE) + (format *file-temp-string* "texture-page~D/dir-tpages" TPAGE_FILE_VERSION)) + ((= kind TPAGE_FILE) + (format *file-temp-string* "texture-page~D/tpage-~S" TPAGE_FILE_VERSION name)) + ((= kind LEVEL_BT_FILE) + (format *file-temp-string* "level~D/~S-bt" LEVEL_BT_FILE_VERSION name)) + ((= kind TX_FILE) + (format *file-temp-string* "res~D/~S-tx" TX_FILE_VERSION name)) + ((= kind LEVEL_VS_FILE) + (format *file-temp-string* "level~D/~S-vs" LEVEL_VS_FILE_VERSION name)) + ((= kind VIS_FILE) + (format *file-temp-string* "~S.VIS" name)) + ((= kind ART_GROUP_FILE) + (format *file-temp-string* "art-group~D/~S-ag" + (if (> art-group-version 0) art-group-version ART_GROUP_FILE_VERSION) + name + ) + ) + ) + *file-temp-string* + ) (defun make-vfile-name ((a0-0 int) (a1-0 string)) "Make another type of file name." - (local-vars - (s5-0 int) - (gp-0 string) - ) - (set! s5-0 a0-0) - (set! gp-0 a1-0) - (clear *file-temp-string*) - (cond - ((zero? s5-0) (format *file-temp-string* "$LEVEL/~S" gp-0)) - ((= s5-0 1) (format *file-temp-string* "$ART_GROUP/~S" gp-0)) - ) - *file-temp-string* - ) + (local-vars + (s5-0 int) + (gp-0 string) + ) + (set! s5-0 a0-0) + (set! gp-0 a1-0) + (clear *file-temp-string*) + (cond + ((zero? s5-0) (format *file-temp-string* "$LEVEL/~S" gp-0)) + ((= s5-0 1) (format *file-temp-string* "$ART_GROUP/~S" gp-0)) + ) + *file-temp-string* + ) (defun file-info-correct-version? ((info file-info) (kind int) (version int)) "Check if the file info is valid. If you call this with version = 0, @@ -134,35 +148,35 @@ (expected-version int) ) - ;; figure out the expected major version - (set! expected-version - (cond - ((zero? version) ;; version not specified. - (set! v1-0 kind) - (cond - ((or (zero? (+ v1-0 -2)) (zero? (+ v1-0 -3))) 7) ;; textures. - ((zero? v1-0) 30) ;; level - ((= v1-0 1) 6) ;; art-group - ) - ) - (else version) ;; version was specified - ) - ) - - ;; figure out the expected kind - (set! expected-kind - (begin - (set! v1-1 kind) - (cond ((= v1-1 2) "texture-page") - ((zero? v1-1) "bsp-header") - ((= v1-1 1) "art-group")) - ) - ) - - ;; check: - (cond - ;; first, check the name is right: - ;; not clear why we dereference the symbol like this. + ;; figure out the expected major version + (set! expected-version + (cond + ((zero? version) ;; version not specified. + (set! v1-0 kind) + (cond + ((or (= v1-0 TPAGE_FILE) (= v1-0 DIR_TPAGE_FILE)) TPAGE_FILE_VERSION) ;; textures. + ((= v1-0 LEVEL_BT_FILE) LEVEL_BT_FILE_VERSION) ;; level + ((= v1-0 ART_GROUP_FILE) ART_GROUP_FILE_VERSION) ;; art-group + ) + ) + (else version) ;; version was specified + ) + ) + + ;; figure out the expected kind + (set! expected-kind + (begin + (set! v1-1 kind) + (cond ((= v1-1 TPAGE_FILE) "texture-page") + ((= v1-1 LEVEL_BT_FILE) "bsp-header") + ((= v1-1 ART_GROUP_FILE) "art-group")) + ) + ) + + ;; check: + (cond + ;; first, check the name is right: + ;; not clear why we dereference the symbol like this. ((not (name= (the-as basic (-> info file-type value)) expected-kind)) (format 0 "ERROR: file ~A is of type ~S but needs to be ~S.~%" @@ -173,18 +187,16 @@ ;; check versions (only major) ((!= expected-version (-> info major-version)) - (format - 0 - "ERROR: file ~A is version ~D.~D, but needs to be ~D.x~%" - (-> info file-name) - (-> info major-version) - (-> info minor-version) - expected-version - ) + (format 0 "ERROR: file ~A is version ~D.~D, but needs to be ~D.x~%" + (-> info file-name) + (-> info major-version) + (-> info minor-version) + expected-version + ) '#f ) ;; both tests pass! (else '#t) ) - ) + ) diff --git a/goal_src/engine/load/loader-h.gc b/goal_src/engine/load/loader-h.gc index f70e8ebaa5..30f69ce00c 100644 --- a/goal_src/engine/load/loader-h.gc +++ b/goal_src/engine/load/loader-h.gc @@ -5,3 +5,184 @@ ;; name in dgo: loader-h ;; dgos: GAME, ENGINE +(define-extern art-group type) + +;; This type didn't have an inspect method, so these field names are made up. +(deftype load-dir (basic) + ((unknown basic) + (string-array (array string)) + (data-array (array basic)) + ) + :flag-assert #xb00000010 + (:methods + (new (symbol type int basic) _type_ 0) + (dummy-9 () none 9) + (dummy-10 () none 10) + ) + ) + +(deftype load-dir-art-group (load-dir) + () + (:methods + (new (symbol type int basic) _type_ 0) + ) + :flag-assert #xb00000010 + ) + + +(defmethod new load-dir ((allocation symbol) (type-to-make type) (length int) (arg1 basic)) + (local-vars (obj load-dir)) + (set! obj (object-new allocation type-to-make (the-as int (-> type-to-make size))) ) + (set! (-> obj unknown) arg1) + (set! (-> obj string-array) + (the (array string) ((method-of-type array new) allocation array string length)) + ) + (set! (-> obj string-array length) 0) + (set! (-> obj data-array) + (the (array basic) ((method-of-type array new) allocation array basic length)) + ) + (set! (-> obj data-array length) 0) + obj + ) + +(defmethod new load-dir-art-group ((allocation symbol) (type-to-make type) (arg0 int) (arg1 basic)) + (local-vars (v0-0 load-dir)) + ;; call parent constructor... + (set! v0-0 ((method-of-type load-dir new) allocation type-to-make arg0 arg1)) + ;; change our content type to art-group + (set! (-> v0-0 data-array content-type) art-group) + ;; cast us to a load-dir-art-group. + (the-as load-dir-art-group v0-0) + ) + +(deftype external-art-buffer (basic) + ((index int32 :offset-assert 4) + (other external-art-buffer :offset-assert 8) + (status basic :offset-assert 12) + (locked? basic :offset-assert 16) + (frame-lock basic :offset-assert 20) + (heap kheap :inline :offset-assert 32) + (pending-load-file basic :offset-assert 48) + (pending-load-file-part int32 :offset-assert 52) + (pending-load-file-owner uint64 :offset-assert 56) + (pending-load-file-priority float :offset-assert 64) + (load-file basic :offset-assert 68) + (load-file-part int32 :offset-assert 72) + (load-file-owner uint64 :offset-assert 80) + (load-file-priority float :offset-assert 88) + (buf uint32 :offset-assert 92) + (len int32 :offset-assert 96) + (art-group basic :offset-assert 100) + ) + :method-count-assert 16 + :size-assert #x68 + :flag-assert #x1000000068 + (:methods + (new (symbol type int) _type_ 0) + (dummy-9 () none 9) + (dummy-10 () none 10) + (dummy-11 () none 11) + (dummy-12 () none 12) + (dummy-13 () none 13) + (dummy-14 () none 14) + (dummy-15 () none 15) + ) + ) + +(defmethod new external-art-buffer ((allocation symbol) (type-to-make type) (arg0 int)) + (local-vars (v0-0 external-art-buffer)) + (set! v0-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))) + (set! (-> v0-0 index) arg0) + (set! (-> v0-0 load-file) #f) + (set! (-> v0-0 load-file-part) -1) + (set! (-> v0-0 load-file-owner) (the uint64 #f)) + (set! (-> v0-0 load-file-priority) 100000000.0) + (set! (-> v0-0 pending-load-file) #f) + (set! (-> v0-0 pending-load-file-part) -1) + (set! (-> v0-0 pending-load-file-owner) (the uint64 #f)) + (set! (-> v0-0 pending-load-file-priority) 100000000.0) + (set! (-> v0-0 art-group) #f) + (set! (-> v0-0 status) 'initialize) + (set! (-> v0-0 locked?) #f) + (set! (-> v0-0 other) #f) + v0-0 + ) + +(deftype spool-anim (basic) + ((name basic :offset 16) ;; why? + (index int32 :offset-assert 20) + (parts int32 :offset-assert 24) + (priority float :offset-assert 28) + (owner uint64 :offset-assert 32) + (command-list basic :offset-assert 40) + ) + :pack-me + :method-count-assert 9 + :size-assert #x2c + :flag-assert #x90000002c + ) + +(deftype external-art-control (basic) + ((buffer external-art-buffer 2 :offset-assert 4) + (rec spool-anim 3 :inline) + (spool-lock uint64 :offset-assert 160) + (reserve-buffer basic :offset-assert 168) + (reserve-buffer-count int32 :offset-assert 172) + (active-stream basic :offset-assert 176) + (preload-stream spool-anim :inline :offset-assert 184) + (last-preload-stream spool-anim :inline :offset-assert 232) + (end-pad uint32) + ) + :method-count-assert 17 + :size-assert #x118 + :flag-assert #x1100000118 + (:methods + (new (symbol type) _type_ 0) + (dummy-9 () none 9) + (dummy-10 () none 10) + (dummy-11 () none 11) + (dummy-12 () none 12) + (dummy-13 () none 13) + (dummy-14 () none 14) + (dummy-15 () none 15) + (dummy-16 () none 16) + ) + ) + +(defmethod new external-art-control ((allocation symbol) (type-to-make type)) + (local-vars (v1-9 int) (s4-0 int) (obj external-art-control)) + (set! obj + (object-new allocation type-to-make (the-as int (-> type-to-make size))) + ) + (set! s4-0 0) + (while (< s4-0 2) + ;; construct buffers. + (set! (-> obj buffer s4-0) + ((method-of-type external-art-buffer new) allocation external-art-buffer s4-0 ) + ) + (+! s4-0 1) + ) + ;; point buffers to each other + (set! (-> obj buffer 0 other) (-> obj buffer 1)) + (set! (-> obj buffer 1 other) (-> obj buffer 0)) + (set! v1-9 0) + ;; setup recs + (while (< v1-9 3) + (set! (-> obj rec v1-9 name) #f) + (set! (-> obj rec v1-9 priority) 100000000.000000) + (set! (-> obj rec v1-9 owner) (the uint64 #f)) + (+! v1-9 1) + ) + ;; setup + (set! (-> obj spool-lock) (the uint64 #f)) + (set! (-> obj reserve-buffer) #f) + (set! (-> obj active-stream) #f) + ;; setup streams + (set! (-> obj preload-stream name) #f) + (set! (-> obj preload-stream priority) 100000000.000000) + (set! (-> obj preload-stream owner) (the uint64 #f)) + (set! (-> obj last-preload-stream name) #f) + (set! (-> obj last-preload-stream priority) 100000000.000000) + (set! (-> obj last-preload-stream owner) (the uint64 #f)) + obj + ) diff --git a/goal_src/engine/ps2/pad.gc b/goal_src/engine/ps2/pad.gc index 1c7b425987..c31a3bbd1a 100644 --- a/goal_src/engine/ps2/pad.gc +++ b/goal_src/engine/ps2/pad.gc @@ -5,3 +5,315 @@ ;; name in dgo: pad ;; dgos: GAME, ENGINE +;; these forward declarations should probably go somewhere else... +(define-extern get-current-time (function uint)) +(define-extern get-integral-current-time (function uint)) + +;; this gets set to #f later on. +(define *cheat-mode* #t) + +(deftype hw-cpad (basic) + ((valid uint8 :offset-assert 4) + (status uint8 :offset-assert 5) + (button0 uint16 :offset-assert 6) + (rightx uint8 :offset-assert 8) + (righty uint8 :offset-assert 9) + (leftx uint8 :offset-assert 10) + (lefty uint8 :offset-assert 11) + (abutton uint8 12 :offset-assert 12) + (dummy uint8 12 :offset-assert 24) + ) + :method-count-assert 9 + :size-assert #x24 + :flag-assert #x900000024 + ) + +(deftype cpad-info (hw-cpad) + ((number int32 :offset-assert 36) + (cpad-file int32 :offset-assert 40) + (button0-abs uint32 3 :offset-assert 44) ;; bitmask of buttons, pressed or not, with history + (button0-shadow-abs uint32 1 :offset-assert 56) ;; modify this to change button history in the future. + (button0-rel uint32 3 :offset-assert 60) ;; bitmask of if button going down. + (stick0-dir float :offset-assert 72) + (stick0-speed float :offset-assert 76) + (new-pad int32 :offset-assert 80) + (state int32 :offset-assert 84) + (align uint8 6 :offset-assert 88) + (direct uint8 6 :offset-assert 94) ;; hardware control of buzzing. + (buzz-val uint8 2 :offset-assert 100) ;; intensity for buzzing + (buzz-time uint64 2 :offset-assert 104) ;; when to stop buzzing + (buzz basic :offset-assert 120) ;; is vibration enabled? + (buzz-act int32 :offset-assert 124) + (change-time uint64 :offset-assert 128) + ) + (:methods + (new (symbol type int) _type_ 0) + ) + :method-count-assert 9 + :size-assert #x88 + :flag-assert #x900000088 + ) + +(deftype cpad-list (basic) + ((num-cpads int32 :offset-assert 4) + (cpads cpad-info 2 :offset-assert 8) ;; guess + ) + (:methods + (new (symbol type) _type_ 0) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +(defun cpad-invalid! ((pad cpad-info)) + "Make everything in a cpad-info set to default" + (local-vars (v1-2 int) (v1-14 int) (v1-17 int)) + (set! (-> pad valid) (logior (-> pad valid) 128)) + (set! (-> pad button0) 0) + (set! (-> pad button0-abs 0) 0) + (set! (-> pad button0-shadow-abs 0) 0) + (set! (-> pad button0-rel 0) 0) + (set! v1-2 0) + (while (< v1-2 12) + (nop!) + (set! (-> pad abutton v1-2) 0) + (+! v1-2 1) + ) + (set! (-> pad stick0-dir) 0.000000) + (set! (-> pad stick0-speed) 0.000000) + (set! (-> pad rightx) 128) + (set! (-> pad righty) 128) + (set! (-> pad leftx) 128) + (set! (-> pad lefty) 128) + (set! (-> pad align 0) 0) + (set! (-> pad align 1) 1) + (set! (-> pad align 2) 255) + (set! (-> pad align 3) 255) + (set! (-> pad align 4) 255) + (set! (-> pad align 5) 255) + (set! v1-14 0) + (while (< v1-14 6) + (set! (-> pad direct v1-14) 0) + (+! v1-14 1) + ) + (set! v1-17 0) + (while (< v1-17 2) + (set! (-> pad buzz-val 0) 0) + (set! (-> pad buzz-time 0) 0) + (+! v1-17 1) + ) + pad + ) + +(defmethod new cpad-info ((alloction symbol) (type-to-make type) (idx int)) + "Allocate a cpad. Also opens it using functions from the kernel." + (local-vars (obj cpad-info)) + (set! obj (object-new alloction type-to-make (the-as int (-> type-to-make size)))) + (set! (-> obj number) idx) + (set! (-> obj buzz) #f) + (cpad-open obj idx) + (cpad-invalid! obj) + ) + +(defmethod new cpad-list ((allocation symbol) (type-to-make type)) + "Allocate a cpad-list and set up two controllers, including openeing them." + (local-vars (gp-0 cpad-list)) + (set! gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))) + (set! (-> gp-0 num-cpads) 2) + (set! (-> gp-0 cpads 0) (new 'global 'cpad-info 0)) + (set! (-> gp-0 cpads 1) (new 'global 'cpad-info 1)) + gp-0 + ) + +(defun analog-input ((in int) (offset float) (center-val float) (max-val float) (out-range float)) + "Take an integer input and convert it to a float between -out-range and +out-range. + The offset is applied directly to the input. + The center val is the expected value for 0 (after offset) + The max val is the expected value with the stick all the way pushed + " + (local-vars + (max-magnitude float) + (magnitude float) + (offset-in float) + ) + ;; do the offset + (set! offset-in (- (the float in) offset)) + ;; figure out the absolute value of the displacement from 0. + (set! magnitude (- (fabs offset-in) center-val)) + ;; the maximum allowed magnitude + (set! max-magnitude (- max-val center-val)) + ;; if we are negative, our output range should be negative. + (when (< offset-in 0.000000) + (set! out-range (- out-range)) + ) + (cond + ((>= 0.000000 magnitude) 0.000000) ;; shouldn't happen + ((>= magnitude max-magnitude) out-range) ;; too big + (else (/ (* magnitude out-range) max-magnitude)) ;; scale! + ) + ) + +(defun cpad-set-buzz! ((pad cpad-info) (buzz-idx int) (buzz-amount int) (duration int)) + "Turn on vibration motor 'buzz-idx' for duration, at magnitude buzz-amount." + (cond + ((zero? buzz-amount) + ;; set buzz-amount to 0, immediately kill it. + (set! (-> pad buzz-val buzz-idx) 0) + ) + ((= buzz-amount (-> pad buzz-val buzz-idx)) + ;; we are already buzzing at this intensity. + ;; buzz for max (old_buzz, new_buzz) duration + (set! (-> pad buzz-time buzz-idx) + (max (the-as int (-> pad buzz-time buzz-idx)) + (the-as int (+ (get-current-time) (the-as uint duration))) + ) + ) + ) + ((< (-> pad buzz-val buzz-idx) (the-as uint buzz-amount)) + ;; buzz harder than the older value, overwrite the old buzz. + (set! (-> pad buzz-val buzz-idx) buzz-amount) + (set! (-> pad buzz-time buzz-idx) + (+ (get-current-time) (the-as uint duration)) + ) + ) + ) + (none) + ) + +;; the two controllers +(define *cpad-list* (new 'global 'cpad-list)) + +;; weird leftover debug thing, enabling overrides the x position of both sticks on both controllers. +(define *cpad-debug* #f) + +(defun service-cpads () + "Call this once a frame to read the pad, handle vibration, and process the left stick" + (local-vars + (v1-10 int) + (current-button0 uint) + (buzz-idx int) + (pad cpad-info) + (pad-idx int) + (pad-list cpad-list) + (lefty-pos float) + (leftx-pos float) + ) + + ;; iterate through cpads. + (set! pad-list *cpad-list*) + (set! pad-idx 0) + (while (< pad-idx (-> pad-list num-cpads)) + (set! pad (-> *cpad-list* cpads pad-idx)) + ;; read data from pad. + (cpad-get-data pad) + (cond + ((zero? (logand (-> pad valid) 128)) + ;; pad is valid! update buzz. + (set! buzz-idx 0) + (while (< buzz-idx 2) + (cond + ;; when buzz enbaled, in buzz time, and in game mode: + ((and (-> pad buzz) + (< (the-as int (get-current-time)) + (the-as int (-> pad buzz-time buzz-idx)) + ) + (= *master-mode* 'game) + ) + ;; case statement? + (set! v1-10 buzz-idx) + (cond ((zero? v1-10) + ;; buzz 0, I think the small one, doesn't have analog control. + ;; I _think_ this is some clever way to pulse it at a duty cycle proportional + ;; to the desired intensity. + (set! (-> pad direct buzz-idx) + (logand (ash (-> pad buzz-val buzz-idx) + (- (the-as int (logand (get-integral-current-time) 7))) + ) + 1 + ) + ) + ) + ((= v1-10 1) + ;; buzz 1, the big motor can be controlled directly by the PS2. + (set! (-> pad direct buzz-idx) (-> pad buzz-val buzz-idx)) + ) + ) + ) + (else + ;; time to stop buzzing. set buzz-val and the hardware command to 0. + (set! (-> pad buzz-val buzz-idx) 0) + (set! (-> pad direct buzz-idx) 0) + ) + ) + (+! buzz-idx 1) + ) + ;; update buttons history + (set! (-> pad button0-abs 2) (-> pad button0-abs 1)) + ;; update abs history from shadow-abs + (set! (-> pad button0-abs 1) (-> pad button0-shadow-abs 0)) + ;; update rel history + (set! (-> pad button0-rel 2) (-> pad button0-rel 1)) + (set! (-> pad button0-rel 1) (-> pad button0-rel 0)) + ;; put in new buttons + (set! current-button0 (-> pad button0)) + (set! (-> pad button0-shadow-abs 0) current-button0) + (set! (-> pad button0-abs 0) current-button0) + ;; buttons going down + (set! (-> pad button0-rel 0) + (logand (-> pad button0-abs 0) (lognot (-> pad button0-abs 1))) + ) + ;; some weird leftover from debugging. + (when *cpad-debug* + (set! (-> pad leftx) 255) + (set! (-> pad rightx) 255) + ) + (set! (-> pad stick0-speed) 1.000) + (cond + ((= (shr (-> pad status) 4) 7) ;; status that we have analog? + (set! leftx-pos (* 0.0078125 (the float (+ (-> pad leftx) -128)))) + (set! lefty-pos (* 0.0078125 (the float (- 127 (-> pad lefty))))) + ;; heading of the stick. note that y -> -x, x -> y, so it's rotated... + (set! (-> pad stick0-dir) (atan (- leftx-pos) lefty-pos)) + ;; the "speed" is just the magnitude. + (set! (-> pad stick0-speed) (fmin 1.0 (sqrtf (+ (* leftx-pos leftx-pos) (* lefty-pos lefty-pos))))) + ;; deadband the speed at 0.3? this seems kinda high. + (when (< (-> pad stick0-speed) 0.3) + (set! (-> pad stick0-speed) 0.0) + ) + ) + (else + ;; invalid analog state, set things to safe defaults. + (set! (-> pad leftx) 128) + (set! (-> pad lefty) 128) + (set! (-> pad rightx) 128) + (set! (-> pad righty) 128) + (set! (-> pad stick0-dir) 0.000000) + (set! (-> pad stick0-speed) 0.0) + ) + ) + ;; did the pad change? + (if (or (!= (-> pad button0-abs 0) (-> pad button0-abs 1)) ;; button pushed + (or (< 0.3 (-> pad stick0-speed)) ;; stick away from origin + (zero? (-> pad change-time)) ;; initially zero + ) + ) + (set! (-> pad change-time) (get-current-time)) + ) + ) + (else + ;; invalid pad + (cpad-invalid! pad) + ) + ) + (+! pad-idx 1) + ) + *cpad-list* + ) + +(defun buzz-stop! ((idx int)) + "Set the buzz to 0 on both vibration motors of the given cpad." + (cpad-set-buzz! (-> *cpad-list* cpads idx) 0 0 0) + (cpad-set-buzz! (-> *cpad-list* cpads idx) 1 0 0) + (none) + ) diff --git a/goal_src/goos-lib.gs b/goal_src/goos-lib.gs index 608b033481..a3aaa8e8ca 100644 --- a/goal_src/goos-lib.gs +++ b/goal_src/goos-lib.gs @@ -137,7 +137,15 @@ ;; goal macro to define a goal macro (defgmacro defmacro (name args &rest body) - `(seval (defgmacro ,name ,args ,@body)) + (if (and + (> (length body) 1) ;; more than one thing in function + (string? (first body)) ;; first thing is a string + ) + ;; then it's a docstring and we ignore it. + `(seval (defgmacro ,name ,args ,@(cdr body))) + ;; otherwise don't ignore it. + `(seval (defgmacro ,name ,args ,@body)) + ) ) ;; goal macro to define a goos macro diff --git a/goal_src/kernel-defs.gc b/goal_src/kernel-defs.gc index 3f313e3602..e2efbc339e 100644 --- a/goal_src/kernel-defs.gc +++ b/goal_src/kernel-defs.gc @@ -123,7 +123,9 @@ ;; gs-store-image (define-extern flush-cache (function int none)) ;; cpad-open -;; cpad-get-data +(declare-type cpad-info structure) +(define-extern cpad-open (function cpad-info int cpad-info)) +(define-extern cpad-get-data (function cpad-info cpad-info)) ;; install-handler ;; install-debug-handler ;; file-stream-open diff --git a/goalc/compiler/compilation/Type.cpp b/goalc/compiler/compilation/Type.cpp index 91df769cdd..1f263f82a8 100644 --- a/goalc/compiler/compilation/Type.cpp +++ b/goalc/compiler/compilation/Type.cpp @@ -412,7 +412,11 @@ Val* Compiler::get_field_of_structure(const StructureType* type, result = fe->alloc_val(di.result_type, loc, MemLoadInfo(di)); result->mark_as_settable(); } else { - auto field_type_info = m_ts.lookup_type(field.type); + auto type_for_offset = field.type; + if (field.type.base_type() == "inline-array") { + type_for_offset = field.type.get_single_arg(); + } + auto field_type_info = m_ts.lookup_type(type_for_offset); result = fe->alloc_val( field.type, object, field.field.offset() + offset + field_type_info->get_offset()); result->mark_as_settable(); diff --git a/scripts/decomp_progress.py b/scripts/decomp_progress.py index f085180d94..45b0d431ca 100644 --- a/scripts/decomp_progress.py +++ b/scripts/decomp_progress.py @@ -6,7 +6,7 @@ import argparse ### Example usage: python3 scripts/decomp_progress.py ~/jak-project/goal_src def get_goal_files(root_dir): - """Get all GOAL source files under root_dir""" + """Get all GOAL source files under root_dir.""" return [goal_file for file in os.walk(root_dir) for goal_file in glob.glob(os.path.join(file[0], '*.gc'))] def lines_in_file(file_path): @@ -17,7 +17,7 @@ def lines_in_file(file_path): return lines -def print_table(stats): +def print_table(stats, total_gc_files): total_lines = 0 print("| {: <24} | {: <6} |".format("file name", "lines")) print("-------------------------------------") @@ -29,6 +29,7 @@ def print_table(stats): print("-------------------------------------") estimated_lines = 500000 print("Progress: {}/{} lines ({:.2f}%)".format(total_lines, estimated_lines, 100. * total_lines / estimated_lines)) + print("{}/{} files modified from template ({:.2f}%)".format(len(stats), total_gc_files, 100. * len(stats)/total_gc_files)) @@ -39,12 +40,19 @@ def main(): all_files = get_goal_files(args.goal_src) file_stats = [] - + total_gc_files = 0 excluded_files = {"all_files.gc", "goal-lib.gc"} + for fn in all_files: short_name = os.path.basename(fn) line_count = lines_in_file(fn) + + if short_name in excluded_files: + continue + + total_gc_files += 1 + if line_count == 7 or short_name in excluded_files: # the template has 7 lines, just skip it. continue @@ -52,7 +60,7 @@ def main(): file_stats.append((short_name, line_count)) file_stats.sort(key=lambda x: x[1]) - print_table(file_stats) + print_table(file_stats, total_gc_files) if __name__ == "__main__": diff --git a/test/decompiler/test_AtomicOpBuilder.cpp b/test/decompiler/test_AtomicOpBuilder.cpp index 13ac970f28..c174a35e8f 100644 --- a/test/decompiler/test_AtomicOpBuilder.cpp +++ b/test/decompiler/test_AtomicOpBuilder.cpp @@ -580,7 +580,7 @@ TEST(DecompilerAtomicOpBuilder, OR) { test_case(assembly_from_list({"or a1, a2, a3"}), {"(set! a1 (logior a2 a3))"}, {{"a1"}}, {{"a2", "a3"}}, {{}}); test_case(assembly_from_list({"or a2, r0, r0"}), {"(set! a2 0)"}, {{"a2"}}, {{}}, {{}}); - test_case(assembly_from_list({"or a1, s7, r0"}), {"(set! a1 '#f)"}, {{"a1"}}, {{}}, {{}}); + test_case(assembly_from_list({"or a1, s7, r0"}), {"(set! a1 #f)"}, {{"a1"}}, {{}}, {{}}); } TEST(DecompilerAtomicOpBuilder, ORI) { @@ -594,24 +594,24 @@ TEST(DecompilerAtomicOpBuilder, SB) { test_case(assembly_from_list({"sb a1, 2(a3)"}), {"(s.b! (+ a3 2) a1)"}, {{}}, {{"a1", "a3"}}, {{}}); test_case(assembly_from_list({"sb a1, 0(a3)"}), {"(s.b! a3 a1)"}, {{}}, {{"a1", "a3"}}, {{}}); - test_case(assembly_from_list({"sb s7, 2(a3)"}), {"(s.b! (+ a3 2) '#f)"}, {{}}, {{"a3"}}, {{}}); - test_case(assembly_from_list({"sb s7, 0(a3)"}), {"(s.b! a3 '#f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sb s7, 2(a3)"}), {"(s.b! (+ a3 2) #f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sb s7, 0(a3)"}), {"(s.b! a3 #f)"}, {{}}, {{"a3"}}, {{}}); } TEST(DecompilerAtomicOpBuilder, SD) { test_case(assembly_from_list({"sd a1, 2(a3)"}), {"(s.d! (+ a3 2) a1)"}, {{}}, {{"a1", "a3"}}, {{}}); test_case(assembly_from_list({"sd a1, 0(a3)"}), {"(s.d! a3 a1)"}, {{}}, {{"a1", "a3"}}, {{}}); - test_case(assembly_from_list({"sd s7, 2(a3)"}), {"(s.d! (+ a3 2) '#f)"}, {{}}, {{"a3"}}, {{}}); - test_case(assembly_from_list({"sd s7, 0(a3)"}), {"(s.d! a3 '#f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sd s7, 2(a3)"}), {"(s.d! (+ a3 2) #f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sd s7, 0(a3)"}), {"(s.d! a3 #f)"}, {{}}, {{"a3"}}, {{}}); } TEST(DecompilerAtomicOpBuilder, SH) { test_case(assembly_from_list({"sh a1, 2(a3)"}), {"(s.h! (+ a3 2) a1)"}, {{}}, {{"a1", "a3"}}, {{}}); test_case(assembly_from_list({"sh a1, 0(a3)"}), {"(s.h! a3 a1)"}, {{}}, {{"a1", "a3"}}, {{}}); - test_case(assembly_from_list({"sh s7, 2(a3)"}), {"(s.h! (+ a3 2) '#f)"}, {{}}, {{"a3"}}, {{}}); - test_case(assembly_from_list({"sh s7, 0(a3)"}), {"(s.h! a3 '#f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sh s7, 2(a3)"}), {"(s.h! (+ a3 2) #f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sh s7, 0(a3)"}), {"(s.h! a3 #f)"}, {{}}, {{"a3"}}, {{}}); } TEST(DecompilerAtomicOpBuilder, SLL) { @@ -756,12 +756,12 @@ TEST(DecompilerAtomicOpBuilder, SUBS) { TEST(DecompilerAtomicOpBuilder, SW) { test_case(assembly_from_list({"sw a1, test(s7)"}), {"(s.w! test a1)"}, {{}}, {{"a1"}}, {{}}); - test_case(assembly_from_list({"sw s7, test(s7)"}), {"(s.w! test '#f)"}, {{}}, {{}}, {{}}); + test_case(assembly_from_list({"sw s7, test(s7)"}), {"(s.w! test #f)"}, {{}}, {{}}, {{}}); test_case(assembly_from_list({"sw a1, 2(a3)"}), {"(s.w! (+ a3 2) a1)"}, {{}}, {{"a1", "a3"}}, {{}}); test_case(assembly_from_list({"sw a1, 0(a3)"}), {"(s.w! a3 a1)"}, {{}}, {{"a1", "a3"}}, {{}}); - test_case(assembly_from_list({"sw s7, 2(a3)"}), {"(s.w! (+ a3 2) '#f)"}, {{}}, {{"a3"}}, {{}}); - test_case(assembly_from_list({"sw s7, 0(a3)"}), {"(s.w! a3 '#f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sw s7, 2(a3)"}), {"(s.w! (+ a3 2) #f)"}, {{}}, {{"a3"}}, {{}}); + test_case(assembly_from_list({"sw s7, 0(a3)"}), {"(s.w! a3 #f)"}, {{}}, {{"a3"}}, {{}}); test_case(assembly_from_list({"sw r0, test(s7)"}), {"(s.w! test 0)"}, {{}}, {{}}, {{}}); test_case(assembly_from_list({"sw r0, 2(a3)"}), {"(s.w! (+ a3 2) 0)"}, {{}}, {{"a3"}}, {{}}); test_case(assembly_from_list({"sw r0, 0(a3)"}), {"(s.w! a3 0)"}, {{}}, {{"a3"}}, {{}}); diff --git a/test/decompiler/test_FormBeforeExpressions.cpp b/test/decompiler/test_FormBeforeExpressions.cpp index d3bf68a78b..34c466963d 100644 --- a/test/decompiler/test_FormBeforeExpressions.cpp +++ b/test/decompiler/test_FormBeforeExpressions.cpp @@ -236,7 +236,7 @@ TEST_F(FormRegressionTest, WhileLoop) { " (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)))\n" " )\n" " )\n" - " (set! v0-0 '#f)\n" + " (set! v0-0 #f)\n" " (ret-value v0-0)\n" " )"; test_no_expr(func, type, expected); @@ -302,7 +302,7 @@ TEST_F(FormRegressionTest, Or) { " (return (begin (set! v1-1 '#t) (set! v0-0 v1-1)))\n" " )\n" " )\n" - " (set! v0-0 '#f)\n" + " (set! v0-0 #f)\n" " (ret-value v0-0)\n" " )"; test_no_expr(func, type, expected); diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index 0fee218b82..708b0f7e3f 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -360,7 +360,7 @@ TEST_F(FormRegressionTest, ExprFalse) { " jr ra\n" " daddu sp, sp, r0"; std::string type = "(function symbol)"; - std::string expected = "'#f"; + std::string expected = "#f"; test_with_expr(func, type, expected); } @@ -464,7 +464,7 @@ TEST_F(FormRegressionTest, ExprBasicTypeP) { " (return '#t)\n" " )\n" " )\n" - " '#f\n" + " #f\n" " )"; test_with_expr(func, type, expected); } @@ -507,7 +507,7 @@ TEST_F(FormRegressionTest, FinalBasicTypeP) { " (begin (set! v1-0 (-> v1-0 parent)) (= v1-0 a0-1))\n" " (if (= v1-0 arg1) (return (quote #t)))\n" " )\n" - " (quote #f)\n" + " #f\n" " )"; test_final_function(func, type, expected); } @@ -561,7 +561,7 @@ TEST_F(FormRegressionTest, ExprTypeTypep) { " )\n" " (if (= arg0 arg1) (return '#t))\n" " )\n" - " '#f\n" + " #f\n" " )"; test_with_expr(func, type, expected, false, ""); } @@ -662,7 +662,7 @@ TEST_F(FormRegressionTest, ExprRef) { " (nop!)\n" " (nop!)\n" " (set! arg0 (cdr arg0))\n" - " (set! v1-0 (+ v1-0 1))\n" + " (+! v1-0 1)\n" " )\n" " (car arg0)\n" " )"; @@ -726,7 +726,7 @@ TEST_F(FormRegressionTest, ExprPairMethod4) { " (and (!= v1-1 '()) " " (< (shl (the-as int v1-1) 62) 0)\n" " )\n" - " (set! v0-0 (+ v0-0 1))\n" + " (+! v0-0 1)\n" " (set! v1-1 (cdr v1-1))\n" " )\n" " )\n" @@ -1582,7 +1582,7 @@ TEST_F(FormRegressionTest, ExprSort) { " (set! v1-1 (arg1 s2-0 s1-0))\n" " (when\n" " (and (or (not v1-1) (> (the-as int v1-1) 0)) (!= v1-1 (quote #t)))\n" - " (set! s4-0 (+ s4-0 1))\n" + " (+! s4-0 1)\n" " (set! (car s3-0) s1-0)\n" " (set! (car (cdr s3-0)) s2-0)\n" " )\n" @@ -1873,9 +1873,9 @@ TEST_F(FormRegressionTest, ExprMemCopy) { " (while\n" " (< v1-0 arg2)\n" " (set! (-> (the-as (pointer int8) arg0)) (-> (the-as (pointer uint8) arg1)))\n" - " (set! arg0 (+ arg0 (the-as uint 1)))\n" - " (set! arg1 (+ arg1 (the-as uint 1)))\n" - " (set! v1-0 (+ v1-0 1))\n" + " (&+! arg0 1)\n" + " (&+! arg1 1)\n" + " (+! v1-0 1)\n" " )\n" " v0-0\n" " )"; @@ -1914,9 +1914,9 @@ TEST_F(FormRegressionTest, ExprMemSet32) { " (while\n" " (< v1-0 arg1)\n" " (set! (-> (the-as (pointer int32) arg0)) arg2)\n" - " (set! arg0 (+ arg0 (the-as uint 4)))\n" + " (&+! arg0 4)\n" " (nop!)\n" - " (set! v1-0 (+ v1-0 1))\n" + " (+! v1-0 1)\n" " )\n" " v0-0\n" " )"; @@ -1964,9 +1964,9 @@ TEST_F(FormRegressionTest, ExprMemOr) { " (-> (the-as (pointer uint8) arg1))\n" " )\n" " )\n" - " (set! arg0 (+ arg0 (the-as uint 1)))\n" - " (set! arg1 (+ arg1 (the-as uint 1)))\n" - " (set! v1-0 (+ v1-0 1))\n" + " (&+! arg0 1)\n" + " (&+! arg1 1)\n" + " (+! v1-0 1)\n" " )\n" " v0-0\n" " )"; @@ -2181,9 +2181,9 @@ TEST_F(FormRegressionTest, ExprPrintTreeBitmask) { " (format (quote #t) \"| \")\n" " )\n" " (set! arg0 (shr arg0 1))\n" - " (set! s4-0 (+ s4-0 1))\n" + " (+! s4-0 1)\n" " )\n" - " (quote #f)\n" + " #f\n" " )"; test_with_expr(func, type, expected, false, "", {{"L323", " "}, {"L322", "| "}}); } @@ -2496,11 +2496,11 @@ TEST_F(FormRegressionTest, StringLt) { " (< v1-4 s4-1)\n" " (cond\n" " ((< (-> arg0 data v1-4) (-> arg1 data v1-4)) (return (quote #t)))\n" - " ((< (-> arg1 data v1-4) (-> arg0 data v1-4)) (return (quote #f)))\n" + " ((< (-> arg1 data v1-4) (-> arg0 data v1-4)) (return #f))\n" " )\n" - " (set! v1-4 (+ v1-4 1))\n" + " (+! v1-4 1)\n" " )\n" - " (quote #f)\n" + " #f\n" " )"; test_with_expr(func, type, expected, false, ""); } \ No newline at end of file diff --git a/test/decompiler/test_FormExpressionBuildLong.cpp b/test/decompiler/test_FormExpressionBuildLong.cpp index 444e36750d..295cf92fba 100644 --- a/test/decompiler/test_FormExpressionBuildLong.cpp +++ b/test/decompiler/test_FormExpressionBuildLong.cpp @@ -552,7 +552,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-0) \"~D\" \" ~D\")\n" " (-> (the-as (array int32) arg0) s5-0)\n" " )\n" - " (set! s5-0 (+ s5-0 1))\n" + " (+! s5-0 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint32))\n" @@ -564,7 +564,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-1) \"~D\" \" ~D\")\n" " (-> (the-as (array uint32) arg0) s5-1)\n" " )\n" - " (set! s5-1 (+ s5-1 1))\n" + " (+! s5-1 1)\n" " )\n" " )\n" " ((= v1-1 (quote int64))\n" @@ -576,7 +576,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-2) \"~D\" \" ~D\")\n" " (-> (the-as (array int64) arg0) s5-2)\n" " )\n" - " (set! s5-2 (+ s5-2 1))\n" + " (+! s5-2 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint64))\n" @@ -588,7 +588,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-3) \"#x~X\" \" #x~X\")\n" " (-> (the-as (array uint64) arg0) s5-3)\n" " )\n" - " (set! s5-3 (+ s5-3 1))\n" + " (+! s5-3 1)\n" " )\n" " )\n" " ((= v1-1 (quote int8))\n" @@ -600,7 +600,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-4) \"~D\" \" ~D\")\n" " (-> (the-as (array int8) arg0) s5-4)\n" " )\n" - " (set! s5-4 (+ s5-4 1))\n" + " (+! s5-4 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint8))\n" @@ -612,7 +612,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-5) \"~D\" \" ~D\")\n" " (-> (the-as (array uint8) arg0) s5-5)\n" " )\n" - " (set! s5-5 (+ s5-5 1))\n" + " (+! s5-5 1)\n" " )\n" " )\n" " ((= v1-1 (quote int16))\n" @@ -624,7 +624,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-6) \"~D\" \" ~D\")\n" " (-> (the-as (array int16) arg0) s5-6)\n" " )\n" - " (set! s5-6 (+ s5-6 1))\n" + " (+! s5-6 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint16))\n" @@ -636,7 +636,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-7) \"~D\" \" ~D\")\n" " (-> (the-as (array uint16) arg0) s5-7)\n" " )\n" - " (set! s5-7 (+ s5-7 1))\n" + " (+! s5-7 1)\n" " )\n" " )\n" " (else\n" @@ -654,7 +654,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " )\n" " (.lq a2-8 12 v1-42)\n" " (t9-10 a0-21 a1-11 a2-8)\n" - " (set! s5-8 (+ s5-8 1))\n" + " (+! s5-8 1)\n" " )\n" " )\n" " (else\n" @@ -666,7 +666,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (if (zero? s5-9) \"~D\" \" ~D\")\n" " (-> (the-as (array int32) arg0) s5-9)\n" " )\n" - " (set! s5-9 (+ s5-9 1))\n" + " (+! s5-9 1)\n" " )\n" " )\n" " )\n" @@ -684,7 +684,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (format (quote #t) \"~f\" (-> (the-as (array float) arg0) s5-10))\n" " (format (quote #t) \" ~f\" (-> (the-as (array float) arg0) s5-10))\n" " )\n" - " (set! s5-10 (+ s5-10 1))\n" + " (+! s5-10 1)\n" " )\n" " )\n" " (else\n" @@ -696,7 +696,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod2) { " (format (quote #t) \"~A\" (-> (the-as (array basic) arg0) s5-11))\n" " (format (quote #t) \" ~A\" (-> (the-as (array basic) arg0) s5-11))\n" " )\n" - " (set! s5-11 (+ s5-11 1))\n" + " (+! s5-11 1)\n" " )\n" " )\n" " )\n" @@ -1212,7 +1212,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-0\n" " (-> (the-as (array int32) arg0) s5-0)\n" " )\n" - " (set! s5-0 (+ s5-0 1))\n" + " (+! s5-0 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint32))\n" @@ -1225,7 +1225,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-1\n" " (-> (the-as (array uint32) arg0) s5-1)\n" " )\n" - " (set! s5-1 (+ s5-1 1))\n" + " (+! s5-1 1)\n" " )\n" " )\n" " ((= v1-1 (quote int64))\n" @@ -1238,7 +1238,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-2\n" " (-> (the-as (array int64) arg0) s5-2)\n" " )\n" - " (set! s5-2 (+ s5-2 1))\n" + " (+! s5-2 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint64))\n" @@ -1251,7 +1251,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-3\n" " (-> (the-as (array uint64) arg0) s5-3)\n" " )\n" - " (set! s5-3 (+ s5-3 1))\n" + " (+! s5-3 1)\n" " )\n" " )\n" " ((= v1-1 (quote int8))\n" @@ -1264,7 +1264,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-4\n" " (-> (the-as (array int8) arg0) s5-4)\n" " )\n" - " (set! s5-4 (+ s5-4 1))\n" + " (+! s5-4 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint8))\n" @@ -1277,7 +1277,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-5\n" " (-> (the-as (array int8) arg0) s5-5)\n" " )\n" - " (set! s5-5 (+ s5-5 1))\n" + " (+! s5-5 1)\n" " )\n" " )\n" " ((= v1-1 (quote int16))\n" @@ -1290,7 +1290,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-6\n" " (-> (the-as (array int16) arg0) s5-6)\n" " )\n" - " (set! s5-6 (+ s5-6 1))\n" + " (+! s5-6 1)\n" " )\n" " )\n" " ((= v1-1 (quote uint16))\n" @@ -1303,7 +1303,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-7\n" " (-> (the-as (array uint16) arg0) s5-7)\n" " )\n" - " (set! s5-7 (+ s5-7 1))\n" + " (+! s5-7 1)\n" " )\n" " )\n" " (else\n" @@ -1322,7 +1322,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " )\n" " (.lq a3-10 12 v1-42)\n" " (t9-14 a0-25 a1-15 a2-13 a3-10)\n" - " (set! s5-8 (+ s5-8 1))\n" + " (+! s5-8 1)\n" " )\n" " )\n" " (else\n" @@ -1330,7 +1330,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " (while\n" " (< s5-9 (-> arg0 length))\n" " (format (quote #t) \"~T [~D] ~D~%\" s5-9 (-> arg0 s5-9))\n" - " (set! s5-9 (+ s5-9 1))\n" + " (+! s5-9 1)\n" " )\n" " )\n" " )\n" @@ -1349,7 +1349,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-10\n" " (-> (the-as (array float) arg0) s5-10)\n" " )\n" - " (set! s5-10 (+ s5-10 1))\n" + " (+! s5-10 1)\n" " )\n" " )\n" " (else\n" @@ -1362,7 +1362,7 @@ TEST_F(FormRegressionTest, ExprArrayMethod3) { " s5-11\n" " (-> (the-as (array basic) arg0) s5-11)\n" " )\n" - " (set! s5-11 (+ s5-11 1))\n" + " (+! s5-11 1)\n" " )\n" " )\n" " )\n" @@ -1940,7 +1940,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg2\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((not v1-1)\n" " (if\n" @@ -1952,7 +1952,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg2\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " (else (quote #t))\n" " )\n" @@ -1973,7 +1973,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((or\n" " (not v1-1)\n" @@ -1993,7 +1993,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " (else (quote #t))\n" " )\n" @@ -2011,7 +2011,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((not v1-1)\n" " (if\n" @@ -2024,7 +2024,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " (else (quote #t))\n" " )\n" @@ -2043,7 +2043,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " )\n" " )\n" @@ -2058,7 +2058,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((not v1-1)\n" " (if\n" @@ -2071,7 +2071,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((and (= arg1 type) (!= (rtype-of arg0) type))\n" " (if\n" @@ -2086,13 +2086,13 @@ TEST_F(FormRegressionTest, ExprValid) { " (rtype-of arg0)\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " (else\n" " (cond\n" " ((and\t\n" " (!= arg1 type)\t\n" - " (not (valid? (rtype-of arg0) type (quote #f) (quote #t) 0))\t\n" + " (not (valid? (rtype-of arg0) type #f (quote #t) 0))\t\n" " )\n" " (if\n" " arg2\n" @@ -2106,7 +2106,7 @@ TEST_F(FormRegressionTest, ExprValid) { " (rtype-of arg0)\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((not (type-type? (rtype-of arg0) arg1))\n" " (if\n" @@ -2121,7 +2121,7 @@ TEST_F(FormRegressionTest, ExprValid) { " (rtype-of arg0)\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " ((= arg1 symbol)\n" " (set! v1-43 32768)\n" @@ -2139,7 +2139,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " (else (quote #t))\n" " )\n" @@ -2160,7 +2160,7 @@ TEST_F(FormRegressionTest, ExprValid) { " arg1\n" " )\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " (else (quote #t))\n" " )\n" @@ -2472,23 +2472,20 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " (a0-2 (pointer uint8))\n" " (a0-3 (pointer uint8))\n" " (a0-4 (pointer uint8))\n" - " (a0-5 symbol)\n" " (a1-8 (pointer uint8))\n" " (a1-14 uint)\n" " (a1-20 uint)\n" " (a1-23 uint)\n" - " (a1-33 symbol)\n" - " (a1-44 symbol)\n" " (a1-47 (pointer uint8))\n" " )\n" " (set! a0-1 (-> arg0 data))\n" " (set! v0-0 0)\n" - " (set! v1-0 (quote #f))\n" + " (set! v1-0 #f)\n" " (cond\n" " ((= (-> a0-1 0) 35)\n" " (set! a0-2 (&-> a0-1 1))\n" " (cond\n" - " ((or (zero? (+ (-> a0-2 0) -120)) (zero? (+ (-> a0-2 0) -88)))\n" + " ((or (= (-> a0-2 0) 120) (= (-> a0-2 0) 88))\n" " (set! a0-3 (&-> a0-2 1))\n" " (when\n" " (= (-> a0-3 1) 45)\n" @@ -2538,7 +2535,7 @@ TEST_F(FormRegressionTest, ExprStringToInt) { " (set! a0-3 (&-> a0-3 1))\n" " )\n" " )\n" - " ((or (zero? (+ (-> a0-2 0) -98)) (zero? (+ (-> a0-2 0) -66)))\n" + " ((or (= (-> a0-2 0) 98) (= (-> a0-2 0) 66))\n" " (set! a0-4 (&-> a0-2 1))\n" " (while\n" " (and (>= (-> a0-4 0) (the-as uint 48)) (>= (the-as uint 49) (-> a0-4 0)))\n" diff --git a/test/decompiler/test_gkernel_decomp.cpp b/test/decompiler/test_gkernel_decomp.cpp index dbc4b4707a..f4f6570a33 100644 --- a/test/decompiler/test_gkernel_decomp.cpp +++ b/test/decompiler/test_gkernel_decomp.cpp @@ -323,11 +323,11 @@ TEST_F(FormRegressionTest, ExprMethod0Thread) { " (set!\n" " v0-0\n" " (cond\n" - " ((-> arg2 top-thread) (+ arg5 (the-as uint -7164)))\n" + " ((-> arg2 top-thread) (&+ arg5 -7164))\n" " (else\n" " (set!\n" " v1-2\n" - " (logand -16 (the-as int (+ (-> arg2 heap-cur) (the-as uint 15))))\n" + " (logand -16 (the-as int (&+ (-> arg2 heap-cur) 15)))\n" " )\n" " (set! (-> arg2 heap-cur) (+ (+ v1-2 (the-as int (-> arg1 size))) arg4))\n" " (+ v1-2 4)\n" @@ -427,9 +427,9 @@ TEST_F(FormRegressionTest, RemoveMethod0ProcessTree) { " (set! v0-0 (object-new arg0 arg1 (the-as int (-> arg1 size))))\n" " (set! (-> v0-0 name) arg2)\n" " (set! (-> v0-0 mask) 256)\n" - " (set! (-> v0-0 parent) (quote #f))\n" - " (set! (-> v0-0 brother) (quote #f))\n" - " (set! (-> v0-0 child) (quote #f))\n" + " (set! (-> v0-0 parent) #f)\n" + " (set! (-> v0-0 brother) #f)\n" + " (set! (-> v0-0 child) #f)\n" " (set! (-> v0-0 self) v0-0)\n" " (set! (-> v0-0 ppointer) (&-> v0-0 self))\n" " v0-0\n" @@ -631,25 +631,25 @@ TEST_F(FormRegressionTest, ExprMethod0Process) { " (set! (-> (the-as process v0-0) name) arg2)\n" " (set! (-> v0-0 status) (quote dead))\n" " (set! (-> v0-0 pid) 0)\n" - " (set! (-> v0-0 pool) (quote #f))\n" + " (set! (-> v0-0 pool) #f)\n" " (set! (-> v0-0 allocated-length) arg3)\n" - " (set! (-> v0-0 top-thread) (quote #f))\n" - " (set! (-> v0-0 main-thread) (quote #f))\n" + " (set! (-> v0-0 top-thread) #f)\n" + " (set! (-> v0-0 main-thread) #f)\n" " (set! v1-5 (-> v0-0 stack))\n" " (set! (-> v0-0 heap-cur) v1-5)\n" " (set! (-> v0-0 heap-base) v1-5)\n" " (set! (-> v0-0 heap-top) (&-> v0-0 stack (-> v0-0 allocated-length)))\n" " (set! (-> v0-0 stack-frame-top) (-> v0-0 heap-top))\n" - " (set! (-> v0-0 stack-frame-top) (quote #f))\n" - " (set! (-> v0-0 state) (quote #f))\n" - " (set! (-> v0-0 next-state) (quote #f))\n" - " (set! (-> v0-0 entity) (quote #f))\n" - " (set! (-> v0-0 trans-hook) (quote #f))\n" - " (set! (-> v0-0 post-hook) (quote #f))\n" - " (set! (-> v0-0 event-hook) (quote #f))\n" - " (set! (-> v0-0 parent) (quote #f))\n" - " (set! (-> v0-0 brother) (quote #f))\n" - " (set! (-> v0-0 child) (quote #f))\n" + " (set! (-> v0-0 stack-frame-top) #f)\n" + " (set! (-> v0-0 state) #f)\n" + " (set! (-> v0-0 next-state) #f)\n" + " (set! (-> v0-0 entity) #f)\n" + " (set! (-> v0-0 trans-hook) #f)\n" + " (set! (-> v0-0 post-hook) #f)\n" + " (set! (-> v0-0 event-hook) #f)\n" + " (set! (-> v0-0 parent) #f)\n" + " (set! (-> v0-0 brother) #f)\n" + " (set! (-> v0-0 child) #f)\n" " (set! (-> v0-0 self) v0-0)\n" " (set! (-> v0-0 ppointer) (&-> v0-0 self))\n" " v0-0\n" @@ -711,16 +711,13 @@ TEST_F(FormRegressionTest, ExprInspectProcessHeap) { std::string type = "(function process symbol)"; std::string expected = "(begin\n" - " (set! s5-0 (+ (-> arg0 heap-base) (the-as uint 4)))\n" + " (set! s5-0 (&+ (-> arg0 heap-base) 4))\n" " (while\n" " (< (the-as int s5-0) (the-as int (-> arg0 heap-cur)))\n" " (inspect (the-as basic s5-0))\n" - " (set!\n" - " (the-as int s5-0)\n" - " (+ (the-as int s5-0) (logand -16 (+ (asize-of s5-0) 15)))\n" - " )\n" + " (+! (the-as int s5-0) (logand -16 (+ (asize-of s5-0) 15)))\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" ""; test_with_expr(func, type, expected, false, "", {}, @@ -921,9 +918,9 @@ TEST_F(FormRegressionTest, ExprMethod0DeadPool) { " (set! s3-0 (object-new arg0 arg1 (the-as int (-> arg1 size))))\n" " (set! (-> s3-0 name) arg4)\n" " (set! (-> s3-0 mask) 256)\n" - " (set! (-> s3-0 parent) (quote #f))\n" - " (set! (-> s3-0 brother) (quote #f))\n" - " (set! (-> s3-0 child) (quote #f))\n" + " (set! (-> s3-0 parent) #f)\n" + " (set! (-> s3-0 brother) #f)\n" + " (set! (-> s3-0 child) #f)\n" " (set! (-> s3-0 self) s3-0)\n" " (set! (-> s3-0 ppointer) (&-> s3-0 self))\n" " (set! s2-1 0)\n" @@ -937,7 +934,7 @@ TEST_F(FormRegressionTest, ExprMethod0DeadPool) { " (set! (-> v1-5 parent) (if a0-4 (-> a0-4 ppointer)))\n" " (set! (-> v1-5 pool) s3-0)\n" " (set! (-> v1-5 brother) s1-0)\n" - " (set! s2-1 (+ s2-1 1))\n" + " (+! s2-1 1)\n" " )\n" " s3-0\n" " )"; @@ -1082,7 +1079,7 @@ TEST_F(FormRegressionTest, ExprMethod14DeadPool) { " (if s4-0 (-> s4-0 0 self))\n" " (-> arg0 name)\n" " )\n" - " (quote #f)\n" + " #f\n" " )\n" " )\n" " )\n" @@ -1235,36 +1232,36 @@ TEST_F(FormRegressionTest, ExprMethod0DeadPoolHeap) { " (set! (-> v0-0 name) arg2)\n" " (set! (-> v0-0 mask) 256)\n" " (set! (-> v0-0 allocated-length) arg3)\n" - " (set! (-> v0-0 parent) (quote #f))\n" - " (set! (-> v0-0 brother) (quote #f))\n" - " (set! (-> v0-0 child) (quote #f))\n" + " (set! (-> v0-0 parent) #f)\n" + " (set! (-> v0-0 brother) #f)\n" + " (set! (-> v0-0 child) #f)\n" " (set! (-> v0-0 self) v0-0)\n" " (set! (-> v0-0 ppointer) (&-> v0-0 self))\n" " (set! v1-4 arg3)\n" " (while\n" " (nonzero? v1-4)\n" - " (set! v1-4 (+ v1-4 -1))\n" + " (+! v1-4 -1)\n" " (set! a0-4 (-> v0-0 process-list v1-4))\n" " (set! (-> a0-4 process) *null-process*)\n" " (set! (-> a0-4 next) (-> v0-0 process-list (+ v1-4 1)))\n" " )\n" " (set! (-> v0-0 dead-list next) (-> v0-0 process-list))\n" - " (set! (-> v0-0 alive-list process) (quote #f))\n" - " (set! (-> v0-0 process-list (+ arg3 -1) next) (quote #f))\n" + " (set! (-> v0-0 alive-list process) #f)\n" + " (set! (-> v0-0 process-list (+ arg3 -1) next) #f)\n" " (set! (-> v0-0 alive-list prev) (-> v0-0 alive-list))\n" - " (set! (-> v0-0 alive-list next) (quote #f))\n" - " (set! (-> v0-0 alive-list process) (quote #f))\n" + " (set! (-> v0-0 alive-list next) #f)\n" + " (set! (-> v0-0 alive-list process) #f)\n" " (set! (-> v0-0 first-gap) (-> v0-0 alive-list))\n" - " (set! (-> v0-0 first-shrink) (quote #f))\n" + " (set! (-> v0-0 first-shrink) #f)\n" " (set!\n" " (-> v0-0 heap base)\n" " (logand\n" " -16\n" - " (the-as int (+ (+ (the-as int v0-0) 115) (the-as uint (* 12 arg3))))\n" + " (the-as int (&+ (+ (the-as int v0-0) 115) (* 12 arg3)))\n" " )\n" " )\n" " (set! (-> v0-0 heap current) (-> v0-0 heap base))\n" - " (set! (-> v0-0 heap top) (+ (-> v0-0 heap base) (the-as uint arg4)))\n" + " (set! (-> v0-0 heap top) (&+ (-> v0-0 heap base) arg4))\n" " (set! (-> v0-0 heap top-base) (-> v0-0 heap top))\n" " v0-0\n" " )"; @@ -1371,15 +1368,15 @@ TEST_F(FormRegressionTest, ExprMethod21DeadPoolHeap) { " ((-> arg1 process)\n" " (set!\n" " v1-3\n" - " (+\n" - " (+ (-> arg1 process) (the-as uint (-> process size)))\n" - " (the-as uint (-> arg1 process allocated-length))\n" + " (&+\n" + " (&+ (-> arg1 process) (-> process size))\n" + " (-> arg1 process allocated-length)\n" " )\n" " )\n" " (if\n" " (-> arg1 next)\n" " (- (-> arg1 next process) (the-as uint v1-3))\n" - " (- (-> arg0 heap top) (the-as uint (+ v1-3 (the-as uint 4))))\n" + " (- (-> arg0 heap top) (the-as uint (&+ v1-3 4)))\n" " )\n" " )\n" " (else\n" @@ -1387,7 +1384,7 @@ TEST_F(FormRegressionTest, ExprMethod21DeadPoolHeap) { " (-> arg1 next)\n" " (-\n" " (-> arg1 next process)\n" - " (the-as uint (+ (-> arg0 heap base) (the-as uint 4)))\n" + " (the-as uint (&+ (-> arg0 heap base) 4))\n" " )\n" " (- (-> arg0 heap top) (the-as uint (-> arg0 heap base)))\n" " )\n" @@ -1564,7 +1561,7 @@ TEST_F(FormRegressionTest, ExprMethod3DeadPoolHeap) { " )\n" " )\n" " (set! s5-1 (-> s5-1 next))\n" - " (set! s4-0 (+ s4-0 1))\n" + " (+! s4-0 1)\n" " )\n" " arg0\n" " )"; @@ -1971,7 +1968,7 @@ TEST_F(FormRegressionTest, ExprMethod14DeadPoolHeap) { std::string expected = "(begin\n" " (set! s4-0 (-> arg0 dead-list next))\n" - " (set! s3-0 (quote #f))\n" + " (set! s3-0 #f)\n" " (set! s1-0 (find-gap-by-size arg0 (+ (-> process size) (the-as uint arg2))))\n" " (cond\n" " ((and s4-0 s1-0)\n" @@ -2182,7 +2179,7 @@ TEST_F(FormRegressionTest, ExprMethod15DeadPoolHeap) { " )\n" " )\n" " (change-parent arg1 arg0)\n" - " (set! (-> arg0 child) (quote #f))\n" + " (set! (-> arg0 child) #f)\n" " (set! s5-1 (-> arg1 ppointer))\n" " (if\n" " (or\n" @@ -2199,7 +2196,7 @@ TEST_F(FormRegressionTest, ExprMethod15DeadPoolHeap) { " (set! (-> arg0 first-shrink) (-> s5-1 1))\n" " (when\n" " (not (-> arg0 first-shrink process))\n" - " (set! (-> arg0 first-shrink) (quote #f))\n" + " (set! (-> arg0 first-shrink) #f)\n" " )\n" " )\n" " (set! (-> s5-1 1 parent) (-> s5-1 2))\n" @@ -2549,7 +2546,7 @@ TEST_F(FormRegressionTest, ExprMethod16DeadPoolHeap) { " (set! (-> arg0 compact-count) 0)\n" " (while\n" " (nonzero? arg1)\n" - " (set! arg1 (+ arg1 -1))\n" + " (+! arg1 -1)\n" " (set! v1-13 (-> arg0 first-shrink))\n" " (when\n" " (not v1-13)\n" @@ -2725,7 +2722,7 @@ TEST_F(FormRegressionTest, ExprMethod18DeadPoolHeap) { "(begin\n" " (while\n" " (nonzero? arg1)\n" - " (set! arg1 (+ arg1 -1))\n" + " (+! arg1 -1)\n" " (set! s4-0 (-> arg0 alive-list next))\n" " (when\n" " s4-0\n" @@ -2744,7 +2741,7 @@ TEST_F(FormRegressionTest, ExprMethod18DeadPoolHeap) { " (set! (-> arg0 first-shrink) (-> s4-0 prev))\n" " (when\n" " (not (-> arg0 first-shrink process))\n" - " (set! (-> arg0 first-shrink) (quote #f))\n" + " (set! (-> arg0 first-shrink) #f)\n" " )\n" " )\n" " (set! (-> s4-0 prev next) (-> s4-0 next))\n" diff --git a/test/goalc/source_templates/with_game/inlined-packed-basics.gc b/test/goalc/source_templates/with_game/inlined-packed-basics.gc new file mode 100644 index 0000000000..2e73c71a99 --- /dev/null +++ b/test/goalc/source_templates/with_game/inlined-packed-basics.gc @@ -0,0 +1,63 @@ +(deftype spool-anim-test (basic) + ((name basic :offset 16) ;; why? + (index int32 :offset-assert 20) + (parts int32 :offset-assert 24) + (priority float :offset-assert 28) + (owner uint64 :offset-assert 32) + (command-list basic :offset-assert 40) + ) + :pack-me + :method-count-assert 9 + :size-assert #x2c + :flag-assert #x90000002c + ) + +(deftype external-art-control-test (basic) + ((buffer basic 2 :offset-assert 4) + (rec spool-anim-test 3 :inline) + (spool-lock uint64 :offset-assert 160) + (reserve-buffer basic :offset-assert 168) + (reserve-buffer-count int32 :offset-assert 172) + (active-stream basic :offset-assert 176) + (preload-stream spool-anim-test :inline :offset-assert 184) + (last-preload-stream spool-anim-test :inline :offset-assert 232) + (end-pad uint32) + ) + :method-count-assert 17 + :size-assert #x118 + :flag-assert #x1100000118 + (:methods + (dummy-9 () none 9) + (dummy-10 () none 10) + (dummy-11 () none 11) + (dummy-12 () none 12) + (dummy-13 () none 13) + (dummy-14 () none 14) + (dummy-15 () none 15) + (dummy-16 () none 16) + ) + ) + +(deftype simple (basic) + ((data float)) + ) + +;; 0 <- type pointer. +;; 4 <- buffer 0 +;; 8 <- buffer 1 +;; 12 <- EMPTY +;; 16 <- rec's type pointer + +(define format _format) +(let ((test (new 'global 'external-art-control-test))) + (format #t "rec stride: ~D~%" (&- (-> test rec 1) (-> test rec 0))) ;; should be 48 + (format #t "offset of float: ~D~%" (&- (&-> test rec 0 priority) test)) ;; should be 40 + (format #t "offset: ~D~%" (&- (-> test rec 0) test)) ;; should be 16 + (format #t "offset2: ~D~%" (&- (-> test preload-stream) test)) ;; should be 184 + ) + +(let ((sb (new 'global 'inline-array 'simple 3))) + (format #t "array: #x~X~%" (logand 15 (the int sb))) + (format #t "first: #x~X~%" (logand 15 (the int (-> sb 0)))) + ) +0 \ No newline at end of file diff --git a/test/goalc/test_with_game.cpp b/test/goalc/test_with_game.cpp index 5d0c368e6a..f0e4d8edeb 100644 --- a/test/goalc/test_with_game.cpp +++ b/test/goalc/test_with_game.cpp @@ -420,6 +420,17 @@ TEST_F(WithGameTests, Trig) { "0\n"}); } +TEST_F(WithGameTests, InlinedPackedBasics) { + runner.run_static_test(env, testCategory, "inlined-packed-basics.gc", + {"rec stride: 48\n" + "offset of float: 40\n" + "offset: 16\n" + "offset2: 184\n" + "array: #x0\n" + "first: #x0\n" + "0\n"}); +} + // VECTOR FLOAT TESTS // ---- One off Tests