[Decompile] pad and gs (#389)

* update stuff

* gs reference added

* update config
This commit is contained in:
water111
2021-04-26 21:40:08 -04:00
committed by GitHub
parent 8619e6df19
commit 3d2ca71fe3
40 changed files with 3716 additions and 1542 deletions
+3
View File
@@ -289,6 +289,8 @@ std::string get_simple_expression_op_name(SimpleExpression::Kind kind) {
return "max.si";
case SimpleExpression::Kind::MAX_UNSIGNED:
return "max.ui";
case SimpleExpression::Kind::PCPYLD:
return "pcypld";
default:
assert(false);
return {};
@@ -338,6 +340,7 @@ int get_simple_expression_arg_count(SimpleExpression::Kind kind) {
case SimpleExpression::Kind::MIN_UNSIGNED:
case SimpleExpression::Kind::MAX_SIGNED:
case SimpleExpression::Kind::MAX_UNSIGNED:
case SimpleExpression::Kind::PCPYLD:
return 2;
default:
assert(false);
+2 -1
View File
@@ -221,7 +221,8 @@ class SimpleExpression {
MIN_SIGNED,
MAX_SIGNED,
MIN_UNSIGNED,
MAX_UNSIGNED
MAX_UNSIGNED,
PCPYLD,
};
// how many arguments?
+4 -1
View File
@@ -636,7 +636,10 @@ Form* LoadVarOp::get_load_src(FormPool& pool, const Env& env) const {
// smaller. We should check that the higher bits are all zero.
int bits = as_bitfield->get_size_in_memory() * 8;
assert(bits <= 64);
assert((value >> bits) == 0);
if (bits < 64) {
assert((value >> bits) == 0);
// technically ub if bits == 64.
}
TypeSpec typespec(hint->second.type_name);
auto defs = decompile_bitfield_from_int(typespec, ts, value);
return pool.alloc_single_element_form<BitfieldStaticDefElement>(nullptr, typespec, defs,
+1
View File
@@ -192,6 +192,7 @@ TP_Type SimpleExpression::get_type(const TypeState& input,
return get_type_int1(input, env, dts);
case Kind::DIV_UNSIGNED:
case Kind::MOD_UNSIGNED:
case Kind::PCPYLD:
return TP_Type::make_from_ts("uint");
default:
throw std::runtime_error("Simple expression can't get_type: " +
+2
View File
@@ -1503,6 +1503,8 @@ std::string fixed_operator_to_string(FixedOperatorKind kind) {
return "pair?";
case FixedOperatorKind::NONE:
return "none";
case FixedOperatorKind::PCPYLD:
return ".pcpyld";
default:
assert(false);
return "";
+5
View File
@@ -177,6 +177,11 @@ class SimpleExpressionElement : public FormElement {
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects);
void update_from_stack_pcypld(const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects);
const SimpleExpression& expr() const { return m_expr; }
+97 -29
View File
@@ -201,6 +201,19 @@ void pop_helper(const std::vector<RegisterAccess>& vars,
}
}
namespace {
Form* strip_pcypld_64(Form* in) {
auto m = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::PCPYLD),
{Matcher::integer(0), Matcher::any(0)}),
in);
if (m.matched) {
return m.maps.forms.at(0);
} else {
return in;
}
}
} // namespace
/*!
* This should be used to generate all casts.
*/
@@ -213,6 +226,9 @@ Form* cast_form(Form* in, const TypeSpec& new_type, FormPool& pool, const Env& e
auto type_info = env.dts->ts.lookup_type(new_type);
auto bitfield_info = dynamic_cast<BitFieldType*>(type_info);
if (bitfield_info) {
if (bitfield_info->get_load_size() == 8) {
in = strip_pcypld_64(in);
}
return cast_to_bitfield(bitfield_info, new_type, pool, env, in);
}
@@ -314,13 +330,6 @@ bool is_ptr_or_child(const Env& env, int my_idx, RegisterAccess var, bool) {
return type == "pointer";
}
bool is_var(Form* form) {
auto atom = form_as_atom(form);
if (atom) {
return atom->is_var();
}
return false;
}
} // namespace
/*!
@@ -846,6 +855,36 @@ void SimpleExpressionElement::update_from_stack_force_ui_2(const Env& env,
result->push_back(new_form);
}
void SimpleExpressionElement::update_from_stack_pcypld(const Env& env,
FormPool& pool,
FormStack& stack,
std::vector<FormElement*>* result,
bool allow_side_effects) {
std::vector<Form*> args;
std::vector<RegisterAccess> ras;
for (int arg_idx = 0; arg_idx < m_expr.args(); arg_idx++) {
if (m_expr.get_arg(arg_idx).is_var()) {
ras.push_back(m_expr.get_arg(arg_idx).var());
}
}
auto popped_args = pop_to_forms(ras, env, pool, stack, allow_side_effects);
int ras_idx = 0;
for (int arg_idx = 0; arg_idx < m_expr.args(); arg_idx++) {
if (m_expr.get_arg(arg_idx).is_var()) {
args.push_back(popped_args.at(ras_idx));
ras_idx++;
} else {
args.push_back(
pool.alloc_single_element_form<SimpleAtomElement>(nullptr, m_expr.get_arg(arg_idx)));
}
}
auto new_form = pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::PCPYLD), args.at(0), args.at(1));
result->push_back(new_form);
}
void SimpleExpressionElement::update_from_stack_copy_first_int_2(const Env& env,
FixedOperatorKind kind,
FormPool& pool,
@@ -966,9 +1005,11 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
if (bitfield_info) {
// either the immediate didn't fit in the 16-bit imm or it's with a variable
bool made_new_read_elt = false;
auto read_elt = dynamic_cast<BitfieldAccessElement*>(args.at(0)->try_as_single_element());
if (!read_elt) {
read_elt = pool.alloc_element<BitfieldAccessElement>(args.at(0), arg0_type);
made_new_read_elt = true;
}
auto stripped_arg1 = strip_int_or_uint_cast(args.at(1));
@@ -987,7 +1028,7 @@ void SimpleExpressionElement::update_from_stack_logor_or_logand(const Env& env,
assert(!other); // shouldn't be complete.
result->push_back(read_elt);
return;
} else {
} else if (!made_new_read_elt) {
BitfieldManip::Kind manip_kind;
if (kind == FixedOperatorKind::LOGAND) {
manip_kind = BitfieldManip::Kind::LOGAND_WITH_FORM;
@@ -1325,6 +1366,9 @@ void SimpleExpressionElement::update_from_stack(const Env& env,
case SimpleExpression::Kind::FLOAT_TO_INT:
update_from_stack_float_to_int(env, pool, stack, result, allow_side_effects);
break;
case SimpleExpression::Kind::PCPYLD:
update_from_stack_pcypld(env, pool, stack, result, allow_side_effects);
break;
default:
throw std::runtime_error(
fmt::format("SimpleExpressionElement::update_from_stack NYI for {}", to_string(env)));
@@ -2292,14 +2336,20 @@ void ShortCircuitElement::update_from_stack(const Env& env,
already_rewritten = true;
}
namespace {
Matcher make_int_uint_cast_matcher(const Matcher& thing) {
return Matcher::match_or({Matcher::cast("uint", thing), Matcher::cast("int", thing), thing});
}
} // namespace
///////////////////
// ConditionElement
///////////////////
FormElement* ConditionElement::make_zero_check_generic(const Env&,
FormElement* ConditionElement::make_zero_check_generic(const Env& env,
FormPool& pool,
const std::vector<Form*>& source_forms,
const std::vector<TypeSpec>&) {
const std::vector<TypeSpec>& source_types) {
// (zero? (+ thing small-integer)) -> (= thing (- small-integer))
assert(source_forms.size() == 1);
auto mr = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
@@ -2311,9 +2361,26 @@ FormElement* ConditionElement::make_zero_check_generic(const Env&,
nullptr, SimpleAtom::make_int_constant(value));
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::EQ),
std::vector<Form*>{mr.maps.forms.at(0), value_form});
} else {
return pool.alloc_element<GenericElement>(GenericOperator::make_compare(m_kind), source_forms);
}
auto enum_type_info = env.dts->ts.try_enum_lookup(source_types.at(0));
if (enum_type_info && !enum_type_info->is_bitfield()) {
// (zero? (+ (the-as uint arg0) (the-as uint -2))) check enum value
mr = match(Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::ADDITION),
{make_int_uint_cast_matcher(Matcher::any(0)),
make_int_uint_cast_matcher(Matcher::any_integer(1))}),
source_forms.at(0));
if (mr.matched) {
s64 value = mr.maps.ints.at(1);
value = -value;
auto enum_constant = cast_to_int_enum(enum_type_info, pool, env, value);
return pool.alloc_element<GenericElement>(
GenericOperator::make_fixed(FixedOperatorKind::EQ),
std::vector<Form*>{mr.maps.forms.at(0), enum_constant});
}
}
return pool.alloc_element<GenericElement>(GenericOperator::make_compare(m_kind), source_forms);
}
FormElement* ConditionElement::make_nonzero_check_generic(const Env& env,
@@ -2682,6 +2749,7 @@ void ReturnElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
}
namespace {
void push_asm_srl_to_stack(const AsmOp* op,
FormElement* form_elt,
const Env& env,
@@ -2714,6 +2782,21 @@ void push_asm_srl_to_stack(const AsmOp* op,
}
}
void push_asm_to_stack(const AsmOp* op,
FormElement* form_elt,
const Env& env,
FormPool& pool,
FormStack& stack) {
switch (op->instruction().kind) {
case InstructionKind::SRL:
push_asm_srl_to_stack(op, form_elt, env, pool, stack);
break;
default:
stack.push_form_element(form_elt, true);
break;
}
}
} // namespace
void AtomicOpElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
@@ -2737,14 +2820,7 @@ void AtomicOpElement::push_to_stack(const Env& env, FormPool& pool, FormStack& s
auto as_asm = dynamic_cast<const AsmOp*>(m_op);
if (as_asm) {
switch (as_asm->instruction().kind) {
case InstructionKind::SRL:
push_asm_srl_to_stack(as_asm, this, env, pool, stack);
break;
default:
stack.push_form_element(this, true);
break;
}
push_asm_to_stack(as_asm, this, env, pool, stack);
return;
}
@@ -2753,15 +2829,7 @@ void AtomicOpElement::push_to_stack(const Env& env, FormPool& pool, FormStack& s
void AsmOpElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
mark_popped();
switch (m_op->instruction().kind) {
case InstructionKind::SRL:
push_asm_srl_to_stack(m_op, this, env, pool, stack);
break;
default:
stack.push_form_element(this, true);
break;
}
push_asm_to_stack(m_op, this, env, pool, stack);
}
void GenericElement::update_from_stack(const Env& env,
+1
View File
@@ -141,6 +141,7 @@ enum class FixedOperatorKind {
NULLP,
PAIRP,
NONE,
PCPYLD,
INVALID
};
+2 -2
View File
@@ -9,8 +9,8 @@ typedef OpenGOALAsm::InstructionModifiers MOD;
const std::map<InstructionKind, OpenGOALAsm::Function> MIPS_ASM_TO_OPEN_GOAL_FUNCS = {
// ----- EE -------
// TODO - these are waiting on proper 128-bit int support in OpenGOAL
{InstructionKind::PSLLW, {"TODO.PSLLW", {}}},
{InstructionKind::PSRAW, {"TODO.PSRAW", {}}},
{InstructionKind::PSLLW, {".pw.sll", {}}},
{InstructionKind::PSRAW, {".pw.sra", {}}},
{InstructionKind::PSUBW, {"TODO.PSUBW", {}}},
{InstructionKind::PEXTUW, {".pextuw", {}}},
+45 -11
View File
@@ -216,6 +216,24 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
return def;
}
// also possible to omit the shr if it would be zero:
auto matcher_no_shr = Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SHL),
{Matcher::any(0), Matcher::any_integer(1)});
auto mr_no_shr = match(matcher_no_shr, strip_int_or_uint_cast(form));
if (mr_no_shr.matched) {
auto value = mr_no_shr.maps.forms.at(0);
int left = mr_no_shr.maps.ints.at(1);
int right = 0;
int size = 64 - left;
int offset = left - right;
auto& f = find_field(ts, type, offset, size, {});
BitFieldDef def;
def.value = value;
def.field_name = f.name();
def.is_signed = false; // we don't know.
return def;
}
return {};
}
@@ -228,7 +246,7 @@ std::optional<BitFieldDef> get_bitfield_initial_set(Form* form,
FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
const TypeSystem& ts,
FormPool& pool,
const Env& env) {
const Env&) {
if (m_steps.empty() && step.kind == BitfieldManip::Kind::LEFT_SHIFT) {
// for left/right shift combo to get a field.
m_steps.push_back(step);
@@ -354,6 +372,12 @@ FormElement* BitfieldAccessElement::push_step(const BitfieldManip step,
std::vector<BitFieldDef>{*val});
}
lg::error("Invalid state in BitfieldReadElement. Previous steps:");
for (auto& old_step : m_steps) {
lg::error(" {}", old_step.print());
}
lg::error("Current: {}\n", step.print());
throw std::runtime_error("Unknown state in BitfieldReadElement");
}
@@ -409,8 +433,14 @@ BitFieldDef BitFieldDef::from_constant(const BitFieldConstantDef& constant, Form
BitFieldDef bfd;
bfd.field_name = constant.field_name;
bfd.is_signed = constant.is_signed;
bfd.value = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(constant.value));
if (constant.enum_constant) {
bfd.value =
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, *constant.enum_constant);
} else {
bfd.value = pool.alloc_single_element_form<SimpleAtomElement>(
nullptr, SimpleAtom::make_int_constant(constant.value));
}
return bfd;
}
@@ -426,7 +456,7 @@ Form* cast_to_bitfield(const BitFieldType* type_info,
in = strip_int_or_uint_cast(in);
// check if it's just a constant:
auto in_as_atom = form_as_atom(in);
if (in_as_atom) {
if (in_as_atom && in_as_atom->is_int()) {
auto fields = decompile_bitfield_from_int(typespec, env.dts->ts, in_as_atom->get_int());
return pool.alloc_single_element_form<BitfieldStaticDefElement>(nullptr, typespec, fields,
pool);
@@ -458,7 +488,8 @@ Form* cast_to_bitfield(const BitFieldType* type_info,
// now variables
for (auto& arg : args) {
auto maybe_field = get_bitfield_initial_set(arg, type_info, env.dts->ts);
auto maybe_field =
get_bitfield_initial_set(strip_int_or_uint_cast(arg), type_info, env.dts->ts);
if (!maybe_field) {
// failed, just return cast.
return pool.alloc_single_element_form<CastElement>(nullptr, typespec, in);
@@ -503,16 +534,19 @@ Form* cast_to_int_enum(const EnumType* type_info,
assert(!type_info->is_bitfield());
auto integer = get_goal_integer_constant(strip_int_or_uint_cast(in), env);
if (integer) {
auto entry =
decompile_int_enum_from_int(TypeSpec(type_info->get_name()), env.dts->ts, *integer);
auto oper = GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, type_info->get_name()));
return pool.alloc_single_element_form<GenericElement>(
nullptr, oper, pool.alloc_single_element_form<ConstantTokenElement>(nullptr, entry));
return cast_to_int_enum(type_info, pool, env, *integer);
} else {
// all failed, just return whatever.
return pool.alloc_single_element_form<CastElement>(nullptr, typespec, in);
}
}
Form* cast_to_int_enum(const EnumType* type_info, FormPool& pool, const Env& env, s64 in) {
auto entry = decompile_int_enum_from_int(TypeSpec(type_info->get_name()), env.dts->ts, in);
auto oper = GenericOperator::make_function(
pool.alloc_single_element_form<ConstantTokenElement>(nullptr, type_info->get_name()));
return pool.alloc_single_element_form<GenericElement>(
nullptr, oper, pool.alloc_single_element_form<ConstantTokenElement>(nullptr, entry));
}
} // namespace decompiler
+26
View File
@@ -54,6 +54,30 @@ struct BitfieldManip {
return result;
}
std::string print() const {
switch (kind) {
case Kind::LEFT_SHIFT:
return "left-shift";
case Kind::RIGHT_SHIFT_LOGICAL:
return "right-shift-logical";
case Kind::RIGHT_SHIFT_LOGICAL_32BIT:
return "right-shift-logical32";
case Kind::LOGAND_WITH_CONSTANT_INT:
return "logand-constant";
case Kind::LOGIOR_WITH_CONSTANT_INT:
return "logior-constant";
case Kind::LOGIOR_WITH_FORM:
return "logior-form";
case Kind::LOGAND_WITH_FORM:
return "logand-form";
case Kind::NONZERO_COMPARE:
return "nonzero-compare";
case Kind::INVALID:
default:
assert(false);
}
}
private:
BitfieldManip() = default;
};
@@ -153,6 +177,8 @@ Form* cast_to_int_enum(const EnumType* type_info,
const Env& env,
Form* in);
Form* cast_to_int_enum(const EnumType* type_info, FormPool& pool, const Env& env, s64 in);
std::optional<u64> get_goal_integer_constant(Form* in, const Env&);
const BitField& find_field(const TypeSystem& ts,
+5 -1
View File
@@ -275,7 +275,11 @@ void ObjectFileDB::ir2_atomic_op_pass() {
func.ir2.atomic_ops_attempted = true;
attempted++;
try {
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels, func.warnings);
bool inline_asm =
get_config().hint_inline_assembly_functions.find(func.guessed_name.to_string()) !=
get_config().hint_inline_assembly_functions.end();
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels, func.warnings,
inline_asm);
func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
func.ir2.atomic_ops_succeeded = true;
func.ir2.env.set_end_var(func.ir2.atomic_ops->end_op().return_var());
+20 -8
View File
@@ -11,7 +11,7 @@ namespace decompiler {
namespace {
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx);
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx, bool hint_inline_asm);
//////////////////////
// Register Helpers
@@ -67,6 +67,9 @@ RegisterAccess make_dst_var(const Instruction& i, int idx) {
////////////////////////
SimpleAtom make_src_atom(Register reg, int idx) {
if (reg == Register(Reg::GPR, Reg::R0)) {
return SimpleAtom::make_int_constant(0);
}
return SimpleAtom::make_var(make_src_var(reg, idx));
}
@@ -399,7 +402,7 @@ std::unique_ptr<AtomicOp> make_branch(const IR2_Condition& condition,
if (branch_delay.is_known()) {
return std::make_unique<BranchOp>(likely, condition, dest_label, branch_delay, my_idx);
} else {
auto delay_op = std::shared_ptr<AtomicOp>(convert_1(delay, my_idx));
auto delay_op = std::shared_ptr<AtomicOp>(convert_1(delay, my_idx, false));
return std::make_unique<AsmBranchOp>(likely, condition, dest_label, delay_op, my_idx);
}
}
@@ -707,7 +710,7 @@ std::unique_ptr<AtomicOp> convert_bnel_1(const Instruction& i0, int idx, bool li
return make_branch_no_delay(condition, likely, dest, idx);
}
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx) {
std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx, bool hint_inline_asm) {
switch (i0.kind) {
case InstructionKind::OR:
return convert_or_1(i0, idx);
@@ -715,6 +718,12 @@ std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx) {
return convert_ori_1(i0, idx);
case InstructionKind::AND:
return make_3reg_op(i0, SimpleExpression::Kind::AND, idx);
case InstructionKind::PCPYLD:
if (hint_inline_asm) {
break;
} else {
return make_3reg_op(i0, SimpleExpression::Kind::PCPYLD, idx);
}
case InstructionKind::MTC1:
return convert_mtc1_1(i0, idx);
case InstructionKind::MFC1:
@@ -835,6 +844,7 @@ std::unique_ptr<AtomicOp> convert_1(const Instruction& i0, int idx) {
default:
return nullptr;
}
return nullptr;
}
///////////////////////
@@ -1406,7 +1416,8 @@ int convert_block_to_atomic_ops(int begin_idx,
std::vector<Instruction>::const_iterator end,
const std::vector<DecompilerLabel>& labels,
FunctionAtomicOps* container,
DecompWarnings& warnings) {
DecompWarnings& warnings,
bool hint_inline_asm) {
container->block_id_to_first_atomic_op.push_back(container->ops.size());
for (auto& instr = begin; instr < end;) {
// how many instructions can we look at, at most?
@@ -1461,7 +1472,7 @@ int convert_block_to_atomic_ops(int begin_idx,
if (!converted) {
// try 1 instruction
op = convert_1(*instr, op_idx);
op = convert_1(*instr, op_idx, hint_inline_asm);
if (op) {
converted = true;
length = 1;
@@ -1502,7 +1513,8 @@ int convert_block_to_atomic_ops(int begin_idx,
FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
const std::vector<DecompilerLabel>& labels,
DecompWarnings& warnings) {
DecompWarnings& warnings,
bool hint_inline_asm) {
FunctionAtomicOps result;
int last_op = 0;
@@ -1512,8 +1524,8 @@ FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
if (block.end_word > block.start_word) {
auto begin = func.instructions.begin() + block.start_word;
auto end = func.instructions.begin() + block.end_word;
last_op =
convert_block_to_atomic_ops(block.start_word, begin, end, labels, &result, warnings);
last_op = convert_block_to_atomic_ops(block.start_word, begin, end, labels, &result, warnings,
hint_inline_asm);
if (i == int(func.basic_blocks.size()) - 1) {
// we're the last block. insert the function end op.
result.ops.push_back(std::make_unique<FunctionEndOp>(int(result.ops.size())));
+4 -2
View File
@@ -47,12 +47,14 @@ int convert_block_to_atomic_ops(int begin_idx,
std::vector<Instruction>::const_iterator end,
const std::vector<DecompilerLabel>& labels,
FunctionAtomicOps* container,
DecompWarnings& warnings);
DecompWarnings& warnings,
bool inline_asm_hint = false);
/*!
* Convert an entire function to AtomicOps
*/
FunctionAtomicOps convert_function_to_atomic_ops(const Function& func,
const std::vector<DecompilerLabel>& labels,
DecompWarnings& warnings);
DecompWarnings& warnings,
bool hint_inline_asm);
} // namespace decompiler
+2
View File
@@ -55,6 +55,8 @@ void set_config(const std::string& path_to_config_file) {
gConfig.analyze_expressions = cfg.at("analyze_expressions").get<bool>();
gConfig.run_ir2 = cfg.at("run_ir2").get<bool>();
gConfig.insert_lets = cfg.at("insert_lets").get<bool>();
gConfig.hint_inline_assembly_functions =
cfg.at("inline_asm_hint").get<std::unordered_set<std::string>>();
std::vector<std::string> asm_functions_by_name =
cfg.at("asm_functions_by_name").get<std::vector<std::string>>();
+2
View File
@@ -78,6 +78,8 @@ struct Config {
std::unordered_map<std::string, std::unordered_map<std::string, LabelType>> label_types;
std::unordered_map<std::string, std::vector<StackVariableHint>> stack_var_hints_by_function;
bool run_ir2 = false;
std::unordered_set<std::string> hint_inline_assembly_functions;
};
Config& get_config();
+85 -17
View File
@@ -2881,14 +2881,32 @@
:flag-assert #x900000008
)
(define-extern psm-size (function int int))
(define-extern psm-page-height (function int int))
(define-extern psm->string (function int string))
(defenum gs-psm
:bitfield #f
:type uint8
(ct32 0)
(ct24 1)
(ct16 2)
(ct16s 10)
(mt8 19)
(mt4 20)
(mt8h 27)
(mt4hl 36)
(mt4hh 44)
(mz32 48)
(mz24 49)
(mz16 50)
(mz16s 58)
)
(define-extern psm-size (function gs-psm int))
(define-extern psm-page-height (function gs-psm int))
(define-extern psm->string (function gs-psm string))
(deftype gs-display-fb (uint64)
((fbp uint16 :offset 0 :size 9)
(fbw uint8 :offset 9 :size 6)
(psm uint8 :offset 15 :size 5)
(psm gs-psm :offset 15 :size 5)
(dbx uint16 :offset 32 :size 11)
(dby uint16 :offset 43 :size 11)
)
@@ -3300,7 +3318,13 @@
:flag-assert #x900000004
)
(deftype gif-tag64 (uint64)
()
((nloop uint16 :offset 0 :size 15)
(eop uint8 :offset 15 :size 1)
(id uint16 :offset 32 :size 14)
(pre uint8 :offset 46 :size 1)
(prim uint16 :offset 47 :size 11)
(flg uint8 :offset 58 :size 2)
(nreg uint8 :offset 60 :size 4))
:flag-assert #x900000008
)
(deftype gif-tag (uint128)
@@ -3331,12 +3355,55 @@
:flag-assert #x900000010
)
(defenum gs-reg-id
:bitfield #f
:type uint8
(prim 0)
(rgbaq 1)
(st 2)
(uv 3)
(xyzf2 4)
(xyz2 5)
(tex0-1 6)
(tex0-2 7)
(clamp-1 8)
(clamp-2 9)
(fog 10)
(xyzf3 12)
(xyz3 13)
(a+d 14)
(nop 15)
)
(deftype gif-tag-regs (uint64)
((regs0 gs-reg-id :offset 0 :size 4)
(regs1 gs-reg-id :offset 4 :size 4)
(regs2 gs-reg-id :offset 8 :size 4)
(regs3 gs-reg-id :offset 12 :size 4)
(regs4 gs-reg-id :offset 16 :size 4)
(regs5 gs-reg-id :offset 20 :size 4)
(regs6 gs-reg-id :offset 24 :size 4)
(regs7 gs-reg-id :offset 28 :size 4)
(regs8 gs-reg-id :offset 32 :size 4)
(regs9 gs-reg-id :offset 36 :size 4)
(regs10 gs-reg-id :offset 40 :size 4)
(regs11 gs-reg-id :offset 44 :size 4)
(regs12 gs-reg-id :offset 48 :size 4)
(regs13 gs-reg-id :offset 52 :size 4)
(regs14 gs-reg-id :offset 56 :size 4)
(regs15 gs-reg-id :offset 60 :size 4)
)
)
(deftype gs-gif-tag (structure)
((qword uint128 :offset-assert 0) ;; is "qword" and inline? in game
(dword uint64 2 :offset 0)
(word uint32 4 :offset 0)
(tag uint64 :offset 0)
(regs uint64 :offset 8)
(tag gif-tag64 :offset 0)
(regs gif-tag-regs :offset 8)
(dword uint64 2 :offset 0)
(word uint32 4 :offset 0)
)
:method-count-assert 9
:size-assert #x10
@@ -3350,8 +3417,9 @@
(deftype gif-packet (basic)
((reg-count int32 :offset-assert 4)
(gif-tag0 uint128 :offset-assert 16)
(gif-tag gs-gif-tag :inline :offset 16) ;; note- added
(gif-tag gs-gif-tag :inline :offset-assert 16) ;; note- added
(gif-tag0 uint128 :offset 16)
(args uint64 1 :offset-assert 32)
)
@@ -3627,15 +3695,15 @@
(define-extern vector-cvt.s.w! (function vector vector vector))
(define-extern rot-zxy-from-vector! (function vector vector vector))
(define-extern rot-zyx-from-vector! (function vector vector vector))
(define-extern vector-lerp! (function vector vector vector))
(define-extern vector-lerp-clamp! (function vector vector float float vector))
(define-extern vector4-lerp! (function vector vector vector))
(define-extern vector4-lerp-clamp! (function vector vector float float vector))
(define-extern vector-lerp! (function vector vector vector float vector))
(define-extern vector-lerp-clamp! (function vector vector vector float vector))
(define-extern vector4-lerp! (function vector vector vector float vector))
(define-extern vector4-lerp-clamp! (function vector vector vector float vector))
(define-extern vector-degi (function vector vector vector))
(define-extern vector-degf (function vector vector vector))
(define-extern vector-degmod (function vector vector vector))
(define-extern vector-deg-diff (function vector vector vector vector))
(define-extern vector-deg-lerp-clamp! function) ;; todo
(define-extern vector-deg-lerp-clamp! (function vector vector vector float vector)) ;; todo
(define-extern vector3s-copy! (function vector vector vector))
(define-extern vector3s+! (function vector vector vector vector))
(define-extern vector3s*float! (function vector vector float vector))
@@ -3643,7 +3711,7 @@
(define-extern spheres-overlap? (function vector vector symbol))
(define-extern sphere<-vector! (function sphere vector sphere))
(define-extern sphere<-vector+r! (function sphere vector float sphere))
(define-extern rand-vu-sphere-point! function) ;; todo
(define-extern rand-vu-sphere-point! (function vector sphere vector)) ;; todo
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -97,6 +97,8 @@
"no_type_analysis_functions_by_name":[],
// this provides a hint to the decompiler that these functions will have a lot of inline assembly.
"inline_asm_hint":["matrix-transpose!"],
"asm_functions_by_name":[
// gcommon
@@ -123,9 +123,13 @@
["L41", "float", true]
],
"dma-disasm": [["L148", "(array vif-disasm-element)", true]],
"gs": [["L53", "gif-tag64", true],
["L51", "gif-tag-regs", true],
["L52", "uint64", true]],
"loader-h": [["L10", "float", true]],
"dma-disasm": [["L148", "(array vif-disasm-element)", true]],
"level-h": [["L3", "level-group", true]],
"level-info": [
@@ -377,6 +381,7 @@
"collide-edge-grab-h": [["L1", "collide-edge-work", true]],
"vector": [
["L114", "float", true],
["L113", "float", true],
["L112", "float", true],
["L111", "float", true]
@@ -211,6 +211,13 @@
[334, "v1", "(pointer uint64)"]
],
"default-buffer-init": [
[[8, 15], "a1", "dma-gif-packet"],
[[18, 24], "a1", "gs-gif-tag"],
[[29, 64], "a1", "(pointer uint64)"],
[[69, 72], "a0", "dma-packet"]
],
// LEVEL
"lookup-level-info": [
[3, "a1", "symbol"],
@@ -762,15 +762,15 @@
"default-buffer-init": {
"args": ["buff"],
"vars": {
"v1-0": "buff",
"v1-1": "buff",
"v1-3": "buff",
"v1-4": "buff",
"a1-4": "tag",
"a1-6": "tag2",
"a1-8": "data",
"a0-1": "tag3",
"v1-2": "buff"
"v1-0": "buff-ptr",
"v1-1": "buff-ptr2",
"v1-3": "buff-ptr3",
"v1-4": "buff-ptr4",
"a1-4": ["packet", "dma-gif-packet"],
"a1-6": ["gif-tag", "gs-gif-tag"],
"a1-8": ["data", "(pointer uint64)"],
"a0-1": ["ret-packet", "dma-packet"],
"v1-2": "buff-ptr5"
}
},
+10 -1
View File
@@ -532,7 +532,11 @@ goos::Object bitfield_defs_print(const TypeSpec& type,
std::vector<goos::Object> result;
result.push_back(pretty_print::to_symbol(fmt::format("new 'static '{}", type.print())));
for (auto& def : defs) {
if (def.is_signed) {
if (def.enum_constant) {
assert(false); // this is untested.
result.push_back(
pretty_print::to_symbol(fmt::format(":{} {}", def.field_name, *def.enum_constant)));
} else if (def.is_signed) {
result.push_back(
pretty_print::to_symbol(fmt::format(":{} {}", def.field_name, (s64)def.value)));
} else {
@@ -865,6 +869,11 @@ std::vector<BitFieldConstantDef> decompile_bitfield_from_int(const TypeSpec& typ
def.value = bitfield_value;
def.field_name = field.name();
def.is_signed = is_signed;
auto enum_info = ts.try_enum_lookup(field.type());
if (enum_info && !enum_info->is_bitfield()) {
auto name = decompile_int_enum_from_int(field.type(), ts, bitfield_value);
def.enum_constant = fmt::format("({} {})", field.type().print(), name);
}
result.push_back(def);
}
+1
View File
@@ -62,6 +62,7 @@ goos::Object decompile_bitfield(const TypeSpec& type,
struct BitFieldConstantDef {
bool is_signed = false;
u64 value = -1;
std::optional<std::string> enum_constant;
std::string field_name;
};
+251 -153
View File
@@ -34,69 +34,81 @@
;; 50 = PSMZ16
;; 58 = PSMZ16S
(defconstant TEX_MZ16S 58)
(defconstant TEX_MZ16 50)
(defconstant TEX_MZ24 49)
(defconstant TEX_MZ32 48)
(defconstant TEX_MT4HH 44)
(defconstant TEX_MT4HL 36)
(defconstant TEX_MT8H 27)
(defconstant TEX_MT4 20)
(defconstant TEX_MT8 19)
(defconstant TEX_CT16S 10)
(defconstant TEX_CT16 2)
(defconstant TEX_CT24 1)
(defconstant TEX_CT32 0)
(defun psm-size ((arg0 int))
"Not sure exactly what 'size' means, but this likely takes a texture format as an input."
(cond
((= arg0 TEX_MT8) 64)
((= arg0 TEX_MT4) 32)
(else
(if (or (= arg0 TEX_CT16) (= arg0 TEX_CT16S) (= arg0 TEX_MZ16) (= arg0 TEX_MZ16S))
128
256
)
(defenum gs-psm
:bitfield #f
:type uint8
(ct32 0)
(ct24 1)
(ct16 2)
(ct16s 10)
(mt8 19)
(mt4 20)
(mt8h 27)
(mt4hl 36)
(mt4hh 44)
(mz32 48)
(mz24 49)
(mz16 50)
(mz16s 58)
)
(defun psm-size ((arg0 gs-psm))
"Convert texture format to some type of size."
(cond
((= arg0 (gs-psm mt8)) 64)
((= arg0 (gs-psm mt4)) 32)
(else
(if (or (= arg0 (gs-psm ct16))
(= arg0 (gs-psm ct16s))
(= arg0 (gs-psm mz16))
(= arg0 (gs-psm mz16s))
)
128
256
)
)
)
)
)
(defun psm-page-height ((arg0 int))
"texture format -> page height?"
(defun psm-page-height ((arg0 gs-psm))
"Convert texture format to some type of page height"
(cond
((= arg0 TEX_MT8) 64)
((= arg0 TEX_MT4) 128)
(else
(if (or (= arg0 TEX_CT16) (= arg0 TEX_CT16S) (= arg0 TEX_MZ16) (= arg0 TEX_MZ16S))
64
32
)
((= arg0 (gs-psm mt8)) 64)
((= arg0 (gs-psm mt4)) 128)
(else
(if (or (= arg0 (gs-psm ct16))
(= arg0 (gs-psm ct16s))
(= arg0 (gs-psm mz16))
(= arg0 (gs-psm mz16s))
)
64
32
)
)
)
)
)
(defun psm->string ((arg0 int))
"Convert texture format to its name"
(local-vars (v1-0 int))
(set! v1-0 arg0)
(cond
((= v1-0 TEX_MZ16S) "mz16s")
((= v1-0 TEX_MZ16) "mz16")
((= v1-0 TEX_MZ24) "mz24")
((= v1-0 TEX_MZ32) "mz32")
((= v1-0 TEX_MT4HH) "mt4hh")
((= v1-0 TEX_MT4HL) "mt4hl")
((= v1-0 TEX_MT8H) "mt8h")
((= v1-0 TEX_MT4) "mt4")
((= v1-0 TEX_MT8) "mt8")
((= v1-0 TEX_CT16S) "ct16s")
((= v1-0 TEX_CT16) "ct16")
((= v1-0 TEX_CT24) "ct24")
((zero? v1-0) "ct32")
(else "*unknown*")
)
(defun psm->string ((arg0 gs-psm))
"Get the name of a texture format."
(let ((v1-0 arg0))
(cond
((= v1-0 (gs-psm mz16s)) "mz16s")
((= v1-0 (gs-psm mz16)) "mz16")
((= v1-0 (gs-psm mz24)) "mz24")
((= v1-0 (gs-psm mz32)) "mz32")
((= v1-0 (gs-psm mt4hh)) "mt4hh")
((= v1-0 (gs-psm mt4hl)) "mt4hl")
((= v1-0 (gs-psm mt8h)) "mt8h")
((= v1-0 (gs-psm mt4)) "mt4")
((= v1-0 (gs-psm mt8)) "mt8")
((= v1-0 (gs-psm ct16s)) "ct16s")
((= v1-0 (gs-psm ct16)) "ct16")
((= v1-0 (gs-psm ct24)) "ct24")
((zero? v1-0) "ct32")
(else "*unknown*")
)
)
)
;; the GS's DISPFB registers make settings for the frame buffer regarding information on
@@ -105,12 +117,13 @@
(deftype gs-display-fb (uint64)
((fbp uint16 :offset 0 :size 9)
(fbw uint8 :offset 9 :size 6)
(psm uint8 :offset 15 :size 5)
(psm gs-psm :offset 15 :size 5)
(dbx uint16 :offset 32 :size 11)
(dby uint16 :offset 43 :size 11)
)
:flag-assert #x900000008
)
;; the GS's DISPLAY registers make settings for the display position on the screen regarding
;; information on Rectangular Area Read Output Circuit n for the PCRTC.
;; write-only
@@ -124,6 +137,7 @@
)
:flag-assert #x900000008
)
;; the GS's BGCOLOR register sets the background color of the PCRTC with RGB value.
;; write-only
(deftype gs-bgcolor (uint64)
@@ -133,6 +147,7 @@
)
:flag-assert #x900000008
)
;; the GS's CSR register sets and obtains various GS statuses.
;; read-write. the fields have different effects depending on whether they're being read from
;; or written to.
@@ -175,6 +190,7 @@
:size-assert #x1048
:flag-assert #x900001048
)
;; the GS's FRAME registers store various settings related to the frame buffer.
(deftype gs-frame (uint64)
((fbp uint16 :offset 0 :size 9)
@@ -184,6 +200,7 @@
)
:flag-assert #x900000008
)
;; the GS's ZBUF registers make various settings regarding Z buffer.
(deftype gs-zbuf (uint64)
((zbp uint16 :offset 0 :size 9)
@@ -517,7 +534,13 @@
:flag-assert #x900000004
)
(deftype gif-tag64 (uint64)
()
((nloop uint16 :offset 0 :size 15)
(eop uint8 :offset 15 :size 1)
(id uint16 :offset 32 :size 14)
(pre uint8 :offset 46 :size 1)
(prim uint16 :offset 47 :size 11)
(flg uint8 :offset 58 :size 2)
(nreg uint8 :offset 60 :size 4))
:flag-assert #x900000008
)
(deftype gif-tag (uint128)
@@ -548,12 +571,52 @@
:flag-assert #x900000010
)
(defenum gs-reg-id
:bitfield #f
:type uint8
(prim 0)
(rgbaq 1)
(st 2)
(uv 3)
(xyzf2 4)
(xyz2 5)
(tex0-1 6)
(tex0-2 7)
(clamp-1 8)
(clamp-2 9)
(fog 10)
(xyzf3 12)
(xyz3 13)
(a+d 14)
(nop 15)
)
(deftype gif-tag-regs (uint64)
((regs0 gs-reg-id :offset 0 :size 4)
(regs1 gs-reg-id :offset 4 :size 4)
(regs2 gs-reg-id :offset 8 :size 4)
(regs3 gs-reg-id :offset 12 :size 4)
(regs4 gs-reg-id :offset 16 :size 4)
(regs5 gs-reg-id :offset 20 :size 4)
(regs6 gs-reg-id :offset 24 :size 4)
(regs7 gs-reg-id :offset 28 :size 4)
(regs8 gs-reg-id :offset 32 :size 4)
(regs9 gs-reg-id :offset 36 :size 4)
(regs10 gs-reg-id :offset 40 :size 4)
(regs11 gs-reg-id :offset 44 :size 4)
(regs12 gs-reg-id :offset 48 :size 4)
(regs13 gs-reg-id :offset 52 :size 4)
(regs14 gs-reg-id :offset 56 :size 4)
(regs15 gs-reg-id :offset 60 :size 4)
)
)
(deftype gs-gif-tag (structure)
((qword uint128 :offset-assert 0) ;; is "qword" and inline? in game
(tag gif-tag64 :offset 0)
(regs gif-tag-regs :offset 8)
(dword uint64 2 :offset 0)
(word uint32 4 :offset 0)
(tag uint64 :offset 0)
(regs uint64 :offset 8)
)
:method-count-assert 9
:size-assert #x10
@@ -570,66 +633,108 @@
(define *default-regs-buffer* (new 'global 'dma-buffer 1024))
(defun default-buffer-init ((buff dma-buffer))
"Puts some currently unknown gif tags in the buffer."
(local-vars
(tag3 gs-gif-tag)
(tag gs-gif-tag)
(tag2 gs-gif-tag)
(data (pointer uint64))
)
;; reset the buffer base and end.
(set! (-> buff base) (-> buff data))
(set! (-> buff end) (&-> buff data-buffer (-> buff allocated-length)))
"Set some GS registers back to default values. Ends with a ret dma-tag.
This is intended to live in its own separate dma-buffer and not be added
to the global buffer. Calling this will reset this dma-buffer."
;; make a tag (maybe this is actually a dma/vif tag?)
(set! tag (the gs-gif-tag (-> buff base)))
(set! (-> tag dword 0) #x1000000a)
(set! (-> tag word 2) #x13000000)
(set! (-> tag word 3) #x5000000a)
(set! (-> buff base) (&+ (the-as pointer tag) 16))
;; reset the buffer.
(let ((buff-ptr buff))
(set! (-> buff-ptr base) (-> buff-ptr data))
(set! (-> buff-ptr end)
(&-> buff-ptr data-buffer (-> buff-ptr allocated-length))
)
)
;; make another tag.
(set! tag2 (the gs-gif-tag (-> buff base)))
;; no idea what this is about, it doesn't matter.
;;(set! a2-3 (l.d L53))
;;(.pcpyld a2-4 r0-0 a2-3)
(set! (-> tag2 dword 0) #x9000000000008001)
(set! (-> tag2 dword 1) #xeeeeeeeeeeeeeeee)
(set! (-> buff base) (&+ (the-as pointer tag2) 16))
;; set up a GIF transfer
(let* ((buff-ptr2 buff)
(tag (the-as dma-gif-packet (-> buff-ptr2 base)))
)
;; transfer 10 quadwords
(set! (-> tag dma-vif dma)
(new 'static 'dma-tag :qwc #xa :id (dma-tag-id cnt))
)
;; flush the VIF
(set! (-> tag dma-vif vif0)
(new 'static 'vif-tag :cmd (vif-cmd flusha) :msk #x1)
)
;; DIRECT transfer to GIF.
(set! (-> tag dma-vif vif1)
(new 'static 'vif-tag :imm #xa :cmd (vif-cmd direct) :msk #x1)
)
(set! (-> buff-ptr2 base) (&+ (the-as pointer tag) 16))
)
;; now some payload.
(set! data (the (pointer uint64) (-> buff base)))
(set! (-> data 0) 68)
(set! (-> data 1) 66)
(set! (-> data 2) #x10001c0)
(set! (-> data 3) 78)
(set! (-> data 4) #x5000e)
(set! (-> data 5) 71)
(set! (-> data 6) 0)
(set! (-> data 7) 73)
(set! (-> data 8) 5)
(set! (-> data 9) 8)
(set! (-> data 10) 96)
(set! (-> data 11) 20)
(set! (-> data 12) (shl 128 32))
(set! (-> data 13) 59)
(set! (-> data 14) 4)
(set! (-> data 15) 28)
(set! (-> data 16) *fog-color*)
(set! (-> data 17) 61)
(set! (-> buff base) (&-> data 18))
;; set up for 9 registers (each reg is 1 qw + 1 qw for this tag)
(let* ((buff-ptr5 buff)
(gif-tag (the-as gs-gif-tag (-> buff-ptr5 base)))
)
;; nreg = 9 here.
(set! (-> gif-tag tag) (new 'static 'gif-tag64 :nloop #x1 :eop #x1 :nreg #x9))
;; this sets all the regs to a+d, but the ones after 9 are ignored.
(set! (-> gif-tag regs)
(new 'static 'gif-tag-regs
:regs0 (gs-reg-id a+d)
:regs1 (gs-reg-id a+d)
:regs2 (gs-reg-id a+d)
:regs3 (gs-reg-id a+d)
:regs4 (gs-reg-id a+d)
:regs5 (gs-reg-id a+d)
:regs6 (gs-reg-id a+d)
:regs7 (gs-reg-id a+d)
:regs8 (gs-reg-id a+d)
:regs9 (gs-reg-id a+d)
:regs10 (gs-reg-id a+d)
:regs11 (gs-reg-id a+d)
:regs12 (gs-reg-id a+d)
:regs13 (gs-reg-id a+d)
:regs14 (gs-reg-id a+d)
:regs15 (gs-reg-id a+d)
)
)
(set! (-> buff-ptr5 base) (&+ (the-as pointer gif-tag) 16))
)
;; and a final tag.
(set! tag3 (the gs-gif-tag (-> buff base)))
(set! (-> tag3 dword 0) #x60000000)
(set! (-> tag3 word 2) 0)
(set! (-> tag3 word 3) 0)
(set! (-> buff base) (&+ (the-as pointer tag3) 16))
;; the actual address + register data.
(let* ((buff-ptr3 buff)
(data (the-as (pointer uint64) (-> buff-ptr3 base)))
)
(set! (-> data 0) (the-as uint 68))
(set! (-> data 1) (the-as uint 66))
(set! (-> data 2) (the-as uint #x10001c0))
(set! (-> data 3) (the-as uint 78))
(set! (-> data 4) (the-as uint #x5000e))
(set! (-> data 5) (the-as uint 71))
(set! (-> data 6) (the-as uint 0))
(set! (-> data 7) (the-as uint 73))
(set! (-> data 8) (the-as uint 5))
(set! (-> data 9) (the-as uint 8))
(set! (-> data 10) (the-as uint 96))
(set! (-> data 11) (the-as uint 20))
(set! (-> data 12) (the-as uint (shl 128 32)))
(set! (-> data 13) (the-as uint 59))
(set! (-> data 14) (the-as uint 4))
(set! (-> data 15) (the-as uint 28))
(set! (-> data 16) (the-as uint *fog-color*))
(set! (-> data 17) (the-as uint 61))
(set! (-> buff-ptr3 base) (&+ (the-as pointer data) 144))
)
;; return dma-tag.
(let* ((buff-ptr4 buff)
(ret-packet (the-as dma-packet (-> buff-ptr4 base)))
)
(set! (-> ret-packet dma) (new 'static 'dma-tag :id (dma-tag-id ret)))
(set! (-> ret-packet vif0) (new 'static 'vif-tag))
(set! (-> ret-packet vif1) (new 'static 'vif-tag))
(set! (-> buff-ptr4 base) (&+ (the-as pointer ret-packet) 16))
)
(none)
)
(default-buffer-init *default-regs-buffer*)
;; This isn't a dynamic type in the type system, but it's used as one.
;; the array at the end is used as a dynamic array.
;; NOTE - this gif-packet stuff seems unused. Instead dma-gif-packet is used.
@@ -644,8 +749,8 @@
(deftype gif-packet (basic)
((reg-count int32 :offset-assert 4)
(gif-tag0 uint128 :offset-assert 16)
(gif-tag gs-gif-tag :inline :offset 16)
(gif-tag gs-gif-tag :inline :offset-assert 16)
(gif-tag0 uint128 :offset 16)
(args uint64 1 :offset-assert 32) ;; there's one here already.
)
(:methods
@@ -664,40 +769,38 @@
)
(defun open-gif-packet ((arg0 gif-packet))
"Initialize a gif packet"
"Initialize an existing gif-packet for 0 registers"
(set! (-> arg0 reg-count) 0)
(set! (-> arg0 gif-tag dword 1) 0)
(set! (-> arg0 gif-tag regs) (new 'static 'gif-tag-regs))
arg0
)
(defun add-reg-gif-packet ((packet gif-packet) (reg-idx int) (reg-val int))
"Adds a register to reglist packet."
(local-vars (tag gs-gif-tag))
(set! tag (-> packet gif-tag))
;; dword 1 contains the list of registers to set. each is 4-bits.
(set! (-> tag dword 1)
(logior (-> tag dword 1)
(the-as uint (ash reg-idx (shl (-> packet reg-count) 2))) ;; shift to the correct spot
"Add a register to the packet"
(let ((tag (-> packet gif-tag)))
;; shift the register index into the right slot
(set! (-> tag regs) (logior
(-> tag regs)
(the-as uint (ash reg-idx (shl (-> packet reg-count) 2)))
)
)
)
)
;; ?? (-> packet args (-> packet reg-count))
;; store the value for the register.
(set! (-> (&-> packet args (-> packet reg-count)) 0) reg-val)
;; increment the reg we're on.
;; set register value and increment count.
(set! (-> packet args (-> packet reg-count)) (the-as uint reg-val))
(set! (-> packet reg-count) (+ (-> packet reg-count) 1))
(none)
)
(defun close-gif-packet ((arg0 gif-packet) (arg1 int))
"Sets the lower dword of the giftag for reglist"
(local-vars (v1-2 int) (v1-3 int))
(set! v1-2
(logior (logior #x400000000000001 (the-as uint (shl (-> arg0 reg-count) 60)))
(the-as uint (shr (shl arg1 63) 48))
)
)
;;(.pcpyld v1-3 r0-0 v1-2)?? GOAL compiler is confused.
(set! (-> arg0 gif-tag dword 0) v1-2)
(defun close-gif-packet ((arg0 gif-packet) (eop int))
"Finish adding registers."
(set! (-> arg0 gif-tag tag)
(new 'static 'gif-tag64
:nloop #x1
:flg #x1
:eop eop
:nreg (-> arg0 reg-count)
)
)
arg0
)
@@ -727,24 +830,19 @@
(color-0 rgba)
)
"Allocate and initialize a draw-context"
(let
((obj
(object-new allocation type-to-make (the-as int (-> type-to-make size)))
)
(let ((obj (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(let ((v1-3 (the int (* (the float org-y) (-> *video-parms* relative-y-scale))))
(a0-2 (the int (* (the float height) (-> *video-parms* relative-y-scale))))
)
(set! (-> obj orgx) org-x)
(set! (-> obj orgy) v1-3)
(set! (-> obj orgz) #xffffff)
(set! (-> obj width) width)
(set! (-> obj height) a0-2)
)
(set! (-> obj color 0) color-0)
obj
)
(let
((v1-3 (the int (* (the float org-y) (-> *video-parms* relative-y-scale))))
(a0-2 (the int (* (the float height) (-> *video-parms* relative-y-scale))))
)
(set! (-> obj orgx) org-x)
(set! (-> obj orgy) v1-3)
(set! (-> obj orgz) #xffffff)
(set! (-> obj width) width)
(set! (-> obj height) a0-2)
)
(set! (-> obj color 0) color-0)
obj
)
)
(defun draw-context-set-xy ((arg0 draw-context) (x int) (y int))
File diff suppressed because it is too large Load Diff
+199 -212
View File
@@ -12,36 +12,38 @@
;; this gets set to #f later on.
(define *cheat-mode* #t)
;; data that comes directly from hardware.
(deftype hw-cpad (basic)
((valid uint8 :offset-assert 4)
(status uint8 :offset-assert 5)
(button0 uint16 :offset-assert 6)
(rightx uint8 :offset-assert 8)
(righty uint8 :offset-assert 9)
(leftx uint8 :offset-assert 10)
(lefty uint8 :offset-assert 11)
(abutton uint8 12 :offset-assert 12)
(dummy uint8 12 :offset-assert 24)
((valid uint8 :offset-assert 4)
(status uint8 :offset-assert 5)
(button0 uint16 :offset-assert 6)
(rightx uint8 :offset-assert 8)
(righty uint8 :offset-assert 9)
(leftx uint8 :offset-assert 10)
(lefty uint8 :offset-assert 11)
(abutton uint8 12 :offset-assert 12)
(dummy uint8 12 :offset-assert 24)
)
:method-count-assert 9
:size-assert #x24
:flag-assert #x900000024
)
;; data from hardware + additional info calculated here.
(deftype cpad-info (hw-cpad)
((number int32 :offset-assert 36)
(cpad-file int32 :offset-assert 40)
(button0-abs uint32 3 :offset-assert 44) ;; bitmask of buttons, pressed or not, with history
(button0-shadow-abs uint32 1 :offset-assert 56) ;; modify this to change button history in the future.
(button0-rel uint32 3 :offset-assert 60) ;; bitmask of if button going down.
(button0-abs uint32 3 :offset-assert 44) ;; bitmask of buttons, pressed or not, with history
(button0-shadow-abs uint32 1 :offset-assert 56) ;; modify this to change button history in the future.
(button0-rel uint32 3 :offset-assert 60) ;; bitmask of if button going down.
(stick0-dir float :offset-assert 72)
(stick0-speed float :offset-assert 76)
(new-pad int32 :offset-assert 80)
(state int32 :offset-assert 84)
(align uint8 6 :offset-assert 88)
(direct uint8 6 :offset-assert 94) ;; hardware control of buzzing.
(buzz-val uint8 2 :offset-assert 100) ;; intensity for buzzing
(buzz-time uint64 2 :offset-assert 104) ;; when to stop buzzing
(align uint8 6 :offset-assert 88)
(direct uint8 6 :offset-assert 94) ;; hardware control of buzzing.
(buzz-val uint8 2 :offset-assert 100) ;; intensity for buzzing
(buzz-time uint64 2 :offset-assert 104) ;; when to stop buzzing
(buzz basic :offset-assert 120) ;; is vibration enabled?
(buzz-act int32 :offset-assert 124)
(change-time uint64 :offset-assert 128)
@@ -54,9 +56,54 @@
:flag-assert #x900000088
)
(defun cpad-invalid! ((pad cpad-info))
"Reset all data in a cpad-info"
(set! (-> pad valid) (logior (-> pad valid) 128))
(set! (-> pad button0) (the-as uint 0))
(set! (-> pad button0-abs 0) (the-as uint 0))
(set! (-> pad button0-shadow-abs 0) (the-as uint 0))
(set! (-> pad button0-rel 0) (the-as uint 0))
(dotimes (v1-2 12)
(nop!)
(set! (-> pad abutton v1-2) 0)
)
(set! (-> pad stick0-dir) 0.0)
(set! (-> pad stick0-speed) 0.0)
(set! (-> pad rightx) (the-as uint 128))
(set! (-> pad righty) (the-as uint 128))
(set! (-> pad leftx) (the-as uint 128))
(set! (-> pad lefty) (the-as uint 128))
(set! (-> pad align 0) (the-as uint 0))
(set! (-> pad align 1) (the-as uint 1))
(set! (-> pad align 2) (the-as uint 255))
(set! (-> pad align 3) (the-as uint 255))
(set! (-> pad align 4) (the-as uint 255))
(set! (-> pad align 5) (the-as uint 255))
(dotimes (v1-14 6)
(set! (-> pad direct v1-14) 0)
)
;; probably a bug here, this should use v1-17 as the index.
(dotimes (v1-17 2)
(set! (-> pad buzz-val 0) (the-as uint 0))
(set! (-> pad buzz-time 0) (the-as uint 0))
)
pad
)
(defmethod new cpad-info ((alloction symbol) (type-to-make type) (idx int))
"Allocate a new cpad-info and open the pad itself through the kernel"
(let ((obj (object-new alloction type-to-make (the-as int (-> type-to-make size)))))
(set! (-> obj number) idx)
(set! (-> obj buzz) #f)
(cpad-open obj idx) ;; kernel function.
(cpad-invalid! obj)
)
)
;; List of controllers. It always has 2 controllers.
(deftype cpad-list (basic)
((num-cpads int32 :offset-assert 4)
(cpads cpad-info 2 :offset-assert 8) ;; guess
((num-cpads int32 :offset-assert 4)
(cpads cpad-info 2 :offset-assert 8)
)
(:methods
(new (symbol type) _type_ 0)
@@ -66,92 +113,44 @@
:flag-assert #x900000010
)
(defun cpad-invalid! ((pad cpad-info))
"Make everything in a cpad-info set to default"
(local-vars (v1-2 int) (v1-14 int) (v1-17 int))
(set! (-> pad valid) (logior (-> pad valid) 128))
(set! (-> pad button0) 0)
(set! (-> pad button0-abs 0) 0)
(set! (-> pad button0-shadow-abs 0) 0)
(set! (-> pad button0-rel 0) 0)
(set! v1-2 0)
(while (< v1-2 12)
(nop!)
(set! (-> pad abutton v1-2) 0)
(+! v1-2 1)
)
(set! (-> pad stick0-dir) 0.000000)
(set! (-> pad stick0-speed) 0.000000)
(set! (-> pad rightx) 128)
(set! (-> pad righty) 128)
(set! (-> pad leftx) 128)
(set! (-> pad lefty) 128)
(set! (-> pad align 0) 0)
(set! (-> pad align 1) 1)
(set! (-> pad align 2) 255)
(set! (-> pad align 3) 255)
(set! (-> pad align 4) 255)
(set! (-> pad align 5) 255)
(set! v1-14 0)
(while (< v1-14 6)
(set! (-> pad direct v1-14) 0)
(+! v1-14 1)
)
(set! v1-17 0)
(while (< v1-17 2)
(set! (-> pad buzz-val 0) 0)
(set! (-> pad buzz-time 0) 0)
(+! v1-17 1)
)
pad
)
(defmethod new cpad-info ((alloction symbol) (type-to-make type) (idx int))
"Allocate a cpad. Also opens it using functions from the kernel."
(local-vars (obj cpad-info))
(set! obj (object-new alloction type-to-make (the-as int (-> type-to-make size))))
(set! (-> obj number) idx)
(set! (-> obj buzz) #f)
(cpad-open obj idx)
(cpad-invalid! obj)
)
(defmethod new cpad-list ((allocation symbol) (type-to-make type))
"Allocate a cpad-list and set up two controllers, including openeing them."
(local-vars (gp-0 cpad-list))
(set! gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size))))
(set! (-> gp-0 num-cpads) 2)
(set! (-> gp-0 cpads 0) (new 'global 'cpad-info 0))
(set! (-> gp-0 cpads 1) (new 'global 'cpad-info 1))
gp-0
"Create a cpad-list for 2 controllers. It's fine to do this even if one or both controllers
aren't connected yet. "
(let ((gp-0 (object-new allocation type-to-make (the-as int (-> type-to-make size)))))
(set! (-> gp-0 num-cpads) 2)
(set! (-> gp-0 cpads 0) (new 'global 'cpad-info 0))
(set! (-> gp-0 cpads 1) (new 'global 'cpad-info 1))
gp-0
)
)
(defun analog-input ((in int) (offset float) (center-val float) (max-val float) (out-range float))
"Take an integer input and convert it to a float between -out-range and +out-range.
"Convert integer input from pad into a float between -out-range and +out-range.
The offset is applied directly to the input.
The center val is the expected value for 0 (after offset)
The max val is the expected value with the stick all the way pushed
"
(local-vars
(max-magnitude float)
(magnitude float)
(offset-in float)
)
;; do the offset
(set! offset-in (- (the float in) offset))
;; figure out the absolute value of the displacement from 0.
(set! magnitude (- (fabs offset-in) center-val))
;; the maximum allowed magnitude
(set! max-magnitude (- max-val center-val))
;; if we are negative, our output range should be negative.
(when (< offset-in 0.000000)
(set! out-range (- out-range))
)
(cond
((>= 0.000000 magnitude) 0.000000) ;; shouldn't happen
((>= magnitude max-magnitude) out-range) ;; too big
(else (/ (* magnitude out-range) max-magnitude)) ;; scale!
)
The center val is the expected value for 0, after applying offset.
The max val is the expected value with the stick pushed all the way"
(let* ((offset-in (- (the float in) offset)) ;; apply offset to in
(magnitude (- (fabs offset-in) center-val)) ;; determine our magnitude
(max-magnitude (- max-val center-val)) ;; maximum expected magnitude.
)
;; flip the output if negative
(if (< offset-in 0.0)
(set! out-range (- out-range))
)
;; scale and return value.
(cond
((>= 0.0 magnitude)
0.0
)
((>= magnitude max-magnitude)
out-range
)
(else
(/ (* magnitude out-range) max-magnitude)
)
)
)
)
(defun cpad-set-buzz! ((pad cpad-info) (buzz-idx int) (buzz-amount int) (duration int))
@@ -188,125 +187,113 @@
(define *cpad-debug* #f)
(defun service-cpads ()
"Call this once a frame to read the pad, handle vibration, and process the left stick"
(local-vars
(v1-10 int)
(current-button0 uint)
(buzz-idx int)
(pad cpad-info)
(pad-idx int)
(pad-list cpad-list)
(lefty-pos float)
(leftx-pos float)
)
;; iterate through cpads.
(set! pad-list *cpad-list*)
(set! pad-idx 0)
(while (< pad-idx (-> pad-list num-cpads))
(set! pad (-> *cpad-list* cpads pad-idx))
;; read data from pad.
(cpad-get-data pad)
(cond
((zero? (logand (-> pad valid) 128))
;; pad is valid! update buzz.
(set! buzz-idx 0)
(while (< buzz-idx 2)
(cond
;; when buzz enbaled, in buzz time, and in game mode:
((and (-> pad buzz)
(< (the-as int (get-current-time))
(the-as int (-> pad buzz-time buzz-idx))
"Read from cpads and update vibration"
;; iterate over pads
(let ((pad-list *cpad-list*))
(dotimes (pad-idx (-> pad-list num-cpads))
(let ((pad (-> *cpad-list* cpads pad-idx)))
;; read from hardware.
(cpad-get-data pad)
(cond
((zero? (logand (-> pad valid) 128))
(dotimes (buzz-idx 2)
(cond
;; check if okay to buzz:
((and (-> pad buzz)
(< (the-as int (get-current-time))
(the-as int (-> pad buzz-time buzz-idx))
)
(= *master-mode* 'game)
)
(let ((v1-10 buzz-idx))
(cond
((zero? v1-10)
;; vibration motor 0 only has on/off. This pulses it to approximate
;; an analog control
(set! (-> pad direct buzz-idx)
(logand (ash (-> pad buzz-val buzz-idx)
(- (the-as int (logand (get-integral-current-time) 7)))
)
1
)
)
)
((= v1-10 1)
;; vibration motor 1 has analog control. set the speed.
(set! (-> pad direct buzz-idx) (-> pad buzz-val buzz-idx))
)
)
(= *master-mode* 'game)
)
;; case statement?
(set! v1-10 buzz-idx)
(cond ((zero? v1-10)
;; buzz 0, I think the small one, doesn't have analog control.
;; I _think_ this is some clever way to pulse it at a duty cycle proportional
;; to the desired intensity.
(set! (-> pad direct buzz-idx)
(logand (ash (-> pad buzz-val buzz-idx)
(- (the-as int (logand (get-integral-current-time) 7)))
)
1
)
)
)
((= v1-10 1)
;; buzz 1, the big motor can be controlled directly by the PS2.
(set! (-> pad direct buzz-idx) (-> pad buzz-val buzz-idx))
)
)
)
(else
;; time to stop buzzing. set buzz-val and the hardware command to 0.
(set! (-> pad buzz-val buzz-idx) 0)
(set! (-> pad direct buzz-idx) 0)
)
)
(+! buzz-idx 1)
)
;; update buttons history
(set! (-> pad button0-abs 2) (-> pad button0-abs 1))
;; update abs history from shadow-abs
(set! (-> pad button0-abs 1) (-> pad button0-shadow-abs 0))
;; update rel history
(set! (-> pad button0-rel 2) (-> pad button0-rel 1))
(set! (-> pad button0-rel 1) (-> pad button0-rel 0))
;; put in new buttons
(set! current-button0 (-> pad button0))
(set! (-> pad button0-shadow-abs 0) current-button0)
(set! (-> pad button0-abs 0) current-button0)
;; buttons going down
(set! (-> pad button0-rel 0)
(logand (-> pad button0-abs 0) (lognot (-> pad button0-abs 1)))
)
;; some weird leftover from debugging.
(when *cpad-debug*
(set! (-> pad leftx) 255)
(set! (-> pad rightx) 255)
)
(set! (-> pad stick0-speed) 1.000)
(cond
((= (shr (-> pad status) 4) 7) ;; status that we have analog?
(set! leftx-pos (* 0.0078125 (the float (+ (-> pad leftx) -128))))
(set! lefty-pos (* 0.0078125 (the float (- 127 (-> pad lefty)))))
;; heading of the stick. note that y -> -x, x -> y, so it's rotated...
(set! (-> pad stick0-dir) (atan (- leftx-pos) lefty-pos))
;; the "speed" is just the magnitude.
(set! (-> pad stick0-speed) (fmin 1.0 (sqrtf (+ (* leftx-pos leftx-pos) (* lefty-pos lefty-pos)))))
;; deadband the speed at 0.3? this seems kinda high.
(when (< (-> pad stick0-speed) 0.3)
(set! (-> pad stick0-speed) 0.0)
)
)
(else
;; invalid analog state, set things to safe defaults.
(set! (-> pad leftx) 128)
(set! (-> pad lefty) 128)
(set! (-> pad rightx) 128)
(set! (-> pad righty) 128)
(set! (-> pad stick0-dir) 0.000000)
(set! (-> pad stick0-speed) 0.0)
)
)
;; did the pad change?
(if (or (!= (-> pad button0-abs 0) (-> pad button0-abs 1)) ;; button pushed
(or (< 0.3 (-> pad stick0-speed)) ;; stick away from origin
(zero? (-> pad change-time)) ;; initially zero
)
)
(else
;; not okay to buzz this motor, set to zero.
(set! (-> pad buzz-val buzz-idx) 0)
(set! (-> pad direct buzz-idx) 0)
)
)
)
;; update button history.
(set! (-> pad button0-abs 2) (-> pad button0-abs 1))
(set! (-> pad button0-abs 1) (-> pad button0-shadow-abs 0))
(set! (-> pad button0-rel 2) (-> pad button0-rel 1))
(set! (-> pad button0-rel 1) (-> pad button0-rel 0))
;; update current button
(let ((current-button0 (-> pad button0)))
(set! (-> pad button0-shadow-abs 0) current-button0)
(set! (-> pad button0-abs 0) current-button0)
)
;; buttons going down
(set! (-> pad button0-rel 0)
(logand (-> pad button0-abs 0) (lognot (-> pad button0-abs 1)))
)
;; ??
(when *cpad-debug*
(set! (-> pad leftx) (the-as uint 255))
(set! (-> pad rightx) (the-as uint 255))
)
;; compute a speed and direction for stick0
(set! (-> pad stick0-speed) 1.0)
(cond
;; check if analog is valid?
((= (shr (-> pad status) 4) 7)
;; compute speed and direction, with deadband.
(let ((f30-0 (* 0.0078125 (the float (+ (-> pad leftx) -128))))
(f28-0 (* 0.0078125 (the float (- 127 (the-as int (-> pad lefty))))))
)
(set! (-> pad stick0-dir) (atan (- f30-0) f28-0))
(set! (-> pad stick0-speed)
(fmin 1.0 (sqrtf (+ (* f30-0 f30-0) (* f28-0 f28-0))))
)
)
(if (< (-> pad stick0-speed) 0.3)
(set! (-> pad stick0-speed) 0.0)
)
)
(else
;; analog is invalid? set to zero.
(set! (-> pad leftx) (the-as uint 128))
(set! (-> pad lefty) (the-as uint 128))
(set! (-> pad rightx) (the-as uint 128))
(set! (-> pad righty) (the-as uint 128))
(set! (-> pad stick0-dir) 0.0)
(set! (-> pad stick0-speed) 0.0)
)
)
;; if the pad was changed or stick0 pushed, update the last changed time.
(if (or (!= (-> pad button0-abs 0) (-> pad button0-abs 1))
(or (< 0.3 (-> pad stick0-speed)) (zero? (-> pad change-time)))
)
(set! (-> pad change-time) (get-current-time))
)
(set! (-> pad change-time) (get-current-time))
)
)
(else
;; invalid pad
(cpad-invalid! pad)
)
(else
;; invalid bits set, controller is not connected.
(cpad-invalid! pad)
)
)
)
)
(+! pad-idx 1)
)
*cpad-list*
)
+2 -2
View File
@@ -1172,13 +1172,13 @@
;; these are not quite right, but it's close enough.
(defmacro start-of-symbol-table ()
`(rlet ((st :reg r15 :reset-here #t :type uint))
`(rlet ((st :reg r14 :reset-here #t :type uint))
(the uint (- st 32768))
)
)
(defmacro end-of-symbol-table ()
`(rlet ((st :reg r15 :reset-here #t :type uint))
`(rlet ((st :reg r14 :reset-here #t :type uint))
(the uint (+ st 32768))
)
)
+4 -4
View File
@@ -96,10 +96,10 @@ class Compiler {
IR_VFMath2Asm::Kind kind,
Env* env);
Val* compile_asm_vf_math2_imm_u8(const goos::Object& form,
const goos::Object& rest,
IR_VFMath2Asm::Kind kind,
Env* env);
Val* compile_asm_int128_math2_imm_u8(const goos::Object& form,
const goos::Object& rest,
IR_Int128Math2Asm::Kind kind,
Env* env);
Val* compile_asm_vf_math4_two_operation(const goos::Object& form,
const goos::Object& rest,
+56 -17
View File
@@ -1523,16 +1523,11 @@ void IR_Int128Math3Asm::do_codegen(emitter::ObjectGenerator* gen,
// AsmVF2
///////////////////////
IR_VFMath2Asm::IR_VFMath2Asm(bool use_color,
const RegVal* dst,
const RegVal* src,
Kind kind,
std::optional<int64_t> imm)
: IR_Asm(use_color), m_dst(dst), m_src(src), m_kind(kind), m_imm(std::move(imm)) {}
IR_VFMath2Asm::IR_VFMath2Asm(bool use_color, const RegVal* dst, const RegVal* src, Kind kind)
: IR_Asm(use_color), m_dst(dst), m_src(src), m_kind(kind) {}
std::string IR_VFMath2Asm::print() {
std::string function;
bool use_imm = false;
switch (m_kind) {
case Kind::ITOF:
function = ".itof.vf";
@@ -1540,6 +1535,56 @@ std::string IR_VFMath2Asm::print() {
case Kind::FTOI:
function = ".ftoi.vf";
break;
default:
assert(false);
}
return fmt::format("{}{} {}, {}", function, get_color_suffix_string(), m_dst->print(),
m_src->print());
}
RegAllocInstr IR_VFMath2Asm::to_rai() {
RegAllocInstr rai;
if (m_use_coloring) {
rai.write.push_back(m_dst->ireg());
rai.read.push_back(m_src->ireg());
}
return rai;
}
void IR_VFMath2Asm::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
auto dst = get_reg_asm(m_dst, allocs, irec, m_use_coloring);
auto src = get_reg_asm(m_src, allocs, irec, m_use_coloring);
switch (m_kind) {
case Kind::ITOF:
gen->add_instr(IGen::itof_vf(dst, src), irec);
break;
case Kind::FTOI:
gen->add_instr(IGen::ftoi_vf(dst, src), irec);
break;
default:
assert(false);
}
}
///////////////////////
// AsmInt128-2
///////////////////////
IR_Int128Math2Asm::IR_Int128Math2Asm(bool use_color,
const RegVal* dst,
const RegVal* src,
Kind kind,
std::optional<int64_t> imm)
: IR_Asm(use_color), m_dst(dst), m_src(src), m_kind(kind), m_imm(std::move(imm)) {}
std::string IR_Int128Math2Asm::print() {
std::string function;
bool use_imm = false;
switch (m_kind) {
case Kind::PW_SLL:
use_imm = true;
function = ".pw.sll";
@@ -1582,7 +1627,7 @@ std::string IR_VFMath2Asm::print() {
}
}
RegAllocInstr IR_VFMath2Asm::to_rai() {
RegAllocInstr IR_Int128Math2Asm::to_rai() {
RegAllocInstr rai;
if (m_use_coloring) {
rai.write.push_back(m_dst->ireg());
@@ -1591,19 +1636,13 @@ RegAllocInstr IR_VFMath2Asm::to_rai() {
return rai;
}
void IR_VFMath2Asm::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
void IR_Int128Math2Asm::do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) {
auto dst = get_reg_asm(m_dst, allocs, irec, m_use_coloring);
auto src = get_reg_asm(m_src, allocs, irec, m_use_coloring);
switch (m_kind) {
case Kind::ITOF:
gen->add_instr(IGen::itof_vf(dst, src), irec);
break;
case Kind::FTOI:
gen->add_instr(IGen::ftoi_vf(dst, src), irec);
break;
case Kind::PW_SLL:
// you are technically allowed to put values > 32 in here.
assert(m_imm.has_value());
+23 -7
View File
@@ -567,14 +567,14 @@ class IR_Int128Math3Asm : public IR_Asm {
Kind m_kind;
};
class IR_VFMath2Asm : public IR_Asm {
class IR_Int128Math2Asm : public IR_Asm {
public:
enum class Kind { ITOF, FTOI, PW_SLL, PW_SRL, PW_SRA, VPSRLDQ, VPSLLDQ, VPSHUFLW, VPSHUFHW };
IR_VFMath2Asm(bool use_color,
const RegVal* dst,
const RegVal* src,
Kind kind,
std::optional<int64_t> = std::nullopt);
enum class Kind { PW_SLL, PW_SRL, PW_SRA, VPSRLDQ, VPSLLDQ, VPSHUFLW, VPSHUFHW };
IR_Int128Math2Asm(bool use_color,
const RegVal* dst,
const RegVal* src,
Kind kind,
std::optional<int64_t> = std::nullopt);
std::string print() override;
RegAllocInstr to_rai() override;
void do_codegen(emitter::ObjectGenerator* gen,
@@ -588,6 +588,22 @@ class IR_VFMath2Asm : public IR_Asm {
std::optional<int64_t> m_imm;
};
class IR_VFMath2Asm : public IR_Asm {
public:
enum class Kind { ITOF, FTOI };
IR_VFMath2Asm(bool use_color, const RegVal* dst, const RegVal* src, Kind kind);
std::string print() override;
RegAllocInstr to_rai() override;
void do_codegen(emitter::ObjectGenerator* gen,
const AllocationResult& allocs,
emitter::IR_Record irec) override;
protected:
const RegVal* m_dst = nullptr;
const RegVal* m_src = nullptr;
Kind m_kind;
};
class IR_BlendVF : public IR_Asm {
public:
IR_BlendVF(bool use_color, const RegVal* dst, const RegVal* src1, const RegVal* src2, u8 mask);
+15 -16
View File
@@ -546,10 +546,10 @@ Val* Compiler::compile_asm_vf_math2(const goos::Object& form,
return get_none();
}
Val* Compiler::compile_asm_vf_math2_imm_u8(const goos::Object& form,
const goos::Object& rest,
IR_VFMath2Asm::Kind kind,
Env* env) {
Val* Compiler::compile_asm_int128_math2_imm_u8(const goos::Object& form,
const goos::Object& rest,
IR_Int128Math2Asm::Kind kind,
Env* env) {
auto args = get_va(form, rest);
va_check(
form, args, {{}, {}, {}},
@@ -561,7 +561,6 @@ Val* Compiler::compile_asm_vf_math2_imm_u8(const goos::Object& form,
auto dest = compile_error_guard(args.unnamed.at(0), env)->to_reg(env);
auto src = compile_error_guard(args.unnamed.at(1), env)->to_reg(env);
check_vector_float_regs(form, env, {{"destination", dest}, {"source", src}});
s64 imm;
if (!try_getting_constant_integer(args.unnamed.at(2), &imm, env)) {
throw_compiler_error(form, "Could not evaluate {} as a compile-time integer.",
@@ -584,11 +583,11 @@ Val* Compiler::compile_asm_vf_math2_imm_u8(const goos::Object& form,
// If the entire destination is to be copied, we can optimize out the blend
if (mask == 0b1111) {
env->emit_ir<IR_VFMath2Asm>(color, dest, src, kind, imm);
env->emit_ir<IR_Int128Math2Asm>(color, dest, src, kind, imm);
} else {
auto temp_reg = env->make_vfr(dest->type());
// Perform the arithmetic operation on the two vectors into a temporary register
env->emit_ir<IR_VFMath2Asm>(color, temp_reg, src, kind, imm);
env->emit_ir<IR_Int128Math2Asm>(color, temp_reg, src, kind, imm);
// Blend the result back into the destination register using the mask
env->emit_ir<IR_BlendVF>(color, dest, dest, temp_reg, mask);
}
@@ -597,15 +596,15 @@ Val* Compiler::compile_asm_vf_math2_imm_u8(const goos::Object& form,
}
Val* Compiler::compile_asm_pw_sll(const goos::Object& form, const goos::Object& rest, Env* env) {
return compile_asm_vf_math2_imm_u8(form, rest, IR_VFMath2Asm::Kind::PW_SLL, env);
return compile_asm_int128_math2_imm_u8(form, rest, IR_Int128Math2Asm::Kind::PW_SLL, env);
}
Val* Compiler::compile_asm_pw_srl(const goos::Object& form, const goos::Object& rest, Env* env) {
return compile_asm_vf_math2_imm_u8(form, rest, IR_VFMath2Asm::Kind::PW_SRL, env);
return compile_asm_int128_math2_imm_u8(form, rest, IR_Int128Math2Asm::Kind::PW_SRL, env);
}
Val* Compiler::compile_asm_pw_sra(const goos::Object& form, const goos::Object& rest, Env* env) {
return compile_asm_vf_math2_imm_u8(form, rest, IR_VFMath2Asm::Kind::PW_SRA, env);
return compile_asm_int128_math2_imm_u8(form, rest, IR_Int128Math2Asm::Kind::PW_SRA, env);
}
Val* Compiler::compile_asm_pextlw(const goos::Object& form, const goos::Object& rest, Env* env) {
@@ -641,12 +640,12 @@ Val* Compiler::compile_asm_ppach(const goos::Object& form, const goos::Object& r
throw_compiler_error(form, "Cannot set destination");
}
env->emit_ir<IR_VFMath2Asm>(true, temp, src1, IR_VFMath2Asm::Kind::VPSHUFLW, 0x88);
env->emit_ir<IR_VFMath2Asm>(true, dest, src2, IR_VFMath2Asm::Kind::VPSHUFLW, 0x88);
env->emit_ir<IR_VFMath2Asm>(true, temp, temp, IR_VFMath2Asm::Kind::VPSHUFHW, 0x88);
env->emit_ir<IR_VFMath2Asm>(true, dest, dest, IR_VFMath2Asm::Kind::VPSHUFHW, 0x88);
env->emit_ir<IR_VFMath2Asm>(true, temp, temp, IR_VFMath2Asm::Kind::VPSRLDQ, 4);
env->emit_ir<IR_VFMath2Asm>(true, dest, dest, IR_VFMath2Asm::Kind::VPSRLDQ, 4);
env->emit_ir<IR_Int128Math2Asm>(true, temp, src1, IR_Int128Math2Asm::Kind::VPSHUFLW, 0x88);
env->emit_ir<IR_Int128Math2Asm>(true, dest, src2, IR_Int128Math2Asm::Kind::VPSHUFLW, 0x88);
env->emit_ir<IR_Int128Math2Asm>(true, temp, temp, IR_Int128Math2Asm::Kind::VPSHUFHW, 0x88);
env->emit_ir<IR_Int128Math2Asm>(true, dest, dest, IR_Int128Math2Asm::Kind::VPSHUFHW, 0x88);
env->emit_ir<IR_Int128Math2Asm>(true, temp, temp, IR_Int128Math2Asm::Kind::VPSRLDQ, 4);
env->emit_ir<IR_Int128Math2Asm>(true, dest, dest, IR_Int128Math2Asm::Kind::VPSRLDQ, 4);
// is actually a VPUNPCKLQDQ with srcs swapped.
env->emit_ir<IR_Int128Math3Asm>(true, dest, temp, dest, IR_Int128Math3Asm::Kind::PCPYLD);
+1 -1
View File
@@ -161,7 +161,7 @@ std::unique_ptr<FormRegressionTest::TestData> FormRegressionTest::make_function(
// convert instruction to atomic ops
DecompWarnings warnings;
auto ops = convert_function_to_atomic_ops(test->func, program.labels, warnings);
auto ops = convert_function_to_atomic_ops(test->func, program.labels, warnings, false);
test->func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
test->func.ir2.atomic_ops_succeeded = true;
test->func.ir2.env.set_end_var(test->func.ir2.atomic_ops->end_op().return_var());
@@ -63,7 +63,17 @@
(define-extern *listener-process* process)
(define-extern *active-pool* process-tree)
(define-extern reset-and-call (function thread function object))
(define-extern ash (function int int int))
(defun ash ((value int) (shift-amount int))
"Arithmetic shift value by shift-amount.
A positive shift-amount will shift to the left and a negative will shift to the right.
"
;; OpenGOAL does not support ash in the compiler, so we implement it here as an inline function.
(declare (inline))
(if (> shift-amount 0)
(shl value shift-amount)
(sar value (- shift-amount))
)
)
(define-extern inspect-process-tree (function process-tree int int symbol process-tree))
(define-extern set-to-run-bootstrap (function none))
(define-extern dead-state state)
@@ -87,6 +97,11 @@
'(none)
)
(defmacro gpr->fpr (in)
in)
(define-extern get-current-time (function uint))
(define-extern get-integral-current-time (function uint))
;; math
(define-extern fabs (function float float))
@@ -199,6 +214,75 @@
(end 7) ;; next, but ends.
)
(defenum gs-psm
:bitfield #f
:type uint8
(ct32 0)
(ct24 1)
(ct16 2)
(ct16s 10)
(mt8 19)
(mt4 20)
(mt8h 27)
(mt4hl 36)
(mt4hh 44)
(mz32 48)
(mz24 49)
(mz16 50)
(mz16s 58)
)
(defenum gs-prim-type
:type uint8
(point 0)
(line 1)
(line-strip 2)
(tri 3)
(tri-strip 4)
(tri-fan 5)
(sprite 6)
)
(defenum gs-reg-id
:bitfield #f
:type uint8
(prim 0)
(rgbaq 1)
(st 2)
(uv 3)
(xyzf2 4)
(xyz2 5)
(tex0-1 6)
(tex0-2 7)
(clamp-1 8)
(clamp-2 9)
(fog 10)
(xyzf3 12)
(xyz3 13)
(a+d 14)
(nop 15)
)
(deftype gif-tag-regs (uint64)
((regs0 gs-reg-id :offset 0 :size 4)
(regs1 gs-reg-id :offset 4 :size 4)
(regs2 gs-reg-id :offset 8 :size 4)
(regs3 gs-reg-id :offset 12 :size 4)
(regs4 gs-reg-id :offset 16 :size 4)
(regs5 gs-reg-id :offset 20 :size 4)
(regs6 gs-reg-id :offset 24 :size 4)
(regs7 gs-reg-id :offset 28 :size 4)
(regs8 gs-reg-id :offset 32 :size 4)
(regs9 gs-reg-id :offset 36 :size 4)
(regs10 gs-reg-id :offset 40 :size 4)
(regs11 gs-reg-id :offset 44 :size 4)
(regs12 gs-reg-id :offset 48 :size 4)
(regs13 gs-reg-id :offset 52 :size 4)
(regs14 gs-reg-id :offset 56 :size 4)
(regs15 gs-reg-id :offset 60 :size 4)
)
)
;; display-h
(deftype display-env (structure)
((pmode uint64 :offset-assert 0)
+1 -1
View File
@@ -9,7 +9,7 @@
(set!
(-> current-bucket tag)
(new 'static 'dma-tag
:id #x2
:id (dma-tag-id next)
:addr (the-as int (&+ (the-as pointer current-bucket) 16))
)
)
+10 -2
View File
@@ -149,7 +149,11 @@
)
(set!
(-> buf-ptr dma)
(new 'static 'dma-tag :id #x3 :addr (the-as int func-ptr) :qwc qwc-now)
(new 'static 'dma-tag
:id (dma-tag-id ref)
:addr (the-as int func-ptr)
:qwc qwc-now
)
)
(set!
(-> buf-ptr vif0)
@@ -157,7 +161,11 @@
)
(set!
(-> buf-ptr vif1)
(new 'static 'vif-tag :cmd #x4a :num (shl qwc-now 1) :imm origin)
(new 'static 'vif-tag
:cmd (vif-cmd mpg)
:num (shl qwc-now 1)
:imm origin
)
)
(set! (-> dma-buf-2 base) (&+ (the-as pointer buf-ptr) 16))
)
+2 -2
View File
@@ -725,8 +725,8 @@
(empty-form)
(cond
((or
(zero? (+ (the-as uint (-> current-tag id)) (the-as uint -3)))
(zero? (+ (the-as uint (-> current-tag id)) (the-as uint -4)))
(= (-> current-tag id) (dma-tag-id ref))
(= (-> current-tag id) (dma-tag-id refs))
(zero? (-> current-tag id))
)
(set! addr (-> current-tag addr))
File diff suppressed because it is too large Load Diff
+371
View File
@@ -0,0 +1,371 @@
;;-*-Lisp-*-
(in-package goal)
;; definition for symbol *cheat-mode*, type symbol
(define *cheat-mode* #t)
;; definition of type hw-cpad
(deftype hw-cpad (basic)
((valid uint8 :offset-assert 4)
(status uint8 :offset-assert 5)
(button0 uint16 :offset-assert 6)
(rightx uint8 :offset-assert 8)
(righty uint8 :offset-assert 9)
(leftx uint8 :offset-assert 10)
(lefty uint8 :offset-assert 11)
(abutton uint8 12 :offset-assert 12)
(dummy uint8 12 :offset-assert 24)
)
:method-count-assert 9
:size-assert #x24
:flag-assert #x900000024
)
;; definition for method 3 of type hw-cpad
(defmethod inspect hw-cpad ((obj hw-cpad))
(format #t "[~8x] ~A~%" obj (-> obj type))
(format #t "~Tvalid: #x~X~%" (-> obj valid))
(format #t "~Tstatus: #x~X~%" (-> obj status))
(format #t "~Tbutton0: #x~X~%" (-> obj button0))
(format #t "~Trightx: ~D~%" (-> obj rightx))
(format #t "~Trighty: ~D~%" (-> obj righty))
(format #t "~Tleftx: ~D~%" (-> obj leftx))
(format #t "~Tlefty: ~D~%" (-> obj lefty))
(format #t "~Tabutton[12] @ #x~X~%" (-> obj abutton))
(format #t "~Tdummy[12] @ #x~X~%" (-> obj dummy))
obj
)
;; definition of type cpad-info
(deftype cpad-info (hw-cpad)
((number int32 :offset-assert 36)
(cpad-file int32 :offset-assert 40)
(button0-abs uint32 3 :offset-assert 44)
(button0-shadow-abs uint32 1 :offset-assert 56)
(button0-rel uint32 3 :offset-assert 60)
(stick0-dir float :offset-assert 72)
(stick0-speed float :offset-assert 76)
(new-pad int32 :offset-assert 80)
(state int32 :offset-assert 84)
(align uint8 6 :offset-assert 88)
(direct uint8 6 :offset-assert 94)
(buzz-val uint8 2 :offset-assert 100)
(buzz-time uint64 2 :offset-assert 104)
(buzz basic :offset-assert 120)
(buzz-act int32 :offset-assert 124)
(change-time uint64 :offset-assert 128)
)
:method-count-assert 9
:size-assert #x88
:flag-assert #x900000088
(:methods
(new (symbol type int) _type_ 0)
)
)
;; definition for method 3 of type cpad-info
(defmethod inspect cpad-info ((obj cpad-info))
(format #t "[~8x] ~A~%" obj (-> obj type))
(format #t "~Tvalid: #x~X~%" (-> obj valid))
(format #t "~Tstatus: #x~X~%" (-> obj status))
(format #t "~Tbutton0: #x~X~%" (-> obj button0))
(format #t "~Trightx: ~D~%" (-> obj rightx))
(format #t "~Trighty: ~D~%" (-> obj righty))
(format #t "~Tleftx: ~D~%" (-> obj leftx))
(format #t "~Tlefty: ~D~%" (-> obj lefty))
(format #t "~Tabutton[12] @ #x~X~%" (-> obj abutton))
(format #t "~Tdummy[12] @ #x~X~%" (-> obj dummy))
(format #t "~Tnumber: ~D~%" (-> obj number))
(format #t "~Tcpad-file: ~D~%" (-> obj cpad-file))
(format #t "~Tbutton0-abs[3] @ #x~X~%" (-> obj button0-abs))
(format #t "~Tbutton0-shadow-abs[1] @ #x~X~%" (-> obj button0-shadow-abs))
(format #t "~Tbutton0-rel[3] @ #x~X~%" (-> obj button0-rel))
(format #t "~Tstick0-dir: ~f~%" (-> obj stick0-dir))
(format #t "~Tstick0-speed: ~f~%" (-> obj stick0-speed))
(format #t "~Tnew-pad: ~D~%" (-> obj new-pad))
(format #t "~Tstate: ~D~%" (-> obj state))
(format #t "~Talign[6] @ #x~X~%" (-> obj align))
(format #t "~Tdirect[6] @ #x~X~%" (-> obj direct))
(format #t "~Tbuzz-val[2] @ #x~X~%" (-> obj buzz-val))
(format #t "~Tbuzz-time[2] @ #x~X~%" (-> obj buzz-time))
(format #t "~Tbuzz: ~A~%" (-> obj buzz))
(format #t "~Tbuzz-act: ~D~%" (-> obj buzz-act))
(format #t "~Tchange-time: ~D~%" (-> obj change-time))
obj
)
;; definition for function cpad-invalid!
(defun cpad-invalid! ((pad cpad-info))
(set! (-> pad valid) (logior (-> pad valid) 128))
(set! (-> pad button0) (the-as uint 0))
(set! (-> pad button0-abs 0) (the-as uint 0))
(set! (-> pad button0-shadow-abs 0) (the-as uint 0))
(set! (-> pad button0-rel 0) (the-as uint 0))
(dotimes (v1-2 12)
(nop!)
(set! (-> pad abutton v1-2) 0)
)
(set! (-> pad stick0-dir) 0.0)
(set! (-> pad stick0-speed) 0.0)
(set! (-> pad rightx) (the-as uint 128))
(set! (-> pad righty) (the-as uint 128))
(set! (-> pad leftx) (the-as uint 128))
(set! (-> pad lefty) (the-as uint 128))
(set! (-> pad align 0) (the-as uint 0))
(set! (-> pad align 1) (the-as uint 1))
(set! (-> pad align 2) (the-as uint 255))
(set! (-> pad align 3) (the-as uint 255))
(set! (-> pad align 4) (the-as uint 255))
(set! (-> pad align 5) (the-as uint 255))
(dotimes (v1-14 6)
(set! (-> pad direct v1-14) 0)
)
(dotimes (v1-17 2)
(set! (-> pad buzz-val 0) (the-as uint 0))
(set! (-> pad buzz-time 0) (the-as uint 0))
)
pad
)
;; definition for method 0 of type cpad-info
(defmethod new cpad-info ((alloction symbol) (type-to-make type) (idx int))
(let
((obj
(object-new alloction type-to-make (the-as int (-> type-to-make size)))
)
)
(set! (-> obj number) idx)
(set! (-> obj buzz) #f)
(cpad-open obj idx)
(cpad-invalid! obj)
)
)
;; definition of type cpad-list
(deftype cpad-list (basic)
((num-cpads int32 :offset-assert 4)
(cpads cpad-info 2 :offset-assert 8)
)
:method-count-assert 9
:size-assert #x10
:flag-assert #x900000010
(:methods
(new (symbol type) _type_ 0)
)
)
;; definition for method 3 of type cpad-list
(defmethod inspect cpad-list ((obj cpad-list))
(format #t "[~8x] ~A~%" obj (-> obj type))
(format #t "~Tnum-cpads: ~D~%" (-> obj num-cpads))
(format #t "~Tcpads[2] @ #x~X~%" (-> obj cpads))
obj
)
;; definition for method 0 of type cpad-list
(defmethod new cpad-list ((allocation symbol) (type-to-make type))
(let
((gp-0
(object-new allocation type-to-make (the-as int (-> type-to-make size)))
)
)
(set! (-> gp-0 num-cpads) 2)
(set! (-> gp-0 cpads 0) (new 'global 'cpad-info 0))
(set! (-> gp-0 cpads 1) (new 'global 'cpad-info 1))
gp-0
)
)
;; definition for function analog-input
(defun
analog-input
((in int) (offset float) (center-val float) (max-val float) (out-range float))
(let* ((in (gpr->fpr in))
(offset-in (- (the float in) offset))
(magnitude (- (fabs offset-in) center-val))
(max-magnitude (- max-val center-val))
)
(if (< offset-in 0.0)
(set! out-range (- out-range))
)
(cond
((>= 0.0 magnitude)
0.0
)
((>= magnitude max-magnitude)
out-range
)
(else
(/ (* magnitude out-range) max-magnitude)
)
)
)
)
;; definition for function cpad-set-buzz!
;; INFO: Return type mismatch int vs none.
(defun
cpad-set-buzz!
((pad cpad-info) (buzz-idx int) (buzz-amount int) (duration int))
(cond
((zero? buzz-amount)
(set! (-> pad buzz-val buzz-idx) 0)
(let ((v1-2 0))
)
)
((= buzz-amount (-> pad buzz-val buzz-idx))
(set!
(-> pad buzz-time buzz-idx)
(max
(the-as int (-> pad buzz-time buzz-idx))
(the-as int (+ (get-current-time) (the-as uint duration)))
)
)
)
((< (-> pad buzz-val buzz-idx) (the-as uint buzz-amount))
(set! (-> pad buzz-val buzz-idx) buzz-amount)
(set!
(-> pad buzz-time buzz-idx)
(+ (get-current-time) (the-as uint duration))
)
)
)
(let ((v0-2 0))
)
(none)
)
;; definition for symbol *cpad-list*, type cpad-list
(define *cpad-list* (new 'global 'cpad-list))
;; definition for symbol *cpad-debug*, type symbol
(define *cpad-debug* #f)
;; definition for function service-cpads
(defun service-cpads ()
(let ((pad-list *cpad-list*))
(dotimes (pad-idx (-> pad-list num-cpads))
(let ((pad (-> *cpad-list* cpads pad-idx)))
(cpad-get-data pad)
(cond
((zero? (logand (-> pad valid) 128))
(dotimes (buzz-idx 2)
(cond
((and
(-> pad buzz)
(<
(the-as int (get-current-time))
(the-as int (-> pad buzz-time buzz-idx))
)
(= *master-mode* 'game)
)
(let ((v1-10 buzz-idx))
(cond
((zero? v1-10)
(set!
(-> pad direct buzz-idx)
(logand
(ash
(-> pad buzz-val buzz-idx)
(- (the-as int (logand (get-integral-current-time) 7)))
)
1
)
)
)
((= v1-10 1)
(set! (-> pad direct buzz-idx) (-> pad buzz-val buzz-idx))
)
)
)
)
(else
(set! (-> pad buzz-val buzz-idx) 0)
(set! (-> pad direct buzz-idx) 0)
(let ((v1-22 0))
)
)
)
)
(set! (-> pad button0-abs 2) (-> pad button0-abs 1))
(set! (-> pad button0-abs 1) (-> pad button0-shadow-abs 0))
(set! (-> pad button0-rel 2) (-> pad button0-rel 1))
(set! (-> pad button0-rel 1) (-> pad button0-rel 0))
(let ((current-button0 (-> pad button0)))
(set! (-> pad button0-shadow-abs 0) current-button0)
(set! (-> pad button0-abs 0) current-button0)
)
(set!
(-> pad button0-rel 0)
(logand (-> pad button0-abs 0) (lognot (-> pad button0-abs 1)))
)
(when *cpad-debug*
(set! (-> pad leftx) (the-as uint 255))
(set! (-> pad rightx) (the-as uint 255))
)
(set! (-> pad stick0-speed) 1.0)
(cond
((= (shr (-> pad status) 4) 7)
(let ((f30-0 (* 0.0078125 (the float (+ (-> pad leftx) -128))))
(f28-0
(* 0.0078125 (the float (- 127 (the-as int (-> pad lefty)))))
)
)
(set! (-> pad stick0-dir) (atan (- f30-0) f28-0))
(set!
(-> pad stick0-speed)
(fmin 1.0 (sqrtf (+ (* f30-0 f30-0) (* f28-0 f28-0))))
)
)
(if (< (-> pad stick0-speed) 0.3)
(let ((f0-8 0.0))
(set! (-> pad stick0-speed) f0-8)
)
)
)
(else
(set! (-> pad leftx) (the-as uint 128))
(set! (-> pad lefty) (the-as uint 128))
(set! (-> pad rightx) (the-as uint 128))
(set! (-> pad righty) (the-as uint 128))
(set! (-> pad stick0-dir) 0.0)
(let ((f0-10 0.0))
(set! (-> pad stick0-speed) f0-10)
)
)
)
(if
(or
(!= (-> pad button0-abs 0) (-> pad button0-abs 1))
(or (< 0.3 (-> pad stick0-speed)) (zero? (-> pad change-time)))
)
(set! (-> pad change-time) (get-current-time))
)
)
(else
(cpad-invalid! pad)
)
)
)
)
)
*cpad-list*
)
;; definition for function buzz-stop!
;; INFO: Return type mismatch int vs none.
(defun buzz-stop! ((idx int))
(cpad-set-buzz! (-> *cpad-list* cpads idx) 0 0 0)
(cpad-set-buzz! (-> *cpad-list* cpads idx) 1 0 0)
(let ((v0-0 0))
)
(none)
)
;; failed to figure out what this is:
(let ((v0-4 0))
)
@@ -967,7 +967,7 @@ TEST_F(FormRegressionTest, DmaBufferAddVuFunction) {
" (quote static)\n"
" (quote dma-tag)\n"
" :id\n"
" 3\n"
" (dma-tag-id ref)\n"
" :addr\n"
" (the-as int v1-0)\n"
" :qwc\n"
@@ -984,7 +984,7 @@ TEST_F(FormRegressionTest, DmaBufferAddVuFunction) {
" )\n"
" (set!\n"
" (-> (the-as dma-packet t2-0) vif1)\n"
" (new (quote static) (quote vif-tag) :cmd 74 :num (shl t0-1 1) :imm a1-1)\n"
" (new (quote static) (quote vif-tag) :cmd (vif-cmd mpg) :num (shl t0-1 1) :imm a1-1)\n"
" )\n"
" (set! (-> t1-1 base) (&+ (the-as pointer t2-0) 16))\n"
" )\n"
+6 -3
View File
@@ -17,7 +17,7 @@ const std::unordered_set<std::string> g_object_files_to_decompile = {
"trigonometry-h", /* transformq-h */ "matrix", "transform", "quaternion",
"euler", /* geometry, trigonometry, */
"gsound-h", "timer-h", "timer", "vif-h", "dma-h", "video-h", "vu1-user-h", "dma", "dma-buffer",
"dma-bucket", "dma-disasm",
"dma-bucket", "dma-disasm", "pad", "gs",
/* gap */
"bounding-box",
/* gap */
@@ -32,7 +32,7 @@ const std::vector<std::string> g_object_files_to_check_against_reference = {
/* transformq-h, */
"matrix", "transform", "quaternion", "euler", /* geometry, trigonometry */
"gsound-h", "timer-h", /* timer, */ "vif-h", "dma-h", "video-h", "vu1-user-h", "dma",
"dma-buffer", "dma-bucket", "dma-disasm",
"dma-buffer", "dma-bucket", "dma-disasm", "pad", "gs",
/* gap */ "bounding-box",
/* gap */
"sync-info-h", "sync-info"};
@@ -118,7 +118,10 @@ const std::unordered_set<std::string> skip_in_compiling = {
"(method 3 profile-frame)", // double definition.
// dma-disasm
"disasm-dma-list",
"disasm-dma-list", // missing a single cast :(
// gs
"(method 3 gif-tag)", // inspect for a 128-bit type.
// sync-info
"(method 15 sync-info)", // needs display stuff first