mirror of
https://github.com/open-goal/jak-project
synced 2026-07-07 14:13:45 -04:00
[decompiler] setup before making IR2 type inspector (#1423)
This commit is contained in:
@@ -444,6 +444,8 @@ void LinkedObjectFile::disassemble_functions() {
|
||||
decode_instruction(words_by_seg.at(seg).at(word), *this, seg, word));
|
||||
if (function.instructions.back().is_valid()) {
|
||||
stats.decoded_ops++;
|
||||
} else {
|
||||
lg::error("Failed to decode op: 0x{:08x}", words_by_seg.at(seg).at(word).data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -582,6 +584,9 @@ std::string LinkedObjectFile::print_function_disassembly(Function& func,
|
||||
result += " ;;";
|
||||
auto& word = words_by_seg[seg].at(func.start_word + i);
|
||||
append_word_to_string(result, word);
|
||||
} else {
|
||||
result += line;
|
||||
result += '\n';
|
||||
}
|
||||
|
||||
if (in_delay_slot) {
|
||||
|
||||
@@ -219,7 +219,8 @@ static uint32_t c_symlink3(LinkedObjectFile& f,
|
||||
static void link_v2_or_v4(LinkedObjectFile& f,
|
||||
const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts) {
|
||||
DecompilerTypeSystem& dts,
|
||||
GameVersion version) {
|
||||
const auto* header = (const LinkHeaderV4*)&data.at(0);
|
||||
ASSERT(header->version == 4 || header->version == 2);
|
||||
|
||||
@@ -251,6 +252,13 @@ static void link_v2_or_v4(LinkedObjectFile& f,
|
||||
const uint8_t* code_start = &data.at(code_offset);
|
||||
const uint8_t* code_end =
|
||||
&data.at(code_offset + code_size - 1) + 1; // get the pointer to one past the end.
|
||||
|
||||
if (version == GameVersion::Jak2) {
|
||||
while (((code_end - code_start) % 4)) {
|
||||
code_end++;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(((code_end - code_start) % 4) == 0);
|
||||
f.set_segment_count(1);
|
||||
for (auto x = code_start; x < code_end; x += 4) {
|
||||
@@ -605,7 +613,7 @@ static void link_v3(LinkedObjectFile& f,
|
||||
const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version) {
|
||||
GameVersion game_version) {
|
||||
auto header = (const LinkHeaderV3*)(&data.at(0));
|
||||
ASSERT(name == header->name);
|
||||
ASSERT(header->segments == 3);
|
||||
@@ -652,11 +660,11 @@ static void link_v3(LinkedObjectFile& f,
|
||||
// HACK!
|
||||
// why is this a thing?
|
||||
// HACK!
|
||||
if (game_version == 1 && name == "level-h" && seg_id == 0) {
|
||||
if (game_version == GameVersion::Jak1 && name == "level-h" && seg_id == 0) {
|
||||
segment_size++;
|
||||
}
|
||||
|
||||
if (game_version == 2) {
|
||||
if (game_version == GameVersion::Jak2) {
|
||||
bool adjusted = false;
|
||||
while (segment_size % 4) {
|
||||
segment_size++;
|
||||
@@ -756,7 +764,16 @@ static void link_v3(LinkedObjectFile& f,
|
||||
s_name = (const char*)(&data.at(link_ptr));
|
||||
} else {
|
||||
s_name = (const char*)(&data.at(link_ptr));
|
||||
dts.ts.forward_declare_type_method_count(s_name, reloc & 0x7f);
|
||||
switch (game_version) {
|
||||
case GameVersion::Jak1:
|
||||
dts.ts.forward_declare_type_method_count(s_name, (reloc & 0x7f));
|
||||
break;
|
||||
case GameVersion::Jak2:
|
||||
dts.ts.forward_declare_type_method_count_multiple_of_4(s_name, (reloc & 0x7f) * 4 + 3);
|
||||
break;
|
||||
default:
|
||||
ASSERT(false);
|
||||
}
|
||||
kind = SymbolLinkKind::TYPE;
|
||||
}
|
||||
|
||||
@@ -795,7 +812,7 @@ static void link_v3(LinkedObjectFile& f,
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version) {
|
||||
GameVersion game_version) {
|
||||
LinkedObjectFile result;
|
||||
const auto* header = (const LinkHeaderCommon*)&data.at(0);
|
||||
|
||||
@@ -805,7 +822,7 @@ LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
link_v3(result, data, name, dts, game_version);
|
||||
} else if (header->version == 4 || header->version == 2) {
|
||||
ASSERT(header->type_tag == 0xffffffff);
|
||||
link_v2_or_v4(result, data, name, dts);
|
||||
link_v2_or_v4(result, data, name, dts, game_version);
|
||||
} else if (header->version == 5) {
|
||||
link_v5(result, data, name, dts);
|
||||
} else {
|
||||
|
||||
@@ -13,5 +13,5 @@ class DecompilerTypeSystem;
|
||||
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
|
||||
const std::string& name,
|
||||
DecompilerTypeSystem& dts,
|
||||
int game_version);
|
||||
GameVersion game_version);
|
||||
} // namespace decompiler
|
||||
|
||||
@@ -115,7 +115,7 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
|
||||
Timer timer;
|
||||
|
||||
lg::info("-Loading types...");
|
||||
dts.parse_type_defs({"decompiler", "config", "all-types.gc"});
|
||||
dts.parse_type_defs({config.all_types_file});
|
||||
|
||||
if (!obj_file_name_map_file.empty()) {
|
||||
lg::info("-Loading obj name map file...");
|
||||
@@ -407,7 +407,9 @@ std::string ObjectFileDB::generate_obj_listing(const std::unordered_set<std::str
|
||||
// this check is extremely important. It makes sure we don't have any repeat names. This could
|
||||
// be caused by two files with the same name, in the same DGOs, but different data.
|
||||
if (int(all_unique_names.size()) != unique_count) {
|
||||
lg::error("Object files are not named properly, data will be lost!");
|
||||
lg::error(
|
||||
"Object files are not named properly, data will be lost! Got {} objs, but only {} names\n",
|
||||
unique_count, all_unique_names.size());
|
||||
}
|
||||
|
||||
if (unique_count > 0) {
|
||||
@@ -530,7 +532,7 @@ void ObjectFileDB::find_code(const Config& config) {
|
||||
obj.linked_data.find_functions();
|
||||
obj.linked_data.disassemble_functions();
|
||||
|
||||
if (config.game_version == 1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
if (config.game_version == GameVersion::Jak1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
obj.linked_data.process_fp_relative_links();
|
||||
} else {
|
||||
lg::warn("Skipping process_fp_relative_links in {}", obj.to_unique_name().c_str());
|
||||
|
||||
Reference in New Issue
Block a user