mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-27 00:10:31 +00:00
Make decompiler naming consistent (#94)
* use a fixed object file naming by default, option to allow new map file creation * fix prints * fixing up edge cases * update json config
This commit is contained in:
parent
0bc2466f86
commit
b561cdfade
@ -1,6 +1,7 @@
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include "Function.h"
|
||||
#include "third-party/spdlog/include/spdlog/spdlog.h"
|
||||
#include "decompiler/Disasm/InstructionMatching.h"
|
||||
#include "decompiler/ObjectFile/LinkedObjectFile.h"
|
||||
#include "decompiler/util/DecompilerTypeSystem.h"
|
||||
@ -89,8 +90,8 @@ void Function::analyze_prologue(const LinkedObjectFile& file) {
|
||||
// storing s7 on the stack is done by interrupt handlers, which we probably don't want to
|
||||
// support
|
||||
if (instr.kind == InstructionKind::SD && instr.get_src(0).get_reg() == make_gpr(Reg::S7)) {
|
||||
printf("[Warning] %s Suspected ASM function based on this instruction in prologue: %s\n",
|
||||
guessed_name.to_string().c_str(), instr.to_string(file).c_str());
|
||||
spdlog::warn("{} Suspected ASM function based on this instruction in prologue: {}\n",
|
||||
guessed_name.to_string(), instr.to_string(file));
|
||||
warnings += "Flagged as ASM function because of " + instr.to_string(file) + "\n";
|
||||
suspected_asm = true;
|
||||
return;
|
||||
|
@ -26,6 +26,9 @@ struct FunctionName {
|
||||
int method_id = -1; // only applicable for METHOD
|
||||
int unique_id = -1;
|
||||
|
||||
int id_in_object = -1;
|
||||
std::string object_name;
|
||||
|
||||
std::string to_string() const {
|
||||
switch (kind) {
|
||||
case FunctionKind::GLOBAL:
|
||||
@ -35,7 +38,7 @@ struct FunctionName {
|
||||
case FunctionKind::TOP_LEVEL_INIT:
|
||||
return "(top-level-login)";
|
||||
case FunctionKind::UNIDENTIFIED:
|
||||
return "(anon-function " + std::to_string(unique_id) + ")";
|
||||
return "(anon-function " + std::to_string(id_in_object) + " " + object_name + ")";
|
||||
default:
|
||||
throw std::runtime_error("Unsupported FunctionKind");
|
||||
}
|
||||
@ -55,10 +58,6 @@ struct FunctionName {
|
||||
type_name = std::move(tn);
|
||||
method_id = id;
|
||||
}
|
||||
|
||||
bool expected_unique() const {
|
||||
return kind == FunctionKind::GLOBAL || kind == FunctionKind::METHOD;
|
||||
}
|
||||
};
|
||||
|
||||
class BasicOpTypeInfo {
|
||||
|
@ -80,7 +80,7 @@ void Function::run_type_analysis(const TypeSpec& my_type,
|
||||
assert(my_type.arg_count() > 0);
|
||||
|
||||
int n_args = int(my_type.arg_count()) - 1;
|
||||
auto& return_type = my_type.get_arg(int(my_type.arg_count()) - 1);
|
||||
// auto& return_type = my_type.get_arg(int(my_type.arg_count()) - 1);
|
||||
|
||||
// all types at the entrance of each basic block.
|
||||
std::vector<TypeMap> bb_entry_types;
|
||||
|
@ -1879,6 +1879,9 @@ void add_basic_ops_to_block(Function* func, const BasicBlock& block, LinkedObjec
|
||||
case InstructionKind::PCPYH:
|
||||
case InstructionKind::PINTEH:
|
||||
|
||||
case InstructionKind::MTDAB:
|
||||
case InstructionKind::MTDABM:
|
||||
|
||||
// 128 bit integer
|
||||
// case InstructionKind::LQ:
|
||||
// case InstructionKind::SQ:
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "decompiler/Disasm/InstructionDecode.h"
|
||||
#include "decompiler/config.h"
|
||||
#include "third-party/json.hpp"
|
||||
#include "third-party/spdlog/include/spdlog/spdlog.h"
|
||||
|
||||
/*!
|
||||
* Set the number of segments in this object file.
|
||||
@ -505,7 +506,7 @@ void LinkedObjectFile::process_fp_relative_links() {
|
||||
}
|
||||
}
|
||||
|
||||
std::string LinkedObjectFile::to_asm_json() {
|
||||
std::string LinkedObjectFile::to_asm_json(const std::string& obj_file_name) {
|
||||
nlohmann::json data;
|
||||
std::vector<nlohmann::json::object_t> functions;
|
||||
|
||||
@ -515,7 +516,10 @@ std::string LinkedObjectFile::to_asm_json() {
|
||||
auto& func = functions_by_seg.at(seg).at(fi);
|
||||
auto fname = func.guessed_name.to_string();
|
||||
if (functions_seen.find(fname) != functions_seen.end()) {
|
||||
printf("duplicated %s\n", fname.c_str()); // todo - this needs fixing
|
||||
spdlog::warn(
|
||||
"Function {} appears multiple times in the same object file {} - it cannot be uniquely "
|
||||
"referenced from config",
|
||||
func.guessed_name.to_string(), obj_file_name);
|
||||
functions_seen[fname]++;
|
||||
fname += "-v" + std::to_string(functions_seen[fname]);
|
||||
} else {
|
||||
@ -527,6 +531,7 @@ std::string LinkedObjectFile::to_asm_json() {
|
||||
f["type"] = func.type.print();
|
||||
f["segment"] = seg;
|
||||
f["warnings"] = func.warnings;
|
||||
f["parent_object"] = obj_file_name;
|
||||
std::vector<nlohmann::json::object_t> ops;
|
||||
|
||||
for (int i = 1; i < func.end_word - func.start_word; i++) {
|
||||
@ -569,6 +574,179 @@ std::string LinkedObjectFile::to_asm_json() {
|
||||
return data.dump();
|
||||
}
|
||||
|
||||
std::string LinkedObjectFile::print_function_disassembly(Function& func,
|
||||
int seg,
|
||||
bool write_hex,
|
||||
const std::string& extra_name) {
|
||||
std::string result;
|
||||
result += ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n";
|
||||
result += "; .function " + func.guessed_name.to_string() + " " + extra_name + "\n";
|
||||
result += ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n";
|
||||
result += func.prologue.to_string(2) + "\n";
|
||||
if (!func.warnings.empty()) {
|
||||
result += "Warnings: " + func.warnings + "\n";
|
||||
}
|
||||
|
||||
// print each instruction in the function.
|
||||
bool in_delay_slot = false;
|
||||
|
||||
for (int i = 1; i < func.end_word - func.start_word; i++) {
|
||||
auto label_id = get_label_at(seg, (func.start_word + i) * 4);
|
||||
if (label_id != -1) {
|
||||
result += labels.at(label_id).name + ":\n";
|
||||
}
|
||||
|
||||
for (int j = 1; j < 4; j++) {
|
||||
// assert(get_label_at(seg, (func.start_word + i)*4 + j) == -1);
|
||||
if (get_label_at(seg, (func.start_word + i) * 4 + j) != -1) {
|
||||
result += "BAD OFFSET LABEL: ";
|
||||
result += labels.at(get_label_at(seg, (func.start_word + i) * 4 + j)).name + "\n";
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
auto& instr = func.instructions.at(i);
|
||||
std::string line = " " + instr.to_string(*this);
|
||||
|
||||
if (write_hex) {
|
||||
if (line.length() < 60) {
|
||||
line.append(60 - line.length(), ' ');
|
||||
}
|
||||
result += line;
|
||||
result += " ;;";
|
||||
auto& word = words_by_seg[seg].at(func.start_word + i);
|
||||
append_word_to_string(result, word);
|
||||
} else {
|
||||
// print basic op stuff
|
||||
if (func.has_basic_ops() && func.instr_starts_basic_op(i)) {
|
||||
if (line.length() < 30) {
|
||||
line.append(30 - line.length(), ' ');
|
||||
}
|
||||
line += ";; " + func.get_basic_op_at_instr(i)->print(*this);
|
||||
for (int iidx = 0; iidx < instr.n_src; iidx++) {
|
||||
if (instr.get_src(iidx).is_label()) {
|
||||
auto lab = labels.at(instr.get_src(iidx).get_label());
|
||||
if (is_string(lab.target_segment, lab.offset)) {
|
||||
line += " " + get_goal_string(lab.target_segment, lab.offset / 4 - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print type map
|
||||
if (func.has_typemaps()) {
|
||||
if (line.length() < 60) {
|
||||
line.append(60 - line.length(), ' ');
|
||||
}
|
||||
line += " tm: ";
|
||||
auto& tm = func.get_typemap_by_instr_idx(i);
|
||||
bool added = false;
|
||||
for (auto reg_kind : {Reg::RegisterKind::GPR, Reg::RegisterKind::FPR}) {
|
||||
for (int reg_idx = 0; reg_idx < 32; reg_idx++) {
|
||||
auto gpr = Register(reg_kind, reg_idx);
|
||||
auto kv = tm.find(gpr);
|
||||
if (kv != tm.end()) {
|
||||
added = true;
|
||||
line += fmt::format("{}: {}, ", gpr.to_charp(), kv->second.print());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added) {
|
||||
line.pop_back();
|
||||
line.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
result += line + "\n";
|
||||
}
|
||||
|
||||
if (in_delay_slot) {
|
||||
result += "\n";
|
||||
in_delay_slot = false;
|
||||
}
|
||||
|
||||
if (gOpcodeInfo[(int)instr.kind].has_delay_slot) {
|
||||
in_delay_slot = true;
|
||||
}
|
||||
}
|
||||
result += "\n";
|
||||
//
|
||||
// int bid = 0;
|
||||
// for(auto& bblock : func.basic_blocks) {
|
||||
// result += "BLOCK " + std::to_string(bid++)+ "\n";
|
||||
// for(int i = bblock.start_word; i < bblock.end_word; i++) {
|
||||
// if(i >= 0 && i < func.instructions.size()) {
|
||||
// result += func.instructions.at(i).to_string(*this) + "\n";
|
||||
// } else {
|
||||
// result += "BAD BBLOCK INSTR ID " + std::to_string(i);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// hack
|
||||
if (func.cfg && !func.cfg->is_fully_resolved()) {
|
||||
result += func.cfg->to_dot();
|
||||
result += "\n";
|
||||
}
|
||||
if (func.cfg) {
|
||||
result += func.cfg->to_form_string() + "\n";
|
||||
|
||||
// To debug block stuff.
|
||||
/*
|
||||
int bid = 0;
|
||||
for(auto& block : func.basic_blocks) {
|
||||
in_delay_slot = false;
|
||||
result += "B" + std::to_string(bid++) + "\n";
|
||||
for(auto i = block.start_word; i < block.end_word; i++) {
|
||||
auto label_id = get_label_at(seg, (func.start_word + i) * 4);
|
||||
if (label_id != -1) {
|
||||
result += labels.at(label_id).name + ":\n";
|
||||
}
|
||||
auto& instr = func.instructions.at(i);
|
||||
result += " " + instr.to_string(*this) + "\n";
|
||||
if (in_delay_slot) {
|
||||
result += "\n";
|
||||
in_delay_slot = false;
|
||||
}
|
||||
|
||||
if (gOpcodeInfo[(int)instr.kind].has_delay_slot) {
|
||||
in_delay_slot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (func.ir) {
|
||||
result += ";; ir\n";
|
||||
result += func.ir->print(*this);
|
||||
}
|
||||
|
||||
result += "\n\n\n";
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string LinkedObjectFile::print_asm_function_disassembly(const std::string& my_name) {
|
||||
std::string result;
|
||||
for (int seg = segments; seg-- > 0;) {
|
||||
bool got_in_seg = false;
|
||||
for (auto& func : functions_by_seg.at(seg)) {
|
||||
if (func.suspected_asm) {
|
||||
if (!got_in_seg) {
|
||||
result += ";------------------------------------------\n; ";
|
||||
result += segment_names[seg];
|
||||
result += " of " + my_name;
|
||||
result += "\n;------------------------------------------\n\n";
|
||||
got_in_seg = true;
|
||||
}
|
||||
result += print_function_disassembly(func, seg, false, my_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Print disassembled functions and data segments.
|
||||
*/
|
||||
@ -585,150 +763,7 @@ std::string LinkedObjectFile::print_disassembly() {
|
||||
|
||||
// functions
|
||||
for (auto& func : functions_by_seg.at(seg)) {
|
||||
result += ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n";
|
||||
result += "; .function " + func.guessed_name.to_string() + "\n";
|
||||
result += ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n";
|
||||
result += func.prologue.to_string(2) + "\n";
|
||||
if (!func.warnings.empty()) {
|
||||
result += "Warnings: " + func.warnings + "\n";
|
||||
}
|
||||
|
||||
// print each instruction in the function.
|
||||
bool in_delay_slot = false;
|
||||
|
||||
for (int i = 1; i < func.end_word - func.start_word; i++) {
|
||||
auto label_id = get_label_at(seg, (func.start_word + i) * 4);
|
||||
if (label_id != -1) {
|
||||
result += labels.at(label_id).name + ":\n";
|
||||
}
|
||||
|
||||
for (int j = 1; j < 4; j++) {
|
||||
// assert(get_label_at(seg, (func.start_word + i)*4 + j) == -1);
|
||||
if (get_label_at(seg, (func.start_word + i) * 4 + j) != -1) {
|
||||
result += "BAD OFFSET LABEL: ";
|
||||
result += labels.at(get_label_at(seg, (func.start_word + i) * 4 + j)).name + "\n";
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
auto& instr = func.instructions.at(i);
|
||||
std::string line = " " + instr.to_string(*this);
|
||||
|
||||
if (write_hex) {
|
||||
if (line.length() < 60) {
|
||||
line.append(60 - line.length(), ' ');
|
||||
}
|
||||
result += line;
|
||||
result += " ;;";
|
||||
auto& word = words_by_seg[seg].at(func.start_word + i);
|
||||
append_word_to_string(result, word);
|
||||
} else {
|
||||
// print basic op stuff
|
||||
if (func.has_basic_ops() && func.instr_starts_basic_op(i)) {
|
||||
if (line.length() < 30) {
|
||||
line.append(30 - line.length(), ' ');
|
||||
}
|
||||
line += ";; " + func.get_basic_op_at_instr(i)->print(*this);
|
||||
for (int iidx = 0; iidx < instr.n_src; iidx++) {
|
||||
if (instr.get_src(iidx).is_label()) {
|
||||
auto lab = labels.at(instr.get_src(iidx).get_label());
|
||||
if (is_string(lab.target_segment, lab.offset)) {
|
||||
line += " " + get_goal_string(lab.target_segment, lab.offset / 4 - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// print type map
|
||||
if (func.has_typemaps()) {
|
||||
if (line.length() < 60) {
|
||||
line.append(60 - line.length(), ' ');
|
||||
}
|
||||
line += " tm: ";
|
||||
auto& tm = func.get_typemap_by_instr_idx(i);
|
||||
bool added = false;
|
||||
for (auto reg_kind : {Reg::RegisterKind::GPR, Reg::RegisterKind::FPR}) {
|
||||
for (int reg_idx = 0; reg_idx < 32; reg_idx++) {
|
||||
auto gpr = Register(reg_kind, reg_idx);
|
||||
auto kv = tm.find(gpr);
|
||||
if (kv != tm.end()) {
|
||||
added = true;
|
||||
line += fmt::format("{}: {}, ", gpr.to_charp(), kv->second.print());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (added) {
|
||||
line.pop_back();
|
||||
line.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
result += line + "\n";
|
||||
}
|
||||
|
||||
if (in_delay_slot) {
|
||||
result += "\n";
|
||||
in_delay_slot = false;
|
||||
}
|
||||
|
||||
if (gOpcodeInfo[(int)instr.kind].has_delay_slot) {
|
||||
in_delay_slot = true;
|
||||
}
|
||||
}
|
||||
result += "\n";
|
||||
//
|
||||
// int bid = 0;
|
||||
// for(auto& bblock : func.basic_blocks) {
|
||||
// result += "BLOCK " + std::to_string(bid++)+ "\n";
|
||||
// for(int i = bblock.start_word; i < bblock.end_word; i++) {
|
||||
// if(i >= 0 && i < func.instructions.size()) {
|
||||
// result += func.instructions.at(i).to_string(*this) + "\n";
|
||||
// } else {
|
||||
// result += "BAD BBLOCK INSTR ID " + std::to_string(i);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// hack
|
||||
if (func.cfg && !func.cfg->is_fully_resolved()) {
|
||||
result += func.cfg->to_dot();
|
||||
result += "\n";
|
||||
}
|
||||
if (func.cfg) {
|
||||
result += func.cfg->to_form_string() + "\n";
|
||||
|
||||
// To debug block stuff.
|
||||
/*
|
||||
int bid = 0;
|
||||
for(auto& block : func.basic_blocks) {
|
||||
in_delay_slot = false;
|
||||
result += "B" + std::to_string(bid++) + "\n";
|
||||
for(auto i = block.start_word; i < block.end_word; i++) {
|
||||
auto label_id = get_label_at(seg, (func.start_word + i) * 4);
|
||||
if (label_id != -1) {
|
||||
result += labels.at(label_id).name + ":\n";
|
||||
}
|
||||
auto& instr = func.instructions.at(i);
|
||||
result += " " + instr.to_string(*this) + "\n";
|
||||
if (in_delay_slot) {
|
||||
result += "\n";
|
||||
in_delay_slot = false;
|
||||
}
|
||||
|
||||
if (gOpcodeInfo[(int)instr.kind].has_delay_slot) {
|
||||
in_delay_slot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (func.ir) {
|
||||
result += ";; ir\n";
|
||||
result += func.ir->print(*this);
|
||||
}
|
||||
|
||||
result += "\n\n\n";
|
||||
result += print_function_disassembly(func, seg, write_hex, "");
|
||||
}
|
||||
|
||||
// print data
|
||||
|
@ -61,7 +61,12 @@ class LinkedObjectFile {
|
||||
std::string print_disassembly();
|
||||
bool has_any_functions();
|
||||
void append_word_to_string(std::string& dest, const LinkedWord& word) const;
|
||||
std::string to_asm_json();
|
||||
std::string to_asm_json(const std::string& obj_file_name);
|
||||
std::string print_function_disassembly(Function& func,
|
||||
int seg,
|
||||
bool write_hex,
|
||||
const std::string& extra_name);
|
||||
std::string print_asm_function_disassembly(const std::string& my_name);
|
||||
|
||||
struct Stats {
|
||||
uint32_t total_code_bytes = 0;
|
||||
|
@ -21,24 +21,29 @@
|
||||
#include "decompiler/IR/BasicOpBuilder.h"
|
||||
#include "decompiler/IR/CfgBuilder.h"
|
||||
#include "third-party/spdlog/include/spdlog/spdlog.h"
|
||||
#include "third-party/json.hpp"
|
||||
|
||||
/*!
|
||||
* Get a unique name for this object file.
|
||||
*/
|
||||
std::string ObjectFileRecord::to_unique_name() const {
|
||||
return name + "-v" + std::to_string(version);
|
||||
namespace {
|
||||
std::string strip_dgo_extension(const std::string& x) {
|
||||
auto ext = x.substr(x.length() - 4, 4);
|
||||
if (ext == ".CGO" || ext == ".cgo" || ext == ".DGO" || ext == ".dgo") {
|
||||
return x.substr(0, x.length() - 4);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
std::string ObjectFileData::to_unique_name() const {
|
||||
if (!name_from_map.empty()) {
|
||||
return name_from_map;
|
||||
}
|
||||
|
||||
if (has_multiple_versions) {
|
||||
std::string result = record.name + "-";
|
||||
auto dgo_names_sorted = dgo_names;
|
||||
std::sort(dgo_names_sorted.begin(), dgo_names_sorted.end());
|
||||
for (auto x : dgo_names_sorted) {
|
||||
auto ext = x.substr(x.length() - 4, 4);
|
||||
if (ext == ".CGO" || ext == ".cgo" || ext == ".DGO" || ext == ".dgo") {
|
||||
x = x.substr(0, x.length() - 4);
|
||||
}
|
||||
x = strip_dgo_extension(x);
|
||||
result += x + "-";
|
||||
}
|
||||
result.pop_back();
|
||||
@ -47,7 +52,7 @@ std::string ObjectFileData::to_unique_name() const {
|
||||
return record.name;
|
||||
}
|
||||
}
|
||||
ObjectFileData& ObjectFileDB::lookup_record(ObjectFileRecord rec) {
|
||||
ObjectFileData& ObjectFileDB::lookup_record(const ObjectFileRecord& rec) {
|
||||
ObjectFileData* result = nullptr;
|
||||
|
||||
for (auto& x : obj_files_by_name[rec.name]) {
|
||||
@ -65,12 +70,23 @@ ObjectFileData& ObjectFileDB::lookup_record(ObjectFileRecord rec) {
|
||||
/*!
|
||||
* Build an object file DB for the given list of DGOs.
|
||||
*/
|
||||
ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos) {
|
||||
ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
|
||||
const std::string& obj_file_name_map_file) {
|
||||
Timer timer;
|
||||
|
||||
spdlog::info("-Loading types...");
|
||||
dts.parse_type_defs({"decompiler", "config", "all-types.gc"});
|
||||
|
||||
if (!obj_file_name_map_file.empty()) {
|
||||
spdlog::info("-Loading obj name map file...");
|
||||
load_map_file(file_util::read_text_file(file_util::get_file_path({obj_file_name_map_file})));
|
||||
} else {
|
||||
spdlog::warn(
|
||||
"Not using an obj name map file! The decompiler will automatically generate object file "
|
||||
"names and write them to out/objs.txt. It is recommended to reuse this map file to get "
|
||||
"consistent naming when doing a partial decompilation.");
|
||||
}
|
||||
|
||||
spdlog::info("-Initializing ObjectFileDB...");
|
||||
for (auto& dgo : _dgos) {
|
||||
get_objs_from_dgo(dgo);
|
||||
@ -82,11 +98,36 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos) {
|
||||
spdlog::info("Total objs: {}", stats.total_obj_files);
|
||||
spdlog::info("Unique objs: {}", stats.unique_obj_files);
|
||||
spdlog::info("Unique data: {} bytes", stats.unique_obj_bytes);
|
||||
spdlog::info("Total {} ms ({:3f} MB/sec, {} obj/sec", timer.getMs(),
|
||||
spdlog::info("Total {:.2f} ms ({:.3f} MB/sec, {:.2f} obj/sec)", timer.getMs(),
|
||||
stats.total_dgo_bytes / ((1u << 20u) * timer.getSeconds()),
|
||||
stats.total_obj_files / timer.getSeconds());
|
||||
}
|
||||
|
||||
void ObjectFileDB::load_map_file(const std::string& map_data) {
|
||||
auto j = nlohmann::json::parse(map_data, nullptr, true, true);
|
||||
|
||||
for (auto& x : j) {
|
||||
auto mapped_name = x[0].get<std::string>();
|
||||
auto game_name = x[1].get<std::string>();
|
||||
auto dgo_names = x[3].get<std::vector<std::string>>();
|
||||
bool is_ag = mapped_name.find("-ag") != std::string::npos;
|
||||
auto game_name_with_ag = game_name;
|
||||
if (is_ag) {
|
||||
game_name_with_ag += "-ag";
|
||||
}
|
||||
|
||||
// add dgo
|
||||
for (auto& dgo : dgo_names) {
|
||||
auto kv = dgo_obj_name_map[dgo].find(game_name_with_ag);
|
||||
if (kv != dgo_obj_name_map[dgo].end()) {
|
||||
spdlog::error("Object {} in dgo {} occurs more than one time.", game_name_with_ag, dgo);
|
||||
assert(false);
|
||||
}
|
||||
dgo_obj_name_map[dgo][game_name_with_ag] = mapped_name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Header for a DGO file
|
||||
struct DgoHeader {
|
||||
uint32_t size;
|
||||
@ -215,6 +256,14 @@ void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
|
||||
assert(reader.bytes_left() >= obj_header.size);
|
||||
assert_string_empty_after(obj_header.name, 60);
|
||||
|
||||
if (std::string(obj_header.name).find("-ag") != std::string::npos) {
|
||||
spdlog::error(
|
||||
"Object file {} has \"-ag\" in its name. This will break any tools which use this to "
|
||||
"detect an art group",
|
||||
obj_header.name);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto name = get_object_file_name(obj_header.name, reader.here(), obj_header.size);
|
||||
|
||||
add_obj_from_dgo(name, obj_header.name, reader.here(), obj_header.size, dgo_base_name);
|
||||
@ -276,6 +325,21 @@ void ObjectFileDB::add_obj_from_dgo(const std::string& obj_name,
|
||||
data.record.version = obj_files_by_name[obj_name].size();
|
||||
data.name_in_dgo = name_in_dgo;
|
||||
data.obj_version = version;
|
||||
if (!dgo_obj_name_map.empty()) {
|
||||
auto dgo_kv = dgo_obj_name_map.find(strip_dgo_extension(dgo_name));
|
||||
if (dgo_kv == dgo_obj_name_map.end()) {
|
||||
spdlog::error("Object {} is from DGO {}, but this DGO wasn't in the map.", obj_name,
|
||||
dgo_name);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
auto name_kv = dgo_kv->second.find(obj_name);
|
||||
if (name_kv == dgo_kv->second.end()) {
|
||||
spdlog::error("Object {} from DGO {} wasn't found in the name map.", obj_name, dgo_name);
|
||||
assert(false);
|
||||
}
|
||||
data.name_from_map = name_kv->second;
|
||||
}
|
||||
obj_files_by_dgo[dgo_name].push_back(data.record);
|
||||
obj_files_by_name[obj_name].emplace_back(std::move(data));
|
||||
stats.unique_obj_files++;
|
||||
@ -421,7 +485,7 @@ void ObjectFileDB::write_object_file_words(const std::string& output_dir, bool d
|
||||
for_each_obj([&](ObjectFileData& obj) {
|
||||
if (obj.linked_data.segments == 3 || !dump_v3_only) {
|
||||
auto file_text = obj.linked_data.print_words();
|
||||
auto file_name = combine_path(output_dir, obj.record.to_unique_name() + ".txt");
|
||||
auto file_name = combine_path(output_dir, obj.to_unique_name() + ".txt");
|
||||
total_bytes += file_text.size();
|
||||
file_util::write_text_file(file_name, file_text);
|
||||
total_files++;
|
||||
@ -430,8 +494,8 @@ void ObjectFileDB::write_object_file_words(const std::string& output_dir, bool d
|
||||
|
||||
spdlog::info("Wrote object file dumps:");
|
||||
spdlog::info(" Total {} files", total_files);
|
||||
spdlog::info(" Total {:3f} MB", total_bytes / ((float)(1u << 20u)));
|
||||
spdlog::info(" Total {} ms ({:3f} MB/sec)", timer.getMs(),
|
||||
spdlog::info(" Total {:.3f} MB", total_bytes / ((float)(1u << 20u)));
|
||||
spdlog::info(" Total {} ms ({:.3f} MB/sec)", timer.getMs(),
|
||||
total_bytes / ((1u << 20u) * timer.getSeconds()));
|
||||
// printf("\n");
|
||||
}
|
||||
@ -445,12 +509,15 @@ void ObjectFileDB::write_disassembly(const std::string& output_dir,
|
||||
Timer timer;
|
||||
uint32_t total_bytes = 0, total_files = 0;
|
||||
|
||||
std::string asm_functions;
|
||||
|
||||
for_each_obj([&](ObjectFileData& obj) {
|
||||
if (obj.linked_data.has_any_functions() || disassemble_objects_without_functions) {
|
||||
auto file_text = obj.linked_data.print_disassembly();
|
||||
auto file_name = combine_path(output_dir, obj.record.to_unique_name() + ".func");
|
||||
asm_functions += obj.linked_data.print_asm_function_disassembly(obj.to_unique_name());
|
||||
auto file_name = combine_path(output_dir, obj.to_unique_name() + ".func");
|
||||
|
||||
auto json_asm_text = obj.linked_data.to_asm_json();
|
||||
auto json_asm_text = obj.linked_data.to_asm_json(obj.to_unique_name());
|
||||
auto json_asm_file_name = combine_path(output_dir, obj.to_unique_name() + "_asm.json");
|
||||
file_util::write_text_file(json_asm_file_name, json_asm_text);
|
||||
|
||||
@ -460,12 +527,15 @@ void ObjectFileDB::write_disassembly(const std::string& output_dir,
|
||||
}
|
||||
});
|
||||
|
||||
total_bytes += asm_functions.size();
|
||||
total_files++;
|
||||
file_util::write_text_file(combine_path(output_dir, "asm_functions.func"), asm_functions);
|
||||
|
||||
spdlog::info("Wrote functions dumps:");
|
||||
spdlog::info(" Total {} files", total_files);
|
||||
spdlog::info(" Total {} MB", total_bytes / ((float)(1u << 20u)));
|
||||
spdlog::info(" Total {} ms ({:3f} MB/sec)", timer.getMs(),
|
||||
spdlog::info(" Total {} ms ({:.3f} MB/sec)", timer.getMs(),
|
||||
total_bytes / ((1u << 20u) * timer.getSeconds()));
|
||||
// printf("\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -482,31 +552,31 @@ void ObjectFileDB::find_code() {
|
||||
obj.linked_data.find_functions();
|
||||
obj.linked_data.disassemble_functions();
|
||||
|
||||
if (get_config().game_version == 1 || obj.record.to_unique_name() != "effect-control-v0") {
|
||||
if (get_config().game_version == 1 || obj.to_unique_name() != "effect-control-v0") {
|
||||
obj.linked_data.process_fp_relative_links();
|
||||
} else {
|
||||
spdlog::warn("Skipping process_fp_relative_links in {}", obj.record.to_unique_name().c_str());
|
||||
spdlog::warn("Skipping process_fp_relative_links in {}", obj.to_unique_name().c_str());
|
||||
}
|
||||
|
||||
auto& obj_stats = obj.linked_data.stats;
|
||||
if (obj_stats.code_bytes / 4 > obj_stats.decoded_ops) {
|
||||
spdlog::warn("Failed to decode all in {} ({} / {})", obj.record.to_unique_name().c_str(),
|
||||
spdlog::warn("Failed to decode all in {} ({} / {})", obj.to_unique_name().c_str(),
|
||||
obj_stats.decoded_ops, obj_stats.code_bytes / 4);
|
||||
}
|
||||
combined_stats.add(obj.linked_data.stats);
|
||||
});
|
||||
|
||||
spdlog::info("Found code:");
|
||||
spdlog::info(" Code {} MB", combined_stats.code_bytes / (float)(1 << 20));
|
||||
spdlog::info(" Data {} MB", combined_stats.data_bytes / (float)(1 << 20));
|
||||
spdlog::info(" Code {:.3f} MB", combined_stats.code_bytes / (float)(1 << 20));
|
||||
spdlog::info(" Data {:.3f} MB", combined_stats.data_bytes / (float)(1 << 20));
|
||||
spdlog::info(" Functions: {}", combined_stats.function_count);
|
||||
spdlog::info(" fp uses resolved: {} / {} ({} %)", combined_stats.n_fp_reg_use_resolved,
|
||||
spdlog::info(" fp uses resolved: {} / {} ({:.3f} %)", combined_stats.n_fp_reg_use_resolved,
|
||||
combined_stats.n_fp_reg_use,
|
||||
100.f * (float)combined_stats.n_fp_reg_use_resolved / combined_stats.n_fp_reg_use);
|
||||
auto total_ops = combined_stats.code_bytes / 4;
|
||||
spdlog::info(" Decoded {} / {} ({} %)", combined_stats.decoded_ops, total_ops,
|
||||
spdlog::info(" Decoded {} / {} ({:.3f} %)", combined_stats.decoded_ops, total_ops,
|
||||
100.f * (float)combined_stats.decoded_ops / total_ops);
|
||||
spdlog::info(" Total {} ms", timer.getMs());
|
||||
spdlog::info(" Total {:.3f} ms", timer.getMs());
|
||||
// printf("\n");
|
||||
}
|
||||
|
||||
@ -523,7 +593,7 @@ void ObjectFileDB::find_and_write_scripts(const std::string& output_dir) {
|
||||
auto scripts = obj.linked_data.print_scripts();
|
||||
if (!scripts.empty()) {
|
||||
all_scripts += ";--------------------------------------\n";
|
||||
all_scripts += "; " + obj.record.to_unique_name() + "\n";
|
||||
all_scripts += "; " + obj.to_unique_name() + "\n";
|
||||
all_scripts += ";---------------------------------------\n";
|
||||
all_scripts += scripts;
|
||||
}
|
||||
@ -533,7 +603,7 @@ void ObjectFileDB::find_and_write_scripts(const std::string& output_dir) {
|
||||
file_util::write_text_file(file_name, all_scripts);
|
||||
|
||||
spdlog::info("Found scripts:");
|
||||
spdlog::info(" Total {} ms\n", timer.getMs());
|
||||
spdlog::info(" Total {:.3f} ms\n", timer.getMs());
|
||||
}
|
||||
|
||||
void ObjectFileDB::analyze_functions() {
|
||||
@ -564,41 +634,46 @@ void ObjectFileDB::analyze_functions() {
|
||||
std::unordered_map<std::string, std::unordered_set<std::string>> duplicated_functions;
|
||||
|
||||
int uid = 1;
|
||||
for_each_function([&](Function& func, int segment_id, ObjectFileData& data) {
|
||||
(void)segment_id;
|
||||
func.guessed_name.unique_id = uid++;
|
||||
auto name = func.guessed_name.to_string();
|
||||
if (func.guessed_name.expected_unique()) {
|
||||
if (unique_names.find(name) != unique_names.end()) {
|
||||
duplicated_functions[name].insert(data.record.to_unique_name());
|
||||
for_each_obj([&](ObjectFileData& data) {
|
||||
int func_in_obj = 0;
|
||||
for (int segment_id = 0; segment_id < int(data.linked_data.segments); segment_id++) {
|
||||
for (auto& func : data.linked_data.functions_by_seg.at(segment_id)) {
|
||||
func.guessed_name.unique_id = uid++;
|
||||
func.guessed_name.id_in_object = func_in_obj++;
|
||||
func.guessed_name.object_name = data.to_unique_name();
|
||||
auto name = func.guessed_name.to_string();
|
||||
|
||||
if (unique_names.find(name) != unique_names.end()) {
|
||||
duplicated_functions[name].insert(data.to_unique_name());
|
||||
}
|
||||
|
||||
unique_names.insert(name);
|
||||
|
||||
if (config.asm_functions_by_name.find(name) != config.asm_functions_by_name.end()) {
|
||||
func.warnings += "flagged as asm by config\n";
|
||||
func.suspected_asm = true;
|
||||
}
|
||||
}
|
||||
|
||||
unique_names.insert(name);
|
||||
}
|
||||
|
||||
if (config.asm_functions_by_name.find(name) != config.asm_functions_by_name.end()) {
|
||||
func.warnings += "flagged as asm by config\n";
|
||||
func.suspected_asm = true;
|
||||
}
|
||||
});
|
||||
|
||||
for_each_function([&](Function& func, int segment_id, ObjectFileData& data) {
|
||||
(void)segment_id;
|
||||
auto name = func.guessed_name.to_string();
|
||||
if (func.guessed_name.expected_unique()) {
|
||||
if (duplicated_functions.find(name) != duplicated_functions.end()) {
|
||||
duplicated_functions[name].insert(data.record.to_unique_name());
|
||||
func.warnings += "this function exists in multiple non-identical object files";
|
||||
}
|
||||
|
||||
if (duplicated_functions.find(name) != duplicated_functions.end()) {
|
||||
duplicated_functions[name].insert(data.to_unique_name());
|
||||
func.warnings += "this function exists in multiple non-identical object files";
|
||||
}
|
||||
});
|
||||
|
||||
// for(const auto& kv : duplicated_functions) {
|
||||
// printf("Function %s is found in non-identical object files:\n", kv.first.c_str());
|
||||
// for(const auto& obj : kv.second) {
|
||||
// printf(" %s\n", obj.c_str());
|
||||
// }
|
||||
// }
|
||||
/*
|
||||
for (const auto& kv : duplicated_functions) {
|
||||
printf("Function %s is found in non-identical object files:\n", kv.first.c_str());
|
||||
for (const auto& obj : kv.second) {
|
||||
printf(" %s\n", obj.c_str());
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
int total_trivial_cfg_functions = 0;
|
||||
@ -616,17 +691,20 @@ void ObjectFileDB::analyze_functions() {
|
||||
timer.start();
|
||||
int total_basic_blocks = 0;
|
||||
for_each_function([&](Function& func, int segment_id, ObjectFileData& data) {
|
||||
// printf("in %s\n", func.guessed_name.to_string().c_str());
|
||||
// printf("in %s from %s\n", func.guessed_name.to_string().c_str(),
|
||||
// data.to_unique_name().c_str());
|
||||
auto blocks = find_blocks_in_function(data.linked_data, segment_id, func);
|
||||
total_basic_blocks += blocks.size();
|
||||
func.basic_blocks = blocks;
|
||||
|
||||
total_functions++;
|
||||
if (!func.suspected_asm) {
|
||||
// run analysis
|
||||
|
||||
// first, find the prologue/epilogue
|
||||
func.analyze_prologue(data.linked_data);
|
||||
}
|
||||
|
||||
if (!func.suspected_asm) {
|
||||
// run analysis
|
||||
|
||||
// build a control flow graph
|
||||
func.cfg = build_cfg(data.linked_data, segment_id, func);
|
||||
@ -649,6 +727,9 @@ void ObjectFileDB::analyze_functions() {
|
||||
|
||||
if (func.cfg->is_fully_resolved()) {
|
||||
resolved_cfg_functions++;
|
||||
} else {
|
||||
spdlog::warn("Function {} from {} failed cfg ir", func.guessed_name.to_string(),
|
||||
data.to_unique_name());
|
||||
}
|
||||
|
||||
// type analysis
|
||||
@ -663,9 +744,11 @@ void ObjectFileDB::analyze_functions() {
|
||||
}
|
||||
// GOOD!
|
||||
func.type = kv->second;
|
||||
/*
|
||||
spdlog::info("Type Analysis on {} {}", func.guessed_name.to_string(),
|
||||
kv->second.print());
|
||||
func.run_type_analysis(kv->second, dts, data.linked_data);
|
||||
*/
|
||||
if (func.has_typemaps()) {
|
||||
successful_type_analysis++;
|
||||
}
|
||||
@ -690,24 +773,20 @@ void ObjectFileDB::analyze_functions() {
|
||||
if (!func.guessed_name.empty()) {
|
||||
total_named_functions++;
|
||||
}
|
||||
|
||||
// if (func.guessed_name.to_string() == "inspect") {
|
||||
// assert(false);
|
||||
// }
|
||||
});
|
||||
|
||||
spdlog::info("Found {} functions ({} with no control flow)", total_functions,
|
||||
total_trivial_cfg_functions);
|
||||
spdlog::info("Named {}/{} functions ({}%)", total_named_functions, total_functions,
|
||||
spdlog::info("Named {}/{} functions ({:.3f}%)", total_named_functions, total_functions,
|
||||
100.f * float(total_named_functions) / float(total_functions));
|
||||
spdlog::info("Excluding {} asm functions", asm_funcs);
|
||||
spdlog::info("Found {} basic blocks in {} ms", total_basic_blocks, timer.getMs());
|
||||
spdlog::info(" {}/{} functions passed cfg analysis stage ({}%)", resolved_cfg_functions,
|
||||
spdlog::info("Found {} basic blocks in {:.3f} ms", total_basic_blocks, timer.getMs());
|
||||
spdlog::info(" {}/{} functions passed cfg analysis stage ({:.3f}%)", resolved_cfg_functions,
|
||||
non_asm_funcs, 100.f * float(resolved_cfg_functions) / float(non_asm_funcs));
|
||||
int successful_basic_ops = total_basic_ops - total_failed_basic_ops;
|
||||
spdlog::info(" {}/{} basic ops converted successfully ({}%)", successful_basic_ops,
|
||||
spdlog::info(" {}/{} basic ops converted successfully ({:.3f}%)", successful_basic_ops,
|
||||
total_basic_ops, 100.f * float(successful_basic_ops) / float(total_basic_ops));
|
||||
spdlog::info(" {}/{} cfgs converted to ir ({}%)", successful_cfg_irs, non_asm_funcs,
|
||||
spdlog::info(" {}/{} cfgs converted to ir ({:.3f}%)", successful_cfg_irs, non_asm_funcs,
|
||||
100.f * float(successful_cfg_irs) / float(non_asm_funcs));
|
||||
spdlog::info(" {}/{} functions passed type analysis ({:.2f}%)\n", successful_type_analysis,
|
||||
non_asm_funcs, 100.f * float(successful_type_analysis) / float(non_asm_funcs));
|
||||
|
@ -21,10 +21,9 @@
|
||||
* A "record" which can be used to identify an object file.
|
||||
*/
|
||||
struct ObjectFileRecord {
|
||||
std::string name;
|
||||
std::string name; // including -ag, not including dgo suffix
|
||||
int version = -1;
|
||||
uint32_t hash = 0;
|
||||
std::string to_unique_name() const;
|
||||
};
|
||||
|
||||
/*!
|
||||
@ -38,13 +37,14 @@ struct ObjectFileData {
|
||||
int obj_version = -1;
|
||||
bool has_multiple_versions = false;
|
||||
std::string name_in_dgo;
|
||||
std::string name_from_map;
|
||||
std::string to_unique_name() const;
|
||||
uint32_t reference_count = 0; // number of times its used.
|
||||
};
|
||||
|
||||
class ObjectFileDB {
|
||||
public:
|
||||
ObjectFileDB(const std::vector<std::string>& _dgos);
|
||||
ObjectFileDB(const std::vector<std::string>& _dgos, const std::string& obj_file_name_map_file);
|
||||
std::string generate_dgo_listing();
|
||||
std::string generate_obj_listing();
|
||||
void process_link_data();
|
||||
@ -55,10 +55,11 @@ class ObjectFileDB {
|
||||
void write_object_file_words(const std::string& output_dir, bool dump_v3_only);
|
||||
void write_disassembly(const std::string& output_dir, bool disassemble_objects_without_functions);
|
||||
void analyze_functions();
|
||||
ObjectFileData& lookup_record(ObjectFileRecord rec);
|
||||
ObjectFileData& lookup_record(const ObjectFileRecord& rec);
|
||||
DecompilerTypeSystem dts;
|
||||
|
||||
private:
|
||||
void load_map_file(const std::string& map_data);
|
||||
void get_objs_from_dgo(const std::string& filename);
|
||||
void add_obj_from_dgo(const std::string& obj_name,
|
||||
const std::string& name_in_dgo,
|
||||
@ -105,6 +106,7 @@ class ObjectFileDB {
|
||||
std::unordered_map<std::string, std::vector<ObjectFileRecord>> obj_files_by_dgo;
|
||||
|
||||
std::vector<std::string> obj_file_order;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, std::string>> dgo_obj_name_map;
|
||||
|
||||
struct {
|
||||
uint32_t total_dgo_bytes = 0;
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include "third-party/json.hpp"
|
||||
#include "util/FileIO.h"
|
||||
#include "common/util/FileUtil.h"
|
||||
#include "third-party/spdlog/include/spdlog/spdlog.h"
|
||||
|
||||
Config gConfig;
|
||||
|
||||
@ -17,6 +16,9 @@ void set_config(const std::string& path_to_config_file) {
|
||||
|
||||
gConfig.game_version = cfg.at("game_version").get<int>();
|
||||
gConfig.dgo_names = cfg.at("dgo_names").get<std::vector<std::string>>();
|
||||
if (cfg.contains("obj_file_name_map_file")) {
|
||||
gConfig.obj_file_name_map_file = cfg.at("obj_file_name_map_file").get<std::string>();
|
||||
}
|
||||
gConfig.write_disassembly = cfg.at("write_disassembly").get<bool>();
|
||||
gConfig.write_hexdump = cfg.at("write_hexdump").get<bool>();
|
||||
gConfig.write_scripts = cfg.at("write_scripts").get<bool>();
|
||||
|
@ -10,6 +10,7 @@
|
||||
struct Config {
|
||||
int game_version = -1;
|
||||
std::vector<std::string> dgo_names;
|
||||
std::string obj_file_name_map_file;
|
||||
bool write_disassembly = false;
|
||||
bool write_hexdump = false;
|
||||
bool write_scripts = false;
|
||||
|
@ -3,14 +3,14 @@
|
||||
{
|
||||
"game_version":1,
|
||||
// the order here matters. KERNEL and GAME should go first
|
||||
"dgo_names":["CGO/KERNEL.CGO", "CGO/GAME.CGO"],
|
||||
/*, "CGO/ENGINE.CGO"
|
||||
"dgo_names":["CGO/KERNEL.CGO", "CGO/GAME.CGO"
|
||||
, "CGO/ENGINE.CGO"
|
||||
, "CGO/ART.CGO", "DGO/BEA.DGO", "DGO/CIT.DGO", "CGO/COMMON.CGO", "DGO/DAR.DGO", "DGO/DEM.DGO",
|
||||
"DGO/FIN.DGO", "DGO/INT.DGO", "DGO/JUB.DGO", "DGO/JUN.DGO", "CGO/JUNGLE.CGO", "CGO/L1.CGO", "DGO/FIC.DGO",
|
||||
"DGO/LAV.DGO", "DGO/MAI.DGO", "CGO/MAINCAVE.CGO", "DGO/MIS.DGO", "DGO/OGR.DGO", "CGO/RACERP.CGO", "DGO/ROB.DGO", "DGO/ROL.DGO",
|
||||
"DGO/SNO.DGO", "DGO/SUB.DGO", "DGO/SUN.DGO", "CGO/SUNKEN.CGO", "DGO/SWA.DGO", "DGO/TIT.DGO", "DGO/TRA.DGO", "DGO/VI1.DGO",
|
||||
"DGO/VI2.DGO", "DGO/VI3.DGO", "CGO/VILLAGEP.CGO", "CGO/WATER-AN.CGO"
|
||||
],*/
|
||||
],
|
||||
|
||||
"write_disassembly":true,
|
||||
"write_hex_near_instructions":false,
|
||||
@ -22,211 +22,412 @@
|
||||
// to write out hexdump on the v3 only, to avoid the huge level data files
|
||||
"write_hexdump_on_v3_only":true,
|
||||
|
||||
// to write out "scripts", which are currently just all the linked lists found
|
||||
"write_scripts":true,
|
||||
// to write out "scripts", which are currently just all the linked lists found. mostly a jak 2/3 thing
|
||||
"write_scripts":false,
|
||||
|
||||
// optional: a predetermined object file name map from a file. Useful if you want to run only on some DGOs but have consistent names
|
||||
"obj_file_name_map_file":"goal_src/build/all_objs.txt",
|
||||
|
||||
// Experimental Stuff
|
||||
"find_basic_blocks":true,
|
||||
|
||||
"asm_functions_by_name":[
|
||||
// functions which have inline assembly
|
||||
"unpack-comp-huf", "(method 29 collide-shape-prim-group)","find-knot-span","dma-send-no-scratch",
|
||||
"raw-ray-sphere-intersect","(method 9 bounding-box)","(method 9 matrix)","shadow-find-single-edges",
|
||||
"generic-tie-dma-to-spad-sync","ray-cylinder-intersect","shadow-scissor-edges","(method 42 collide-shape)",
|
||||
"(method 9 texture-page-dir)",
|
||||
"(method 24 collide-shape-prim)",
|
||||
"(method 23 collide-shape-prim-group)",
|
||||
"shadow-find-double-edges",
|
||||
"(method 16 collide-shape-prim)",
|
||||
"(method 15 collide-shape-prim-group)",
|
||||
"generic-tie-upload-next",
|
||||
"(method 17 collide-edge-work)",
|
||||
"(method 16 drawable-tree)",
|
||||
"(method 10 collide-mesh)",
|
||||
"particle-adgif",
|
||||
"(method 14 collide-shape-prim-group)",
|
||||
"(method 12 collide-shape-prim-group)",
|
||||
"(method 14 bounding-box)",
|
||||
"process-drawable-birth-fuel-cell",
|
||||
"(method 13 collide-shape-prim-group)",
|
||||
"ray-triangle-intersect",
|
||||
"(method 20 collide-shape-prim-group)",
|
||||
"(method 10 collide-puss-work)",
|
||||
"setup-blerc-chains-for-one-fragment",
|
||||
"curve-evaluate!",
|
||||
"(method 16 collide-edge-work)",
|
||||
"(method 9 collide-cache-prim)",
|
||||
"(method 11 collide-mesh)",
|
||||
"stats-tfrag-asm",
|
||||
"(method 10 collide-cache-prim)",
|
||||
"high-speed-reject",
|
||||
"(method 12 collide-mesh)",
|
||||
"(method 19 collide-cache)",
|
||||
"(method 9 collide-puss-work)",
|
||||
"(method 29 collide-cache)",
|
||||
"time-of-day-interp-colors-scratch",
|
||||
"(method 30 collide-cache)",
|
||||
"calc-animation-from-spr",
|
||||
"(method 14 collide-shape-prim-mesh)",
|
||||
"(method 12 collide-shape-prim-mesh)",
|
||||
"(method 19 process-drawable)",
|
||||
"(method 13 collide-shape-prim-mesh)",
|
||||
"moving-sphere-triangle-intersect",
|
||||
"(method 14 collide-mesh)",
|
||||
"circle-circle-xz-intersect",
|
||||
"get-string-length",
|
||||
"draw-node-cull",
|
||||
"collide-probe-node",
|
||||
"(method 28 collide-cache)",
|
||||
"(method 26 collide-cache)",
|
||||
"load-game-text-info",
|
||||
"(method 27 collide-cache)",
|
||||
"clip-polygon-against-positive-hyperplane",
|
||||
"sp-process-block-2d",
|
||||
"sp-init-fields!",
|
||||
"clip-polygon-against-negative-hyperplane",
|
||||
"(method 9 edge-grab-info)",
|
||||
"(method 18 collide-edge-work)",
|
||||
"sp-process-block-3d",
|
||||
"time-of-day-interp-colors",
|
||||
"(method 23 collide-shape-prim-sphere)",
|
||||
"(method 15 collide-edge-work)",
|
||||
"(method 15 collide-mesh)",
|
||||
"(method 21 collide-cache)",
|
||||
"mercneric-shader-asm",
|
||||
"shadow-execute",
|
||||
"(method 16 level)",
|
||||
"(method 40 collide-shape)",
|
||||
"(method 32 collide-cache)",
|
||||
"bones-mtx-calc",
|
||||
"draw-inline-array-prototype-tie-near-asm",
|
||||
"decompress-fixed-data-to-accumulator",
|
||||
"draw-inline-array-prototype-tie-asm",
|
||||
"(method 10 external-art-buffer)",
|
||||
"level-update-after-load",
|
||||
"draw-inline-array-prototype-tie-generic-asm",
|
||||
"draw-inline-array-tfrag-near",
|
||||
"collide-probe-instance-tie",
|
||||
"draw-inline-array-tfrag",
|
||||
"mercneric-matrix-asm",
|
||||
"(method 32 nav-control)",
|
||||
"(method 11 fact-info-target)",
|
||||
"mercneric-convert",
|
||||
"generic-envmap-only-proc",
|
||||
"draw-inline-array-instance-tie",
|
||||
"generic-tie-convert-proc",
|
||||
"draw-string",
|
||||
"draw-inline-array-instance-shrub",
|
||||
"generic-tie-convert",
|
||||
"(anon-function 2503)",
|
||||
"(anon-function 5635)",
|
||||
"(anon-function 2504)",
|
||||
"(anon-function 2502)",
|
||||
"(anon-function 2501)",
|
||||
"(anon-function 2505)",
|
||||
"(anon-function 2500)",
|
||||
"(anon-function 3717)",
|
||||
"rand-uint31-gen",
|
||||
"dma-sync-with-count",
|
||||
"ripple-create-wave-table",
|
||||
"generic-debug-light-proc",
|
||||
"draw-bones-hud",
|
||||
"(method 27 ropebridge)",
|
||||
"ocean-interp-wave",
|
||||
"ocean-generate-verts",
|
||||
"draw-large-polygon-ocean",
|
||||
"(method 23 collide-shape-prim-mesh)",
|
||||
"(method 13 collide-mesh)",
|
||||
"draw-boundary-polygon",
|
||||
"draw-large-polygon",
|
||||
"update-mood-lava",
|
||||
"update-mood-lightning",
|
||||
"memcpy",
|
||||
"background-upload-vu0",
|
||||
"upload-vis-bits",
|
||||
"generic-envmap-dproc",
|
||||
"generic-prepare-dma-double",
|
||||
"generic-envmap-proc",
|
||||
"generic-light-proc",
|
||||
"generic-merc-execute-asm",
|
||||
"generic-merc-init-asm",
|
||||
"shadow-calc-dual-verts",
|
||||
"shadow-scissor-top",
|
||||
"shadow-find-facing-single-tris",
|
||||
"shadow-find-facing-double-tris",
|
||||
"shadow-add-verts",
|
||||
"shadow-add-facing-single-tris",
|
||||
"shadow-add-single-edges",
|
||||
"shadow-add-double-tris",
|
||||
"shadow-add-double-edges",
|
||||
"test-func",
|
||||
"(method 14 collide-cache)",
|
||||
"symlink2",
|
||||
"draw-bones-merc",
|
||||
"dma-count-until-done",
|
||||
"symlink3",
|
||||
"blerc-execute",
|
||||
"merc-dma-chain-to-spr",
|
||||
"ripple-matrix-scale",
|
||||
"ripple-apply-wave-table",
|
||||
"ripple-execute-init",
|
||||
"bones-mtx-calc-execute",
|
||||
"texscroll-execute",
|
||||
"generic-light",
|
||||
"generic-no-light",
|
||||
"generic-no-light+envmap",
|
||||
"generic-dma-from-spr",
|
||||
"upload-vu0-program",
|
||||
"generic-merc-execute-all",
|
||||
"closest-pt-in-triangle",
|
||||
"(method 11 sparticle-launch-control)",
|
||||
"(anon-function 3751)",
|
||||
"look-for-points-of-interest",
|
||||
"asm_functions_by_name":[
|
||||
// gcommon
|
||||
"quad-copy!",
|
||||
|
||||
// gcommon
|
||||
"(method 2 vec4s)", "quad-copy!", "(method 3 vec4s)", "breakpoint-range-set!",
|
||||
// gkernel
|
||||
"(method 11 cpu-thread)",
|
||||
|
||||
// pskernel
|
||||
"resend-exception", "kernel-set-interrupt-vector", "kernel-set-exception-vector", "return-from-exception",
|
||||
"kernel-read", "kernel-read-function", "kernel-write", "kernel-write-function", "kernel-copy-to-kernel-ram",
|
||||
// pskernel
|
||||
"return-from-exception", // F: eret
|
||||
"kernel-read-function", // F: delay slot tricks
|
||||
"kernel-write-function", // F: delay slot tricks
|
||||
"kernel-copy-function",
|
||||
|
||||
// this one needs more investigation. nothing looks weird about it but it fails...
|
||||
"camera-change-to",
|
||||
// math
|
||||
"rand-uint31-gen",
|
||||
|
||||
// two back to back arithmetic shifts...
|
||||
"texture-relocate",
|
||||
// bounding box
|
||||
"(method 9 bounding-box)", // F: asm branching
|
||||
"(method 14 bounding-box)",
|
||||
|
||||
// this one fails due to false compaction where an else case has only a not expression in it.
|
||||
"master-is-hopeful-better?",
|
||||
// matrix
|
||||
"(method 9 matrix)", // F: asm branching
|
||||
"matrix-axis-sin-cos!", // F: asm branching
|
||||
"matrix-axis-sin-cos-vu!",
|
||||
|
||||
// fails for unknown reason
|
||||
"target-falling-anim-trans", "change-brother",
|
||||
// geometry
|
||||
"curve-evaluate!", // BUG: cfg fails, suspected weird gotos
|
||||
"circle-circle-xz-intersect", // F: asm branching
|
||||
"closest-pt-in-triangle", // F: asm branching
|
||||
"find-knot-span", // ??
|
||||
"vector-segment-distance-point!",
|
||||
|
||||
// merged right typecase... can probably handle this
|
||||
"cspace-inspect-tree",
|
||||
// trigonometry
|
||||
"exp", // BUG: cfg is wrong.
|
||||
"atan0", // P: manual use of stack
|
||||
"sincos!", // P: manual use of stack
|
||||
"sincos-rad!",
|
||||
|
||||
// these are all valid, but use short circuiting branches in strange ways. There's probably a few compiler uses that we're not
|
||||
"(method 21 actor-link-info)","(method 20 actor-link-info)","(method 28 collide-shape-prim-mesh)", "(method 35 collide-shape)",
|
||||
"debug-menu-item-var-render", "(method 14 level)","add-blue-motion","anim-tester-add-newobj","(method 27 orb-cache-top)",
|
||||
// dma-h
|
||||
"dma-count-until-done", // F: asm branching
|
||||
"dma-sync-with-count", // F: asm branching
|
||||
"dma-send-no-scratch", // F: asm branching
|
||||
"dma-sync-fast",
|
||||
|
||||
// real asm
|
||||
"cspace<-parented-transformq-joint!", "blerc-a-fragment", "render-boundary-tri", "render-boundary-quad",
|
||||
"(method 19 collide-shape-prim-sphere)","vector-segment-distance-point!", "exp", "(method 11 collide-mesh-cache)",
|
||||
"(method 13 collide-edge-work)", "ambient-inspect",
|
||||
// dma
|
||||
"symlink3", // F: asm branching
|
||||
"symlink2", // F: asm branching
|
||||
"dma-sync-hang",
|
||||
|
||||
"(method 11 cpu-thread)", "atan0", "sincos!", "sincos-rad!", "disasm-dma-list", "vblank-handler", "vif1-handler",
|
||||
"vif1-handler-debug", "entity-actor-count", "decompress-frame-data-pair-to-accumulator",
|
||||
"decompress-frame-data-to-accumulator", "normalize-frame-quaternions", "clear-frame-accumulator",
|
||||
"generic-copy-vtx-dclr-dtex", "generic-no-light-dproc-only", "generic-no-light-proc", "mercneric-bittable-asm",
|
||||
"generic-tie-decompress", "matrix-axis-sin-cos!", "matrix-axis-sin-cos-vu!", "generic-prepare-dma-single",
|
||||
"(method 13 collide-shape-prim-sphere)", "(method 14 collide-shape-prim-sphere)", "(method 12 collide-shape-prim-sphere)",
|
||||
"adgif-shader<-texture-with-update!", "generic-interp-dproc", "sprite-draw-distorters", "draw-bones", "(method 9 collide-mesh-cache)",
|
||||
"(method 18 collide-shape-prim-sphere)","birth-pickup-at-point",
|
||||
// dma-disasm (BUG)
|
||||
"disasm-dma-list",
|
||||
|
||||
"collide-do-primitives", "draw-bones-check-longest-edge-asm",
|
||||
"sp-launch-particles-var", "(method 15 collide-shape-prim-mesh)", "(method 15 collide-shape-prim-sphere)",
|
||||
"(method 45 collide-shape)", "cam-layout-save-cam-trans", "kernel-copy-function", "dma-sync-hang", "generic-no-light-dproc",
|
||||
"dma-sync-fast", "bsp-camera-asm",
|
||||
"generic-none-dma-wait", "unpack-comp-rle", "level-remap-texture", "(method 10 collide-edge-hold-list)"
|
||||
]
|
||||
// display
|
||||
"vblank-handler", // F: weird asm for interrupt handler
|
||||
"vif1-handler", // F: weird asm for interrupt handler
|
||||
"vif1-handler-debug",
|
||||
|
||||
// texture
|
||||
"adgif-shader<-texture-with-update!", // F: asm branching
|
||||
"(method 9 texture-page-dir)",
|
||||
|
||||
// collide-mesh-h
|
||||
"(method 11 collide-mesh-cache)",
|
||||
|
||||
// actor-link-h (BUG)
|
||||
"(method 21 actor-link-info)", // BUG: sc cfg / cfg-ir bug
|
||||
"(method 20 actor-link-info)",
|
||||
|
||||
// collide-func
|
||||
"moving-sphere-triangle-intersect", // P: weird branching
|
||||
"collide-do-primitives", // P: asm branching
|
||||
"ray-triangle-intersect", // F: asm branching
|
||||
"ray-cylinder-intersect", // F: asm branching
|
||||
"raw-ray-sphere-intersect",
|
||||
|
||||
// joint
|
||||
"calc-animation-from-spr", // F: asm branching
|
||||
"decompress-frame-data-pair-to-accumulator", // P: asm calling
|
||||
"decompress-frame-data-to-accumulator", // P: asm calling
|
||||
"decompress-fixed-data-to-accumulator", // P: asm calling
|
||||
"normalize-frame-quaternions", // F: asm branching, return
|
||||
"clear-frame-accumulator", // F: asm branching
|
||||
"cspace<-parented-transformq-joint!",
|
||||
|
||||
// bsp
|
||||
"level-remap-texture", // BUG: probably missing branch case?
|
||||
"bsp-camera-asm", // F: asm branching
|
||||
"sprite-draw-distorters",
|
||||
|
||||
// merc-blend-shape
|
||||
"setup-blerc-chains-for-one-fragment", // F: asm branching
|
||||
"blerc-execute", // F: asm branching
|
||||
"merc-dma-chain-to-spr", // F: asm branching
|
||||
"blerc-a-fragment",
|
||||
|
||||
// ripple
|
||||
"ripple-matrix-scale",
|
||||
"ripple-apply-wave-table",
|
||||
"ripple-create-wave-table",
|
||||
"ripple-execute-init",
|
||||
|
||||
// bones
|
||||
"draw-bones-hud",
|
||||
"draw-bones",
|
||||
"draw-bones-check-longest-edge-asm",
|
||||
"draw-bones-merc",
|
||||
"bones-mtx-calc-execute",
|
||||
"bones-mtx-calc",
|
||||
"texscroll-execute",
|
||||
|
||||
// generic-effect
|
||||
"generic-debug-light-proc",
|
||||
"generic-none-dma-wait",
|
||||
"generic-copy-vtx-dclr-dtex",
|
||||
"generic-light",
|
||||
"generic-envmap-only-proc",
|
||||
"generic-no-light",
|
||||
"generic-no-light+envmap",
|
||||
"generic-no-light-dproc",
|
||||
"generic-no-light-dproc-only",
|
||||
"generic-no-light-proc",
|
||||
"generic-interp-dproc",
|
||||
"generic-envmap-dproc",
|
||||
"generic-prepare-dma-single",
|
||||
"generic-prepare-dma-double",
|
||||
"generic-envmap-proc",
|
||||
"generic-light-proc",
|
||||
"generic-dma-from-spr",
|
||||
"upload-vu0-program",
|
||||
|
||||
// generic-merc
|
||||
"generic-merc-execute-all",
|
||||
"generic-merc-execute-asm",
|
||||
"high-speed-reject",
|
||||
"mercneric-convert",
|
||||
"mercneric-bittable-asm",
|
||||
"mercneric-shader-asm",
|
||||
"mercneric-matrix-asm",
|
||||
"generic-merc-init-asm",
|
||||
|
||||
// generic-tie
|
||||
"generic-tie-convert",
|
||||
"generic-tie-convert-proc",
|
||||
"generic-tie-upload-next",
|
||||
"generic-tie-decompress",
|
||||
"generic-tie-dma-to-spad-sync",
|
||||
|
||||
// shadow-cpu
|
||||
"shadow-execute",
|
||||
"shadow-add-double-edges",
|
||||
"shadow-add-double-tris",
|
||||
"shadow-add-single-edges",
|
||||
"shadow-add-facing-single-tris",
|
||||
"shadow-add-verts",
|
||||
"shadow-find-double-edges",
|
||||
"shadow-find-facing-double-tris",
|
||||
"shadow-find-single-edges",
|
||||
"shadow-find-facing-single-tris",
|
||||
"shadow-scissor-top",
|
||||
"shadow-scissor-edges",
|
||||
"shadow-calc-dual-verts",
|
||||
|
||||
// font
|
||||
"get-string-length",
|
||||
"draw-string",
|
||||
|
||||
// decomp
|
||||
"(method 16 level)", // BUG: cfg fails
|
||||
"unpack-comp-huf",
|
||||
"unpack-comp-rle",
|
||||
|
||||
// background
|
||||
"upload-vis-bits",
|
||||
"background-upload-vu0",
|
||||
|
||||
// draw-node
|
||||
"draw-node-cull",
|
||||
|
||||
// shrubbery
|
||||
"test-func",
|
||||
"draw-inline-array-instance-shrub",
|
||||
|
||||
// tfrag
|
||||
"stats-tfrag-asm",
|
||||
"draw-inline-array-tfrag-near",
|
||||
"draw-inline-array-tfrag",
|
||||
|
||||
// tie-methods
|
||||
"draw-inline-array-prototype-tie-near-asm",
|
||||
"draw-inline-array-prototype-tie-asm",
|
||||
"draw-inline-array-prototype-tie-generic-asm",
|
||||
"draw-inline-array-instance-tie",
|
||||
|
||||
// sparticle-launcher
|
||||
"(method 11 sparticle-launch-control)", // BUG: cfg ir
|
||||
"sp-launch-particles-var",
|
||||
"particle-adgif",
|
||||
"sp-init-fields!",
|
||||
|
||||
// sparticle
|
||||
"memcpy",
|
||||
"sp-process-block-3d",
|
||||
"sp-process-block-2d",
|
||||
|
||||
// loader BUG
|
||||
"(method 10 external-art-buffer)",
|
||||
|
||||
// game-info BUG
|
||||
"(method 11 fact-info-target)",
|
||||
|
||||
// game-save BUG
|
||||
"(anon-function 5 game-save)", // BUG:
|
||||
"(anon-function 6 game-save)", // BUG:
|
||||
"(anon-function 7 game-save)", // BUG:
|
||||
"(anon-function 8 game-save)", // BUG:
|
||||
"(anon-function 9 game-save)", // BUG:
|
||||
"(anon-function 10 game-save)",
|
||||
|
||||
// mood BUG
|
||||
"update-mood-lava", // BUG:
|
||||
"update-mood-lightning",
|
||||
|
||||
// time-of-day
|
||||
"time-of-day-interp-colors-scratch",
|
||||
"time-of-day-interp-colors",
|
||||
|
||||
// sky-tng
|
||||
"clip-polygon-against-negative-hyperplane",
|
||||
"clip-polygon-against-positive-hyperplane",
|
||||
"draw-large-polygon",
|
||||
|
||||
// load-boundary
|
||||
"render-boundary-tri",
|
||||
"render-boundary-quad",
|
||||
"draw-boundary-polygon",
|
||||
|
||||
// level BUG
|
||||
"level-update-after-load",
|
||||
|
||||
// text BUG
|
||||
"load-game-text-info",
|
||||
|
||||
// collide-probe
|
||||
"collide-probe-instance-tie",
|
||||
"collide-probe-node",
|
||||
|
||||
// collide-mesh
|
||||
"(method 10 collide-mesh)",
|
||||
"(method 13 collide-mesh)",
|
||||
"(method 9 collide-mesh-cache)",
|
||||
"(method 15 collide-mesh)",
|
||||
"(method 14 collide-mesh)",
|
||||
"(method 11 collide-mesh)",
|
||||
"(method 12 collide-mesh)",
|
||||
|
||||
// collide-edge-grab
|
||||
"(method 13 collide-edge-work)",
|
||||
"(method 17 collide-edge-work)",
|
||||
"(method 15 collide-edge-work)",
|
||||
"(method 16 collide-edge-work)",
|
||||
"(method 9 edge-grab-info)", // maybe bug
|
||||
"(method 18 collide-edge-work)",
|
||||
"(method 10 collide-edge-hold-list)",
|
||||
|
||||
// collide-shape
|
||||
"(method 15 collide-shape-prim-mesh)", // BUG:
|
||||
"(method 15 collide-shape-prim-sphere)", // BUG:
|
||||
"(method 16 collide-shape-prim)",
|
||||
"(method 15 collide-shape-prim-group)",
|
||||
"(method 40 collide-shape)",
|
||||
"(method 45 collide-shape)",
|
||||
"(method 28 collide-shape-prim-mesh)", // BUG:
|
||||
"(method 29 collide-shape-prim-group)",
|
||||
"(method 20 collide-shape-prim-group)",
|
||||
"(method 19 collide-shape-prim-sphere)",
|
||||
"(method 18 collide-shape-prim-sphere)",
|
||||
"(method 23 collide-shape-prim-sphere)",
|
||||
"(method 23 collide-shape-prim-mesh)", // BUG: maybe
|
||||
"(method 24 collide-shape-prim)",
|
||||
"(method 23 collide-shape-prim-group)",
|
||||
"(method 42 collide-shape)",
|
||||
|
||||
// collide-shape-rider
|
||||
"(method 35 collide-shape)",
|
||||
|
||||
// cam-master BUG
|
||||
"master-is-hopeful-better?",
|
||||
|
||||
// cam-layout BUG
|
||||
"cam-layout-save-cam-trans",
|
||||
|
||||
// process-drawable BUG
|
||||
"cspace-inspect-tree", // BUG:
|
||||
"process-drawable-birth-fuel-cell", // BUG:
|
||||
"(method 19 process-drawable)",
|
||||
|
||||
// ambient
|
||||
"ambient-inspect",
|
||||
|
||||
// generic-obs BUG
|
||||
"camera-change-to",
|
||||
|
||||
// target BUG
|
||||
"target-falling-anim-trans",
|
||||
|
||||
// target2 BUG
|
||||
"(anon-function 33 target2)", // BUG:
|
||||
"(anon-function 67 target2)", // BUG:
|
||||
"look-for-points-of-interest",
|
||||
|
||||
// menu BUG
|
||||
"debug-menu-item-var-render",
|
||||
|
||||
// drawable-tree
|
||||
"(method 16 drawable-tree)",
|
||||
|
||||
// collide-cache
|
||||
"(method 10 collide-puss-work)",
|
||||
"(method 9 collide-puss-work)",
|
||||
"(method 19 collide-cache)",
|
||||
"(method 10 collide-cache-prim)",
|
||||
"(method 9 collide-cache-prim)",
|
||||
"(method 30 collide-cache)",
|
||||
"(method 13 collide-shape-prim-group)",
|
||||
"(method 13 collide-shape-prim-sphere)",
|
||||
"(method 13 collide-shape-prim-mesh)",
|
||||
"(method 14 collide-shape-prim-group)",
|
||||
"(method 14 collide-shape-prim-sphere)",
|
||||
"(method 14 collide-shape-prim-mesh)",
|
||||
"(method 12 collide-shape-prim-group)", // BUG: maybe
|
||||
"(method 12 collide-shape-prim-sphere)",
|
||||
"(method 12 collide-shape-prim-mesh)",
|
||||
"(method 29 collide-cache)",
|
||||
"(method 27 collide-cache)",
|
||||
"(method 14 collide-cache)",
|
||||
"(method 28 collide-cache)",
|
||||
"(method 26 collide-cache)",
|
||||
"(method 21 collide-cache)",
|
||||
"(method 32 collide-cache)",
|
||||
|
||||
// memory-usage BUG
|
||||
"(method 14 level)",
|
||||
|
||||
// navigate BUG
|
||||
"(method 32 nav-control)",
|
||||
|
||||
// collectables BUG
|
||||
"birth-pickup-at-point",
|
||||
"add-blue-motion",
|
||||
|
||||
// ocean
|
||||
"draw-large-polygon-ocean",
|
||||
|
||||
// ocean-vu0
|
||||
"ocean-generate-verts",
|
||||
"ocean-interp-wave",
|
||||
|
||||
// anim-tester BUG
|
||||
"anim-tester-add-newobj",
|
||||
|
||||
// nav-enemy BUG
|
||||
"(anon-function 28 nav-enemy)",
|
||||
|
||||
// orb-cache BUG
|
||||
"(method 27 orb-cache-top)",
|
||||
|
||||
// ropebridge BUG
|
||||
"(method 27 ropebridge)",
|
||||
|
||||
// all unchecked.and in level DGO code
|
||||
"(anon-function 11 robotboss)",
|
||||
"(anon-function 18 robotboss)",
|
||||
"(anon-function 49 robotboss)",
|
||||
"(anon-function 21 plant-boss)",
|
||||
"(anon-function 10 ice-cube)",
|
||||
"(anon-function 15 ice-cube)",
|
||||
"(anon-function 45 lavatube-energy)",
|
||||
"(anon-function 5 game-save)",
|
||||
"(anon-function 6 game-save)",
|
||||
"(anon-function 7 game-save)",
|
||||
"(anon-function 8 game-save)",
|
||||
"(anon-function 9 game-save)",
|
||||
"(anon-function 10 game-save)",
|
||||
"(anon-function 28 nav-enemy)",
|
||||
"mistycannon-find-best-solution",
|
||||
"target-flut-falling-anim-trans",
|
||||
"kermit-check-to-hit-player?",
|
||||
"(anon-function 6 title-obs)",
|
||||
"(anon-function 36 mistycannon)",
|
||||
"(anon-function 5 battlecontroller)",
|
||||
"(anon-function 43 maincave-obs)",
|
||||
"(anon-function 2 target-tube)",
|
||||
"(anon-function 5 orbit-plat)",
|
||||
"(anon-function 2 ogreboss)"
|
||||
|
||||
|
||||
|
||||
|
||||
]
|
||||
}
|
@ -208,7 +208,7 @@ class ObjectFileView(QDialog):
|
||||
self.asm_pane.setModel(asm_model)
|
||||
self.warnings_label.setText(func["warnings"])
|
||||
self.asm_display.setPlainText("")
|
||||
self.function_header_label.setText("{}, type: {}".format(name, func["type"]))
|
||||
self.function_header_label.setText("{}, type: {}\nfunc: {} obj: {}".format(name, func["type"], func["name"], func["parent_object"]))
|
||||
|
||||
def basic_op_clicked(self, item):
|
||||
text = ""
|
||||
@ -227,6 +227,9 @@ class ObjectFileView(QDialog):
|
||||
|
||||
for i in range(asm_idx, self.basic_id_to_asm[item.row() + 1]):
|
||||
text += self.functions_by_name[self.current_function]["asm"][i]["asm_op"] + "\n"
|
||||
op = self.functions_by_name[self.current_function]["asm"][asm_idx]
|
||||
if "referenced_string" in op:
|
||||
text += op["referenced_string"]
|
||||
self.asm_display.setPlainText(text)
|
||||
self.asm_display.setFont(get_monospaced_font())
|
||||
self.asm_pane.setCurrentIndex(self.asm_pane.model().index(asm_idx, 0))
|
||||
|
@ -33,7 +33,7 @@ int main(int argc, char** argv) {
|
||||
dgos.push_back(combine_path(in_folder, dgo_name));
|
||||
}
|
||||
|
||||
ObjectFileDB db(dgos);
|
||||
ObjectFileDB db(dgos, get_config().obj_file_name_map_file);
|
||||
file_util::write_text_file(combine_path(out_folder, "dgo.txt"), db.generate_dgo_listing());
|
||||
file_util::write_text_file(combine_path(out_folder, "obj.txt"), db.generate_obj_listing());
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
["gcommon", "gcommon", 3, ["KERNEL"], "kernel"],
|
||||
[["gcommon", "gcommon", 3, ["KERNEL"], "kernel"],
|
||||
["gstring-h", "gstring-h", 3, ["KERNEL"], "kernel"],
|
||||
["gkernel-h", "gkernel-h", 3, ["KERNEL"], "kernel"],
|
||||
["gkernel", "gkernel", 3, ["KERNEL"], "kernel"],
|
||||
@ -1084,4 +1084,4 @@
|
||||
["vil3-bridge-36-ag", "vil3-bridge-36", 4, ["VI3"], "levels/village3"],
|
||||
["water-anim-village3-ag", "water-anim-village3", 4, ["VI3"], "levels/village3"],
|
||||
["village3-vis", "village3-vis", 4, ["VI3"], "levels/village3"],
|
||||
["lava", "lava", 3, ["WATER-AN"], "old/lava"]
|
||||
["lava", "lava", 3, ["WATER-AN"], "old/lava"]]
|
Loading…
Reference in New Issue
Block a user