mirror of
https://github.com/open-goal/jak-project
synced 2026-05-23 15:02:01 -04:00
[decomp] better handling of animation code and art files (#1352)
* update refs * [decompiler] read and process art groups * finish decompiler art group selection & detect in `ja-group?` * make art stuff work on offline tests! * [decompiler] detect `ja-group!` (primitive) * corrections. * more * use new feature on skel groups! * find `loop!` as well * fully fledged `ja` macro & decomp + `loop` detect * fancy fixed point printing! * update source * `:num! max` (i knew i should've done this) * Update jak1_ntsc_black_label.jsonc * hi imports * make compiling the game work * fix `defskelgroup` * clang * update refs * fix chan * fix seek and finalboss * fix tests * delete unused function * track let rewrite stats * reorder `rewrite_let` * Update .gitattributes * fix bug with `:num! max` * Update robotboss-part.gc * Update goal-lib.gc * document `ja` * get rid of pc fixes thing * use std::abs
This commit is contained in:
@@ -58,26 +58,28 @@ void ObjectFileDB::analyze_functions_ir2(
|
||||
ir2_do_segment_analysis_phase1(MAIN_SEGMENT, config, data);
|
||||
ir2_setup_labels(config, data);
|
||||
ir2_do_segment_analysis_phase2(TOP_LEVEL_SEGMENT, config, data);
|
||||
try {
|
||||
if (data.linked_data.functions_by_seg.size() == 3) {
|
||||
if (data.linked_data.functions_by_seg.size() == 3) {
|
||||
enum { DEFPART, DEFSTATE, DEFSKELGROUP } step = DEFPART;
|
||||
try {
|
||||
run_defpartgroup(data.linked_data.functions_by_seg.at(TOP_LEVEL_SEGMENT).front());
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
lg::error("Failed to find defpartgroups: {}", e.what());
|
||||
}
|
||||
try {
|
||||
if (data.linked_data.functions_by_seg.size() == 3) {
|
||||
step = DEFSTATE;
|
||||
run_defstate(data.linked_data.functions_by_seg.at(TOP_LEVEL_SEGMENT).front(), skip_states);
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
lg::error("Failed to find defstates: {}", e.what());
|
||||
}
|
||||
try {
|
||||
if (data.linked_data.functions_by_seg.size() == 3) {
|
||||
step = DEFSKELGROUP;
|
||||
run_defskelgroups(data.linked_data.functions_by_seg.at(TOP_LEVEL_SEGMENT).front());
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
switch (step) {
|
||||
case DEFPART:
|
||||
lg::error("Failed to find defpartgroups: {}", e.what());
|
||||
break;
|
||||
case DEFSTATE:
|
||||
lg::error("Failed to find defstates: {}", e.what());
|
||||
break;
|
||||
case DEFSKELGROUP:
|
||||
lg::error("Failed to find defskelgroups: {}", e.what());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (const std::exception& e) {
|
||||
lg::error("Failed to find defskelgroups: {}", e.what());
|
||||
}
|
||||
ir2_do_segment_analysis_phase2(DEBUG_SEGMENT, config, data);
|
||||
ir2_do_segment_analysis_phase2(MAIN_SEGMENT, config, data);
|
||||
@@ -104,6 +106,20 @@ void ObjectFileDB::analyze_functions_ir2(
|
||||
fmt::print("Done in {:.2f}ms\n", file_timer.getMs());
|
||||
});
|
||||
|
||||
int total = stats.let.total();
|
||||
lg::info("LET REWRITE STATS: {} total", total);
|
||||
lg::info(" dotimes: {}", stats.let.dotimes);
|
||||
lg::info(" countdown: {}", stats.let.countdown);
|
||||
lg::info(" abs: {}", stats.let.abs);
|
||||
lg::info(" abs2: {}", stats.let.abs2);
|
||||
lg::info(" ja: {}", stats.let.ja);
|
||||
lg::info(" set_vector: {}", stats.let.set_vector);
|
||||
lg::info(" set_vector2: {}", stats.let.set_vector2);
|
||||
lg::info(" case_no_else: {}", stats.let.case_no_else);
|
||||
lg::info(" case_with_else: {}", stats.let.case_with_else);
|
||||
lg::info(" unused: {}", stats.let.unused);
|
||||
lg::info(" send_event: {}", stats.let.send_event);
|
||||
|
||||
if (config.generate_symbol_definition_map) {
|
||||
lg::info("Generating symbol definition map...");
|
||||
map_builder.build_map();
|
||||
@@ -403,6 +419,7 @@ Value try_lookup(const std::unordered_map<Key, Value>& map, const Key& key) {
|
||||
* - NOTE: this will update register info usage more accurately for functions.
|
||||
*/
|
||||
void ObjectFileDB::ir2_type_analysis_pass(int seg, const Config& config, ObjectFileData& data) {
|
||||
auto obj_name = data.to_unique_name();
|
||||
for_each_function_in_seg_in_obj(seg, data, [&](Function& func) {
|
||||
if (!func.suspected_asm) {
|
||||
TypeSpec ts;
|
||||
@@ -414,9 +431,11 @@ void ObjectFileDB::ir2_type_analysis_pass(int seg, const Config& config, ObjectF
|
||||
auto register_casts =
|
||||
try_lookup(config.register_type_casts_by_function_by_atomic_op_idx, func_name);
|
||||
func.ir2.env.set_type_casts(register_casts);
|
||||
|
||||
auto stack_casts =
|
||||
try_lookup(config.stack_type_casts_by_function_by_stack_offset, func_name);
|
||||
func.ir2.env.set_stack_casts(stack_casts);
|
||||
|
||||
if (config.hacks.pair_functions_by_name.find(func_name) !=
|
||||
config.hacks.pair_functions_by_name.end()) {
|
||||
func.ir2.env.set_sloppy_pair_typing();
|
||||
@@ -426,8 +445,18 @@ void ObjectFileDB::ir2_type_analysis_pass(int seg, const Config& config, ObjectF
|
||||
config.hacks.reject_cond_to_value.end()) {
|
||||
func.ir2.env.aggressively_reject_cond_to_value_rewrite = true;
|
||||
}
|
||||
|
||||
func.ir2.env.set_stack_structure_hints(
|
||||
try_lookup(config.stack_structure_hints_by_function, func_name));
|
||||
|
||||
if (config.art_groups_by_function.find(func_name) != config.art_groups_by_function.end()) {
|
||||
func.ir2.env.set_art_group(config.art_groups_by_function.at(func_name));
|
||||
} else if (config.art_groups_by_file.find(obj_name) != config.art_groups_by_file.end()) {
|
||||
func.ir2.env.set_art_group(config.art_groups_by_file.at(obj_name));
|
||||
} else {
|
||||
func.ir2.env.set_art_group(obj_name + "-ag");
|
||||
}
|
||||
|
||||
if (run_type_analysis_ir2(ts, dts, func)) {
|
||||
func.ir2.env.types_succeeded = true;
|
||||
} else {
|
||||
@@ -446,7 +475,7 @@ void ObjectFileDB::ir2_register_usage_pass(int seg, ObjectFileData& data) {
|
||||
if (!func.suspected_asm && func.ir2.atomic_ops_succeeded) {
|
||||
func.ir2.env.set_reg_use(analyze_ir2_register_usage(func));
|
||||
|
||||
auto block_0_start = func.ir2.env.reg_use().block.at(0).input;
|
||||
auto& block_0_start = func.ir2.env.reg_use().block.at(0).input;
|
||||
std::vector<Register> dep_regs;
|
||||
for (auto x : block_0_start) {
|
||||
dep_regs.push_back(x);
|
||||
@@ -572,12 +601,14 @@ void ObjectFileDB::ir2_insert_lets(int seg, ObjectFileData& data) {
|
||||
for_each_function_in_seg_in_obj(seg, data, [&](Function& func) {
|
||||
if (func.ir2.expressions_succeeded) {
|
||||
try {
|
||||
insert_lets(func, func.ir2.env, *func.ir2.form_pool, func.ir2.top_form);
|
||||
insert_lets(func, func.ir2.env, *func.ir2.form_pool, func.ir2.top_form, stats.let);
|
||||
} catch (const std::exception& e) {
|
||||
func.warnings.general_warning(
|
||||
fmt::format("Error while inserting lets: {}. Make sure that the return type is not "
|
||||
"none if something is actually returned.",
|
||||
e.what()));
|
||||
const auto err = fmt::format(
|
||||
"Error while inserting lets: {}. Make sure that the return type is not "
|
||||
"none if something is actually returned.",
|
||||
e.what());
|
||||
lg::warn(err);
|
||||
func.warnings.general_warning(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user