mirror of
https://github.com/open-goal/jak-project
synced 2026-08-22 07:04:29 -04:00
decompiler: obj -> this, set-time! and time-elapsed? macros (#3026)
This renames the method object in `defmethod`s to `this` and adds detection for the `set-time!` and `time-elapsed?` macros. Definitely my biggest PR yet...
This commit is contained in:
@@ -2621,6 +2621,16 @@ void SetVarElement::push_to_stack(const Env& env, FormPool& pool, FormStack& sta
|
||||
}
|
||||
}
|
||||
|
||||
FormElement* SetFormFormElement::make_set_time(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
auto matcher = match(
|
||||
Matcher::op(GenericOpMatcher::func(Matcher::constant_token("current-time")), {}), m_src);
|
||||
if (matcher.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("set-time!")), m_dst);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack& stack) {
|
||||
ASSERT(m_popped);
|
||||
ASSERT(m_real_push_count == 0);
|
||||
@@ -2689,6 +2699,12 @@ void SetFormFormElement::push_to_stack(const Env& env, FormPool& pool, FormStack
|
||||
|
||||
const static InplaceCallInfo in_place_calls[] = {{"seek", "seek!", 0}, {"seekl", "seekl!", 0}};
|
||||
|
||||
auto as_set_time = make_set_time(env, pool, stack);
|
||||
if (as_set_time) {
|
||||
stack.push_form_element(as_set_time, true);
|
||||
return;
|
||||
}
|
||||
|
||||
auto src_as_generic = m_src->try_as_element<GenericElement>();
|
||||
if (src_as_generic) {
|
||||
if (src_as_generic->op().is_func()) {
|
||||
@@ -3926,27 +3942,47 @@ ConstantTokenElement* DerefElement::try_as_art_const(const Env& env, FormPool& p
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GenericElement* DerefElement::try_as_curtime(FormPool& pool) {
|
||||
auto mr = match(Matcher::deref(Matcher::s6(), false,
|
||||
{DerefTokenMatcher::string("clock"),
|
||||
DerefTokenMatcher::string("frame-counter")}),
|
||||
this);
|
||||
if (mr.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("current-time")));
|
||||
GenericElement* DerefElement::try_as_curtime(const Env& env, FormPool& pool) {
|
||||
if (env.version == GameVersion::Jak1) {
|
||||
auto mr = match(Matcher::deref(Matcher::symbol("*display*"), false,
|
||||
{DerefTokenMatcher::string("base-frame-counter")}),
|
||||
this);
|
||||
if (mr.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("current-time")));
|
||||
}
|
||||
} else {
|
||||
auto mr = match(Matcher::deref(Matcher::s6(), false,
|
||||
{DerefTokenMatcher::string("clock"),
|
||||
DerefTokenMatcher::string("frame-counter")}),
|
||||
this);
|
||||
if (mr.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("current-time")));
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GenericElement* DerefElement::try_as_seconds_per_frame(FormPool& pool) {
|
||||
auto mr = match(Matcher::deref(Matcher::s6(), false,
|
||||
{DerefTokenMatcher::string("clock"),
|
||||
DerefTokenMatcher::string("seconds-per-frame")}),
|
||||
this);
|
||||
if (mr.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("seconds-per-frame")));
|
||||
GenericElement* DerefElement::try_as_seconds_per_frame(const Env& env, FormPool& pool) {
|
||||
if (env.version == GameVersion::Jak1) {
|
||||
auto mr = match(Matcher::deref(Matcher::symbol("*display*"), false,
|
||||
{DerefTokenMatcher::string("seconds-per-frame")}),
|
||||
this);
|
||||
if (mr.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("seconds-per-frame")));
|
||||
}
|
||||
} else {
|
||||
auto mr = match(Matcher::deref(Matcher::s6(), false,
|
||||
{DerefTokenMatcher::string("clock"),
|
||||
DerefTokenMatcher::string("seconds-per-frame")}),
|
||||
this);
|
||||
if (mr.matched) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("seconds-per-frame")));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -3987,14 +4023,14 @@ void DerefElement::update_from_stack(const Env& env,
|
||||
}
|
||||
|
||||
// current-time macro
|
||||
auto as_curtime = try_as_curtime(pool);
|
||||
auto as_curtime = try_as_curtime(env, pool);
|
||||
if (as_curtime) {
|
||||
result->push_back(as_curtime);
|
||||
return;
|
||||
}
|
||||
|
||||
// seconds-per-frame macro
|
||||
auto as_seconds_per_frame = try_as_seconds_per_frame(pool);
|
||||
auto as_seconds_per_frame = try_as_seconds_per_frame(env, pool);
|
||||
if (as_seconds_per_frame) {
|
||||
result->push_back(as_seconds_per_frame);
|
||||
return;
|
||||
@@ -5223,6 +5259,48 @@ FormElement* ConditionElement::make_geq_zero_unsigned_check_generic(
|
||||
return pool.alloc_element<GenericElement>(GenericOperator::make_fixed(FixedOperatorKind::GEQ),
|
||||
casted);
|
||||
}
|
||||
|
||||
FormElement* ConditionElement::make_time_elapsed(const Env& env,
|
||||
FormPool& pool,
|
||||
const std::vector<Form*>& source_forms,
|
||||
const std::vector<TypeSpec>& types) {
|
||||
// geq case:
|
||||
// (>= (- (current-time) (-> self state-time)) (seconds 5))
|
||||
// to
|
||||
// (time-elapsed? (-> self state-time) (seconds 5))
|
||||
|
||||
// lt case:
|
||||
// (< (- (current-time) (-> self state-time)) (seconds 5))
|
||||
// to
|
||||
// (not (time-elapsed? (-> self state-time) (seconds 5)))
|
||||
auto matcher = match(
|
||||
Matcher::op(GenericOpMatcher::fixed(FixedOperatorKind::SUBTRACTION),
|
||||
{Matcher::op(GenericOpMatcher::func(Matcher::constant_token("current-time")), {}),
|
||||
Matcher::any(0)}),
|
||||
source_forms.at(0));
|
||||
if (matcher.matched) {
|
||||
auto time_elapsed = matcher.maps.forms.at(0);
|
||||
auto time = source_forms.at(1);
|
||||
std::vector<Form*> args;
|
||||
args.push_back(time_elapsed);
|
||||
args.push_back(time);
|
||||
if (m_kind == IR2_Condition::Kind::LESS_THAN_SIGNED ||
|
||||
m_kind == IR2_Condition::Kind::LESS_THAN_UNSIGNED) {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_compare(IR2_Condition::Kind::FALSE),
|
||||
pool.form<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("time-elapsed?")),
|
||||
make_casts_if_needed(args, types, TypeSpec("time-frame"), pool, env)));
|
||||
} else {
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_function(pool.form<ConstantTokenElement>("time-elapsed?")),
|
||||
make_casts_if_needed(args, types, TypeSpec("time-frame"), pool, env));
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FormElement* ConditionElement::make_generic(const Env& env,
|
||||
FormPool& pool,
|
||||
const std::vector<Form*>& source_forms,
|
||||
@@ -5248,23 +5326,43 @@ FormElement* ConditionElement::make_generic(const Env& env,
|
||||
case IR2_Condition::Kind::NOT_EQUAL:
|
||||
return make_not_equal_check_generic(env, pool, source_forms, types);
|
||||
|
||||
case IR2_Condition::Kind::LESS_THAN_SIGNED:
|
||||
case IR2_Condition::Kind::LESS_THAN_SIGNED: {
|
||||
auto time_elapsed = make_time_elapsed(env, pool, source_forms, types);
|
||||
if (time_elapsed) {
|
||||
return time_elapsed;
|
||||
}
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::LT),
|
||||
make_casts_if_needed(source_forms, types, TypeSpec("int"), pool, env));
|
||||
case IR2_Condition::Kind::LESS_THAN_UNSIGNED:
|
||||
}
|
||||
case IR2_Condition::Kind::LESS_THAN_UNSIGNED: {
|
||||
auto time_elapsed = make_time_elapsed(env, pool, source_forms, types);
|
||||
if (time_elapsed) {
|
||||
return time_elapsed;
|
||||
}
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::LT),
|
||||
make_casts_if_needed(source_forms, types, TypeSpec("uint"), pool, env));
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::GEQ_SIGNED:
|
||||
case IR2_Condition::Kind::GEQ_SIGNED: {
|
||||
auto time_elapsed = make_time_elapsed(env, pool, source_forms, types);
|
||||
if (time_elapsed) {
|
||||
return time_elapsed;
|
||||
}
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::GEQ),
|
||||
make_casts_if_needed(source_forms, types, TypeSpec("int"), pool, env));
|
||||
case IR2_Condition::Kind::GEQ_UNSIGNED:
|
||||
}
|
||||
case IR2_Condition::Kind::GEQ_UNSIGNED: {
|
||||
auto time_elapsed = make_time_elapsed(env, pool, source_forms, types);
|
||||
if (time_elapsed) {
|
||||
return time_elapsed;
|
||||
}
|
||||
return pool.alloc_element<GenericElement>(
|
||||
GenericOperator::make_fixed(FixedOperatorKind::GEQ),
|
||||
make_casts_if_needed(source_forms, types, TypeSpec("uint"), pool, env));
|
||||
}
|
||||
|
||||
case IR2_Condition::Kind::LESS_THAN_ZERO_SIGNED: {
|
||||
return make_less_than_zero_signed_check_generic(env, pool, source_forms, types);
|
||||
|
||||
Reference in New Issue
Block a user