mirror of
https://github.com/open-goal/jak-project
synced 2026-07-08 22:45:00 -04:00
decompiler: better automatic detection of art groups and joint-node-index macro detection (#3061)
This commit is contained in:
@@ -873,6 +873,24 @@ std::string ObjectFileDB::process_game_count_file() {
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct JointGeo {
|
||||
u32 offset{};
|
||||
std::string name;
|
||||
u32 length{};
|
||||
};
|
||||
|
||||
void get_joint_info(ObjectFileDB& db, ObjectFileData& obj, JointGeo jg) {
|
||||
const auto& words = obj.linked_data.words_by_seg.at(MAIN_SEGMENT);
|
||||
for (size_t i = 0; i < jg.length; ++i) {
|
||||
const auto& label = words.at((jg.offset / 4) + 7 + i).label_id();
|
||||
const auto& joint = obj.linked_data.labels.at(label);
|
||||
const auto& name =
|
||||
obj.linked_data.get_goal_string_by_label(words.at(joint.offset / 4).label_id());
|
||||
// lg::print("{} joint idx {}/{}: {}\n", jg.name, i + 1, jg.length, name);
|
||||
db.dts.add_joint_node(jg.name, name, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void get_art_info(ObjectFileDB& db, ObjectFileData& obj) {
|
||||
if (obj.obj_version == 4) {
|
||||
const auto& words = obj.linked_data.words_by_seg.at(MAIN_SEGMENT);
|
||||
@@ -908,6 +926,11 @@ void get_art_info(ObjectFileDB& db, ObjectFileData& obj) {
|
||||
if (elt_type == "art-joint-geo") {
|
||||
// the skeleton!
|
||||
unique_name += "-jg";
|
||||
JointGeo jg;
|
||||
jg.offset = label.offset;
|
||||
jg.name = unique_name;
|
||||
jg.length = words.at(label.offset / 4 + 2).data;
|
||||
get_joint_info(db, obj, jg);
|
||||
} else if (elt_type == "merc-ctrl" || elt_type == "shadow-geo") {
|
||||
// (maybe mesh-geo as well but that doesnt exist)
|
||||
// the skin!
|
||||
@@ -953,7 +976,7 @@ void ObjectFileDB::dump_art_info(const fs::path& output_dir) {
|
||||
lg::info("Writing art group info...");
|
||||
Timer timer;
|
||||
|
||||
if (!dts.art_group_info.empty()) {
|
||||
if (!dts.art_group_info.empty() || !dts.jg_info.empty()) {
|
||||
file_util::create_dir_if_needed(output_dir / "import");
|
||||
}
|
||||
for (const auto& [ag_name, info] : dts.art_group_info) {
|
||||
@@ -970,6 +993,18 @@ void ObjectFileDB::dump_art_info(const fs::path& output_dir) {
|
||||
file_util::write_text_file(filename, result);
|
||||
}
|
||||
|
||||
auto jg_fpath = output_dir / "import" / "joint-nodes.gc";
|
||||
std::string jg_result;
|
||||
|
||||
for (const auto& [jg_name, info] : dts.jg_info) {
|
||||
for (const auto& [idx, joint] : info) {
|
||||
jg_result += print_jg_for_dump(jg_name, joint, idx);
|
||||
}
|
||||
jg_result += "\n";
|
||||
}
|
||||
|
||||
file_util::write_text_file(jg_fpath, jg_result);
|
||||
|
||||
lg::info("Written art group info: in {:.2f} ms", timer.getMs());
|
||||
}
|
||||
|
||||
@@ -988,4 +1023,7 @@ std::string print_art_elt_for_dump(const std::string& group_name,
|
||||
int idx) {
|
||||
return fmt::format("(def-art-elt {} {} {})\n", group_name, name, idx);
|
||||
}
|
||||
std::string print_jg_for_dump(const std::string& jg_name, const std::string& joint_name, int idx) {
|
||||
return fmt::format("(def-joint-node {} \"{}\" {})\n", jg_name, joint_name, idx);
|
||||
}
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -395,4 +395,5 @@ class ObjectFileDB {
|
||||
};
|
||||
|
||||
std::string print_art_elt_for_dump(const std::string& group_name, const std::string& name, int idx);
|
||||
std::string print_jg_for_dump(const std::string& jg_name, const std::string& joint_name, int idx);
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -548,14 +548,32 @@ void ObjectFileDB::ir2_type_analysis_pass(int seg, const Config& config, ObjectF
|
||||
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));
|
||||
if (func.guessed_name.kind == FunctionName::FunctionKind::V_STATE) {
|
||||
if (config.art_group_type_remap.find(func.guessed_name.type_name) !=
|
||||
config.art_group_type_remap.end()) {
|
||||
func.ir2.env.set_art_group(config.art_group_type_remap.at(func.guessed_name.type_name));
|
||||
} else {
|
||||
func.ir2.env.set_art_group(func.guessed_name.type_name + "-ag");
|
||||
}
|
||||
} else if (func.guessed_name.kind == FunctionName::FunctionKind::NV_STATE ||
|
||||
func.type.try_get_tag("behavior").has_value()) {
|
||||
std::string type = func.type.get_tag("behavior");
|
||||
if (config.art_group_type_remap.find(type) != config.art_group_type_remap.end()) {
|
||||
func.ir2.env.set_art_group(config.art_group_type_remap.at(type));
|
||||
} else {
|
||||
func.ir2.env.set_art_group(type + "-ag");
|
||||
}
|
||||
} else {
|
||||
func.ir2.env.set_art_group(obj_name + "-ag");
|
||||
}
|
||||
|
||||
func.ir2.env.set_jg(func.ir2.env.art_group());
|
||||
|
||||
if (config.joint_node_hacks.find(func.ir2.env.art_group()) !=
|
||||
config.joint_node_hacks.end()) {
|
||||
func.ir2.env.set_jg(config.joint_node_hacks.at(func.ir2.env.art_group()));
|
||||
}
|
||||
|
||||
constexpr bool kForceNewTypes = false;
|
||||
if (config.game_version == GameVersion::Jak2 || kForceNewTypes) {
|
||||
// use new types for jak 2 always
|
||||
|
||||
Reference in New Issue
Block a user