From 78928e4c04b43c93ccda82d8e2e4e31d6e6158ea Mon Sep 17 00:00:00 2001 From: water Date: Sat, 14 Aug 2021 23:15:10 -0400 Subject: [PATCH] temp --- decompiler/Disasm/Register.cpp | 2 +- decompiler/Function/CfgVtx.cpp | 4 + decompiler/IR2/AtomicOpTypeAnalysis.cpp | 6 +- decompiler/IR2/Env.cpp | 8 + decompiler/IR2/Form.cpp | 4 + decompiler/IR2/FormExpressionAnalysis.cpp | 18 + decompiler/IR2/bitfields.cpp | 26 + decompiler/IR2/bitfields.h | 2 + decompiler/config/all-types.gc | 57 +- .../config/jak1_ntsc_black_label/hacks.jsonc | 4 +- .../jak1_ntsc_black_label/label_types.jsonc | 14 + .../stack_structures.jsonc | 4 + .../jak1_ntsc_black_label/type_casts.jsonc | 49 +- .../jak1_ntsc_black_label/var_names.jsonc | 68 +- decompiler/util/data_decompile.cpp | 2 +- goal_src/engine/data/art-h.gc | 3 +- goal_src/engine/dma/dma-bucket.gc | 20 +- goal_src/engine/draw/drawable.gc | 4 +- goal_src/engine/gfx/eye-h.gc | 2 + goal_src/engine/gfx/hw/display-h.gc | 2 +- goal_src/engine/gfx/hw/vu1-user-h.gc | 4 +- goal_src/engine/gfx/merc/merc-blend-shape.gc | 115 +++ goal_src/engine/gfx/merc/merc-h.gc | 32 +- goal_src/engine/gfx/merc/merc-vu1.gc | 2 + goal_src/engine/gfx/merc/merc.gc | 681 +++++++++++++++++- goal_src/engine/level/level.gc | 2 +- goal_src/engine/load/loader.gc | 6 +- 27 files changed, 1070 insertions(+), 71 deletions(-) diff --git a/decompiler/Disasm/Register.cpp b/decompiler/Disasm/Register.cpp index 6811a2e360..8917b21fef 100644 --- a/decompiler/Disasm/Register.cpp +++ b/decompiler/Disasm/Register.cpp @@ -20,7 +20,7 @@ const bool allowed_local_gprs[Reg::MAX_GPR] = { true /*S0*/, true /*S1*/, true /*S2*/, true /*S3*/, true /*S4*/, true /*S5*/, false /*S6*/, false /*S7*/, true /*T8*/, true /*T9*/, false /*K0*/, false /*K1*/, - true /*GP*/, true /*SP*/, false /*FP*/, false /*RA*/ + true /*GP*/, true /*SP*/, false /*FP*/, true /*RA*/ }; // clang-format on } // namespace Reg diff --git a/decompiler/Function/CfgVtx.cpp b/decompiler/Function/CfgVtx.cpp index 6e0110155f..3f98b6c548 100644 --- a/decompiler/Function/CfgVtx.cpp +++ b/decompiler/Function/CfgVtx.cpp @@ -1659,6 +1659,10 @@ bool ControlFlowGraph::find_cond_w_else(const CondWithElseLengthHack& hack) { return true; } + if (b0->end_branch.asm_branch) { + return true; + } + // printf("cwe try %s %s\n", c0->to_string().c_str(), b0->to_string().c_str()); // first condition should have the _option_ to fall through to first body diff --git a/decompiler/IR2/AtomicOpTypeAnalysis.cpp b/decompiler/IR2/AtomicOpTypeAnalysis.cpp index 59f23b1e5b..c4cb7b8daa 100644 --- a/decompiler/IR2/AtomicOpTypeAnalysis.cpp +++ b/decompiler/IR2/AtomicOpTypeAnalysis.cpp @@ -261,10 +261,8 @@ TP_Type get_stack_type_at_constant_offset(int offset, if (offset == structure.hint.stack_offset) { // special case just getting the variable - if (structure.hint.container_type == StackStructureHint::ContainerType::NONE || - structure.hint.container_type == StackStructureHint::ContainerType::INLINE_ARRAY) { - return TP_Type::make_from_ts(coerce_to_reg_type(structure.ref_type)); - } + + return TP_Type::make_from_ts(coerce_to_reg_type(structure.ref_type)); } // Note: GOAL doesn't seem to constant propagate memory access on the stack, so the code diff --git a/decompiler/IR2/Env.cpp b/decompiler/IR2/Env.cpp index 2db0a059a2..dd1b876695 100644 --- a/decompiler/IR2/Env.cpp +++ b/decompiler/IR2/Env.cpp @@ -563,6 +563,14 @@ void Env::set_stack_structure_hints(const std::vector& hints type_info->get_in_memory_alignment()); } } break; + + case StackStructureHint::ContainerType::ARRAY: { + TypeSpec base_typespec = dts->parse_type_spec(hint.element_type); + entry.ref_type = TypeSpec("pointer", {TypeSpec(base_typespec)}); + entry.size = 1; // we assume that there is no constant propagation into this array and + // make this only trigger in get_stack_type if we hit exactly. + break; + } default: assert(false); } diff --git a/decompiler/IR2/Form.cpp b/decompiler/IR2/Form.cpp index 428e65580a..153560da17 100644 --- a/decompiler/IR2/Form.cpp +++ b/decompiler/IR2/Form.cpp @@ -2621,6 +2621,10 @@ goos::Object StackStructureDefElement::to_form_internal(const Env&) const { return pretty_print::build_list(fmt::format("new 'stack-no-clear 'inline-array '{} {}", m_entry.ref_type.get_single_arg().print(), m_entry.hint.container_size)); + case StackStructureHint::ContainerType::ARRAY: + return pretty_print::build_list(fmt::format("new 'stack-no-clear 'array '{} {}", + m_entry.ref_type.get_single_arg().print(), + m_entry.hint.container_size)); default: assert(false); } diff --git a/decompiler/IR2/FormExpressionAnalysis.cpp b/decompiler/IR2/FormExpressionAnalysis.cpp index 9e606cd051..345e83543c 100644 --- a/decompiler/IR2/FormExpressionAnalysis.cpp +++ b/decompiler/IR2/FormExpressionAnalysis.cpp @@ -2140,6 +2140,24 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack fmt::print("invalid bf set: {}\n", src_as_bf_set->to_string(env)); } + // setting a bitfield to zero is wonky. + auto bfa = dynamic_cast(m_src->try_as_single_element()); + if (bfa) { + fmt::print("setting bfa: {}\n", bfa->to_string(env)); + auto zero_set = bfa->get_set_field_0(env.dts->ts); + if (zero_set) { + auto field_token = DerefToken::make_field_name(zero_set->name()); + auto loc_elt = pool.alloc_element(m_dst, false, field_token); + loc_elt->inline_nested(); + auto loc = pool.alloc_single_form(nullptr, loc_elt); + loc->parent_element = this; + m_dst = loc; + auto zero = SimpleAtom::make_int_constant(0); + auto zero_form = pool.alloc_single_element_form(nullptr, zero); + m_src = zero_form; + } + } + const std::pair in_place_ops[] = { {FixedOperatorKind::ADDITION, FixedOperatorKind::ADDITION_IN_PLACE}, {FixedOperatorKind::ADDITION_PTR, FixedOperatorKind::ADDITION_PTR_IN_PLACE}, diff --git a/decompiler/IR2/bitfields.cpp b/decompiler/IR2/bitfields.cpp index 04262241a5..db63d806a2 100644 --- a/decompiler/IR2/bitfields.cpp +++ b/decompiler/IR2/bitfields.cpp @@ -379,6 +379,32 @@ std::string BitfieldAccessElement::debug_print(const Env& env) const { return result; } +std::optional BitfieldAccessElement::get_set_field_0(const TypeSystem& ts) const { + if (m_got_pcpyud) { + return {}; + } + if (m_steps.size() != 1) { + return {}; + } + + auto& step = m_steps.at(0); + if (step.kind != BitfieldManip::Kind::LOGAND_WITH_CONSTANT_INT) { + return {}; + } + + u64 mask = step.amount; + auto type = ts.lookup_type(m_type); + auto as_bitfield = dynamic_cast(type); + assert(as_bitfield); + // use the mask to figure out the field. + auto field = find_field_from_mask(ts, as_bitfield, ~mask, m_got_pcpyud); + if (field) { + return field; + } else { + return {}; + } +} + /*! * Add a step to the bitfield access. If this completes the access, returns a form representing the * access diff --git a/decompiler/IR2/bitfields.h b/decompiler/IR2/bitfields.h index 8715378b67..e828fba3c5 100644 --- a/decompiler/IR2/bitfields.h +++ b/decompiler/IR2/bitfields.h @@ -103,6 +103,8 @@ class BitfieldAccessElement : public FormElement { void push_pcpyud(const TypeSystem& ts, FormPool& pool, const Env& env); std::string debug_print(const Env& env) const; bool has_pcpyud() const { return m_got_pcpyud; } + const std::vector& steps() const { return m_steps; } + std::optional get_set_field_0(const TypeSystem& ts) const; private: bool m_got_pcpyud = false; diff --git a/decompiler/config/all-types.gc b/decompiler/config/all-types.gc index fa60a2ce3e..004af9d440 100644 --- a/decompiler/config/all-types.gc +++ b/decompiler/config/all-types.gc @@ -3477,9 +3477,9 @@ ;; - Functions -(define-extern dma-buffer-add-buckets (function dma-buffer int dma-bucket)) -(define-extern dma-buffer-patch-buckets (function dma-bucket int dma-bucket)) -(define-extern dma-bucket-insert-tag (function dma-bucket bucket-id pointer (pointer dma-tag) pointer)) +(define-extern dma-buffer-add-buckets (function dma-buffer int (inline-array dma-bucket))) +(define-extern dma-buffer-patch-buckets (function (inline-array dma-bucket) int (inline-array dma-bucket))) +(define-extern dma-bucket-insert-tag (function (inline-array dma-bucket) bucket-id pointer (pointer dma-tag) pointer)) ;; ---------------------- @@ -4284,7 +4284,7 @@ (vu1-buf dma-buffer :offset 8) (debug-buf dma-buffer :offset 36) (global-buf dma-buffer :offset 40) - (bucket-group dma-bucket :offset 44) + (bucket-group (inline-array dma-bucket) :offset 44) (buffer dma-buffer 11 :offset 4) (profile-bar profile-bar 2 :offset 48) (run-time uint64 :offset 56) @@ -7574,7 +7574,7 @@ :size-assert #x14 :flag-assert #xd00000014 (:methods - (dummy-9 (_type_) _type_ 9) + (login (_type_) _type_ 9) (dummy-10 (_type_ string type) art-element 10) (dummy-11 (_type_ string type) int 11) (dummy-12 (_type_) symbol 12) @@ -7587,7 +7587,6 @@ :size-assert #x20 :flag-assert #xd00000020 (:methods - (dummy-9 (_type_) _type_ 9) (dummy-10 (_type_ string type) art-element 10) (dummy-11 (_type_ string type) int 11) (dummy-12 (_type_) symbol 12) @@ -7609,6 +7608,7 @@ (artist-step float :offset 28) (master-art-group-name string :offset 32) (master-art-group-index int32 :offset 36) + (blerc-data (pointer uint8) :offset 40) (frames pointer :offset 44) ;; this structure doesn't exist? it's a structure with an array of joint-anim-compressed-hdr starting at offset 12 (data joint-anim-compressed :dynamic :offset-assert 48) ) @@ -7619,7 +7619,7 @@ (deftype art-group (art) ((info file-info :offset 4) - (data art-element :dynamic :offset 32) + (data art-element :dynamic :offset 32) ;; might just be art? ) :method-count-assert 15 :size-assert #x20 @@ -7854,7 +7854,7 @@ :size-assert #x18 :flag-assert #xa00000018 (:methods - (dummy-9 () none 9) + (login-adgifs (_type_) none 9) ) ) @@ -7895,6 +7895,7 @@ ((matrix-number uint8 :offset-assert 0) (matrix-dest uint8 :offset-assert 1) ) + :pack-me :method-count-assert 9 :size-assert #x2 :flag-assert #x900000002 @@ -7905,7 +7906,7 @@ (lump-four-count uint8 :offset-assert 1) (fp-qwc uint8 :offset-assert 2) (mat-xfer-count uint8 :offset-assert 3) - (mat-dest-data uint8 :dynamic :offset-assert 4) + (mat-dest-data merc-mat-dest :inline :dynamic :offset-assert 4) ) :method-count-assert 9 :size-assert #x4 @@ -7970,6 +7971,9 @@ :flag-assert #x900000010 ) +;;effect-bits: +;; 1 - swap with last effect. + (deftype merc-effect (structure) ((frag-geo merc-fragment :offset-assert 0) (frag-ctrl merc-fragment-control :offset-assert 4) @@ -7984,12 +7988,15 @@ (dummy1 uint8 :offset-assert 26) (envmap-usage uint8 :offset-assert 27) (extra-info merc-extra-info :offset-assert 28) + + ;; added + (data uint64 4 :offset 0) ) :method-count-assert 10 :size-assert #x20 :flag-assert #xa00000020 (:methods - (dummy-9 () none 9) + (login-adgifs (_type_) none 9) ) ) @@ -8038,7 +8045,7 @@ (st-vif-add uint32 :offset-assert 16) (st-int-off uint16 :offset-assert 20) (st-int-scale uint16 :offset-assert 22) - (effect-count uint32 :offset-assert 24) + (effect-count uint32 :offset-assert 24) ;; number of effects in merc-ctrl effect (blend-target-count uint32 :offset-assert 28) (fragment-count uint16 :offset-assert 32) (tri-count uint16 :offset-assert 34) @@ -8089,8 +8096,8 @@ ) (deftype merc-vu1-low-mem (structure) - ((tri-strip-gif qword :inline :offset-assert 0) - (ad-gif qword :inline :offset-assert 16) + ((tri-strip-gif gs-gif-tag :inline :offset-assert 0) ;; was qword + (ad-gif gs-gif-tag :inline :offset-assert 16) ;; was qword (hvdf-offset vector :inline :offset-assert 32) (perspective uint128 4 :offset-assert 48) (fog vector :inline :offset-assert 112) @@ -8149,7 +8156,7 @@ ;; - Functions -(define-extern merc-fragment-fp-data (function merc-fragment pointer)) +(define-extern merc-fragment-fp-data (function merc-fragment merc-fp-header)) ;; ---------------------- @@ -15285,14 +15292,14 @@ ;; - Functions (define-extern setup-blerc-chains-for-one-fragment function) -(define-extern setup-blerc-chains function) +(define-extern setup-blerc-chains (function merc-ctrl (pointer int16) dma-buffer none)) (define-extern blerc-stats-init (function none)) (define-extern blerc-init (function none)) (define-extern blerc-a-fragment function) (define-extern dma-from-spr function) (define-extern merc-dma-chain-to-spr function) (define-extern blerc-execute (function none)) -(define-extern merc-blend-shape function) +(define-extern merc-blend-shape (function process-drawable object)) ;; - Unknowns @@ -15308,18 +15315,18 @@ ;; - Functions -(define-extern merc-vu1-init-buffer function) -(define-extern merc-vu1-initialize-chain function) -(define-extern merc-vu1-add-vu-function function) -(define-extern get-eye-block function) -(define-extern merc-stats-display function) -(define-extern merc-stats function) -(define-extern merc-edge-stats function) +(define-extern merc-vu1-init-buffer (function bucket-id gs-test int none)) +(define-extern merc-vu1-initialize-chain (function dma-gif-packet none)) +(define-extern merc-vu1-add-vu-function (function dma-packet vu-function int dma-gif-packet)) +(define-extern get-eye-block (function int int int)) +(define-extern merc-stats-display (function merc-ctrl none)) +(define-extern merc-stats (function none)) +(define-extern merc-edge-stats (function none)) (define-extern merc-vu1-init-buffers (function none)) ;; - Unknowns -;;(define-extern *merc-ctrl-header* object) ;; unknown type +(define-extern *merc-ctrl-header* merc-ctrl-header) ;; ---------------------- @@ -15840,7 +15847,7 @@ ;; - Unknowns -;;(define-extern background-vu0-block object) ;; unknown type +(define-extern background-vu0-block vu-function) ;; ---------------------- diff --git a/decompiler/config/jak1_ntsc_black_label/hacks.jsonc b/decompiler/config/jak1_ntsc_black_label/hacks.jsonc index ca78098841..6df1744675 100644 --- a/decompiler/config/jak1_ntsc_black_label/hacks.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/hacks.jsonc @@ -118,7 +118,6 @@ // merc-blend-shape "setup-blerc-chains-for-one-fragment", // F: asm branching - "blerc-execute", // F: asm branching "merc-dma-chain-to-spr", // F: asm branching "blerc-a-fragment", @@ -517,7 +516,8 @@ "get-string-length":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50], "unpack-comp-rle":[1, 3, 5, 6], "(method 16 level)":[ 1, 5, 13, 14, 15, 19, 26, 53], - "unpack-comp-huf":[2, 4, 5, 6, 7, 8, 9] + "unpack-comp-huf":[2, 4, 5, 6, 7, 8, 9], + "blerc-execute":[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33] } } diff --git a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc index 745ca97576..e6c74f94d9 100644 --- a/decompiler/config/jak1_ntsc_black_label/label_types.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/label_types.jsonc @@ -1684,6 +1684,20 @@ ["L393", "rgba", true] ], + "merc-blend-shape": [ + ["L62", "(pointer int16)", true, 32] + ], + + "merc": [ + ["L50", "uint64", true], + ["L51", "uint64", true], + ["L52", "uint64", true], + ["L54", "uint64", true], + ["L53", "uint64", true], + ["L55", "uint64", true], + ["L56", "uint64", true] + ], + // please do not add things after this entry! git is dumb. "object-file-that-doesnt-actually-exist-and-i-just-put-this-here-to-prevent-merge-conflicts-with-this-file": [] } diff --git a/decompiler/config/jak1_ntsc_black_label/stack_structures.jsonc b/decompiler/config/jak1_ntsc_black_label/stack_structures.jsonc index ca587ed0c5..931a681929 100644 --- a/decompiler/config/jak1_ntsc_black_label/stack_structures.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/stack_structures.jsonc @@ -1023,5 +1023,9 @@ [16, "vector"] ], + "merc-blend-shape": [ + [16, ["array", "int16", 128]] + ], + "placeholder-do-not-add-below!": [] } diff --git a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc index 5cebe6dbb0..d15fae4484 100644 --- a/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/type_casts.jsonc @@ -152,12 +152,13 @@ ], "dma-buffer-patch-buckets": [ - [7, "a0", "pointer"], - [14, "a0", "pointer"], - [3, "a0", "dma-bucket"], - [11, "a0", "dma-bucket"], - [13, "a0", "dma-bucket"], - [19, "a0", "dma-bucket"] + [7, "a0", "(inline-array dma-bucket)"], + [8, "a3", "pointer"], + [14, "a0", "(inline-array dma-bucket)"], + [3, "a0", "(inline-array dma-bucket)"], + [11, "a0", "(inline-array dma-bucket)"], + [13, "a0", "(inline-array dma-bucket)"], + [19, "a0", "(inline-array dma-bucket)"] ], "dma-bucket-insert-tag": [ @@ -2174,5 +2175,41 @@ [[21, 23], "t3", "(pointer uint16)"] ], + "(method 9 merc-fragment)": [ + [[13,161], "s3", "adgif-shader"] + ], + + "(method 9 merc-effect)": [ + [49, "s4", "pointer"], + [50, "s5", "pointer"], + [[0, 49], "s4", "merc-fragment"], + [[0, 50], "s5", "merc-fragment-control"] + ], + + "merc-vu1-initialize-chain": [ + [[19, 47], "s5", "merc-vu1-low-mem"], + [58, "gp", "(inline-array dma-packet)"], + [[12, 18], "gp", "(pointer vif-tag)"] + ], + + "merc-vu1-init-buffer":[ + [[27, 31], "a0", "dma-packet"], + [[37, 40], "a0", "gs-gif-tag"], + [44, "a0", "(pointer gs-test)"], + [46, "a0", "(pointer gs-reg64)"], + [[55, 58], "v1", "dma-packet"] + ], + + "(method 8 merc-ctrl)": [ + [46, "s2", "pointer"], // was merc-fragment-control + [[22, 45], "s2", "merc-fragment-control"], + [[89, 93], "a1", "merc-blend-ctrl"], + [103, "a1", "pointer"] + ], + + "merc-edge-stats": [ + [[33, 35], "v1", "merc-ctrl"] + ], + "placeholder-do-not-add-below": [] } diff --git a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc index ce42b06f17..ac65ea16eb 100644 --- a/decompiler/config/jak1_ntsc_black_label/var_names.jsonc +++ b/decompiler/config/jak1_ntsc_black_label/var_names.jsonc @@ -3159,7 +3159,73 @@ "s3-2":"list-len", "v1-49":"list-qwc", "v0-1":"result" - + } + }, + + "(method 9 merc-fragment)": { + "vars":{ + "s5-0":"fp-data", + "s4-0":"eye-ctrl", + "s3-0":"shader", + "v1-7":"eye-tex-block", + "v1-34":"eye-tex-block-2", + "v1-57":"tex", + "a0-36":"seg" + } + }, + + "(method 9 merc-effect)": { + "vars":{ + "v1-0":"data", + "v1-1":"tex", + "a0-8":"seg", + "s3-0":"frag-idx", + "s2-0":"ctrl-size", + "s1-0":"geo-size", + "s4-0":["geo", "merc-fragment"], + "s5-0":["ctrl", "merc-fragment-control"] + } + }, + + "merc-vu1-add-vu-function": { + "args":["dma", "func", "flush-mode"], + "vars": { + "v1-0":"func-data", + "a3-0":"qwc", + "a1-1":"dst", + "t0-1":"qwc-this-time" + } + }, + + "(method 8 merc-ctrl)": { + "vars": { + "s4-0":"ctrl-mem", + "s3-0":"effect-idx", + "s2-0":["fctrl", "merc-fragment-control"], + "s1-0":"frag-idx", + "v1-35":"effect-mem", + "a0-15":"effect-idx2", + "a1-9":["bctrl", "merc-blend-ctrl"], + "a2-1":"blend-frag-idx" + } + }, + + "(method 9 merc-ctrl)": { + "vars":{ + "v1-3":"seg", + "s5-0":"effect-idx", + "a0-4":"idx-with-bit1", + "a0-7":"this-effect", + "a1-5":"last-effect", + "a2-6":"copy-idx" + } + }, + + "merc-vu1-init-buffer": { + "args":["dma-bucket", "test"], + "vars": { + "gp-0":"bucket", + "s4-0":"dma-buf" } }, "aaaaaaaaaaaaaaaaaaaaaaa": {} diff --git a/decompiler/util/data_decompile.cpp b/decompiler/util/data_decompile.cpp index 0f124156a1..f450728b5c 100644 --- a/decompiler/util/data_decompile.cpp +++ b/decompiler/util/data_decompile.cpp @@ -1043,7 +1043,7 @@ goos::Object decompile_pair_elt(const LinkedWord& word, } else if (word.kind == LinkedWord::EMPTY_PTR) { return pretty_print::to_symbol("'()"); } else if (word.kind == LinkedWord::PLAIN_DATA && (word.data & 0b111) == 0) { - return pretty_print::to_symbol(fmt::format("(the binteger {})", word.data >> 3)); + return pretty_print::to_symbol(fmt::format("(the binteger {})", ((s32)word.data) >> 3)); } else { throw std::runtime_error(fmt::format("Pair elt did not have a good word kind")); } diff --git a/goal_src/engine/data/art-h.gc b/goal_src/engine/data/art-h.gc index a4b61e2ad7..a189ae473d 100644 --- a/goal_src/engine/data/art-h.gc +++ b/goal_src/engine/data/art-h.gc @@ -128,7 +128,7 @@ :size-assert #x14 :flag-assert #xd00000014 (:methods - (dummy-9 (_type_) _type_ 9) + (login (_type_) _type_ 9) (dummy-10 (_type_ string type) art-element 10) (dummy-11 (_type_ string type) int 11) (dummy-12 (_type_) symbol 12) @@ -141,7 +141,6 @@ :size-assert #x20 :flag-assert #xd00000020 (:methods - (dummy-9 (_type_) _type_ 9) (dummy-10 (_type_ string type) art-element 10) (dummy-11 (_type_ string type) int 11) (dummy-12 (_type_) symbol 12) diff --git a/goal_src/engine/dma/dma-bucket.gc b/goal_src/engine/dma/dma-bucket.gc index 651dc76dce..3e51532885 100644 --- a/goal_src/engine/dma/dma-bucket.gc +++ b/goal_src/engine/dma/dma-bucket.gc @@ -54,31 +54,30 @@ ) ;; update base ptr of dma-buffer to point after the buckets. (set! (-> dma-buf base) (the-as pointer current-bucket)) - initial-bucket + (the (inline-array dma-bucket) initial-bucket) ) ) - -(defun dma-buffer-patch-buckets ((bucket dma-bucket) (count int)) +(defun dma-buffer-patch-buckets ((bucket (inline-array dma-bucket)) (count int)) "After adding all data to buckets, call this to stitch together the chains for - count consecutive buckets" + count consecutive buckets" (when (nonzero? bucket) (dotimes (i count) ;; set last tag's address to the next bucket. - (set! (-> bucket last 0 addr) (the-as int (&+ (the-as pointer bucket) 16))) + (set! (-> bucket 0 last 0 addr) (the-as int (the-as pointer (-> bucket 1)))) ;; clear last pointer. - (set! (-> bucket last) (the-as (pointer dma-tag) 0)) + (set! (-> bucket 0 last) (the-as (pointer dma-tag) 0)) ;; next bucket - (set! bucket (&+ bucket 16)) + (set! bucket (the-as (inline-array dma-bucket) (-> bucket 1))) ) ) bucket ) -(defun dma-bucket-insert-tag ((base dma-bucket) (idx bucket-id) (tag-start pointer) (tag-end (pointer dma-tag))) - "Add a dma chain to the idx bucket" +(defun dma-bucket-insert-tag ((base (inline-array dma-bucket)) (idx bucket-id) (tag-start pointer) (tag-end (pointer dma-tag))) + "Add a DMA chain to the bucket" ;; find the bucket - (let ((bucket (the-as dma-bucket (&+ base (the-as uint (shl idx 4)))))) + (let ((bucket (-> base idx))) ;; update our last bucket to point to this one. ;; this is abusing the dma-bucket type to set the "addr" field of the dma-tag. (set! (-> (the-as dma-bucket (-> bucket last)) next) (the-as uint tag-start)) @@ -87,3 +86,4 @@ ) tag-start ) + diff --git a/goal_src/engine/draw/drawable.gc b/goal_src/engine/draw/drawable.gc index 85892e58e2..3f4e373396 100644 --- a/goal_src/engine/draw/drawable.gc +++ b/goal_src/engine/draw/drawable.gc @@ -232,9 +232,7 @@ ) ;; add the buckets - (set! (-> new-frame bucket-group) - (the-as dma-bucket (dma-buffer-add-buckets (-> new-frame calc-buf) 69)) - ) + (set! (-> new-frame bucket-group)(dma-buffer-add-buckets (-> new-frame calc-buf) 69)) ) ;; initialize the debug bucket diff --git a/goal_src/engine/gfx/eye-h.gc b/goal_src/engine/gfx/eye-h.gc index db04ac9ac6..3e288bf6ae 100644 --- a/goal_src/engine/gfx/eye-h.gc +++ b/goal_src/engine/gfx/eye-h.gc @@ -66,3 +66,5 @@ (set! (-> *eye-control-array* data v1-5 random-time) (the-as uint 60)) (set! (-> *eye-control-array* data v1-5 blink) 0.0) ) + +(define-extern get-eye-block (function int int int)) \ No newline at end of file diff --git a/goal_src/engine/gfx/hw/display-h.gc b/goal_src/engine/gfx/hw/display-h.gc index 56b8669906..58dd0ca2e5 100644 --- a/goal_src/engine/gfx/hw/display-h.gc +++ b/goal_src/engine/gfx/hw/display-h.gc @@ -74,7 +74,7 @@ (vu1-buf dma-buffer :offset 8) (debug-buf dma-buffer :offset 36) (global-buf dma-buffer :offset 40) - (bucket-group dma-bucket :offset 44) + (bucket-group (inline-array dma-bucket) :offset 44) (buffer dma-buffer 11 :offset 4) (profile-bar profile-bar 2 :offset 48) (run-time uint64 :offset 56) diff --git a/goal_src/engine/gfx/hw/vu1-user-h.gc b/goal_src/engine/gfx/hw/vu1-user-h.gc index ade528b5a1..7856a8b201 100644 --- a/goal_src/engine/gfx/hw/vu1-user-h.gc +++ b/goal_src/engine/gfx/hw/vu1-user-h.gc @@ -8,8 +8,8 @@ ;; VU1 renderers are enabled/disabled with a bitmask. ;; I believe this is renderers which can be enabled/disabled in the debug menu? -(define *vu1-enable-user-menu* - #x1FFFF8) +;; 1024 = merc +(define *vu1-enable-user-menu* #x1FFFF8) ;; by default, all off. ;; the menu renderers get copied to this on each frame diff --git a/goal_src/engine/gfx/merc/merc-blend-shape.gc b/goal_src/engine/gfx/merc/merc-blend-shape.gc index 93ed9243b2..f09bb80e96 100644 --- a/goal_src/engine/gfx/merc/merc-blend-shape.gc +++ b/goal_src/engine/gfx/merc/merc-blend-shape.gc @@ -5,3 +5,118 @@ ;; name in dgo: merc-blend-shape ;; dgos: GAME, ENGINE +;; The merc-blend-shape renderer does face animations. +;; This is missing most functions right now, but just has the types that we need for +;; looking into merc. + +(define *stats-blerc* #f) + +(deftype blerc-block-header (structure) + ((tag generic-merc-tag :inline :offset-assert 0) + (vtx-count uint32 :offset-assert 16) + (overlap uint32 :offset-assert 20) + (lump-dest uint32 :offset-assert 24) + (lump-qwc uint32 :offset-assert 28) + ) + :method-count-assert 9 + :size-assert #x20 + :flag-assert #x900000020 + ) + +(deftype blerc-block (structure) + ((output uint8 848 :offset-assert 0) + (header blerc-block-header :inline :offset-assert 848) + ) + :method-count-assert 9 + :size-assert #x370 + :flag-assert #x900000370 + ) + +(deftype blerc-dcache (structure) + ((repl-mult vector 40 :inline :offset-assert 0) + ) + :method-count-assert 9 + :size-assert #x280 + :flag-assert #x900000280 + ) + +(deftype blerc-globals (structure) + ((first uint32 :offset-assert 0) + (next uint32 :offset-assert 4) + (min-val int16 :offset-assert 8) + (max-val int16 :offset-assert 10) + (fragment-count int32 :offset-assert 12) + (vtx-count int32 :offset-assert 16) + (target-vtx-count int32 :offset-assert 20) + ) + :method-count-assert 9 + :size-assert #x18 + :flag-assert #x900000018 + ) + +(define *blerc-globals* (new 'global 'blerc-globals)) + +(deftype blerc-context (structure) + ((block-a blerc-block :inline :offset-assert 0) + (dummy uint8 7312 :offset-assert 880) + (block-b blerc-block :inline :offset-assert 8192) + ) + :method-count-assert 9 + :size-assert #x2370 + :flag-assert #x900002370 + ) + +(defun-debug blerc-stats-init () + (when *stats-blerc* + (when (nonzero? (-> *blerc-globals* fragment-count)) + (format *stdcon* "~%BLERC (merc blend target) STATS~%") + (format *stdcon* " ~D fragments, ~D vertices~%" + (-> *blerc-globals* fragment-count) + (-> *blerc-globals* vtx-count) + ) + (format *stdcon* " ~D blend target computations (~F average)~%" + (-> *blerc-globals* target-vtx-count) + (/ (the float (-> *blerc-globals* target-vtx-count)) + (the float (-> *blerc-globals* vtx-count)) + ) + ) + (if (< (-> *blerc-globals* min-val) 0) + (format *stdcon* "MINIMUM OUT OF RANGE: ~D~%" (-> *blerc-globals* min-val)) + ) + (if (< 255 (-> *blerc-globals* max-val)) + (format *stdcon* "MAXIMUM OUT OF RANGE: ~D~%" (-> *blerc-globals* max-val)) + ) + ) + (let ((a0-7 *blerc-globals*)) + (set! (-> a0-7 min-val) 255) + (set! (-> a0-7 max-val) 0) + (set! (-> a0-7 fragment-count) 0) + (set! (-> a0-7 vtx-count) 0) + (set! (-> a0-7 target-vtx-count) 0) + ) + ) + 0 + (none) + ) + +(defun blerc-init () + (blerc-stats-init) + (let ((v1-0 *blerc-globals*)) + (set! (-> v1-0 first) (the-as uint 0)) + (set! (-> v1-0 next) (the-as uint 0)) + ) + 0 + (none) + ) + +;; todo blerc-a-fragment (unused) + +;; todo dma-from-spr (unused) + +;; todo merc-dma-chain-to-spr (unused) + +;; todo blerc-execute + +;; todo merc-blend-shape + +;; todo setup-blerc-chains \ No newline at end of file diff --git a/goal_src/engine/gfx/merc/merc-h.gc b/goal_src/engine/gfx/merc/merc-h.gc index bd750d92d7..4e289fc4ff 100644 --- a/goal_src/engine/gfx/merc/merc-h.gc +++ b/goal_src/engine/gfx/merc/merc-h.gc @@ -19,6 +19,7 @@ (set! (-> ripple-merc-query heap-base) 16) +;; header to fragments uploaded to VU. (deftype merc-byte-header (structure) ((srcdest-off uint8 :offset-assert 0) (rgba-off uint8 :offset-assert 1) @@ -40,6 +41,12 @@ :flag-assert #x900000017 ) +;; merc VU fragment. +;; The mm-quadword-size includes the header. +;; The data itself is split into two parts: +;; - ?? +;; - fp data, containing a merc-fp-data then "fp" data. +;; the merc-fragment-fp-data function will get a pointer to fp data. (deftype merc-fragment (structure) ((header merc-byte-header :inline :offset-assert 0) (rest uint8 1 :offset-assert 23) @@ -48,7 +55,7 @@ :size-assert #x18 :flag-assert #xa00000018 (:methods - (dummy-9 () none 9) + (login-adgifs (_type_) none 9) ) ) @@ -71,11 +78,13 @@ :flag-assert #x90000000c ) +;; header for fp data within a fragment. Is included in fp data. +;; adgifs come right after the header (deftype merc-fp-header (structure) ((x-add float :offset-assert 0) (y-add float :offset-assert 4) (z-add float :offset-assert 8) - (shader-cnt uint8 :offset-assert 12) + (shader-cnt uint8 :offset-assert 12) ;; number of adgifs (kick-info-offset uint8 :offset-assert 13) (kick-info-step uint8 :offset-assert 14) (hword-cnt uint8 :offset-assert 15) @@ -87,24 +96,27 @@ (defun merc-fragment-fp-data ((arg0 merc-fragment)) "Get the floating-point data of a merc-fragment" - (the pointer (&+ arg0 (the-as uint (shl (-> arg0 header mm-quadword-fp-off) 4)))) + (the merc-fp-header (&+ arg0 (the-as uint (shl (-> arg0 header mm-quadword-fp-off) 4)))) ) (deftype merc-mat-dest (structure) ((matrix-number uint8 :offset-assert 0) (matrix-dest uint8 :offset-assert 1) ) + :pack-me :method-count-assert 9 :size-assert #x2 :flag-assert #x900000002 ) +;; some info about a merc fragment that will stay on the EE. +;; the merc-effect contains a ref to one of these (deftype merc-fragment-control (structure) ((unsigned-four-count uint8 :offset-assert 0) (lump-four-count uint8 :offset-assert 1) (fp-qwc uint8 :offset-assert 2) (mat-xfer-count uint8 :offset-assert 3) - (mat-dest-data uint8 :dynamic :offset-assert 4) + (mat-dest-data merc-mat-dest :inline :dynamic :offset-assert 4) ) :method-count-assert 9 :size-assert #x4 @@ -188,12 +200,15 @@ (dummy1 uint8 :offset-assert 26) (envmap-usage uint8 :offset-assert 27) (extra-info merc-extra-info :offset-assert 28) + + ;; added + (data uint64 4 :offset 0) ) :method-count-assert 10 :size-assert #x20 :flag-assert #xa00000020 (:methods - (dummy-9 () none 9) + (login-adgifs (_type_) none 9) ) ) @@ -234,6 +249,8 @@ :flag-assert #x900000008 ) + +;; metadata for merc art (deftype merc-ctrl-header (structure) ((xyz-scale float :offset-assert 0) (st-magic uint32 :offset-assert 4) @@ -282,6 +299,7 @@ ;; field xyz-scale is a float printed as hex? ) +;; the actual merc art object. (deftype merc-ctrl (art-element) ((num-joints int32 :offset 20) (header merc-ctrl-header :inline :offset-assert 32) @@ -293,8 +311,8 @@ ) (deftype merc-vu1-low-mem (structure) - ((tri-strip-gif qword :inline :offset-assert 0) - (ad-gif qword :inline :offset-assert 16) + ((tri-strip-gif gs-gif-tag :inline :offset-assert 0) ;; was qword + (ad-gif gs-gif-tag :inline :offset-assert 16) ;; was qword (hvdf-offset vector :inline :offset-assert 32) (perspective uint128 4 :offset-assert 48) (fog vector :inline :offset-assert 112) diff --git a/goal_src/engine/gfx/merc/merc-vu1.gc b/goal_src/engine/gfx/merc/merc-vu1.gc index ffe1eb5016..323abca808 100644 --- a/goal_src/engine/gfx/merc/merc-vu1.gc +++ b/goal_src/engine/gfx/merc/merc-vu1.gc @@ -6,3 +6,5 @@ ;; dgos: GAME, ENGINE ;; all this contains is the merc-vu1-block + +(define merc-vu1-block (the vu-function 0)) \ No newline at end of file diff --git a/goal_src/engine/gfx/merc/merc.gc b/goal_src/engine/gfx/merc/merc.gc index aa84dc70be..d4b2591b54 100644 --- a/goal_src/engine/gfx/merc/merc.gc +++ b/goal_src/engine/gfx/merc/merc.gc @@ -5,6 +5,683 @@ ;; name in dgo: merc ;; dgos: GAME, ENGINE -(defun merc-vu1-init-buffers () - ;; TODO stub +;; This file contains the EE code for MERC +;; The merc renderer is used to draw characters and other dynamic things. +;; It supports a number of effects and can interact with other renderers. +;; It's the most complicated renderer in the game and its code uses almost the entire VU1 code memory. + +;; The interface with the rest of the art world is merc-ctrl, which is an art-element. +;; It contains a merc-ctrl-header which has the metadata. +;; It also has an array of merc-effects which contain the actual data. + +;; contains the header for the currently logging-in thing. +(define *merc-ctrl-header* (the-as merc-ctrl-header #f)) + +(defmethod asize-of merc-fragment ((obj merc-fragment)) + "Get the size in memory of a merc-fragment" + (the-as int (* (-> obj header mm-quadword-size) 16)) + ) + +(defmethod login-adgifs merc-fragment ((obj merc-fragment)) + "Set up a merc-fragment. Does adgifs and eye stuff" + (let* ((fp-data (merc-fragment-fp-data obj)) + (eye-ctrl + (the-as merc-eye-ctrl (if (nonzero? (-> *merc-ctrl-header* eye-ctrl)) + (-> *merc-ctrl-header* eye-ctrl) + (the-as merc-eye-ctrl #f) + ) + ) + ) + (shader (the-as adgif-shader (&+ fp-data 16))) + ) + (dotimes (s2-0 (the-as int (-> fp-data shader-cnt))) + (cond + ((and eye-ctrl (= (logand -256 (-> shader texture-id)) #x1cf06f00)) + ;; eye slot 0 + (adgif-shader-login shader) + (let ((eye-tex-block (get-eye-block (-> eye-ctrl eye-slot) 0))) + (set! (-> shader tex0 tbp0) eye-tex-block) + ) + (set! (-> shader tex0 tw) 5) + (set! (-> shader tex0 th) 5) + (set! (-> shader tex0 tcc) 1) + (set! (-> shader tex0 tbw) 1) + (set! (-> shader tex0 psm) 0) + (set! (-> shader tex1 mxl) 0) + (set! (-> shader clamp) + (new 'static 'gs-clamp + :wms (gs-tex-wrap-mode clamp) + :wmt (gs-tex-wrap-mode clamp) + :maxu #x1f + :maxv #x1f + ) + ) + ) + ((and eye-ctrl (= (logand -256 (-> shader texture-id)) #x1cf07000)) + ;; eye slot 1 + (adgif-shader-login shader) + (let ((eye-tex-block-2 (get-eye-block (-> eye-ctrl eye-slot) 1))) + (set! (-> shader tex0 tbp0) eye-tex-block-2) + ) + (set! (-> shader tex0 tw) 5) + (set! (-> shader tex0 th) 5) + (set! (-> shader tex0 tcc) 1) + (set! (-> shader tex0 tbw) 1) + (set! (-> shader tex0 psm) 0) + (set! (-> shader tex1 mxl) 0) + (set! (-> shader clamp) + (new 'static 'gs-clamp + :wms (gs-tex-wrap-mode clamp) + :wmt (gs-tex-wrap-mode clamp) + :maxu #x1f + :maxv #x1f + ) + ) + ) + (else + ;; normal. just login and set tex masks. + (let ((tex (adgif-shader-login shader))) + (when tex + (dotimes (seg 3) + (logior! (-> *merc-ctrl-header* masks seg) (-> tex masks seg)) + ) + ) + ) + ) + ) + (&+! shader 80) + ) + ) + (none) + ) + +(defmethod inspect merc-fragment-control ((obj merc-fragment-control)) + "Debug print a merc-fragment-control" + (format #t "[~8x] ~A~%" obj 'merc-fragment-control) + (format #t "~Tunsigned-four-count: ~D~%" (-> obj unsigned-four-count)) + (format #t "~Tlump-four-count: ~D~%" (-> obj lump-four-count)) + (format #t "~Tfp-qwc: ~D~%" (-> obj fp-qwc)) + (format #t "~Tmat-xfer-count: ~D~%" (-> obj mat-xfer-count)) + (dotimes (s5-0 (the-as int (-> obj mat-xfer-count))) + (format #t "~Tmat-dest-data[~d]:~%" s5-0) + (format #t "~T~Tmatrix-number: ~D~%"(-> obj mat-dest-data s5-0 matrix-number)) + (format #t "~T~Tmatrix-dest: ~D~%" (-> obj mat-dest-data s5-0 matrix-dest)) + ) + obj + ) + +(defmethod login-adgifs merc-effect ((obj merc-effect)) + "Login everything for this merc-effect." + + ;; login adgifs, if we have them. + (let ((data (-> obj extra-info))) + (when (nonzero? data) + (when (nonzero? (-> data shader-offset)) + (let ((tex (adgif-shader-login + (the-as + adgif-shader + (+ (the-as uint data) (* (-> data shader-offset) 16)) + ) + ) + ) + ) + (when tex + (dotimes (seg 3) + (logior! (-> *merc-ctrl-header* masks seg) (-> tex masks seg)) + ) + ) + ) + ) + ) + ) + + ;; login fragment geometry and control. ctrls don't need logins + (let ((ctrl (-> obj frag-ctrl)) + (geo (-> obj frag-geo)) + ) + (dotimes (frag-idx (the-as int (-> obj frag-count))) + (let ((ctrl-size (asize-of ctrl))) + (let ((geo-size (asize-of geo))) + (login-adgifs geo) + (set! geo (the-as merc-fragment (&+ (the-as pointer geo) geo-size))) + ) + (set! ctrl (the-as merc-fragment-control (&+ (the-as pointer ctrl) ctrl-size))) + ) + ) + ) + (none) + ) + +(defmethod inspect merc-ctrl ((obj merc-ctrl)) + "Print a merc-ctrl" + (format #t "[~8x] ~A~%" obj (-> obj type)) + (format #t "~Tname: ~A~%" (-> obj name)) + (format #t "~Tlength: ~D~%" (-> obj length)) + (format #t "~Tnum-joints: ~D~%" (-> obj num-joints)) + (format #t "~Textra: ~A~%" (-> obj extra)) + (inspect (-> obj header)) + (dotimes (s5-0 (the-as int (-> obj header effect-count))) + (inspect (-> obj effect s5-0)) + ) + obj + ) + +(defmethod mem-usage merc-ctrl ((obj merc-ctrl) (arg0 memory-usage-block) (arg1 int)) + "Compute memory usage stats for a merc-ctrl" + + ;; do extra + (if (-> obj extra) + (mem-usage (-> obj extra) arg0 arg1) + ) + + ;; do merc ctrls in each effect: + (let ((ctrl-mem (+ 32 80 (* (-> obj header effect-count) 32)))) + (dotimes (effect-idx (the-as int (-> obj header effect-count))) + (let ((fctrl (-> obj effect effect-idx frag-ctrl))) + (dotimes (frag-idx (the-as int (-> obj effect effect-idx frag-count))) + (set! ctrl-mem (+ ctrl-mem + (* (shr (+ (-> fctrl unsigned-four-count) 3) 2) 16) + (* (shr (+ (-> fctrl lump-four-count) 3) 2) 16) + (* (-> fctrl fp-qwc) 16) + (asize-of fctrl) + ) + ) + (set! fctrl (the-as merc-fragment-control (&+ (the-as pointer fctrl) (asize-of fctrl)))) + ) + ) + ) + (set! (-> arg0 length) (max 76 (-> arg0 length))) + (set! (-> arg0 data 75 name) "merc-ctrl") + (+! (-> arg0 data 75 count) 1) + (+! (-> arg0 data 75 used) ctrl-mem) + (+! (-> arg0 data 75 total) (logand -16 (+ ctrl-mem 15))) + ) + + ;; do effect blend shapes + (let ((effect-mem 0)) + (dotimes (effect-idx2 (the-as int (-> obj header effect-count))) + (when (nonzero? (-> obj effect effect-idx2 blend-frag-count)) + (let ((bctrl (-> obj effect effect-idx2 blend-ctrl))) + (dotimes (blend-frag-idx (the-as int (-> obj effect effect-idx2 blend-frag-count)) ) + (let ((v1-36 (+ effect-mem + (* (+ (-> bctrl nonzero-index-count) 1) + (the-as uint (logand (+ (* (the-as uint 6) (-> bctrl blend-vtx-count)) 15) #xfff0)) + ) + ) + ) + ) + (set! effect-mem (the-as int (+ (-> obj header blend-target-count) 2 v1-36))) + ) + (set! bctrl (the-as merc-blend-ctrl (&+ (the-as pointer bctrl) (+ (-> obj header blend-target-count) 2)))) + ) + ) + ) + ) + (when (nonzero? effect-mem) + (set! (-> arg0 length) (max 78 (-> arg0 length))) + (set! (-> arg0 data 77 name) "blend-shape") + (+! (-> arg0 data 77 count) 1) + (+! (-> arg0 data 77 used) effect-mem) + (+! (-> arg0 data 77 total) (logand -16 (+ effect-mem 15))) + ) + ) + + ;; do eyes. + (when (nonzero? (-> obj header eye-ctrl)) + (let ((a0-28 (-> obj header eye-ctrl))) + (set! (-> arg0 length) (max 109 (-> arg0 length))) + (set! (-> arg0 data 108 name) "eye-anim") + (+! (-> arg0 data 108 count) 1) + (let ((v1-47 (asize-of a0-28))) + (+! (-> arg0 data 108 used) v1-47) + (+! (-> arg0 data 108 total) (logand -16 (+ v1-47 15))) + ) + ) + ) + obj + ) + +(defmethod login merc-ctrl ((obj merc-ctrl)) + "Log in a merc-ctrl." + + ;; so we can find it + (set! *merc-ctrl-header* (-> obj header)) + + ;; clear masks. logging in will set these for textures we need. + (dotimes (v1-1 3) + (set! (-> *merc-ctrl-header* masks v1-1) (the-as uint 0)) + ) + + ;; login the effects + (dotimes (effect-idx (the-as int (-> obj header effect-count))) + (login-adgifs (-> obj effect effect-idx)) + ) + + ;; some weird hack to swap two effects. + (let ((idx-with-bit1 -1) + (a1-1 (-> obj header effect-count)) + ) + (dotimes (v1-11 (the-as int a1-1)) + (if (logtest? (-> obj effect v1-11 effect-bits) 2) + (set! idx-with-bit1 v1-11) + ) + ) + (when (!= idx-with-bit1 -1) + (let ((v1-16 4) + (this-effect (-> obj effect idx-with-bit1)) + (last-effect (-> obj effect (+ a1-1 -1))) + ) + (dotimes (copy-idx v1-16) + (let ((a3-2 (-> this-effect data copy-idx))) + (set! (-> this-effect data copy-idx) (-> last-effect data copy-idx)) + (set! (-> last-effect data copy-idx) a3-2) + ) + ) + ) + ) + ) + + ;; login eye. + (cond + ((zero? (logand -65536 (the-as int (-> obj header eye-ctrl)))) + ;; no idea what this is for. + (set! (-> obj header eye-ctrl) (the-as merc-eye-ctrl 0)) + 0 + ) + (else + (let ((s5-1 (-> obj header eye-ctrl))) + ;; login and set masks + (dotimes (s4-0 3) + (let ((v1-25 (adgif-shader-login (-> s5-1 shader s4-0)))) + (when v1-25 + (dotimes (a0-11 3) + (logior! (-> *merc-ctrl-header* masks a0-11) (-> v1-25 masks a0-11)) + ) + ) + ) + ) + ) + ) + ) + obj + ) + +(defun-debug merc-stats-display ((arg0 merc-ctrl)) + "Print debug stats to #t." + (format #t "~30s:" (-> arg0 name)) + (let ((s5-0 (-> arg0 header st-int-scale)) + (s4-0 (ash 1 (- 12 (the-as int (-> arg0 header st-int-scale))))) + ) + (format #t " ST ~3D, " s4-0) + (cond + ((>= s5-0 (the-as uint 5)) + (format #t "RANGE ~D+," (/ 128 s4-0)) + ) + ((= s5-0 4) + (format #t "RANGE 0.5+,") + ) + ) + ) + (dotimes (s5-1 (the-as int (-> arg0 header effect-count))) + (let ((s3-0 (-> arg0 effect s5-1))) + (if (nonzero? s5-1) + (format #t "~48s " " ") + ) + (let ((a2-4 (-> s3-0 frag-count)) + (s4-1 (-> s3-0 tri-count)) + (f30-0 (the float (-> s3-0 frag-count))) + (f28-0 (the float (-> s3-0 dvert-count))) + (f26-0 (the float (-> s3-0 tri-count))) + ) + (if (>= (/ (+ 50.0 f28-0) f30-0) 50.0) + (format #t "~3D frags, ~2,,1f dverts/frag " a2-4 (/ f28-0 f30-0)) + (format #t "~3D frags, ~2,,1f ******/**** " a2-4 (/ f28-0 f30-0)) + ) + (format #t "(~4D tris, striplen ~2,,2f, ~2,,1f tris/frag)~%" + s4-1 + (/ (* 2.0 f26-0) (- f28-0 f26-0)) + (/ f26-0 f30-0) + ) + ) + ) + ) + (none) + ) + +(defun-debug merc-stats () + "Iterate through all merc-ctrls and print." + + (dotimes (gp-0 3) ;; levels + (let ((s5-0 (-> *level* level gp-0 art-group))) + (when (nonzero? s5-0) + (dotimes (s4-0 (-> s5-0 art-group-array length)) ;; art-groups + (let ((s3-0 (-> s5-0 art-group-array s4-0))) + (dotimes (s2-0 (-> s3-0 length)) ;; arts + (let* ((s1-0 (-> s3-0 data s2-0)) + (a0-3 (if (and (nonzero? s1-0) (type-type? (-> s1-0 type) merc-ctrl)) + s1-0 + ) + ) + ) + (if a0-3 + (merc-stats-display (the-as merc-ctrl a0-3)) + ) + ) + ) + ) + ) + ) + ) + ) + 0 + (none) + ) + +(defun-debug merc-edge-stats () + "Print the longest edges in each." + (dotimes (gp-0 3) + (let ((s5-0 (-> *level* level gp-0 art-group))) + (when (nonzero? s5-0) + (dotimes (s4-0 (-> s5-0 art-group-array length)) + (let ((s3-0 (-> s5-0 art-group-array s4-0))) + (dotimes (s2-0 (-> s3-0 length)) + (let* ((s1-0 (-> s3-0 data s2-0)) + (v1-10 + (if (and (nonzero? s1-0) (type-type? (-> s1-0 type) merc-ctrl)) + s1-0 + ) + ) + ) + (if v1-10 + (format + #t + "~30s: ~f~%" + (-> (the-as merc-ctrl v1-10) name) + (-> (the-as merc-ctrl v1-10) header longest-edge) + ) + ) + ) + ) + ) + ) + ) + ) + ) + 0 + (none) + ) + +(defun merc-vu1-add-vu-function ((dma dma-packet) (func vu-function) (flush-mode int)) + "Add a function to a dma chain. Return pointer to chain after the upload data." + (let ((func-data (&-> func data 4)) + (qwc (-> func qlength)) + (dst (-> func origin)) + ) + (while (> qwc 0) + (let ((qwc-this-time (min 127 qwc))) ;; only 127 at a time + (set! (-> dma dma) + (new 'static 'dma-tag + :id (dma-tag-id ref) + :qwc qwc-this-time + :addr (the-as int func-data) + ) + ) + (set! (-> dma vif0) (new 'static 'vif-tag :cmd (if (zero? flush-mode) (vif-cmd flushe) (vif-cmd flusha)))) + (set! (-> dma vif1) + (new 'static 'vif-tag + :cmd (vif-cmd mpg) + :num (* qwc-this-time 2) + :imm dst + ) + ) + (&+! dma 16) + (&+! func-data (* qwc-this-time 16)) + (set! qwc (- qwc qwc-this-time)) + (+! dst (* qwc-this-time 2)) + ) + ) + ) + (the-as dma-gif-packet dma) + ) + +(defun merc-vu1-initialize-chain ((arg0 dma-gif-packet)) + "Initialize a merc chain." + ;; upload the function. + (let ((gp-0 (the-as object (merc-vu1-add-vu-function (the-as dma-packet arg0) merc-vu1-block 1)))) + ;; now set up the VIF. + (set! (-> (the-as dma-gif-packet gp-0) dma-vif dma) (new 'static 'dma-tag :qwc #xa :id (dma-tag-id cnt))) + (set! (-> (the-as dma-gif-packet gp-0) dma-vif vif0) (new 'static 'vif-tag :imm #x404 :cmd (vif-cmd stcycl))) + (set! (-> (the-as dma-gif-packet gp-0) dma-vif vif1) (new 'static 'vif-tag :cmd (vif-cmd stmod))) + (set! (-> (the-as (pointer vif-tag) gp-0) 4) (new 'static 'vif-tag :imm #x1ba :cmd (vif-cmd base))) + (set! (-> (the-as (pointer vif-tag) gp-0) 5) (new 'static 'vif-tag :imm #xfe46 :cmd (vif-cmd offset))) + (set! (-> (the-as (pointer vif-tag) gp-0) 6) (new 'static 'vif-tag)) + + ;; upload VU low memory + (set! (-> (the-as (pointer vif-tag) gp-0) 7) (new 'static 'vif-tag :num #x8 :cmd (vif-cmd unpack-v4-32))) + + ;; template: + (let ((s5-0 (the-as merc-vu1-low-mem (&+ (the-as dma-gif-packet gp-0) 32)))) + (set! (-> s5-0 tri-strip-gif tag) + (new 'static 'gif-tag64 + :pre #x1 + :prim (new 'static 'gs-prim :prim (gs-prim-type tri-strip) :iip #x1 :tme #x1 :fge #x1) + :nreg #x3 + ) + ) + (set! (-> s5-0 tri-strip-gif regs) + (new 'static 'gif-tag-regs + :regs0 (gif-reg-id st) + :regs1 (gif-reg-id rgbaq) + :regs2 (gif-reg-id xyzf2) + ) + ) + ;; what is this, they snuck something in here... + (set! (-> s5-0 tri-strip-gif word 3) + (shr (make-u128 0 (shl #x303e4000 32)) 32) + ) + + (set! (-> s5-0 ad-gif tag) (new 'static 'gif-tag64 :nloop #x5 :nreg #x1)) + (set! (-> s5-0 ad-gif regs) (new 'static 'gif-tag-regs :regs0 (gif-reg-id a+d))) + (set! (-> s5-0 hvdf-offset quad) (-> *math-camera* hvdf-off quad)) + + (quad-copy! (-> s5-0 perspective) (the-as pointer (-> *math-camera* perspective)) 4) + (set-vector! + (-> s5-0 fog) + (-> *math-camera* pfog0) + (-> *math-camera* fog-min) + (-> *math-camera* fog-max) + 0.0 + ) + ) + ;; end. + (let ((v1-20 (-> (the-as (inline-array dma-packet) gp-0) 10))) + (set! (-> v1-20 dma) (new 'static 'dma-tag :id (dma-tag-id cnt))) + (set! (-> v1-20 vif0) (new 'static 'vif-tag)) + (set! (-> v1-20 vif1) (new 'static 'vif-tag :cmd (vif-cmd mscal) :msk #x1 :imm #x0)) + (&+ v1-20 16) + ) + ) + (none) + ) + + +(defun merc-vu1-init-buffer ((dma-bucket bucket-id) (test gs-test) (arg2 int)) + "Setup merc DMA buffer." + + ;; This function works differently from most and splices to the beginning of the bucket, as + ;; drawing has already put stuff in buckets. + ;; The advantage of this is that we can check if nothing was drawn, then skip this. + ;; NOTE: This runs as part of display-frame-finish, so after previous DMA is synced. + + ;; grab out bucket directly. + (let ((bucket (-> *display* frames (-> *display* on-screen) frame bucket-group dma-bucket))) + ;; only if we draw anything. + (when (!= bucket (-> bucket last)) + (let* ((dma-buf (-> *display* frames (-> *display* on-screen) frame global-buf)) + (draw-data-start (-> dma-buf base)) ;; remember old beginning + ) + ;; set the beginning to be the merc init stuff. + (set! (-> dma-buf base) + (the-as pointer (merc-vu1-initialize-chain (the-as dma-gif-packet (-> dma-buf base))) ) + ) + ;; some other merc setup for the GS. + (let* ((v1-8 dma-buf) + (a0-6 (the-as object (-> v1-8 base))) + ) + (set! (-> (the-as dma-packet a0-6) dma) (new 'static 'dma-tag :qwc #x2 :id (dma-tag-id cnt))) + (set! (-> (the-as dma-packet a0-6) vif0) (new 'static 'vif-tag)) + (set! (-> (the-as dma-packet a0-6) vif1) + (new 'static 'vif-tag :imm #x2 :cmd (vif-cmd direct) :msk #x1) + ) + (set! (-> v1-8 base) (&+ (the-as pointer a0-6) 16)) + ) + (let* ((v1-9 dma-buf) + (a0-8 (the-as object (-> v1-9 base))) + ) + (set! (-> (the-as gs-gif-tag a0-8) tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x1)) + (set! (-> (the-as gs-gif-tag a0-8) regs) + (new 'static 'gif-tag-regs + :regs0 (gif-reg-id a+d) + :regs1 (gif-reg-id a+d) + :regs2 (gif-reg-id a+d) + :regs3 (gif-reg-id a+d) + :regs4 (gif-reg-id a+d) + :regs5 (gif-reg-id a+d) + :regs6 (gif-reg-id a+d) + :regs7 (gif-reg-id a+d) + :regs8 (gif-reg-id a+d) + :regs9 (gif-reg-id a+d) + :regs10 (gif-reg-id a+d) + :regs11 (gif-reg-id a+d) + :regs12 (gif-reg-id a+d) + :regs13 (gif-reg-id a+d) + :regs14 (gif-reg-id a+d) + :regs15 (gif-reg-id a+d) + ) + ) + (set! (-> v1-9 base) (&+ (the-as pointer a0-8) 16)) + ) + (let* ((v1-10 dma-buf) + (a0-10 (-> v1-10 base)) + ) + (set! (-> (the-as (pointer gs-test) a0-10) 0) test) + (set! (-> (the-as (pointer gs-reg64) a0-10) 1) (gs-reg64 test-1)) + (set! (-> v1-10 base) (&+ a0-10 16)) + ) + + ;; terminate as normal + (let ((v1-11 (the-as object (-> dma-buf base)))) + (set! (-> (the-as dma-packet v1-11) dma) + (new 'static 'dma-tag :id (dma-tag-id next) :addr (-> bucket next)) + ) + (set! (-> (the-as dma-packet v1-11) vif0) (new 'static 'vif-tag)) + (set! (-> (the-as dma-packet v1-11) vif1) (new 'static 'vif-tag)) + (set! (-> dma-buf base) (&+ (the-as pointer v1-11) 16)) + ) + + ;; but splice the existing chain. + (set! (-> bucket next) (the-as uint draw-data-start)) + ) + ) + ) + 0 + (none) + ) + +(defun merc-vu1-init-buffers () + "Setup merc DMA buffers. Call this _after_ drawing." + (when (logtest? *vu1-enable-user* 1024) + (merc-vu1-init-buffer + (bucket-id bucket-10) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x26 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-49) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x26 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-17) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x26 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-52) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x26 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-45) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x26 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-55) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x26 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-58) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x80 + :afail #x1 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + (merc-vu1-init-buffer + (bucket-id bucket-61) + (new 'static 'gs-test + :ate #x1 + :atst (gs-atest greater-equal) + :aref #x80 + :afail #x1 + :zte #x1 + :ztst (gs-ztest greater-equal) + ) + 0 + ) + ) + 0 + (none) ) diff --git a/goal_src/engine/level/level.gc b/goal_src/engine/level/level.gc index 2810daa1ac..a51603071f 100644 --- a/goal_src/engine/level/level.gc +++ b/goal_src/engine/level/level.gc @@ -573,7 +573,7 @@ (let ((v1-39 (- (the-as uint current-login-pos) (the-as uint (-> level-drawable-trees length))))) (when (< (the-as int v1-39) (-> loaded-level art-group art-group-array length)) (let ((s2-2 (-> loaded-level art-group art-group-array v1-39))) - (dummy-9 s2-2) + (login s2-2) (if (dummy-12 s2-2) (link-art! s2-2) ) diff --git a/goal_src/engine/load/loader.gc b/goal_src/engine/load/loader.gc index 857453dbc6..48d9d3c3f6 100644 --- a/goal_src/engine/load/loader.gc +++ b/goal_src/engine/load/loader.gc @@ -134,7 +134,7 @@ )|# (let ((s5-0 (the-as art (loado arg0 arg1)))) (if (type-type? (-> s5-0 type) art) - (dummy-9 s5-0) + (login s5-0) (the-as art #f) ) ) @@ -164,7 +164,7 @@ (the-as art-group #f) ) (else - (dummy-9 s3-1) + (login s3-1) ) ) ) @@ -462,7 +462,7 @@ (set! (-> obj status) 'error) ) (else - (dummy-9 s4-0) + (login s4-0) (set! (-> obj status) 'locked) ;; make file ready to be used ) )