diff --git a/common/goos/PrettyPrinter.cpp b/common/goos/PrettyPrinter.cpp index 52ba6cc32..71ac8b01b 100644 --- a/common/goos/PrettyPrinter.cpp +++ b/common/goos/PrettyPrinter.cpp @@ -574,18 +574,19 @@ void insertSpecialBreaks(NodePool& pool, PrettyPrinterNode* node) { } if (name == "defun" || name == "defmethod" || name == "defun-debug" || name == "let" || - name == "let*") { + name == "let*" || name == "rlet") { auto* first_list = getNextListOrEmptyListOnLine(node); if (first_list) { if (first_list->tok->kind == FormToken::TokenKind::EMPTY_PAIR) { insertNewlineAfter(pool, first_list, 0); + breakList(pool, node->paren, first_list); } else { insertNewlineAfter(pool, first_list->paren, 0); breakList(pool, node->paren, first_list); } } - if ((name == "let" || name == "let*") && first_list) { + if ((name == "let" || name == "let*" || name == "rlet") && first_list) { if (first_list->tok->kind == FormToken::TokenKind::OPEN_PAREN) { // we only want to break the variable list if it has multiple. bool single_var = false; diff --git a/decompiler/Disasm/Instruction.cpp b/decompiler/Disasm/Instruction.cpp index 05ed7514a..1b43fc2d6 100644 --- a/decompiler/Disasm/Instruction.cpp +++ b/decompiler/Disasm/Instruction.cpp @@ -184,6 +184,16 @@ std::string Instruction::cop2_dest_to_char() const { return dest; } +int Instruction::cop2_dest_mask_intel() const { + int mask = 0; + for (int i = 0; i < 4; i++) { // x,y,z,w order + if (cop2_dest & (1 << (3 - i))) { // set for ps2 + mask |= (1 << i); + } + } + return mask; +} + /*! * Convert just the name of the opcode to a string, omitting src/dst, but including * suffixes (interlock, broadcasts and destination) diff --git a/decompiler/Disasm/Instruction.h b/decompiler/Disasm/Instruction.h index b38be3d7f..36edab264 100644 --- a/decompiler/Disasm/Instruction.h +++ b/decompiler/Disasm/Instruction.h @@ -102,12 +102,14 @@ class Instruction { bool operator!=(const Instruction& other) const { return !((*this) == other); } // extra fields for some COP2 instructions. + // this is stored like in the PS2 instruction, which is different from intel uint8_t cop2_dest = 0xff; // 0xff indicates "don't print dest" uint8_t cop2_bc = 0xff; // 0xff indicates "don't print bc" uint8_t il = 0xff; // 0xff indicates "don't print il" char cop2_bc_to_char() const; std::string cop2_dest_to_char() const; + int cop2_dest_mask_intel() const; }; } // namespace decompiler #endif // NEXT_INSTRUCTION_H diff --git a/decompiler/Function/Function.h b/decompiler/Function/Function.h index 37f048538..ed29fc1d9 100644 --- a/decompiler/Function/Function.h +++ b/decompiler/Function/Function.h @@ -169,7 +169,6 @@ class Function { std::string debug_form_string; bool print_debug_forms = false; bool expressions_succeeded = false; - bool types_succeeded = false; } ir2; private: diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 0de4952b5..dc9b36b07 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -125,6 +125,11 @@ TP_Type SimpleAtom::get_type(const TypeState& input, } else if ((label.offset & 7) == PAIR_OFFSET) { return TP_Type::make_from_ts(TypeSpec("pair")); } + + auto hint_kv = env.label_types().find(label.name); + if (hint_kv != env.label_types().end()) { + return TP_Type::make_from_ts(dts.parse_type_spec(hint_kv->second.type_name)); + } // throw std::runtime_error("IR_StaticAddress couldn't figure out the type: " + label.name); lg::error("IR_StaticAddress doesn't know the type of {}", label.name); return TP_Type::make_from_ts("object"); diff --git a/decompiler/IR2/Env.cpp b/decompiler/IR2/Env.cpp index e2f0497ef..7f8415ff6 100644 --- a/decompiler/IR2/Env.cpp +++ b/decompiler/IR2/Env.cpp @@ -102,64 +102,67 @@ goos::Object Env::get_variable_name_with_cast(Register reg, int atomic_idx, Acce lookup_name = remapped->second; } - // get the type of the variable. This is the type of thing if we do no casts. - // first, get the type the decompiler found - auto type_of_var = var_info.type.typespec(); - // and the user's type. - auto retype_kv = m_var_retype.find(original_name); - if (retype_kv != m_var_retype.end()) { - type_of_var = retype_kv->second; - } + if (types_succeeded) { + // get the type of the variable. This is the type of thing if we do no casts. + // first, get the type the decompiler found + auto type_of_var = var_info.type.typespec(); + // and the user's type. + auto retype_kv = m_var_retype.find(original_name); + if (retype_kv != m_var_retype.end()) { + type_of_var = retype_kv->second; + } - // next, we insert type casts that make enforce the user override. - auto type_kv = m_typecasts.find(atomic_idx); - if (type_kv != m_typecasts.end()) { - for (auto& x : type_kv->second) { - if (x.reg == reg) { - // let's make sure the above claim is true - TypeSpec type_in_reg; - if (has_type_analysis() && mode == AccessMode::READ) { - type_in_reg = get_types_for_op_mode(atomic_idx, AccessMode::READ).get(reg).typespec(); - if (type_in_reg.print() != x.type_name) { - lg::error( - "Decompiler type consistency error. There was a typecast for reg {} at idx {} " - "(var {}) to type {}, but the actual type is {} ({})", - reg.to_charp(), atomic_idx, lookup_name, x.type_name, type_in_reg.print(), - type_in_reg.print()); - assert(false); + // next, we insert type casts that make enforce the user override. + auto type_kv = m_typecasts.find(atomic_idx); + if (type_kv != m_typecasts.end()) { + for (auto& x : type_kv->second) { + if (x.reg == reg) { + // let's make sure the above claim is true + TypeSpec type_in_reg; + if (has_type_analysis() && mode == AccessMode::READ) { + type_in_reg = get_types_for_op_mode(atomic_idx, AccessMode::READ).get(reg).typespec(); + if (type_in_reg.print() != x.type_name) { + lg::error( + "Decompiler type consistency error. There was a typecast for reg {} at idx {} " + "(var {}) to type {}, but the actual type is {} ({})", + reg.to_charp(), atomic_idx, lookup_name, x.type_name, type_in_reg.print(), + type_in_reg.print()); + assert(false); + } } - } - if (type_of_var != type_in_reg) { - // TODO - use the when possible? - return pretty_print::build_list("the-as", x.type_name, lookup_name); + if (type_of_var != type_in_reg) { + // TODO - use the when possible? + return pretty_print::build_list("the-as", x.type_name, lookup_name); + } } } } - } - // type analysis stuff runs before variable types, so we insert casts that account - // for the changing types due to the lca(uses) that is used to generate variable types. - auto type_of_reg = get_types_for_op_mode(atomic_idx, mode).get(reg).typespec(); - if (mode == AccessMode::READ) { - // note - this may be stricter than needed. but that's ok. + // type analysis stuff runs before variable types, so we insert casts that account + // for the changing types due to the lca(uses) that is used to generate variable types. + auto type_of_reg = get_types_for_op_mode(atomic_idx, mode).get(reg).typespec(); + if (mode == AccessMode::READ) { + // note - this may be stricter than needed. but that's ok. - if (type_of_var != type_of_reg) { - // fmt::print("casting {} (reg {}, idx {}): reg type {} var type {} remapped var type - // {}\n ", - // lookup_name, reg.to_charp(), atomic_idx, type_of_reg.print(), - // var_info.type.typespec().print(), type_of_var.print()); - return pretty_print::build_list("the-as", type_of_reg.print(), lookup_name); + if (type_of_var != type_of_reg) { + // fmt::print("casting {} (reg {}, idx {}): reg type {} var type {} remapped var + // type + // {}\n ", + // lookup_name, reg.to_charp(), atomic_idx, type_of_reg.print(), + // var_info.type.typespec().print(), type_of_var.print()); + return pretty_print::build_list("the-as", type_of_reg.print(), lookup_name); + } + } else { + // if we're setting a variable, we are a little less strict. + // let's leave this to set!'s for now. This is tricky with stuff like (if y x) where the + // move is eliminated so the RegisterAccess points to the "wrong" place. + // if (!dts->ts.tc(type_of_var, type_of_reg)) { + // fmt::print("op {} reg {} type {}\n", atomic_idx, reg.to_charp(), + // get_types_for_op_mode(atomic_idx, mode).get(reg).print()); return + // pretty_print::build_list("the-as", type_of_reg.print(), lookup_name); + // } } - } else { - // if we're setting a variable, we are a little less strict. - // let's leave this to set!'s for now. This is tricky with stuff like (if y x) where the move - // is eliminated so the RegisterAccess points to the "wrong" place. - // if (!dts->ts.tc(type_of_var, type_of_reg)) { - // fmt::print("op {} reg {} type {}\n", atomic_idx, reg.to_charp(), - // get_types_for_op_mode(atomic_idx, mode).get(reg).print()); return - // pretty_print::build_list("the-as", type_of_reg.print(), lookup_name); - // } } return pretty_print::to_symbol(lookup_name); diff --git a/decompiler/IR2/Env.h b/decompiler/IR2/Env.h index 456263546..7778d1ceb 100644 --- a/decompiler/IR2/Env.h +++ b/decompiler/IR2/Env.h @@ -24,6 +24,7 @@ struct FunctionAtomicOps; */ class Env { public: + bool types_succeeded = false; bool has_local_vars() const { return m_has_local_vars; } bool has_type_analysis() const { return m_has_types; } bool has_reg_use() const { return m_has_reg_use; } diff --git a/decompiler/IR2/Form.h b/decompiler/IR2/Form.h index 932aa4f09..136b70f84 100644 --- a/decompiler/IR2/Form.h +++ b/decompiler/IR2/Form.h @@ -1205,7 +1205,7 @@ class LetElement : public FormElement { RegisterAccess dest; Form* src = nullptr; }; - std::vector entries() { return m_entries; } + std::vector& entries() { return m_entries; } void add_entry(const Entry& e); bool is_star() const { return m_star; } diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index cf32f58ad..85aa2f6ef 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -141,8 +141,8 @@ void pop_helper(const std::vector& vars, // fmt::print("Unsafe to pop {}: used {} times, def {} times, expected use {}\n", // var.to_string(env), use_def.use_count(), use_def.def_count(), // times); - // if (var.to_string(env) == "v1-3") { - // for (auto& use : use_def.defs) { + // if (var.to_string(env) == "a3-0") { + // for (auto& use : use_def.uses) { // if (!use.disabled) { // fmt::print(" at instruction {}\n", use.op_id); // } @@ -1155,6 +1155,7 @@ Form* make_optional_cast(const std::optional& cast_type, Form* in, For void StorePlainDeref::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) { mark_popped(); if (m_expr.is_var()) { + // this matches the order in Compiler::compile_set auto vars = std::vector({m_expr.var(), m_base_var}); auto popped = pop_to_forms(vars, env, pool, stack, true); m_dst->set_base(make_optional_cast(m_dst_cast_type, popped.at(1), pool)); diff --git a/decompiler/IR2/OpenGoalMapping.cpp b/decompiler/IR2/OpenGoalMapping.cpp index 50f9d1793..05341b433 100644 --- a/decompiler/IR2/OpenGoalMapping.cpp +++ b/decompiler/IR2/OpenGoalMapping.cpp @@ -199,7 +199,8 @@ std::vector OpenGOALAsm::get_args(const std::vectorsrc().get_arg(0).var()); + // fix up the other ones: + f.ir2.env.disable_use(branch->op()->condition().src(0).var()); // bgezl X, L + auto dsubu_var = dynamic_cast(dsubu_set->src()->try_as_single_element()) + ->expr() + .get_arg(0) + .var(); + f.ir2.env.disable_use(dsubu_var); + + // and the def too + f.ir2.env.disable_def(dsrav_set->dst()); + return b0_c_ptr; } diff --git a/decompiler/analysis/insert_lets.cpp b/decompiler/analysis/insert_lets.cpp index 8a7c054bd..6a390f75d 100644 --- a/decompiler/analysis/insert_lets.cpp +++ b/decompiler/analysis/insert_lets.cpp @@ -199,6 +199,66 @@ FormElement* fix_up_abs(LetElement* in, const Env& env, FormPool& pool) { src); } +FormElement* fix_up_abs_2(LetElement* in, const Env& env, FormPool& pool) { + /* + * (let ((result in)) + * (set! result (abs result)) + * ... + * ) + * + * -> should become. + * (let ((result (abs in))) + * ) + */ + + if (in->entries().size() != 1) { + return nullptr; + } + + if (in->body()->elts().empty()) { + return nullptr; + } + + // look for setting a temp. + auto temp = in->entries().at(0).dest; + auto temp_name = env.get_variable_name(temp); + + Form* src = in->entries().at(0).src; + + auto first_as_set = dynamic_cast(in->body()->elts().front()); + if (!first_as_set) { + return nullptr; + } + + auto dest_var_name = env.get_variable_name(first_as_set->dst()); + if (dest_var_name != temp_name) { + return nullptr; + } + + auto matcher = + Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ABS), {Matcher::any_reg(0)}); + + auto mr = match(matcher, first_as_set->src()); + if (!mr.matched) { + return nullptr; + } + + assert(mr.maps.regs.at(0)); + + auto abs_var_name = env.get_variable_name(*mr.maps.regs.at(0)); + if (abs_var_name != temp_name) { + return nullptr; + } + + // success! + // modify the let entry: + in->entries().at(0).src = pool.alloc_single_element_form( + nullptr, GenericOperator::make_fixed(FixedOperatorKind::ABS), src); + // remove the (set! x (abs x)) + in->body()->elts().erase(in->body()->elts().begin()); + return in; +} + /*! * Attempt to rewrite a let as another form. If it cannot be rewritten, this will return nullptr. */ @@ -213,6 +273,11 @@ FormElement* rewrite_let(LetElement* in, const Env& env, FormPool& pool) { return as_abs; } + auto as_abs_2 = fix_up_abs_2(in, env, pool); + if (as_abs_2) { + return as_abs_2; + } + // nothing matched. return nullptr; } diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index f75d46756..1fc77519f 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -736,50 +736,9 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; -;; math -(deftype random-generator (basic) - ((seed uint32 :offset-assert 4) - ) - :method-count-assert 9 - :size-assert #x8 - :flag-assert #x900000008 - ) - (define-extern truncate (function float float)) (define-extern integral? (function float symbol)) (define-extern fractional-part (function float float)) -(define-extern log2 (function int int)) -(define-extern seek (function float float float float)) -(define-extern lerp (function float float float float)) -(define-extern lerp-scale (function float float float float float float)) -(define-extern lerp-clamp (function float float float float)) -(define-extern seekl (function int int int int)) -(define-extern rand-vu-init (function float float)) -(define-extern rand-vu (function float)) -(define-extern rand-vu-nostep (function float)) -(define-extern rand-vu-float-range (function float float float)) -(define-extern rand-vu-percent? (function float symbol)) -(define-extern rand-vu-int-range (function int int int)) -(define-extern rand-vu-int-count (function int int)) - -; ;;(define-extern xyzwh object) ;; unknown type -; -; -; -; (define-extern lerp function) -; (define-extern lerp-scale function) -; - -; ;;(define-extern random-generator object) ;; unknown type -; (define-extern integral? function) -; (define-extern rand-uint31-gen function) -; -; (define-extern fractional-part function) -; (define-extern seek function) -; ;;(define-extern xyzw object) ;; unknown type -; -(define-extern *random-generator* random-generator) ;; unknown type -; (deftype rgba (uint32) ((r uint8 :offset 0) @@ -802,6 +761,29 @@ :flag-assert #x900000010 ) +(define-extern log2 (function int int)) +(define-extern seek (function float float float float)) +(define-extern lerp (function float float float float)) +(define-extern lerp-scale (function float float float float float float)) +(define-extern lerp-clamp (function float float float float)) +(define-extern seekl (function int int int int)) +(define-extern rand-vu-init (function float float)) +(define-extern rand-vu (function float)) +(define-extern rand-vu-nostep (function float)) +(define-extern rand-vu-float-range (function float float float)) +(define-extern rand-vu-percent? (function float symbol)) +(define-extern rand-vu-int-range (function int int int)) +(define-extern rand-vu-int-count (function int int)) + +(deftype random-generator (basic) + ((seed uint32 :offset-assert 4) + ) + :method-count-assert 9 + :size-assert #x8 + :flag-assert #x900000008 + ) +(define-extern *random-generator* random-generator) +(define-extern rand-uint31-gen (function random-generator uint)) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; @@ -1180,13 +1162,13 @@ :size-assert #x20 :flag-assert #x1000000020 (: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) + (add-spheres! (_type_ (pointer sphere) int) int 9) + (add-point! (_type_ vector3s) int 10) + (set-from-point-offset! (_type_ vector3s vector3s) int 11) + (set-from-point-offset-pad! (_type_ vector3s vector3s float) int 12) + (set-from-sphere! (_type_ sphere) int 13) + (set-from-spheres! (_type_ (pointer sphere) int) int 14) + (add-box! (_type_ bounding-box) int 15) ) ) @@ -1247,6 +1229,7 @@ :flag-assert #x900000020 ) +(define-extern matrix-copy! (function matrix matrix matrix)) ;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -3572,6 +3555,7 @@ :size-assert #x50 :flag-assert #x900000050 ) + ;; level-h (deftype level (basic) ((name basic :offset-assert 4) @@ -4225,6 +4209,7 @@ ) (define-extern *dproc* process) +(define-extern *display-strip-lines* int) ;;;;;;;;;;;;;; ;; mspace-h @@ -13638,6 +13623,12 @@ :flag-assert #x900000014 ) + +;;;; level + +(define-extern lookup-level-info (function symbol level-load-info)) +(define-extern remap-level-name (function level-load-info object)) + ; ;; text ; (deftype game-text-info (basic) ; () @@ -32501,7 +32492,7 @@ ;;(define-extern bounding-box4w object) ;; unknown type ;;(define-extern bounding-box-both object) ;; unknown type ;;(define-extern matrix4h object) ;; unknown type -; (define-extern matrix-copy! function) + ;;(define-extern matrix3 object) ;; unknown type ;;(define-extern matrix object) ;; unknown type ;;(define-extern *unity-quaternion* object) ;; unknown type @@ -32889,7 +32880,7 @@ ;;(define-extern *display-cam-coll-marks* object) ;; unknown type ;;(define-extern *display-ambient-hint-marks* object) ;; unknown type ;;(define-extern *display-cam-los-debug* object) ;; unknown type -;;(define-extern *display-strip-lines* object) ;; unknown type + ;;(define-extern *display-process-anim* object) ;; unknown type ;;(define-extern *display-actor-marks* object) ;; unknown type (define-extern *menu-hook* (function none)) @@ -34371,7 +34362,6 @@ ;;(define-extern save object) ;; unknown type ;;(define-extern restore object) ;; unknown type ;;(define-extern mc-unformat object) ;; unknown type -(define-extern lookup-level-info function) ;;(define-extern done object) ;; unknown type (define-extern get-aspect-ratio function) (define-extern progress-allowed? function) @@ -34802,7 +34792,6 @@ (define-extern load-vis-info function) (define-extern level-update-after-load function) (define-extern update-sound-banks function) -(define-extern remap-level-name function) (define-extern add-bsp-drawable function) ;;(define-extern *print-login* object) ;; unknown type ;;(define-extern link-resume object) ;; unknown type diff --git a/decompiler/config/jak1_ntsc_black_label.jsonc b/decompiler/config/jak1_ntsc_black_label.jsonc index 45a3ac7dc..496b8e696 100644 --- a/decompiler/config/jak1_ntsc_black_label.jsonc +++ b/decompiler/config/jak1_ntsc_black_label.jsonc @@ -505,5 +505,5 @@ ], "pair_functions_by_name":["ref", "last", "member", "nmember", "assoc", "assoce", "append!", "delete!", "delete-car!", - "insert-cons!", "sort", "unload-package", "(method 4 pair)", "nassoc", "nassoce"] + "insert-cons!", "sort", "unload-package", "(method 4 pair)", "nassoc", "nassoce", "lookup-level-info", "(method 21 level-group)"] } \ No newline at end of file diff --git a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc index ddd202bdf..2aadb0a17 100644 --- a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc @@ -28,6 +28,16 @@ ["L35", "float", true] ], + "vector-h": [ + ["L32", "vector", true], + ["L31", "vector", true], + ["L30", "vector", true], + ["L29", "vector", true], + ["L28", "vector", true], + ["L27", "vector", true], + ["L26", "vector", true] + ], + "trigonometry": [ ["L143", "float", true], ["L144", "float", true], diff --git a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc index 8ce56c1ad..cd8fba906 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc @@ -109,10 +109,22 @@ [4, "s5", "string"] ], - // GSTATE "enter-state":[ [68, "s0", "protect-frame"] + ], + + // MATH + "log2":[ + [3, "v1", "int"] + ], + + // LEVEL + "lookup-level-info":[ + [3, "a1", "symbol"], + [4, "a1", "level-load-info"], + [8, "a1", "level-load-info"], + [12, "a1", "level-load-info"] ] } diff --git a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc index cec502891..14a54341a 100644 --- a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc @@ -617,9 +617,18 @@ }, "(method 11 touching-prims-entry-pool)":{ "vars":{"a1-0":"current", "v1-0":"prev", "a2-0":"next"} + }, + + // LEVEL + "lookup-level-info":{ + "args":["name"], + "vars":{"a1-1":["info", "level-load-info"], "v1-0":"rest", "a1-0":"current-sym"} + }, + + "(method 21 level-group)":{ + "args":["obj", "name", "cmd-idx"], + "vars":{"v1-1":"cmd-lst"} } - - } \ No newline at end of file diff --git a/goal_src/engine/geometry/bounding-box-h.gc b/goal_src/engine/geometry/bounding-box-h.gc index f2304ba51..55a841968 100644 --- a/goal_src/engine/geometry/bounding-box-h.gc +++ b/goal_src/engine/geometry/bounding-box-h.gc @@ -8,6 +8,9 @@ ;; Types related to bounding boxes. ;; floating point bounding box. +;; min is the corner with lowest x,y,z values. +;; max is the corner with highest x,y,z values. +;; the w value should be 1 in both min and max. (deftype bounding-box (structure) ((min vector :inline :offset-assert 0) (max vector :inline :offset-assert 16) @@ -16,14 +19,14 @@ :size-assert #x20 :flag-assert #x1000000020 (: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) - ) + (add-spheres! (_type_ (pointer sphere) int) int 9) + (add-point! (_type_ vector3s) int 10) + (set-from-point-offset! (_type_ vector3s vector3s) int 11) + (set-from-point-offset-pad! (_type_ vector3s vector3s float) int 12) + (set-from-sphere! (_type_ sphere) int 13) + (set-from-spheres! (_type_ (pointer sphere) int) int 14) + (add-box! (_type_ bounding-box) int 15) + ) ) ;; integer (word) bounding box. @@ -44,4 +47,4 @@ :method-count-assert 9 :size-assert #x40 :flag-assert #x900000040 - ) \ No newline at end of file + ) diff --git a/goal_src/engine/geometry/bounding-box.gc b/goal_src/engine/geometry/bounding-box.gc index 4f4b3bb9f..61d7ff77a 100644 --- a/goal_src/engine/geometry/bounding-box.gc +++ b/goal_src/engine/geometry/bounding-box.gc @@ -28,3 +28,183 @@ (>= (-> box max data 2) (-> pt data 2)) ) ) + +;; definition for method 11 of type bounding-box +(defmethod set-from-point-offset! bounding-box + ((obj bounding-box) (arg0 vector3s) (arg1 vector3s)) + "Set box to smallest containing the points arg0, (arg0 + arg1)" + (rlet ((vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + (vf4 :class vf) + (vf5 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf3 arg1) + (.lvf vf4 arg0) + (.add.vf vf5 vf4 vf3) + (.min.vf vf1 vf4 vf5) + (.max.vf vf2 vf4 vf5) + (.mov.vf vf1 vf0 :mask #b1000) + (.mov.vf vf2 vf0 :mask #b1000) + (.svf obj vf1) + (.svf obj vf2 :offset 16) + 0 + ) + ) + +;; definition for method 10 of type bounding-box +(defmethod add-point! bounding-box ((obj bounding-box) (arg0 vector3s)) + "Expand the box if needed to contain the given point" + (rlet ((vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + ) + (.lvf vf1 obj) + (.lvf vf2 obj :offset 16) + (.lvf vf3 arg0) + (.min.vf vf1 vf1 vf3) + (.max.vf vf2 vf2 vf3) + (.svf obj vf1) + (.svf obj vf2 :offset 16) + 0 + ) + ) + +;; definition for method 15 of type bounding-box +(defmethod add-box! bounding-box ((obj bounding-box) (arg0 bounding-box)) + "Expand the box if needed to contain the given box" + (rlet ((vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + (vf4 :class vf) + ) + (.lvf vf1 obj) + (.lvf vf2 obj :offset 16) + (.lvf vf3 arg0) + (.lvf vf4 arg0 :offset 16) + (.min.vf vf1 vf1 vf3) + (.max.vf vf2 vf2 vf4) + (.svf obj vf1) + (.svf obj vf2 :offset 16) + 0 + ) + ) + +;; definition for method 12 of type bounding-box +(defmethod set-from-point-offset-pad! bounding-box + ((obj bounding-box) (arg0 vector3s) (arg1 vector3s) (arg2 float)) + "Set the box size to contain pt, pt + offset, with some padding" + (rlet ((vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + (vf4 :class vf) + (vf5 :class vf) + (vf6 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf4 arg1) + (.lvf vf5 arg0) + (.mov vf1 arg2) + (.add.vf vf6 vf5 vf4) + (.min.vf vf2 vf5 vf6) + (.max.vf vf3 vf5 vf6) + (.add.x.vf vf3 vf3 vf1 :mask #b111) + (.sub.x.vf vf2 vf2 vf1 :mask #b111) + (.mov.vf vf2 vf0 :mask #b1000) + (.mov.vf vf3 vf0 :mask #b1000) + (.svf obj vf2) + (.svf obj vf3 :offset 16) + 0 + ) + ) + +;; definition for method 13 of type bounding-box +(defmethod set-from-sphere! bounding-box ((obj bounding-box) (arg0 sphere)) + "Set the box size to contain the given sphere" + (rlet ((vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf1 arg0) + (.sub.w.vf vf2 vf1 vf1 :mask #b111) + (.add.w.vf vf3 vf1 vf1 :mask #b111) + (.mov.vf vf2 vf0 :mask #b1000) + (.mov.vf vf3 vf0 :mask #b1000) + (.svf obj vf2) + (.svf obj vf3 :offset 16) + 0 + ) + ) + +(defmethod add-spheres! bounding-box ((obj bounding-box) (spheres (pointer sphere)) (count int)) + "Add count spheres." + ;; the PS2 implementation is very optimized + ;; It is unrolled and 'software pipelined' to do 4 at a time. + ;; This is slightly less optimized. + (rlet ((current-min :class vf) + (current-max :class vf) + (sph-min :class vf) + (sph-max :class vf) + (sph :class vf)) + + (when (nonzero? count) + ;; load these outside the loop + (.lvf current-min (-> obj min)) + (.lvf current-max (-> obj max)) + + (dotimes (i count) + (.lvf sph (-> spheres i)) + (.sub.w.vf sph-min sph sph :mask #b111) + (.add.w.vf sph-max sph sph :mask #b111) + (.min.vf current-min current-min sph-min :mask #b111) + (.max.vf current-max current-max sph-max :mask #b111) + ) + + (.svf (-> obj min) current-min) + (.svf (-> obj max) current-max) + ) + ) + 0 + ) + +(defmethod set-from-spheres! bounding-box ((obj bounding-box) (spheres (pointer sphere)) (count int)) + "Reset box to hold the given spheres. Note: this implementation could be optimized." + ;; This is also unrolled, but does 7 at a time. + (rlet ((vf0 :class vf) + (current-min :class vf) + (current-max :class vf) + (sph-min :class vf) + (sph-max :class vf) + (sph :class vf)) + ;; init constant + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + ;; init min/max. in the case we don't have any spheres, we should return (0,0,0,1) for min/max. + (set! current-min vf0) + (set! current-max vf0) + + (dotimes (i count) + (.lvf sph (-> spheres i)) + (.sub.w.vf sph-min sph sph :mask #b111) + (.add.w.vf sph-max sph sph :mask #b111) + (cond + ((zero? count) + (set! current-min sph-min) + (set! current-max sph-max) + ) + (else + (.min.vf current-min current-min sph-min :mask #b111) + (.max.vf current-max current-max sph-max :mask #b111) + ) + ) + ) + + (.svf (-> obj min) current-min) + (.svf (-> obj max) current-max) + ) + 0 + ) diff --git a/goal_src/engine/math/math.gc b/goal_src/engine/math/math.gc index c0b98bf3a..e10710c80 100644 --- a/goal_src/engine/math/math.gc +++ b/goal_src/engine/math/math.gc @@ -296,6 +296,6 @@ ) (set! result (shr (logand #xffffffff (shl result 1)) 1)) (set! (-> gen seed) result) - result + (the uint result) ) ) diff --git a/goal_src/engine/math/vector-h.gc b/goal_src/engine/math/vector-h.gc index ed7139629..c43a65970 100644 --- a/goal_src/engine/math/vector-h.gc +++ b/goal_src/engine/math/vector-h.gc @@ -444,7 +444,6 @@ ) ) -;; vector-h (deftype vertical-planes (structure) ((data uint128 4 :offset-assert 0) ;; probably wrong ) diff --git a/goalc/compiler/compilation/Define.cpp b/goalc/compiler/compilation/Define.cpp index 62b2ea3de..97b58b495 100644 --- a/goalc/compiler/compilation/Define.cpp +++ b/goalc/compiler/compilation/Define.cpp @@ -209,9 +209,8 @@ Val* Compiler::compile_set(const goos::Object& form, const goos::Object& rest, E va_check(form, args, {{}, {}}, {}); auto& destination = args.unnamed.at(0); - // todo, I don't know if this is the correct order or not. Right now the value is computed - // and to_reg'd first, then the destination is computed, if the destination requires math to - // compute. + // this is the order I'm using in the decompiler and it seems to be right. + // see StorePlainDeref::push_to_stack for example auto source = compile_error_guard(args.unnamed.at(1), env); auto source_reg = source->to_reg(env); auto dest = compile_error_guard(destination, env); diff --git a/test/decompiler/FormRegressionTest.cpp b/test/decompiler/FormRegressionTest.cpp index e130f5ad8..7afe955f3 100644 --- a/test/decompiler/FormRegressionTest.cpp +++ b/test/decompiler/FormRegressionTest.cpp @@ -152,6 +152,7 @@ std::unique_ptr FormRegressionTest::make_function( test->func.ir2.env.set_end_var(test->func.ir2.atomic_ops->end_op().return_var()); EXPECT_TRUE(test->func.run_type_analysis_ir2(function_type, *dts, test->file, casts, {})); + test->func.ir2.env.types_succeeded = true; test->func.ir2.env.set_reg_use(analyze_ir2_register_usage(test->func)); diff --git a/test/decompiler/reference/all_forward_declarations.gc b/test/decompiler/reference/all_forward_declarations.gc index fe4bda2d9..44e24be2a 100644 --- a/test/decompiler/reference/all_forward_declarations.gc +++ b/test/decompiler/reference/all_forward_declarations.gc @@ -80,4 +80,11 @@ (define-extern throw (function symbol object int)) (defmacro suspend() '(none) - ) \ No newline at end of file + ) + + +;; math +(define-extern fabs (function float float)) +(define-extern abs (function int int)) +(define-extern rand-vu-init (function float none)) +(define-extern rand-vu (function float)) \ No newline at end of file diff --git a/test/decompiler/reference/bounding-box-h_REF.gc b/test/decompiler/reference/bounding-box-h_REF.gc new file mode 100644 index 000000000..2943d83c9 --- /dev/null +++ b/test/decompiler/reference/bounding-box-h_REF.gc @@ -0,0 +1,72 @@ +;;-*-Lisp-*- +(in-package goal) + +;; definition of type bounding-box +(deftype bounding-box (structure) + ((min vector :inline :offset-assert 0) + (max vector :inline :offset-assert 16) + ) + :method-count-assert 16 + :size-assert #x20 + :flag-assert #x1000000020 + (:methods + (add-spheres! (_type_ (pointer sphere) int) int 9) + (add-point! (_type_ vector3s) int 10) + (set-from-point-offset! (_type_ vector3s vector3s) int 11) + (set-from-point-offset-pad! (_type_ vector3s vector3s float) int 12) + (set-from-sphere! (_type_ sphere) int 13) + (set-from-spheres! (_type_ (pointer sphere) int) int 14) + (add-box! (_type_ bounding-box) int 15) + ) + ) + +;; definition for method 3 of type bounding-box +(defmethod inspect bounding-box ((obj bounding-box)) + (format #t "[~8x] ~A~%" obj 'bounding-box) + (format #t "~Tmin: ~`vector`P~%" (-> obj min)) + (format #t "~Tmax: ~`vector`P~%" (-> obj max)) + obj + ) + +;; definition of type bounding-box4w +(deftype bounding-box4w (structure) + ((min vector4w :inline :offset-assert 0) + (max vector4w :inline :offset-assert 16) + ) + :method-count-assert 9 + :size-assert #x20 + :flag-assert #x900000020 + ) + +;; definition for method 3 of type bounding-box4w +(defmethod inspect bounding-box4w ((obj bounding-box4w)) + (format #t "[~8x] ~A~%" obj 'bounding-box4w) + (format #t "~Tmin: ~`vector4w`P~%" (-> obj min)) + (format #t "~Tmax: ~`vector4w`P~%" (-> obj max)) + obj + ) + +;; definition of type bounding-box-both +(deftype bounding-box-both (structure) + ((box bounding-box :inline :offset-assert 0) + (box4w bounding-box4w :inline :offset-assert 32) + ) + :method-count-assert 9 + :size-assert #x40 + :flag-assert #x900000040 + ) + +;; definition for method 3 of type bounding-box-both +(defmethod inspect bounding-box-both ((obj bounding-box-both)) + (format #t "[~8x] ~A~%" obj 'bounding-box-both) + (format #t "~Tbox: #~%" (-> obj box)) + (format #t "~Tbox4w: #~%" (-> obj box4w)) + obj + ) + +;; failed to figure out what this is: +(let ((v0-3 0)) + ) + +;; failed to figure out what this is: +(none) \ No newline at end of file diff --git a/test/decompiler/reference/bounding-box_REF.gc b/test/decompiler/reference/bounding-box_REF.gc new file mode 100644 index 000000000..2869f436e --- /dev/null +++ b/test/decompiler/reference/bounding-box_REF.gc @@ -0,0 +1,146 @@ +;;-*-Lisp-*- +(in-package goal) + +;; definition for function box-vector-enside? +(defun box-vector-enside? ((box bounding-box) (pt vector)) + (and + (< (-> box min data 0) (-> pt data 0)) + (< (-> box min data 1) (-> pt data 1)) + (< (-> box min data 2) (-> pt data 2)) + (< (-> pt data 0) (-> box max data 0)) + (< (-> pt data 1) (-> box max data 1)) + (< (-> pt data 2) (-> box max data 2)) + ) + ) + +;; definition for function box-vector-inside? +(defun box-vector-inside? ((box bounding-box) (pt vector)) + (and + (>= (-> pt data 0) (-> box min data 0)) + (>= (-> pt data 1) (-> box min data 1)) + (>= (-> pt data 2) (-> box min data 2)) + (>= (-> box max data 0) (-> pt data 0)) + (>= (-> box max data 1) (-> pt data 1)) + (>= (-> box max data 2) (-> pt data 2)) + ) + ) + +;; definition for method 11 of type bounding-box +(defmethod + set-from-point-offset! + bounding-box + ((obj bounding-box) (arg0 vector3s) (arg1 vector3s)) + (rlet ((vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + (vf4 :class vf) + (vf5 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf3 arg1) + (.lvf vf4 arg0) + (.add.vf vf5 vf4 vf3) + (.min.vf vf1 vf4 vf5) + (.max.vf vf2 vf4 vf5) + (.mov.vf vf1 vf0 :mask #b1000) + (.mov.vf vf2 vf0 :mask #b1000) + (.svf obj vf1) + (.svf obj vf2 :offset 16) + 0 + ) + ) + +;; definition for method 10 of type bounding-box +(defmethod add-point! bounding-box ((obj bounding-box) (arg0 vector3s)) + (rlet ((vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + ) + (.lvf vf1 obj) + (.lvf vf2 obj :offset 16) + (.lvf vf3 arg0) + (.min.vf vf1 vf1 vf3) + (.max.vf vf2 vf2 vf3) + (.svf obj vf1) + (.svf obj vf2 :offset 16) + 0 + ) + ) + +;; definition for method 15 of type bounding-box +(defmethod add-box! bounding-box ((obj bounding-box) (arg0 bounding-box)) + (rlet ((vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + (vf4 :class vf) + ) + (.lvf vf1 obj) + (.lvf vf2 obj :offset 16) + (.lvf vf3 arg0) + (.lvf vf4 arg0 :offset 16) + (.min.vf vf1 vf1 vf3) + (.max.vf vf2 vf2 vf4) + (.svf obj vf1) + (.svf obj vf2 :offset 16) + 0 + ) + ) + +;; definition for method 12 of type bounding-box +(defmethod + set-from-point-offset-pad! + bounding-box + ((obj bounding-box) (arg0 vector3s) (arg1 vector3s) (arg2 float)) + (rlet ((vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + (vf4 :class vf) + (vf5 :class vf) + (vf6 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf4 arg1) + (.lvf vf5 arg0) + (.mov vf1 arg2) + (.add.vf vf6 vf5 vf4) + (.min.vf vf2 vf5 vf6) + (.max.vf vf3 vf5 vf6) + (.add.x.vf vf3 vf3 vf1 :mask #b111) + (.sub.x.vf vf2 vf2 vf1 :mask #b111) + (.mov.vf vf2 vf0 :mask #b1000) + (.mov.vf vf3 vf0 :mask #b1000) + (.svf obj vf2) + (.svf obj vf3 :offset 16) + 0 + ) + ) + +;; definition for method 13 of type bounding-box +(defmethod set-from-sphere! bounding-box ((obj bounding-box) (arg0 sphere)) + (rlet ((vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf1 arg0) + (.sub.w.vf vf2 vf1 vf1 :mask #b111) + (.add.w.vf vf3 vf1 vf1 :mask #b111) + (.mov.vf vf2 vf0 :mask #b1000) + (.mov.vf vf3 vf0 :mask #b1000) + (.svf obj vf2) + (.svf obj vf3 :offset 16) + 0 + ) + ) + +;; definition for method 14 of type bounding-box +;; ERROR: function was not converted to expressions. Cannot decompile. + +;; definition for method 9 of type bounding-box +;; ERROR: function was not converted to expressions. Cannot decompile. + +;; failed to figure out what this is: +(none) diff --git a/test/decompiler/reference/gkernel_REF.gc b/test/decompiler/reference/gkernel_REF.gc index 3aadc3b47..ca44d814f 100644 --- a/test/decompiler/reference/gkernel_REF.gc +++ b/test/decompiler/reference/gkernel_REF.gc @@ -208,12 +208,13 @@ ;; definition for function remove-exit (defun remove-exit () - (local-vars (pp process)) (if (-> pp stack-frame-top) - (let ((v0-0 (-> pp stack-frame-top next))) - (set! (-> pp stack-frame-top) v0-0) - v0-0 - ) - ) + (local-vars (pp process)) + (if (-> pp stack-frame-top) + (let ((v0-0 (-> pp stack-frame-top next))) + (set! (-> pp stack-frame-top) v0-0) + v0-0 + ) + ) ) ;; definition (debug) for function stream<-process-mask @@ -1506,11 +1507,9 @@ (while s2-1 (inspect-process-tree (-> s2-1 0) (+ arg1 1) (if (not (-> s2-1 0 brother)) arg2 - (let* ((v1-7 1) - (a2-4 (+ arg1 1)) - (v1-8 (ash v1-7 a2-4)) - ) - (logior arg2 v1-8) + (logior + arg2 + (ash 1 (+ arg1 1)) ) ) arg3 diff --git a/test/decompiler/reference/math_REF.gc b/test/decompiler/reference/math_REF.gc new file mode 100644 index 000000000..8a9471231 --- /dev/null +++ b/test/decompiler/reference/math_REF.gc @@ -0,0 +1,247 @@ +;;-*-Lisp-*- +(in-package goal) + +;; definition for function truncate +(defun truncate ((arg0 float)) + (the float (the int arg0)) + ) + +;; definition for function integral? +(defun integral? ((arg0 float)) + (= (the float (the int arg0)) arg0) + ) + +;; definition for function fractional-part +(defun fractional-part ((arg0 float)) + (- arg0 (the float (the int arg0))) + ) + +;; definition of type rgba +(deftype rgba (uint32) + ((r uint8 :offset 0 :size 8) + (g uint8 :offset 8 :size 8) + (b uint8 :offset 16 :size 8) + (a uint8 :offset 24 :size 8) + ) + :method-count-assert 9 + :size-assert #x4 + :flag-assert #x900000004 + ) + +;; definition of type xyzw +(deftype xyzw (uint128) + () + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition of type xyzwh +(deftype xyzwh (uint128) + () + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for function log2 +(defun log2 ((arg0 int)) + (let ((arg0 (gpr->fpr arg0))) + (+ (sar (the-as int (the float arg0)) 23) -127) + ) + ) + +;; definition for function seek +(defun seek ((x float) (target float) (diff float)) + (let ((err (- target x))) + (cond + ((>= diff (fabs err)) + target + ) + ((>= err 0.0) + (+ x diff) + ) + (else + (- x diff) + ) + ) + ) + ) + +;; definition for function lerp +(defun lerp ((minimum float) (maximum float) (amount float)) + (+ minimum (* amount (- maximum minimum))) + ) + +;; definition for function lerp-scale +(defun + lerp-scale + ((min-out float) (max-out float) (in float) (min-in float) (max-in float)) + (let ((scale (fmax 0.0 (fmin 1.0 (/ (- in min-in) (- max-in min-in)))))) + (+ (* (- 1.0 scale) min-out) (* scale max-out)) + ) + ) + +;; definition for function lerp-clamp +(defun lerp-clamp ((minimum float) (maximum float) (amount float)) + (cond + ((>= 0.0 amount) + minimum + ) + ((>= amount 1.0) + maximum + ) + (else + (+ (* (- 1.0 amount) minimum) (* amount maximum)) + ) + ) + ) + +;; definition for function seekl +(defun seekl ((arg0 int) (arg1 int) (arg2 int)) + (let* ((v1-0 (- arg1 arg0)) + (a3-0 (abs v1-0)) + ) + (cond + ((>= arg2 a3-0) + arg1 + ) + ((>= v1-0 0) + (+ arg0 arg2) + ) + (else + (- arg0 arg2) + ) + ) + ) + ) + +;; definition for function rand-vu-init +;; INFO: Return type mismatch int vs float. +;; WARN: Unsupported inline assembly instruction kind - [56] +;; WARN: Unsupported inline assembly instruction kind - [57] +(defun rand-vu-init ((arg0 float)) + (local-vars (v0-0 int)) + (.ctc2.i vi_R arg0) + (.cfc2.i v0-0 vi_R) + (the-as float v0-0) + ) + +;; failed to figure out what this is: +(rand-vu-init 1.418091) + +;; definition for function rand-vu +;; INFO: Return type mismatch int vs float. +;; WARN: Inline assembly instruction marked with TODO - [TODO.VRGET] +;; WARN: Inline assembly instruction marked with TODO - [TODO.VRXOR] +;; WARN: Inline assembly instruction marked with TODO - [TODO.VRNEXT] +(defun rand-vu () + (local-vars (v0-0 int)) + (rlet ((Q :class vf) + (vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (TODO.VRGET vf1) + (.sqrt.vf Q vf1 :ftf #b0) + (.add.vf vf2 vf0 Q :mask #b1) + (TODO.VRXOR vf2) + (TODO.VRNEXT vf1) + (.sub.w.vf vf1 vf1 vf0) + (.mov v0-0 vf1) + (the-as float v0-0) + ) + ) + +;; definition for function rand-vu-nostep +;; INFO: Return type mismatch int vs float. +;; WARN: Inline assembly instruction marked with TODO - [TODO.VRGET] +(defun rand-vu-nostep () + (local-vars (v0-0 int)) + (rlet ((vf0 :class vf) + (vf1 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (TODO.VRGET vf1) + (.sub.w.vf vf1 vf1 vf0) + (.mov v0-0 vf1) + (the-as float v0-0) + ) + ) + +;; definition for function rand-vu-float-range +(defun rand-vu-float-range ((arg0 float) (arg1 float)) + (+ arg0 (* (rand-vu) (- arg1 arg0))) + ) + +;; definition for function rand-vu-percent? +(defun rand-vu-percent? ((arg0 float)) + (>= arg0 (rand-vu)) + ) + +;; definition for function rand-vu-int-range +(defun rand-vu-int-range ((first int) (second int)) + (cond + ((< first second) + (set! second (+ second 1)) + (let ((v1-1 second)) + ) + ) + (else + (set! first (+ first 1)) + (let ((v1-3 first)) + ) + ) + ) + (let + ((float-in-range (rand-vu-float-range (the float first) (the float second)))) + (when (< float-in-range 0.0) + (set! float-in-range (+ -1.0 float-in-range)) + (let ((v1-5 float-in-range)) + ) + ) + (the int float-in-range) + ) + ) + +;; definition for function rand-vu-int-count +(defun rand-vu-int-count ((arg0 int)) + (the int (* (rand-vu) (the float arg0))) + ) + +;; definition of type random-generator +(deftype random-generator (basic) + ((seed uint32 :offset-assert 4) + ) + :method-count-assert 9 + :size-assert #x8 + :flag-assert #x900000008 + ) + +;; definition for method 3 of type random-generator +(defmethod inspect random-generator ((obj random-generator)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tseed: ~D~%" (-> obj seed)) + obj + ) + +;; definition for symbol *random-generator*, type random-generator +(define + *random-generator* + (the-as random-generator (new 'global 'random-generator)) + ) + +;; failed to figure out what this is: +(set! (-> *random-generator* seed) (the-as uint #x666edd1e)) + +;; definition for function rand-uint31-gen +;; ERROR: function was not converted to expressions. Cannot decompile. + +;; failed to figure out what this is: +(let ((v0-6 0)) + ) + +;; failed to figure out what this is: +(none) + diff --git a/test/decompiler/reference/types-h_REF.gc b/test/decompiler/reference/types-h_REF.gc new file mode 100644 index 000000000..16d8d2b74 --- /dev/null +++ b/test/decompiler/reference/types-h_REF.gc @@ -0,0 +1,25 @@ +;;-*-Lisp-*- +(in-package goal) + +;; definition of type time-frame +(deftype time-frame (int64) + () + :method-count-assert 9 + :size-assert #x8 + :flag-assert #x900000008 + ) + +;; definition of type part-id +(deftype part-id (uint32) + () + :method-count-assert 9 + :size-assert #x4 + :flag-assert #x900000004 + ) + +;; failed to figure out what this is: +(let ((v0-2 0)) + ) + +;; failed to figure out what this is: +(none) diff --git a/test/decompiler/reference/vector-h_REF.gc b/test/decompiler/reference/vector-h_REF.gc new file mode 100644 index 000000000..82a7be363 --- /dev/null +++ b/test/decompiler/reference/vector-h_REF.gc @@ -0,0 +1,1033 @@ +;;-*-Lisp-*- +(in-package goal) + +;; definition of type bit-array +(deftype bit-array (basic) + ((length int32 :offset-assert 4) + (allocated-length int32 :offset-assert 8) + (_pad uint8 :offset-assert 12) + (bytes uint8 :dynamic :offset 12) + ) + :method-count-assert 13 + :size-assert #xd + :flag-assert #xd0000000d + (:methods + (new (symbol type int) _type_ 0) + (get-bit (_type_ int) symbol 9) + (clear-bit (_type_ int) int 10) + (set-bit (_type_ int) int 11) + (clear (_type_) _type_ 12) + ) + ) + +;; definition for method 3 of type bit-array +(defmethod inspect bit-array ((obj bit-array)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) + obj + ) + +;; definition for method 0 of type bit-array +(defmethod new bit-array ((allocation symbol) (type-to-make type) (length int)) + (let + ((obj + (object-new + allocation + type-to-make + (+ + (+ (sar (logand -8 (+ length 7)) 3) -1) + (the-as int (-> type-to-make size)) + ) + ) + ) + ) + (set! (-> obj length) length) + (set! (-> obj allocated-length) length) + obj + ) + ) + +;; definition for method 4 of type bit-array +(defmethod length bit-array ((obj bit-array)) + (-> obj length) + ) + +;; definition for method 5 of type bit-array +;; INFO: Return type mismatch uint vs int. +(defmethod asize-of bit-array ((obj bit-array)) + (the-as + int + (+ + (-> obj type size) + (the-as uint (sar (logand -8 (+ (-> obj allocated-length) 7)) 3)) + ) + ) + ) + +;; definition for method 9 of type bit-array +(defmethod get-bit bit-array ((obj bit-array) (arg0 int)) + (let ((v1-2 (-> obj bytes (sar arg0 3)))) + (nonzero? (logand v1-2 (the-as uint (ash 1 (logand arg0 7))))) + ) + ) + +;; definition for method 10 of type bit-array +(defmethod clear-bit bit-array ((obj bit-array) (arg0 int)) + (set! + (-> obj bytes (sar arg0 3)) + (logand + (-> obj bytes (sar arg0 3)) + (the-as uint (lognot (ash 1 (logand arg0 7)))) + ) + ) + 0 + ) + +;; definition for method 11 of type bit-array +(defmethod set-bit bit-array ((obj bit-array) (arg0 int)) + (set! + (-> obj bytes (sar arg0 3)) + (logior (-> obj bytes (sar arg0 3)) (the-as uint (ash 1 (logand arg0 7)))) + ) + 0 + ) + +;; definition for method 12 of type bit-array +(defmethod clear bit-array ((obj bit-array)) + (let ((idx (sar (logand -8 (+ (-> obj allocated-length) 7)) 3))) + (while (nonzero? idx) + (+! idx -1) + (nop!) + (nop!) + (set! (-> obj bytes idx) 0) + ) + ) + obj + ) + +;; definition of type vector4ub +(deftype vector4ub (structure) + ((data uint8 4 :offset-assert 0) + (x uint8 :offset 0) + (y uint8 :offset 1) + (z uint8 :offset 2) + (w uint8 :offset 3) + (clr uint32 :offset 0) + ) + :pack-me + :method-count-assert 9 + :size-assert #x4 + :flag-assert #x900000004 + ) + +;; definition for method 3 of type vector4ub +(defmethod inspect vector4ub ((obj vector4ub)) + (format #t "[~8x] ~A~%" obj 'vector4ub) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tz: ~D~%" (-> obj data 2)) + (format #t "~Tw: ~D~%" (-> obj data 3)) + (format #t "~Tclr: ~D~%" (-> obj clr)) + obj + ) + +;; definition of type vector4b +(deftype vector4b (structure) + ((data int8 4 :offset-assert 0) + (x int8 :offset 0) + (y int8 :offset 1) + (z int8 :offset 2) + (w int8 :offset 3) + ) + :method-count-assert 9 + :size-assert #x4 + :flag-assert #x900000004 + ) + +;; definition for method 3 of type vector4b +(defmethod inspect vector4b ((obj vector4b)) + (format #t "[~8x] ~A~%" obj 'vector4b) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tz: ~D~%" (-> obj data 2)) + (format #t "~Tw: ~D~%" (-> obj data 3)) + obj + ) + +;; definition of type vector2h +(deftype vector2h (structure) + ((data int16 2 :offset-assert 0) + (x int16 :offset 0) + (y int16 :offset 2) + ) + :pack-me + :method-count-assert 9 + :size-assert #x4 + :flag-assert #x900000004 + ) + +;; definition for method 3 of type vector2h +(defmethod inspect vector2h ((obj vector2h)) + (format #t "[~8x] ~A~%" obj 'vector2h) + (format #t "~Tdata[2] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + obj + ) + +;; definition of type vector2uh +(deftype vector2uh (structure) + ((data uint16 2 :offset-assert 0) + (x uint16 :offset 0) + (y uint16 :offset 2) + (val uint32 :offset 0) + ) + :pack-me + :method-count-assert 9 + :size-assert #x4 + :flag-assert #x900000004 + ) + +;; definition for method 3 of type vector2uh +(defmethod inspect vector2uh ((obj vector2uh)) + (format #t "[~8x] ~A~%" obj 'vector2uh) + (format #t "~Tdata[2] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tval: ~D~%" (-> obj val)) + obj + ) + +;; definition of type vector3h +(deftype vector3h (structure) + ((data int16 2 :offset-assert 0) + (x int16 :offset 0) + (y int16 :offset 2) + (z int16 :offset-assert 4) + ) + :method-count-assert 9 + :size-assert #x6 + :flag-assert #x900000006 + ) + +;; definition for method 3 of type vector3h +(defmethod inspect vector3h ((obj vector3h)) + (format #t "[~8x] ~A~%" obj 'vector3h) + (format #t "~Tdata[2] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tz: ~D~%" (-> obj z)) + obj + ) + +;; definition of type vector2w +(deftype vector2w (structure) + ((data int32 2 :offset-assert 0) + (x int32 :offset 0) + (y int32 :offset 4) + ) + :pack-me + :method-count-assert 9 + :size-assert #x8 + :flag-assert #x900000008 + ) + +;; definition for method 3 of type vector2w +(defmethod inspect vector2w ((obj vector2w)) + (format #t "[~8x] ~A~%" obj 'vector2w) + (format #t "~Tdata[2] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + obj + ) + +;; definition of type vector3w +(deftype vector3w (structure) + ((data int32 3 :offset-assert 0) + (x int32 :offset 0) + (y int32 :offset 4) + (z int32 :offset 8) + ) + :method-count-assert 9 + :size-assert #xc + :flag-assert #x90000000c + ) + +;; definition for method 3 of type vector3w +(defmethod inspect vector3w ((obj vector3w)) + (format #t "[~8x] ~A~%" obj 'vector3w) + (format #t "~Tdata[3] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tz: ~D~%" (-> obj data 2)) + obj + ) + +;; definition of type vector4w +(deftype vector4w (structure) + ((data int32 4 :offset-assert 0) + (x int32 :offset 0) + (y int32 :offset 4) + (z int32 :offset 8) + (w int32 :offset 12) + (dword uint64 2 :offset 0) + (quad uint128 :offset 0) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type vector4w +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect vector4w ((obj vector4w)) + (local-vars (a2-7 int)) + (format #t "[~8x] ~A~%" obj 'vector4w) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tz: ~D~%" (-> obj data 2)) + (format #t "~Tw: ~D~%" (-> obj data 3)) + (format #t "~Tdword[2] @ #x~X~%" (-> obj data)) + (let ((t9-7 format) + (a0-8 #t) + (a1-7 "~Tquad: ~D~%") + ) + (TODO.LQ a2-7 obj) + (t9-7 a0-8 a1-7 a2-7) + ) + obj + ) + +;; definition for method 2 of type vector4w +(defmethod print vector4w ((obj vector4w)) + (format + #t + "#" + (-> obj data 0) + (-> obj data 1) + (-> obj data 2) + (-> obj data 3) + obj + ) + obj + ) + +;; definition of type vector4w-2 +(deftype vector4w-2 (structure) + ((data int32 8 :offset-assert 0) + (quad uint128 2 :offset 0) + (vector vector4w 2 :offset 0) + ) + :method-count-assert 9 + :size-assert #x20 + :flag-assert #x900000020 + ) + +;; definition for method 3 of type vector4w-2 +(defmethod inspect vector4w-2 ((obj vector4w-2)) + (format #t "[~8x] ~A~%" obj 'vector4w-2) + (format #t "~Tdata[8] @ #x~X~%" (-> obj data)) + (format #t "~Tquad[2] @ #x~X~%" (-> obj data)) + (format #t "~Tvector[2] @ #x~X~%" (-> obj data)) + obj + ) + +;; definition of type vector4w-3 +(deftype vector4w-3 (structure) + ((data int32 12 :offset-assert 0) + (quad uint128 3 :offset 0) + (vector vector4w 3 :offset 0) + ) + :method-count-assert 9 + :size-assert #x30 + :flag-assert #x900000030 + ) + +;; definition for method 3 of type vector4w-3 +(defmethod inspect vector4w-3 ((obj vector4w-3)) + (format #t "[~8x] ~A~%" obj 'vector4w-3) + (format #t "~Tdata[12] @ #x~X~%" (-> obj data)) + (format #t "~Tquad[3] @ #x~X~%" (-> obj data)) + (format #t "~Tvector[3] @ #x~X~%" (-> obj data)) + obj + ) + +;; definition of type vector4w-4 +(deftype vector4w-4 (structure) + ((data int32 16 :offset-assert 0) + (quad uint128 4 :offset 0) + (vector vector4w 4 :offset 0) + ) + :method-count-assert 9 + :size-assert #x40 + :flag-assert #x900000040 + ) + +;; definition for method 3 of type vector4w-4 +(defmethod inspect vector4w-4 ((obj vector4w-4)) + (format #t "[~8x] ~A~%" obj 'vector4w-4) + (format #t "~Tdata[16] @ #x~X~%" (-> obj data)) + (format #t "~Tquad[4] @ #x~X~%" (-> obj data)) + (format #t "~Tvector[4] @ #x~X~%" (-> obj data)) + obj + ) + +;; definition of type vector4h +(deftype vector4h (structure) + ((data int16 4 :offset-assert 0) + (x int16 :offset 0) + (y int16 :offset 2) + (z int16 :offset 4) + (w int16 :offset 6) + (long uint64 :offset 0) + ) + :pack-me + :method-count-assert 9 + :size-assert #x8 + :flag-assert #x900000008 + ) + +;; definition for method 3 of type vector4h +(defmethod inspect vector4h ((obj vector4h)) + (format #t "[~8x] ~A~%" obj 'vector4h) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~D~%" (-> obj data 0)) + (format #t "~Ty: ~D~%" (-> obj data 1)) + (format #t "~Tz: ~D~%" (-> obj data 2)) + (format #t "~Tw: ~D~%" (-> obj data 3)) + (format #t "~Tlong: ~D~%" (-> obj long)) + obj + ) + +;; definition of type vector8h +(deftype vector8h (structure) + ((data int16 8 :offset-assert 0) + (quad uint128 :offset 0) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type vector8h +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect vector8h ((obj vector8h)) + (local-vars (a2-2 int)) + (format #t "[~8x] ~A~%" obj 'vector8h) + (format #t "~Tdata[8] @ #x~X~%" (-> obj data)) + (let ((t9-2 format) + (a0-3 #t) + (a1-2 "~Tquad: ~D~%") + ) + (TODO.LQ a2-2 obj) + (t9-2 a0-3 a1-2 a2-2) + ) + obj + ) + +;; definition of type vector16b +(deftype vector16b (structure) + ((data int8 8 :offset-assert 0) + (quad uint128 :offset 0) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type vector16b +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect vector16b ((obj vector16b)) + (local-vars (a2-2 int)) + (format #t "[~8x] ~A~%" obj 'vector16b) + (format #t "~Tdata[8] @ #x~X~%" (-> obj data)) + (let ((t9-2 format) + (a0-3 #t) + (a1-2 "~Tquad: ~D~%") + ) + (TODO.LQ a2-2 obj) + (t9-2 a0-3 a1-2 a2-2) + ) + obj + ) + +;; definition of type vector +(deftype vector (structure) + ((data float 4 :offset-assert 0) + (x float :offset 0) + (y float :offset 4) + (z float :offset 8) + (w float :offset 12) + (quad uint128 :offset 0) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type vector +;; INFO: this function exists in multiple non-identical object files +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect vector ((obj vector)) + (local-vars (a2-6 int)) + (format #t "[~8x] ~A~%" obj 'vector) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~f~%" (-> obj data 0)) + (format #t "~Ty: ~f~%" (-> obj data 1)) + (format #t "~Tz: ~f~%" (-> obj data 2)) + (format #t "~Tw: ~f~%" (-> obj data 3)) + (let ((t9-6 format) + (a0-7 #t) + (a1-6 "~Tquad: ~D~%") + ) + (TODO.LQ a2-6 obj) + (t9-6 a0-7 a1-6 a2-6) + ) + obj + ) + +;; definition for method 3 of type vector +;; INFO: this function exists in multiple non-identical object files +(defmethod inspect vector ((obj vector)) + (format #t "[~8x] vector~%" obj) + (format + #t + "~T[~F] [~F] [~F] [~F]~%" + (-> obj data 0) + (-> obj data 1) + (-> obj data 2) + (-> obj data 3) + ) + obj + ) + +;; definition for method 2 of type vector +(defmethod print vector ((obj vector)) + (format + #t + "#" + (-> obj data 0) + (-> obj data 1) + (-> obj data 2) + (-> obj data 3) + obj + ) + obj + ) + +;; definition for symbol *null-vector*, type vector +(define *null-vector* (new 'static 'vector :w 1.0)) + +;; definition for symbol *identity-vector*, type vector +(define *identity-vector* (new 'static 'vector :x 1.0 :y 1.0 :z 1.0 :w 1.0)) + +;; definition for symbol *x-vector*, type vector +(define *x-vector* (new 'static 'vector :x 1.0 :w 1.0)) + +;; definition for symbol *y-vector*, type vector +(define *y-vector* (new 'static 'vector :y 1.0 :w 1.0)) + +;; definition for symbol *z-vector*, type vector +(define *z-vector* (new 'static 'vector :z 1.0 :w 1.0)) + +;; definition for symbol *up-vector*, type vector +(define *up-vector* (new 'static 'vector :y 1.0 :w 1.0)) + +;; definition of type vector4s-3 +(deftype vector4s-3 (structure) + ((data float 12 :offset-assert 0) + (quad uint128 3 :offset 0) + (vector vector 3 :inline :offset 0) + ) + :method-count-assert 9 + :size-assert #x30 + :flag-assert #x900000030 + ) + +;; definition for method 3 of type vector4s-3 +(defmethod inspect vector4s-3 ((obj vector4s-3)) + (format #t "[~8x] ~A~%" obj 'vector4s-3) + (format #t "~Tdata[12] @ #x~X~%" (-> obj data)) + (format #t "~Tquad[3] @ #x~X~%" (-> obj data)) + (format #t "~Tvector[3] @ #x~X~%" (-> obj data)) + obj + ) + +;; definition of type vector-array +(deftype vector-array (inline-array-class) + () + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type vector-array +(defmethod inspect vector-array ((obj vector-array)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) + (format #t "~Tdata[0] @ #x~X~%" (&-> obj data 4)) + obj + ) + +;; failed to figure out what this is: +(set! (-> vector-array heap-base) (the-as uint 16)) + +;; definition of type rgbaf +(deftype rgbaf (vector) + ((r float :offset 0) + (g float :offset 4) + (b float :offset 8) + (a float :offset 12) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type rgbaf +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect rgbaf ((obj rgbaf)) + (local-vars (a2-6 int)) + (format #t "[~8x] ~A~%" obj 'rgbaf) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~f~%" (-> obj data 0)) + (format #t "~Ty: ~f~%" (-> obj data 1)) + (format #t "~Tz: ~f~%" (-> obj data 2)) + (format #t "~Tw: ~f~%" (-> obj data 3)) + (let ((t9-6 format) + (a0-7 #t) + (a1-6 "~Tquad: ~D~%") + ) + (TODO.LQ a2-6 obj) + (t9-6 a0-7 a1-6 a2-6) + ) + (format #t "~Tr: ~f~%" (-> obj data 0)) + (format #t "~Tg: ~f~%" (-> obj data 1)) + (format #t "~Tb: ~f~%" (-> obj data 2)) + (format #t "~Ta: ~f~%" (-> obj data 3)) + obj + ) + +;; definition of type plane +(deftype plane (vector) + ((a float :offset 0) + (b float :offset 4) + (c float :offset 8) + (d float :offset 12) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type plane +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect plane ((obj plane)) + (local-vars (a2-6 int)) + (format #t "[~8x] ~A~%" obj 'plane) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~f~%" (-> obj data 0)) + (format #t "~Ty: ~f~%" (-> obj data 1)) + (format #t "~Tz: ~f~%" (-> obj data 2)) + (format #t "~Tw: ~f~%" (-> obj data 3)) + (let ((t9-6 format) + (a0-7 #t) + (a1-6 "~Tquad: ~D~%") + ) + (TODO.LQ a2-6 obj) + (t9-6 a0-7 a1-6 a2-6) + ) + (format #t "~Ta: ~f~%" (-> obj data 0)) + (format #t "~Tb: ~f~%" (-> obj data 1)) + (format #t "~Tc: ~f~%" (-> obj data 2)) + (format #t "~Td: ~f~%" (-> obj data 3)) + obj + ) + +;; definition of type sphere +(deftype sphere (vector) + ((r float :offset 12) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type sphere +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect sphere ((obj sphere)) + (local-vars (a2-6 int)) + (format #t "[~8x] ~A~%" obj 'sphere) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~f~%" (-> obj data 0)) + (format #t "~Ty: ~f~%" (-> obj data 1)) + (format #t "~Tz: ~f~%" (-> obj data 2)) + (format #t "~Tw: ~f~%" (-> obj data 3)) + (let ((t9-6 format) + (a0-7 #t) + (a1-6 "~Tquad: ~D~%") + ) + (TODO.LQ a2-6 obj) + (t9-6 a0-7 a1-6 a2-6) + ) + (format #t "~Tr: ~f~%" (-> obj data 3)) + obj + ) + +;; definition of type isphere +(deftype isphere (vec4s) + () + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition of type box8s +(deftype box8s (structure) + ((data float 8 :offset-assert 0) + (quad uint128 2 :offset 0) + (vector vector 2 :offset 0) + (min vector :inline :offset 0) + (max vector :inline :offset 16) + ) + :method-count-assert 9 + :size-assert #x20 + :flag-assert #x900000020 + ) + +;; definition for method 3 of type box8s +(defmethod inspect box8s ((obj box8s)) + (format #t "[~8x] ~A~%" obj 'box8s) + (format #t "~Tdata[8] @ #x~X~%" (-> obj data)) + (format #t "~Tquad[2] @ #x~X~%" (-> obj data)) + (format #t "~Tvector[2] @ #x~X~%" (-> obj data)) + (format #t "~Tmin: #~%" (-> obj data)) + (format #t "~Tmax: #~%" (&-> obj data 4)) + obj + ) + +;; definition of type box8s-array +(deftype box8s-array (inline-array-class) + () + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type box8s-array +(defmethod inspect box8s-array ((obj box8s-array)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tallocated-length: ~D~%" (-> obj allocated-length)) + (format #t "~Tdata[0] @ #x~X~%" (&-> obj data 4)) + obj + ) + +;; failed to figure out what this is: +(set! (-> box8s-array heap-base) (the-as uint 32)) + +;; definition of type cylinder +(deftype cylinder (structure) + ((origin vector :inline :offset-assert 0) + (axis vector :inline :offset-assert 16) + (radius float :offset-assert 32) + (length float :offset-assert 36) + ) + :method-count-assert 11 + :size-assert #x28 + :flag-assert #xb00000028 + (:methods + (dummy-9 () none 9) + (dummy-10 () none 10) + ) + ) + +;; definition for method 3 of type cylinder +(defmethod inspect cylinder ((obj cylinder)) + (format #t "[~8x] ~A~%" obj 'cylinder) + (format #t "~Torigin: #~%" (-> obj origin)) + (format #t "~Taxis: #~%" (-> obj axis)) + (format #t "~Tradius: ~f~%" (-> obj radius)) + (format #t "~Tlength: ~f~%" (-> obj length)) + obj + ) + +;; definition of type cylinder-flat +(deftype cylinder-flat (structure) + ((origin vector :inline :offset-assert 0) + (axis vector :inline :offset-assert 16) + (radius float :offset-assert 32) + (length float :offset-assert 36) + ) + :method-count-assert 11 + :size-assert #x28 + :flag-assert #xb00000028 + (:methods + (dummy-9 () none 9) + (dummy-10 () none 10) + ) + ) + +;; definition for method 3 of type cylinder-flat +(defmethod inspect cylinder-flat ((obj cylinder-flat)) + (format #t "[~8x] ~A~%" obj 'cylinder-flat) + (format #t "~Torigin: #~%" (-> obj origin)) + (format #t "~Taxis: #~%" (-> obj axis)) + (format #t "~Tradius: ~f~%" (-> obj radius)) + (format #t "~Tlength: ~f~%" (-> obj length)) + obj + ) + +;; definition of type vertical-planes +(deftype vertical-planes (structure) + ((data uint128 4 :offset-assert 0) + ) + :method-count-assert 9 + :size-assert #x40 + :flag-assert #x900000040 + ) + +;; definition for method 3 of type vertical-planes +(defmethod inspect vertical-planes ((obj vertical-planes)) + (format #t "[~8x] ~A~%" obj 'vertical-planes) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + obj + ) + +;; definition of type vertical-planes-array +(deftype vertical-planes-array (basic) + ((length uint32 :offset-assert 4) + (data vertical-planes :dynamic :offset 16) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type vertical-planes-array +(defmethod inspect vertical-planes-array ((obj vertical-planes-array)) + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tdata[0] @ #x~X~%" (-> obj data)) + obj + ) + +;; definition of type qword +(deftype qword (structure) + ((data uint32 4 :offset-assert 0) + (byte uint8 16 :offset 0) + (hword uint16 8 :offset 0) + (word uint32 4 :offset 0) + (dword uint64 2 :offset 0) + (quad uint128 :offset 0) + (vector vector :inline :offset 0) + (vector4w vector4w :inline :offset 0) + ) + :method-count-assert 9 + :size-assert #x10 + :flag-assert #x900000010 + ) + +;; definition for method 3 of type qword +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +(defmethod inspect qword ((obj qword)) + (local-vars (a2-6 int)) + (format #t "[~8x] ~A~%" obj 'qword) + (format #t "~Tdata[4] @ #x~X~%" (-> obj data)) + (format #t "~Tbyte[16] @ #x~X~%" (-> obj data)) + (format #t "~Thword[8] @ #x~X~%" (-> obj data)) + (format #t "~Tword[4] @ #x~X~%" (-> obj data)) + (format #t "~Tdword[2] @ #x~X~%" (-> obj data)) + (let ((t9-6 format) + (a0-7 #t) + (a1-6 "~Tquad: ~D~%") + ) + (TODO.LQ a2-6 obj) + (t9-6 a0-7 a1-6 a2-6) + ) + (format #t "~Tvector: #~%" (-> obj data)) + (format #t "~Tvector4w: #~%" (-> obj data)) + obj + ) + +;; definition of type vector3s +(deftype vector3s (structure) + ((data float 3 :offset-assert 0) + (x float :offset 0) + (y float :offset 4) + (z float :offset 8) + ) + :method-count-assert 9 + :size-assert #xc + :flag-assert #x90000000c + ) + +;; definition for method 3 of type vector3s +(defmethod inspect vector3s ((obj vector3s)) + (format #t "[~8x] ~A~%" obj 'vector3s) + (format #t "~Tdata[3] @ #x~X~%" (-> obj data)) + (format #t "~Tx: ~f~%" (-> obj data 0)) + (format #t "~Ty: ~f~%" (-> obj data 1)) + (format #t "~Tz: ~f~%" (-> obj data 2)) + obj + ) + +;; definition for function vector-dot +;; INFO: Return type mismatch int vs float. +;; WARN: Unsupported inline assembly instruction kind - [153] +;; WARN: Unsupported inline assembly instruction kind - [154] +;; WARN: Unsupported inline assembly instruction kind - [157] +(defun vector-dot ((arg0 vector) (arg1 vector)) + (local-vars (f0-1 int)) + (let ((f0-0 (-> arg0 data 0)) + (f1-0 (-> arg0 data 1)) + (f2-0 (-> arg0 data 2)) + (f3-0 (-> arg1 data 0)) + (f4-0 (-> arg1 data 1)) + (f5-0 (-> arg1 data 2)) + ) + (.mula.s f0-0 f3-0) + (.madda.s f1-0 f4-0) + (.madd.s f0-1 f2-0 f5-0) + ) + (the-as float f0-1) + ) + +;; definition for function vector-dot-vu +;; INFO: Return type mismatch int vs float. +(defun vector-dot-vu ((arg0 vector) (arg1 vector)) + (local-vars (v0-0 int)) + (rlet ((vf1 :class vf) + (vf2 :class vf) + ) + (.lvf vf1 arg0) + (.lvf vf2 arg1) + (.mul.vf vf1 vf1 vf2) + (.add.y.vf vf1 vf1 vf1 :mask #b1) + (.add.z.vf vf1 vf1 vf1 :mask #b1) + (.mov v0-0 vf1) + (the-as float v0-0) + ) + ) + +;; definition for function vector4-dot +;; INFO: Return type mismatch int vs float. +;; WARN: Unsupported inline assembly instruction kind - [153] +;; WARN: Unsupported inline assembly instruction kind - [154] +;; WARN: Unsupported inline assembly instruction kind - [154] +;; WARN: Unsupported inline assembly instruction kind - [157] +(defun vector4-dot ((arg0 vector) (arg1 vector)) + (local-vars (f0-1 int)) + (let ((f0-0 (-> arg0 data 0)) + (f1-0 (-> arg0 data 1)) + (f2-0 (-> arg0 data 2)) + (f3-0 (-> arg0 data 3)) + (f4-0 (-> arg1 data 0)) + (f5-0 (-> arg1 data 1)) + (f6-0 (-> arg1 data 2)) + (f7-0 (-> arg1 data 3)) + ) + (.mula.s f0-0 f4-0) + (.madda.s f1-0 f5-0) + (.madda.s f2-0 f6-0) + (.madd.s f0-1 f3-0 f7-0) + ) + (the-as float f0-1) + ) + +;; definition for function vector4-dot-vu +;; INFO: Return type mismatch int vs float. +(defun vector4-dot-vu ((arg0 vector) (arg1 vector)) + (local-vars (v0-0 int)) + (rlet ((acc :class vf) + (vf0 :class vf) + (vf1 :class vf) + (vf2 :class vf) + (vf3 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf1 arg0) + (.lvf vf2 arg1) + (.mul.vf vf1 vf1 vf2) + (.add.w.vf vf3 vf0 vf0 :mask #b1) + (.mul.x.vf acc vf3 vf1 :mask #b1) + (.add.mul.y.vf acc vf3 vf1 acc :mask #b1) + (.add.mul.z.vf acc vf3 vf1 acc :mask #b1) + (.add.mul.w.vf vf1 vf3 vf1 acc :mask #b1) + (.mov v0-0 vf1) + (the-as float v0-0) + ) + ) + +;; definition for function vector+! +(defun vector+! ((arg0 vector) (arg1 vector) (arg2 vector)) + (rlet ((vf0 :class vf) + (vf4 :class vf) + (vf5 :class vf) + (vf6 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.mov.vf vf6 vf0 :mask #b1000) + (.lvf vf4 arg1) + (.lvf vf5 arg2) + (.add.vf vf6 vf4 vf5 :mask #b111) + (.svf arg0 vf6) + arg0 + ) + ) + +;; definition for function vector-! +(defun vector-! ((arg0 vector) (arg1 vector) (arg2 vector)) + (rlet ((vf0 :class vf) + (vf4 :class vf) + (vf5 :class vf) + (vf6 :class vf) + ) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.lvf vf4 arg1) + (.lvf vf5 arg2) + (.mov.vf vf6 vf0 :mask #b1000) + (.sub.vf vf6 vf4 vf5 :mask #b111) + (.svf arg0 vf6) + arg0 + ) + ) + +;; definition for function vector-zero! +;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ] +(defun vector-zero! ((arg0 vector)) + (local-vars (r0-0 none)) + (TODO.SQ r0-0 arg0) + arg0 + ) + +;; definition for function vector-reset! +(defun vector-reset! ((arg0 vector)) + (rlet ((vf0 :class vf)) + (.lvf vf0 (new 'static 'vector :x 0.0 :y 0.0 :z 0.0 :w 1.0)) + (.svf arg0 vf0) + arg0 + ) + ) + +;; definition for function vector-copy! +;; WARN: Inline assembly instruction marked with TODO - [TODO.LQ] +;; WARN: Inline assembly instruction marked with TODO - [TODO.SQ] +(defun vector-copy! ((arg0 vector) (arg1 vector)) + (local-vars (v1-0 int)) + (TODO.LQ v1-0 arg1) + (TODO.SQ v1-0 arg0) + arg0 + ) + +;; definition for symbol *zero-vector*, type vector +(define *zero-vector* (new 'static 'vector)) + +;; failed to figure out what this is: +(none) + diff --git a/test/decompiler/reference/vu1-macros_REF.gc b/test/decompiler/reference/vu1-macros_REF.gc new file mode 100644 index 000000000..ded789d55 --- /dev/null +++ b/test/decompiler/reference/vu1-macros_REF.gc @@ -0,0 +1,9 @@ +;;-*-Lisp-*- +(in-package goal) + +;; failed to figure out what this is: +(let ((v0-0 0)) + ) + +;; failed to figure out what this is: +(none) diff --git a/test/decompiler/test_FormExpressionBuild.cpp b/test/decompiler/test_FormExpressionBuild.cpp index b1e2d551c..164bc58f8 100644 --- a/test/decompiler/test_FormExpressionBuild.cpp +++ b/test/decompiler/test_FormExpressionBuild.cpp @@ -2822,4 +2822,131 @@ TEST_F(FormRegressionTest, LoopingCode) { " (the-as symbol #f)\n" " )"; test_with_expr(func, type, expected); +} + +TEST_F(FormRegressionTest, AbsAsSideEffect) { + std::string func = + "sll r0, r0, 0\n" + " dsubu v1, a1, a0\n" + " or a3, v1, r0\n" + " bltzl a3, L14\n" + + " dsubu a3, r0, a3\n" + + "L14:\n" + " slt a3, a2, a3\n" + " bne a3, r0, L15\n" + " sll r0, r0, 0\n" + + " or v0, a1, r0\n" + " beq r0, r0, L17\n" + " sll r0, r0, 0\n" + + "L15:\n" + " slt v1, v1, r0\n" + " bne v1, r0, L16\n" + " sll r0, r0, 0\n" + + " daddu v0, a0, a2\n" + " beq r0, r0, L17\n" + " sll r0, r0, 0\n" + + "L16:\n" + " dsubu v0, a0, a2\n" + + "L17:\n" + " jr ra\n" + " daddu sp, sp, r0"; + std::string type = "(function int int int int)"; + std::string expected = + "(let* ((v1-0 (- arg1 arg0))\n" + " (a3-0 (abs v1-0))\n" // modified + " )\n" + //" (set! a3-0 (abs a3-0))\n" + " (cond\n" + " ((>= arg2 a3-0)\n" + " arg1\n" + " )\n" + " ((>= v1-0 0)\n" + " (+ arg0 arg2)\n" + " )\n" + " (else\n" + " (- arg0 arg2)\n" + " )\n" + " )\n" + " )"; + test_with_expr(func, type, expected); +} + +// for github https://github.com/water111/jak-project/issues/332 +// method 11 bit-array +TEST_F(FormRegressionTest, AshPropagation) { + // (ash a2-0 a3-0) + std::string func = + "sll r0, r0, 0\n" + " dsra v1, a1, 3\n" + " daddu v1, v1, a0\n" + " lbu v1, 8(v1)\n" // (-> arg0 bytes (sar arg1 3)) [LOAD] + " addiu a2, r0, 1\n" + " andi a3, a1, 7\n" + " bgezl a3, L17\n" // use + + " dsllv a2, a2, a3\n" // use, def + + " dsubu a3, r0, a3\n" // use + " dsrav a2, a2, a3\n" // (ash 1 (logand arg1 7) + + "L17:\n" + " or v1, v1, a2\n" // (logior (-> arg0 bytes (sar arg1 3)) (ash 1 (logand arg1 7))) + " dsra a1, a1, 3\n" // compute source. + " daddu a0, a1, a0\n" + + " sb v1, 8(a0)\n" + " or v0, r0, r0\n" + " jr ra\n" + " daddu sp, sp, r0"; + std::string type = "(function bit-array int int)"; + std::string expected = + "(begin\n" + " (set!\n" + " (-> arg0 bytes (sar arg1 3))\n" + " (logior (-> arg0 bytes (sar arg1 3)) (the-as uint (ash 1 (logand arg1 7))))\n" + " )\n" + " 0\n" + " )"; + test_with_expr(func, type, expected); +} + +// for github https://github.com/water111/jak-project/issues/332 +// method 9 bit-array +// also checks output prop. +TEST_F(FormRegressionTest, AshPropagation2) { + // (ash a2-0 a3-0) + std::string func = + "sll r0, r0, 0\n" + "L20:\n" + " dsra v1, a1, 3\n" + " daddu v1, v1, a0\n" + " lbu v1, 8(v1)\n" + " daddiu v0, s7, 8\n" + " addiu a0, r0, 1\n" + " andi a1, a1, 7\n" + " bgezl a1, L21\n" + + " dsllv a0, a0, a1\n" + + " dsubu a1, r0, a1\n" + " dsrav a0, a0, a1\n" + + "L21:\n" + " and v1, v1, a0\n" + " movz v0, s7, v1\n" + " jr ra\n" + " daddu sp, sp, r0"; + std::string type = "(function bit-array int symbol)"; + std::string expected = + "(let ((v1-2 (-> arg0 bytes (sar arg1 3))))\n" + " (nonzero? (logand v1-2 (the-as uint (ash 1 (logand arg1 7)))))\n" + " )"; + test_with_expr(func, type, expected); } \ No newline at end of file diff --git a/test/decompiler/test_InstructionDecode.cpp b/test/decompiler/test_InstructionDecode.cpp index 38b5a57ac..849b01119 100644 --- a/test/decompiler/test_InstructionDecode.cpp +++ b/test/decompiler/test_InstructionDecode.cpp @@ -33,4 +33,15 @@ TEST(InstructionDecode, VSQRT) { LinkedWord vdiv_word(vdiv_test); auto instr = decode_instruction(vdiv_word, file, 0, 0); EXPECT_EQ(instr.to_string({}), "vsqrt Q, vf20.z"); +} + +TEST(Instruction, IntelMaskMove) { + init_opcode_info(); + LinkedObjectFile file; + u32 vmove_instr = 0b010010'1'1100'00001'00010'01100111100; + LinkedWord vmove_word(vmove_instr); + auto instr = decode_instruction(vmove_word, file, 0, 0); + EXPECT_EQ(instr.to_string({}), "vmove.xy vf1, vf2"); + // this should be flipped from the PS2... + EXPECT_EQ(instr.cop2_dest_mask_intel(), 0b0011); } \ No newline at end of file diff --git a/test/offline/offline_test_main.cpp b/test/offline/offline_test_main.cpp index 83ce17852..fc94a8f91 100644 --- a/test/offline/offline_test_main.cpp +++ b/test/offline/offline_test_main.cpp @@ -6,18 +6,29 @@ #include "decompiler/config.h" #include "decompiler/ObjectFile/ObjectFileDB.h" #include "goalc/compiler/Compiler.h" +#include "common/util/Timer.h" namespace { // the object files to test -const std::unordered_set g_object_files_to_decompile = { - "gcommon", "gstring-h", "gkernel-h", "gkernel", /*"pskernel",*/ "gstring", "dgo-h", "gstate", -}; +const std::unordered_set g_object_files_to_decompile = {"gcommon", + "gstring-h", + "gkernel-h", + "gkernel", + /*"pskernel",*/ "gstring", + "dgo-h", + "gstate", + "types-h", + "vu1-macros", + "math", + "vector-h", + "bounding-box-h", + /* gap */ "bounding-box"}; // the object files to check against a reference in test/decompiler/reference const std::vector g_object_files_to_check_against_reference = { "gcommon", // NOTE: this file needs work, but adding it for now just to test the framework. - "gstring-h", "gkernel-h", "gkernel", "gstring", "dgo-h", "gstate", -}; + "gstring-h", "gkernel-h", "gkernel", "gstring", "dgo-h", "gstate", + "types-h", "vu1-macros", "math", "vector-h", "bounding-box-h", /* gap */ "bounding-box"}; // the functions we expect the decompiler to skip const std::unordered_set expected_skip_in_decompiler = { @@ -39,14 +50,16 @@ const std::unordered_set expected_skip_in_decompiler = { "kernel-check-hardwired-addresses", // ps2 ee kernel debug hook "kernel-read-function", // ps2 ee kernel debug hook "kernel-write-function", // ps2 ee kernel debug hook - "kernel-copy-function" // ps2 ee kernel debug hook + "kernel-copy-function", // ps2 ee kernel debug hook + // math + "rand-uint31-gen", // weird and terrible random generator + // bounding-box + "(method 9 bounding-box)", // handwritten asm loop + "(method 14 bounding-box)", // handwritten asm loop }; const std::unordered_set skip_in_compiling = { - ////////////////////// - // GCOMMON - ////////////////////// - + /// GCOMMON // these functions are not implemented by the compiler in OpenGOAL, but are in GOAL. "abs", "ash", "min", "max", "lognor", // weird PS2 specific debug registers: @@ -60,23 +73,34 @@ const std::unordered_set skip_in_compiling = { // inline assembly "valid?", - ////////////////////// - // GKERNEL-H - ////////////////////// + /// GKERNEL-H // bitfields, possibly inline assembly "(method 2 handle)", - ////////////////////// - // GKERNEL - ////////////////////// + /// GKERNEL // asm "(method 10 process)", - ////////////////////// - // GSTATE - ////////////////////// + /// GSTATE "enter-state", // stack pointer asm + /// MATH + "rand-vu-init", "rand-vu", "rand-vu-nostep", // random hardware + "log2", // weird tricky int-as-float stuff + + /// VECTOR-H + "(method 3 vector4w)", // print quad + "(method 3 vector8h)", // print quad + "(method 3 vector16b)", // print quad + "(method 3 vector)", // print quad + "(method 3 rgbaf)", // print quad + "(method 3 plane)", // print quad + "(method 3 sphere)", // print quad + "(method 3 qword)", // print quad + "vector-zero!", // i128 + "vector-copy!", // i128 + "vector-dot", // fpu acc + "vector4-dot", // fpu acc }; // default location for the data. It can be changed with a command line argument. @@ -264,7 +288,7 @@ TEST_F(OfflineDecompilation, TypeAnalysis) { int failed_count = 0; db->for_each_function([&](decompiler::Function& func, int, decompiler::ObjectFileData&) { if (!func.suspected_asm) { - if (!func.ir2.env.has_type_analysis() || !func.ir2.types_succeeded) { + if (!func.ir2.env.has_type_analysis() || !func.ir2.env.types_succeeded) { lg::error("Function {} failed types", func.guessed_name.to_string()); failed_count++; } @@ -359,18 +383,36 @@ TEST_F(OfflineDecompilation, Reference) { } } +namespace { +int line_count(const std::string& str) { + int result = 0; + for (auto& c : str) { + if (c == '\n') { + result++; + } + } + return result; +} +} // namespace + TEST_F(OfflineDecompilation, Compile) { Compiler compiler; compiler.run_front_end_on_string(file_util::read_text_file(file_util::get_file_path( {"test", "decompiler", "reference", "all_forward_declarations.gc"}))); + Timer timer; + int total_lines = 0; for (auto& file : g_object_files_to_check_against_reference) { auto& obj_l = db->obj_files_by_name.at(file); ASSERT_EQ(obj_l.size(), 1); std::string src = db->ir2_final_out(obj_l.at(0), skip_in_compiling); + total_lines += line_count(src); compiler.run_full_compiler_on_string_no_save(src); } + auto time = timer.getSeconds(); + lg::info("Total Lines Compiled: {}. Lines/second: {:.1f}\n", total_lines, + (float)total_lines / time); } \ No newline at end of file