more fixes

This commit is contained in:
water111
2026-04-13 19:47:54 -04:00
parent 5670fce5bd
commit 0da265f87b
12 changed files with 319 additions and 176 deletions
+10 -6
View File
@@ -62,7 +62,8 @@ FormElement* SetVarOp::get_as_form(FormPool& pool, const Env& env) const {
m_dst,
pool.alloc_single_element_form<GenericElement>(
nullptr, GenericOperator::make_fixed(FixedOperatorKind::ADDRESS_OF),
pool.alloc_single_element_form<StackSpillValueElement>(nullptr, -1, offset, false)),
pool.alloc_single_element_form<StackSpillValueElement>(
nullptr, -1, offset, make_stack_slot_access(offset), false)),
true, env.stack_slot_entries.at(offset).typespec);
}
} else {
@@ -847,10 +848,12 @@ FormElement* StackSpillLoadOp::get_as_form(FormPool& pool, const Env& env) const
if (env.has_type_analysis()) {
read_type = env.get_types_before_op(m_my_idx).get_slot(m_offset).typespec();
}
return pool.alloc_element<SetVarElement>(m_dst,
pool.alloc_single_element_form<StackSpillValueElement>(
nullptr, m_size, m_offset, m_is_signed, read_type),
true, type);
return pool.alloc_element<SetVarElement>(
m_dst,
pool.alloc_single_element_form<StackSpillValueElement>(
nullptr, m_size, m_offset, env.get_stack_slot_access_for_op(m_my_idx, m_offset),
m_is_signed, read_type),
true, type);
}
FormElement* StackSpillStoreOp::get_as_form(FormPool& pool, const Env& env) const {
@@ -870,6 +873,7 @@ FormElement* StackSpillStoreOp::get_as_form(FormPool& pool, const Env& env) cons
}
}
return pool.alloc_element<StackSpillStoreElement>(m_value, m_size, m_offset, cast_type);
return pool.alloc_element<StackSpillStoreElement>(
m_value, m_size, m_offset, env.get_stack_slot_access_for_op(m_my_idx, m_offset), cast_type);
}
} // namespace decompiler
+127 -32
View File
@@ -623,7 +623,7 @@ std::unordered_set<RegId, RegId::hash> Env::get_ssa_var(const RegAccessSet& vars
RegId Env::get_program_var_id(const RegisterAccess& var) const {
if (is_stack_slot_access(var)) {
return RegId(Register(Reg::GPR, Reg::SP), get_stack_slot_offset_from_access(var));
return RegId(Register(Reg::GPR, Reg::SP), get_stack_slot_var_id_from_access(var));
}
return m_var_names.lookup(var.reg(), var.idx(), var.mode()).reg_id;
}
@@ -637,17 +637,20 @@ const UseDefInfo& Env::get_use_def_info(const RegisterAccess& ra) const {
return m_var_names.use_def_info.at(var_id);
}
RegisterAccess Env::get_stack_slot_access_for_op(int op_id, int offset) const {
auto it = m_stack_slot_var_by_op.find(op_id);
if (it == m_stack_slot_var_by_op.end()) {
return make_stack_slot_access(offset);
}
return make_stack_slot_access(offset, it->second);
}
void Env::disable_def(const RegisterAccess& access, DecompWarnings& warnings) {
if (is_stack_slot_access(access)) {
auto& info = m_stack_slot_use_def_info.at(get_program_var_id(access));
for (auto& def : info.defs) {
if (!def.disabled) {
def.disabled = true;
return;
}
}
warnings.warning("disable stack def twice: {}",
get_spill_slot_var_name(get_stack_slot_offset_from_access(access)));
// Stack-slot use/def info is intentionally immutable during expression building.
// Unlike registers, the stack-slot analysis models value lifetimes through merged control flow
// with synthetic phi-like vars, and mutating counts here would desynchronize later accesses
// from that analysis.
return;
}
if (has_local_vars()) {
@@ -657,16 +660,7 @@ void Env::disable_def(const RegisterAccess& access, DecompWarnings& warnings) {
void Env::disable_use(const RegisterAccess& access) {
if (is_stack_slot_access(access)) {
auto& info = m_stack_slot_use_def_info.at(get_program_var_id(access));
for (auto& use : info.uses) {
if (!use.disabled) {
use.disabled = true;
return;
}
}
throw std::runtime_error(
fmt::format("Invalid disable use on stack slot {}",
get_spill_slot_var_name(get_stack_slot_offset_from_access(access))));
// See disable_def above.
return;
}
if (has_local_vars()) {
@@ -676,33 +670,134 @@ void Env::disable_use(const RegisterAccess& access) {
void Env::rebuild_stack_slot_use_def_info() {
m_stack_slot_use_def_info.clear();
m_stack_slot_var_by_op.clear();
if (!func || !func->ir2.atomic_ops) {
return;
}
const auto& ops = *func->ir2.atomic_ops;
const int block_count = (int)ops.block_id_to_first_atomic_op.size();
std::vector<int> op_to_block(ops.ops.size(), -1);
for (int block_id = 0; block_id < (int)ops.block_id_to_first_atomic_op.size(); block_id++) {
for (int block_id = 0; block_id < block_count; block_id++) {
for (int op_id = ops.block_id_to_first_atomic_op.at(block_id);
op_id < ops.block_id_to_end_atomic_op.at(block_id); op_id++) {
op_to_block.at(op_id) = block_id;
}
}
std::unordered_set<int> offsets;
for (int op_id = 0; op_id < (int)ops.ops.size(); op_id++) {
const auto* op = ops.ops.at(op_id).get();
if (auto* store = dynamic_cast<const StackSpillStoreOp*>(op)) {
auto var_id = RegId(Register(Reg::GPR, Reg::SP), store->offset());
auto& info = m_stack_slot_use_def_info[var_id];
info.defs.push_back({op_id, op_to_block.at(op_id), AccessMode::WRITE, false});
info.ssa_vars.insert(store->offset());
if (auto* store = dynamic_cast<const StackSpillStoreOp*>(ops.ops.at(op_id).get())) {
offsets.insert(store->offset());
} else if (auto* load = dynamic_cast<const StackSpillLoadOp*>(ops.ops.at(op_id).get())) {
offsets.insert(load->offset());
}
if (auto* load = dynamic_cast<const StackSpillLoadOp*>(op)) {
auto var_id = RegId(Register(Reg::GPR, Reg::SP), load->offset());
auto& info = m_stack_slot_use_def_info[var_id];
info.uses.push_back({op_id, op_to_block.at(op_id), AccessMode::READ, false});
info.ssa_vars.insert(load->offset());
}
int next_var_id = 1;
for (int offset : offsets) {
std::vector<bool> reads_before_write(block_count, false);
std::vector<bool> writes(block_count, false);
for (int block_id = 0; block_id < block_count; block_id++) {
bool seen_write = false;
for (int op_id = ops.block_id_to_first_atomic_op.at(block_id);
op_id < ops.block_id_to_end_atomic_op.at(block_id); op_id++) {
const auto* op = ops.ops.at(op_id).get();
if (auto* load = dynamic_cast<const StackSpillLoadOp*>(op)) {
if (load->offset() == offset && !seen_write) {
reads_before_write.at(block_id) = true;
}
} else if (auto* store = dynamic_cast<const StackSpillStoreOp*>(op)) {
if (store->offset() == offset) {
writes.at(block_id) = true;
seen_write = true;
}
}
}
}
std::vector<bool> live_in(block_count, false);
std::vector<bool> live_out(block_count, false);
bool changed = true;
while (changed) {
changed = false;
for (int block_id = block_count - 1; block_id >= 0; block_id--) {
bool new_live_out = false;
for (int succ : {func->basic_blocks.at(block_id).succ_branch,
func->basic_blocks.at(block_id).succ_ft}) {
if (succ != -1 && live_in.at(succ)) {
new_live_out = true;
}
}
bool new_live_in =
reads_before_write.at(block_id) || (new_live_out && !writes.at(block_id));
if (new_live_in != live_in.at(block_id) || new_live_out != live_out.at(block_id)) {
live_in.at(block_id) = new_live_in;
live_out.at(block_id) = new_live_out;
changed = true;
}
}
}
std::vector<int> phi_var(block_count, -1);
std::vector<std::vector<int>> phi_sources(block_count);
for (int block_id = 0; block_id < block_count; block_id++) {
if (live_in.at(block_id)) {
phi_var.at(block_id) = next_var_id++;
}
}
for (int block_id = 0; block_id < block_count; block_id++) {
int current_var = live_in.at(block_id) ? phi_var.at(block_id) : -1;
for (int op_id = ops.block_id_to_first_atomic_op.at(block_id);
op_id < ops.block_id_to_end_atomic_op.at(block_id); op_id++) {
const auto* op = ops.ops.at(op_id).get();
if (auto* load = dynamic_cast<const StackSpillLoadOp*>(op)) {
if (load->offset() != offset) {
continue;
}
ASSERT(current_var != -1);
m_stack_slot_var_by_op[op_id] = current_var;
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), current_var)];
info.uses.push_back({op_id, block_id, AccessMode::READ, false});
info.ssa_vars.insert(current_var);
} else if (auto* store = dynamic_cast<const StackSpillStoreOp*>(op)) {
if (store->offset() != offset) {
continue;
}
current_var = next_var_id++;
m_stack_slot_var_by_op[op_id] = current_var;
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), current_var)];
info.defs.push_back({op_id, block_id, AccessMode::WRITE, false});
info.ssa_vars.insert(current_var);
}
}
if (!live_out.at(block_id)) {
continue;
}
ASSERT(current_var != -1);
for (int succ :
{func->basic_blocks.at(block_id).succ_branch, func->basic_blocks.at(block_id).succ_ft}) {
if (succ != -1 && live_in.at(succ)) {
phi_sources.at(succ).push_back(current_var);
}
}
}
for (int block_id = 0; block_id < block_count; block_id++) {
if (phi_var.at(block_id) == -1) {
continue;
}
int first_op = ops.block_id_to_first_atomic_op.at(block_id);
for (int src_var : phi_sources.at(block_id)) {
auto& info = m_stack_slot_use_def_info[RegId(Register(Reg::GPR, Reg::SP), src_var)];
info.uses.push_back({first_op, block_id, AccessMode::READ, false});
}
}
}
}
+15 -3
View File
@@ -44,17 +44,27 @@ struct StackSpillEntry {
}
};
constexpr int STACK_SLOT_VAR_STRIDE = 1 << 16;
inline bool is_stack_slot_access(const RegisterAccess& access) {
return access.reg() == Register(Reg::GPR, Reg::SP) && access.idx() < 0;
}
inline int get_stack_slot_offset_from_access(const RegisterAccess& access) {
ASSERT(is_stack_slot_access(access));
return -access.idx() - 1;
return (-access.idx() - 1) / STACK_SLOT_VAR_STRIDE;
}
inline RegisterAccess make_stack_slot_access(int offset) {
return RegisterAccess(AccessMode::READ, Register(Reg::GPR, Reg::SP), -offset - 1, true);
inline int get_stack_slot_var_id_from_access(const RegisterAccess& access) {
ASSERT(is_stack_slot_access(access));
return (-access.idx() - 1) % STACK_SLOT_VAR_STRIDE;
}
inline RegisterAccess make_stack_slot_access(int offset, int var_id = 0) {
ASSERT(var_id >= 0);
ASSERT(var_id < STACK_SLOT_VAR_STRIDE);
return RegisterAccess(AccessMode::READ, Register(Reg::GPR, Reg::SP),
-1 - (offset * STACK_SLOT_VAR_STRIDE + var_id), true);
}
inline bool same_expression_var(const RegisterAccess& a, const RegisterAccess& b) {
@@ -214,6 +224,7 @@ class Env {
}
const UseDefInfo& get_use_def_info(const RegisterAccess& ra) const;
RegisterAccess get_stack_slot_access_for_op(int op_id, int offset) const;
void disable_use(const RegisterAccess& access);
void disable_def(const RegisterAccess& access, DecompWarnings& warnings);
@@ -259,6 +270,7 @@ class Env {
bool m_has_local_vars = false;
VariableNames m_var_names;
std::unordered_map<RegId, UseDefInfo, RegId::hash> m_stack_slot_use_def_info;
std::unordered_map<int, int> m_stack_slot_var_by_op;
bool m_has_types = false;
bool m_pp_mapped_by_behavior = false;
+10 -3
View File
@@ -2776,8 +2776,13 @@ void VectorFloatLoadStoreElement::collect_vf_regs(RegSet& regs) const {
StackSpillStoreElement::StackSpillStoreElement(SimpleAtom value,
int size,
int stack_offset,
RegisterAccess access,
const std::optional<TypeSpec>& cast_type)
: m_value(value), m_size(size), m_stack_offset(stack_offset), m_cast_type(cast_type) {}
: m_value(value),
m_size(size),
m_stack_offset(stack_offset),
m_access(access),
m_cast_type(cast_type) {}
goos::Object StackSpillStoreElement::to_form_internal(const Env& env) const {
return pretty_print::build_list(
@@ -2804,15 +2809,17 @@ void StackSpillStoreElement::get_modified_regs(RegSet&) const {}
StackSpillValueElement::StackSpillValueElement(int size,
int stack_offset,
RegisterAccess access,
bool is_signed,
std::optional<TypeSpec> read_type)
: m_size(size),
m_stack_offset(stack_offset),
m_access(access),
m_is_signed(is_signed),
m_read_type(std::move(read_type)) {}
goos::Object StackSpillValueElement::to_form_internal(const Env& env) const {
auto var = make_stack_slot_access(m_stack_offset);
auto var = m_access;
auto base = pretty_print::to_symbol(env.get_spill_slot_var_name(m_stack_offset));
if (m_read_type && env.get_variable_type(var, true) != *m_read_type) {
return pretty_print::build_list("the-as", m_read_type->print(), base);
@@ -2826,7 +2833,7 @@ void StackSpillValueElement::apply(const std::function<void(FormElement*)>& f) {
void StackSpillValueElement::apply_form(const std::function<void(Form*)>&) {}
void StackSpillValueElement::collect_vars(RegAccessSet& vars, bool) const {
vars.insert(make_stack_slot_access(m_stack_offset));
vars.insert(m_access);
}
void StackSpillValueElement::get_modified_regs(RegSet&) const {}
+7
View File
@@ -1545,6 +1545,7 @@ class StackSpillStoreElement : public FormElement {
StackSpillStoreElement(SimpleAtom value,
int size,
int stack_offset,
RegisterAccess access,
const std::optional<TypeSpec>& cast_type);
goos::Object to_form_internal(const Env& env) const override;
void apply(const std::function<void(FormElement*)>& f) override;
@@ -1553,11 +1554,14 @@ class StackSpillStoreElement : public FormElement {
void get_modified_regs(RegSet& regs) const override;
void push_to_stack(const Env& env, FormPool& pool, FormStack& stack) override;
const std::optional<TypeSpec>& cast_type() const { return m_cast_type; }
const RegisterAccess& access() const { return m_access; }
int stack_offset() const { return m_stack_offset; }
private:
SimpleAtom m_value;
int m_size = -1;
int m_stack_offset = -1;
RegisterAccess m_access;
std::optional<TypeSpec> m_cast_type;
};
@@ -1566,9 +1570,11 @@ class StackSpillValueElement : public FormElement {
public:
StackSpillValueElement(int size,
int stack_offset,
RegisterAccess access,
bool is_signed,
std::optional<TypeSpec> read_type = std::nullopt);
int stack_offset() const { return m_stack_offset; }
const RegisterAccess& access() const { return m_access; }
goos::Object to_form_internal(const Env& env) const override;
void apply(const std::function<void(FormElement*)>& f) override;
void apply_form(const std::function<void(Form*)>& f) override;
@@ -1583,6 +1589,7 @@ class StackSpillValueElement : public FormElement {
private:
int m_size = -1;
int m_stack_offset = -1;
RegisterAccess m_access;
bool m_is_signed = false;
std::optional<TypeSpec> m_read_type;
};
+4 -5
View File
@@ -2738,8 +2738,7 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
if (m_src->is_single_element()) {
auto spill_value = dynamic_cast<StackSpillValueElement*>(m_src->back());
if (spill_value) {
stack.push_non_seq_reg_to_reg(m_dst, make_stack_slot_access(spill_value->stack_offset()),
m_src, m_src_type, m_var_info);
stack.push_non_seq_reg_to_reg(m_dst, spill_value->access(), m_src, m_src_type, m_var_info);
return;
}
@@ -7076,7 +7075,7 @@ void StackSpillStoreElement::push_to_stack(const Env& env, FormPool& pool, FormS
InplaceOpInfo{FixedOperatorKind::LOGXOR, FixedOperatorKind::LOGXOR_IN_PLACE},
};
auto dst_var = make_stack_slot_access(m_stack_offset);
auto dst_var = m_access;
auto dst_form = pool.form<SimpleAtomElement>(SimpleAtom::make_var(dst_var))->to_form(env);
for (const auto& [kind, inplace_kind] : in_place_ops) {
if (!src_as_generic->op().is_fixed(kind)) {
@@ -7098,7 +7097,7 @@ void StackSpillStoreElement::push_to_stack(const Env& env, FormPool& pool, FormS
}
}
stack.push_value_to_reg(make_stack_slot_access(m_stack_offset), src, true, stack_type);
stack.push_value_to_reg(m_access, src, true, stack_type);
}
namespace {
@@ -7358,7 +7357,7 @@ void StackSpillValueElement::update_from_stack(const Env& env,
std::vector<FormElement*>* result,
bool) {
mark_popped();
auto var = make_stack_slot_access(m_stack_offset);
auto var = m_access;
Form* form =
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, SimpleAtom::make_var(var));
if (m_read_type && env.get_variable_type(var, true) != *m_read_type) {
+22 -9
View File
@@ -18,6 +18,15 @@ bool nonempty_intersection(const RegSet& a, const RegSet& b) {
}
return false;
}
bool can_inline_non_seq_source(const RegisterAccess& src, const Env& env) {
if (!is_stack_slot_access(src)) {
return true;
}
const auto& use_def = env.get_use_def_info(src);
return use_def.use_count() == 1 && use_def.def_count() == 1;
}
} // namespace
std::string FormStack::StackEntry::print(const Env& env) const {
@@ -147,9 +156,11 @@ Form* FormStack::pop_reg(const RegisterAccess& var,
ASSERT(entry.source);
if (entry.non_seq_source.has_value()) {
ASSERT(entry.sequence_point == false);
auto result = pop_reg(*entry.non_seq_source, barrier, env, allow_side_effects, i);
if (result) {
return result;
if (can_inline_non_seq_source(*entry.non_seq_source, env)) {
auto result = pop_reg(*entry.non_seq_source, barrier, env, allow_side_effects, i);
if (result) {
return result;
}
}
}
@@ -215,13 +226,15 @@ Form* FormStack::pop_reg(Register reg,
ASSERT(entry.source);
if (entry.non_seq_source.has_value()) {
ASSERT(entry.sequence_point == false);
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects, i);
if (result) {
if (found_orig_out) {
*found_orig_out = true;
*orig_out = *entry.destination;
if (can_inline_non_seq_source(*entry.non_seq_source, env)) {
auto result = pop_reg(entry.non_seq_source->reg(), barrier, env, allow_side_effects, i);
if (result) {
if (found_orig_out) {
*found_orig_out = true;
*orig_out = *entry.destination;
}
return result;
}
return result;
}
}
+1 -1
View File
@@ -309,7 +309,7 @@ bool Matcher::do_match(Form* input, MatchResult::Maps* maps_out, const Env* cons
dynamic_cast<StackSpillValueElement*>(input->try_as_single_active_element());
if (as_stack_spill) {
got = true;
result = make_stack_slot_access(as_stack_spill->stack_offset());
result = as_stack_spill->access();
}
if (got) {
+2
View File
@@ -153,6 +153,8 @@ with open(decomp_file_path) as f:
decomp_form_paren_stack = []
i = i + 1
break
if i + 1 == len(lines):
break
else:
decomp_lines.append(line)
i = i + 1
+4
View File
@@ -1729,6 +1729,10 @@
)
)
(defmacro square (x)
`(* ,x ,x)
)
(import "goal_src/jak1/engine/data/tpages.gc")
(import "goal_src/jak1/engine/data/textures.gc")
@@ -114,7 +114,6 @@
;; definition for method 9 of type lod-set
;; INFO: Used lq/sq
(defmethod setup-lods! ((this lod-set) (arg0 skeleton-group) (arg1 art-group) (arg2 entity))
(local-vars (sv-16 res-tag))
(let ((s4-0 arg0)
(s5-0 arg1)
)
@@ -138,13 +137,13 @@
(set! (-> this lod s3-0 dist) (res-lump-float arg2 'vis-dist :default 4095996000.0))
)
)
(let ((v1-13 (-> s5-0 data (-> s4-0 jgeo))))
(set! sv-16 (new 'static 'res-tag))
(let ((v1-14 (res-lump-data (-> v1-13 extra) 'lod-dist pointer :tag-ptr (& sv-16))))
(when v1-14
(dotimes (a0-6 (the-as int (-> sv-16 elt-count)))
(set! (-> this lod a0-6 dist) (-> (the-as (pointer float) (&+ v1-14 (* a0-6 4)))))
)
(let* ((v1-13 (-> s5-0 data (-> s4-0 jgeo)))
(sv-16 (new 'static 'res-tag))
(v1-14 (res-lump-data (-> v1-13 extra) 'lod-dist pointer :tag-ptr (& sv-16)))
)
(when v1-14
(dotimes (a0-6 (the-as int (-> sv-16 elt-count)))
(set! (-> this lod a0-6 dist) (-> (the-as (pointer float) (&+ v1-14 (* a0-6 4)))))
)
)
)
@@ -428,7 +427,7 @@
;; WARN: Stack slot offset 20 signed mismatch
;; INFO: Return type mismatch draw-control vs none.
(defmethod initialize-skeleton ((this process-drawable) (arg0 skeleton-group) (arg1 pair))
(local-vars (s3-0 draw-control) (sv-16 art-element) (sv-20 int))
(local-vars (s3-0 draw-control))
(let ((s1-0 (cond
((= (-> arg0 texture-level) 2)
(-> *level* level-default)
@@ -448,122 +447,124 @@
(set! s3-0 (the-as draw-control #f))
(goto cfg-59)
)
(set! sv-16 (-> s4-0 data (-> arg0 jgeo)))
(set! sv-20 (-> s4-0 length))
(when (or (>= (-> arg0 jgeo) sv-20) (!= (-> sv-16 type) art-joint-geo))
(go process-drawable-art-error "joint-geo")
(set! s3-0 (the-as draw-control #f))
(goto cfg-59)
)
(let ((v0-3 (new 'process 'draw-control this (the-as art-joint-geo sv-16))))
(set! (-> this draw) v0-3)
(set! s3-0 v0-3)
)
(let ((v1-26 s3-0))
(set! (-> v1-26 status) (draw-status no-skeleton-update))
(set! (-> v1-26 art-group) s4-0)
(set! (-> v1-26 jgeo) (the-as art-joint-geo sv-16))
(set! (-> v1-26 force-lod) -1)
(set! (-> v1-26 cur-lod) -1)
(set! (-> v1-26 shadow) #f)
(set! (-> v1-26 shadow-ctrl) #f)
(set! (-> v1-26 data-format) (the-as uint 1))
(set! (-> v1-26 color-mult quad) (-> (new 'static 'vector :x 1.0 :y 1.0 :z 1.0 :w 1.0) quad))
(set! (-> v1-26 color-emissive quad) (-> (new 'static 'vector) quad))
(set! (-> v1-26 level-index) (the-as uint (-> (if (-> this entity)
(-> this entity extra level)
(-> *level* level-default)
)
index
)
)
(let ((sv-16 (-> s4-0 data (-> arg0 jgeo)))
(sv-20 (-> s4-0 length))
)
(when (or (>= (-> arg0 jgeo) sv-20) (!= (-> sv-16 type) art-joint-geo))
(go process-drawable-art-error "joint-geo")
(set! s3-0 (the-as draw-control #f))
(goto cfg-59)
)
(let ((v0-3 (new 'process 'draw-control this (the-as art-joint-geo sv-16))))
(set! (-> this draw) v0-3)
(set! s3-0 v0-3)
)
(let ((v1-26 s3-0))
(set! (-> v1-26 status) (draw-status no-skeleton-update))
(set! (-> v1-26 art-group) s4-0)
(set! (-> v1-26 jgeo) (the-as art-joint-geo sv-16))
(set! (-> v1-26 force-lod) -1)
(set! (-> v1-26 cur-lod) -1)
(set! (-> v1-26 shadow) #f)
(set! (-> v1-26 shadow-ctrl) #f)
(set! (-> v1-26 data-format) (the-as uint 1))
(set! (-> v1-26 color-mult quad) (-> (new 'static 'vector :x 1.0 :y 1.0 :z 1.0 :w 1.0) quad))
(set! (-> v1-26 color-emissive quad) (-> (new 'static 'vector) quad))
(set! (-> v1-26 level-index) (the-as uint (-> (if (-> this entity)
(-> this entity extra level)
(-> *level* level-default)
)
index
)
)
)
(set! (-> v1-26 longest-edge) (-> arg0 longest-edge))
(set! (-> v1-26 ripple) #f)
)
(set! (-> s3-0 bounds quad) (-> arg0 bounds quad))
(let ((v1-28 (-> arg0 shadow)))
(when (and (> v1-28 0) (< v1-28 sv-20))
(let ((s0-0 (-> s4-0 data v1-28))
(v1-32 (res-lump-value (-> this entity) 'options uint128))
)
(if (and (not (logtest? #x20000 v1-32)) (= (-> s0-0 type) shadow-geo))
(set! (-> s3-0 shadow) (the-as shadow-geo s0-0))
)
)
(set! (-> v1-26 longest-edge) (-> arg0 longest-edge))
(set! (-> v1-26 ripple) #f)
)
(set! (-> s3-0 bounds quad) (-> arg0 bounds quad))
(let ((v1-28 (-> arg0 shadow)))
(when (and (> v1-28 0) (< v1-28 sv-20))
(let ((s0-0 (-> s4-0 data v1-28))
(v1-32 (res-lump-value (-> this entity) 'options uint128))
)
(if (and (not (logtest? #x20000 v1-32)) (= (-> s0-0 type) shadow-geo))
(set! (-> s3-0 shadow) (the-as shadow-geo s0-0))
)
)
)
)
(if (not (setup-lods! (-> s3-0 lod-set) arg0 s4-0 (-> this entity)))
(go process-drawable-art-error "mesh")
(if (not (setup-lods! (-> s3-0 lod-set) arg0 s4-0 (-> this entity)))
(go process-drawable-art-error "mesh")
)
(let ((v1-43 (res-lump-value (-> sv-16 extra) 'texture-bucket int :default (the-as uint128 1))))
(let ((a0-39 (if (= (-> arg0 texture-level) 2)
2
(-> s1-0 index)
)
)
)
(if (= (the-as uint v1-43) 4)
(set! v1-43 2)
)
(if (= a0-39 2)
(set! v1-43 (-> arg0 sort))
)
)
(set! (-> s3-0 sink-group) (-> s1-0 foreground-sink-group v1-43))
)
(let ((v1-43 (res-lump-value (-> sv-16 extra) 'texture-bucket int :default (the-as uint128 1))))
(let ((a0-39 (if (= (-> arg0 texture-level) 2)
2
(-> s1-0 index)
)
)
)
(if (= (the-as uint v1-43) 4)
(set! v1-43 2)
)
(if (= a0-39 2)
(set! v1-43 (-> arg0 sort))
)
)
(set! (-> s3-0 sink-group) (-> s1-0 foreground-sink-group v1-43))
)
(set! (-> s3-0 dma-add-func) (the-as (function process-drawable draw-control symbol object none) nothing))
(set! (-> this node-list) (make-nodes-from-jg (the-as art-joint-geo sv-16) arg1 'process))
(set! (-> s3-0 dma-add-func) dma-add-process-drawable)
(set! (-> s3-0 shadow-mask) (res-lump-value (-> this entity) 'shadow-mask uint))
(set! (-> s3-0 light-index) (res-lump-value (-> this entity) 'light-index uint))
(lod-set! s3-0 0)
(let ((a2-10 (res-lump-value (-> sv-16 extra) 'joint-channel int :default (the-as uint128 6))))
(cond
((> a2-10 0)
(logior! (-> s3-0 status) (draw-status has-joint-channels))
(let ((v0-13 (new 'process 'joint-control a2-10)))
(set! (-> this skel) v0-13)
(let ((s2-1 v0-13))
(cond
((>= (-> arg0 janim) 0)
(when (or (>= (-> arg0 janim) sv-20) (!= (-> s4-0 data (-> arg0 janim) type) art-joint-anim))
(go process-drawable-art-error "initial joint-anim")
(set! s3-0 (the-as draw-control #f))
(goto cfg-59)
)
(ja-channel-set! 1)
(let ((s1-1 (-> this skel root-channel 0)))
(joint-control-channel-group-eval!
s1-1
(the-as art-joint-anim (-> s4-0 data (-> arg0 janim)))
num-func-identity
(set! (-> s3-0 dma-add-func) (the-as (function process-drawable draw-control symbol object none) nothing))
(set! (-> this node-list) (make-nodes-from-jg (the-as art-joint-geo sv-16) arg1 'process))
(set! (-> s3-0 dma-add-func) dma-add-process-drawable)
(set! (-> s3-0 shadow-mask) (res-lump-value (-> this entity) 'shadow-mask uint))
(set! (-> s3-0 light-index) (res-lump-value (-> this entity) 'light-index uint))
(lod-set! s3-0 0)
(let ((a2-10 (res-lump-value (-> sv-16 extra) 'joint-channel int :default (the-as uint128 6))))
(cond
((> a2-10 0)
(logior! (-> s3-0 status) (draw-status has-joint-channels))
(let ((v0-13 (new 'process 'joint-control a2-10)))
(set! (-> this skel) v0-13)
(let ((s2-1 v0-13))
(cond
((>= (-> arg0 janim) 0)
(when (or (>= (-> arg0 janim) sv-20) (!= (-> s4-0 data (-> arg0 janim) type) art-joint-anim))
(go process-drawable-art-error "initial joint-anim")
(set! s3-0 (the-as draw-control #f))
(goto cfg-59)
)
(ja-channel-set! 1)
(let ((s1-1 (-> this skel root-channel 0)))
(joint-control-channel-group-eval!
s1-1
(the-as art-joint-anim (-> s4-0 data (-> arg0 janim)))
num-func-identity
)
(set! (-> s1-1 frame-num) 0.0)
)
(set! (-> s1-1 frame-num) 0.0)
)
)
(else
(ja-channel-set! 0)
(else
(ja-channel-set! 0)
)
)
(set! (-> s2-1 effect) (new 'process 'effect-control this))
)
(set! (-> s2-1 effect) (new 'process 'effect-control this))
)
)
)
(else
(set! (-> s3-0 skeleton bones 0 transform vector 3 quad) (-> (the-as vector (get-property-struct
(-> sv-16 extra)
'trans-offset
'interp
-1000000000.0
*null-vector*
(the-as (pointer res-tag) #f)
*res-static-buf*
)
)
quad
)
)
(else
(set! (-> s3-0 skeleton bones 0 transform vector 3 quad) (-> (the-as vector (get-property-struct
(-> sv-16 extra)
'trans-offset
'interp
-1000000000.0
*null-vector*
(the-as (pointer res-tag) #f)
*res-static-buf*
)
)
quad
)
)
)
)
)
)
@@ -63,7 +63,6 @@
;; WARN: Stack slot offset 16 signed mismatch
;; INFO: Return type mismatch vector4w vs pointer.
(defun render-eyes ((arg0 dma-buffer) (arg1 eye-control) (arg2 int))
(local-vars (sv-16 float))
(let ((s4-0 32)
(s3-0 (+ (* arg2 32) 32))
(s2-0 (* arg2 32))
@@ -71,8 +70,8 @@
(let ((f28-0 (* 16.0 (+ (the float (+ s4-0 16)) (* 32.0 (-> arg1 left data 0 x)))))
(f26-0 (* 16.0 (+ (the float (+ s3-0 16)) (* 32.0 (-> arg1 left data 0 y)))))
(f30-0 (* 16.0 (+ (the float (+ s4-0 48)) (* 32.0 (-> arg1 right data 0 x)))))
(sv-16 (* 16.0 (+ (the float (+ s3-0 16)) (* 32.0 (-> arg1 right data 0 y)))))
)
(set! sv-16 (* 16.0 (+ (the float (+ s3-0 16)) (* 32.0 (-> arg1 right data 0 y)))))
(let ((s1-0 (-> arg1 shaders 0)))
(let ((v1-6 (the-as object (-> arg0 base))))
(set! (-> (the-as dma-gif-packet v1-6) dma-vif quad) (-> *eye-work* adgif-tmpl dma-vif quad))