[decompiler] Clean up config more (#458)

* remove global config

* fix dir
This commit is contained in:
water111 2021-05-11 20:49:54 -04:00 committed by GitHub
parent d7d563814f
commit 0599d144f8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 926 additions and 690 deletions

View file

@ -727,7 +727,8 @@ int detect(int idx, Function& function, LinkedObjectFile& file, TypeInspectorRes
TypeInspectorResult inspect_inspect_method(Function& inspect,
const std::string& type_name,
DecompilerTypeSystem& dts,
LinkedObjectFile& file) {
LinkedObjectFile& file,
bool skip_fields) {
TypeInspectorResult result;
TypeFlags flags;
flags.flag = 0;
@ -740,9 +741,8 @@ TypeInspectorResult inspect_inspect_method(Function& inspect,
result.type_heap_base = flags.heap_base;
assert(flags.pad == 0);
auto& bad_set = get_config().bad_inspect_types;
int idx = get_start_idx(inspect, file, &result, result.parent_type_name);
if (idx == 0 || bad_set.find(type_name) != bad_set.end()) {
if (idx == 0 || skip_fields) {
// printf("was weird: %s\n", result.warnings.c_str());
return result;
}

View file

@ -35,5 +35,6 @@ struct TypeInspectorResult {
TypeInspectorResult inspect_inspect_method(Function& inspect,
const std::string& type_name,
DecompilerTypeSystem& dts,
LinkedObjectFile& file);
LinkedObjectFile& file,
bool skip_fields);
} // namespace decompiler

View file

@ -680,8 +680,7 @@ std::string LinkedObjectFile::print_asm_function_disassembly(const std::string&
/*!
* Print disassembled functions and data segments.
*/
std::string LinkedObjectFile::print_disassembly() {
bool write_hex = get_config().write_hex_near_instructions;
std::string LinkedObjectFile::print_disassembly(bool write_hex) {
std::string result;
assert(segments <= 3);

View file

@ -51,7 +51,7 @@ class LinkedObjectFile {
void disassemble_functions();
void process_fp_relative_links();
std::string print_scripts();
std::string print_disassembly();
std::string print_disassembly(bool write_hex);
bool has_any_functions();
void append_word_to_string(std::string& dest, const LinkedWord& word) const;
std::string print_function_disassembly(Function& func,

View file

@ -609,7 +609,8 @@ static void link_v5(LinkedObjectFile& f,
static void link_v3(LinkedObjectFile& f,
const std::vector<uint8_t>& data,
const std::string& name,
DecompilerTypeSystem& dts) {
DecompilerTypeSystem& dts,
int game_version) {
auto header = (const LinkHeaderV3*)(&data.at(0));
assert(name == header->name);
assert(header->segments == 3);
@ -656,11 +657,11 @@ static void link_v3(LinkedObjectFile& f,
// HACK!
// why is this a thing?
// HACK!
if (get_config().game_version == 1 && name == "level-h" && seg_id == 0) {
if (game_version == 1 && name == "level-h" && seg_id == 0) {
segment_size++;
}
if (get_config().game_version == 2) {
if (game_version == 2) {
bool adjusted = false;
while (segment_size % 4) {
segment_size++;
@ -800,14 +801,15 @@ static void link_v3(LinkedObjectFile& f,
*/
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
const std::string& name,
DecompilerTypeSystem& dts) {
DecompilerTypeSystem& dts,
int game_version) {
LinkedObjectFile result;
const auto* header = (const LinkHeaderCommon*)&data.at(0);
// use appropriate linker
if (header->version == 3) {
assert(header->type_tag == 0);
link_v3(result, data, name, dts);
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);

View file

@ -6,16 +6,12 @@
* This implements a decoder for the GOAL linking format.
*/
#ifndef NEXT_LINKEDOBJECTFILECREATION_H
#define NEXT_LINKEDOBJECTFILECREATION_H
#include "LinkedObjectFile.h"
namespace decompiler {
class DecompilerTypeSystem;
LinkedObjectFile to_linked_object_file(const std::vector<uint8_t>& data,
const std::string& name,
DecompilerTypeSystem& dts);
DecompilerTypeSystem& dts,
int game_version);
} // namespace decompiler
#endif // NEXT_LINKEDOBJECTFILECREATION_H

View file

@ -110,7 +110,8 @@ ObjectFileData& ObjectFileDB::lookup_record(const ObjectFileRecord& rec) {
ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
const std::string& obj_file_name_map_file,
const std::vector<std::string>& object_files,
const std::vector<std::string>& str_files) {
const std::vector<std::string>& str_files,
const Config& config) {
Timer timer;
lg::info("-Loading types...");
@ -128,14 +129,14 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
lg::info("-Loading {} DGOs...", _dgos.size());
for (auto& dgo : _dgos) {
get_objs_from_dgo(dgo);
get_objs_from_dgo(dgo, config);
}
lg::info("-Loading {} plain object files...", object_files.size());
for (auto& obj : object_files) {
auto data = file_util::read_binary_file(obj);
auto name = obj_filename_to_name(obj);
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO");
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
}
lg::info("-Loading {} streaming object files...", str_files.size());
@ -149,7 +150,7 @@ ObjectFileDB::ObjectFileDB(const std::vector<std::string>& _dgos,
// append the chunk ID to the full name
std::string name = obj_name + fmt::format("+{}", i);
auto& data = reader.get_chunk(i);
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO");
add_obj_from_dgo(name, name, data.data(), data.size(), "NO-XGO", config);
}
}
@ -190,7 +191,7 @@ constexpr int MAX_CHUNK_SIZE = 0x8000;
/*!
* Load the objects stored in the given DGO into the ObjectFileDB
*/
void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
void ObjectFileDB::get_objs_from_dgo(const std::string& filename, const Config& config) {
auto dgo_data = file_util::read_binary_file(filename);
stats.total_dgo_bytes += dgo_data.size();
@ -221,7 +222,8 @@ void ObjectFileDB::get_objs_from_dgo(const std::string& filename) {
auto name = get_object_file_name(obj_header.name, reader.here(), obj_header.object_count);
add_obj_from_dgo(name, obj_header.name, reader.here(), obj_header.object_count, dgo_base_name);
add_obj_from_dgo(name, obj_header.name, reader.here(), obj_header.object_count, dgo_base_name,
config);
reader.ffwd(obj_header.object_count);
}
@ -236,8 +238,8 @@ void ObjectFileDB::add_obj_from_dgo(const std::string& obj_name,
const std::string& name_in_dgo,
const uint8_t* obj_data,
uint32_t obj_size,
const std::string& dgo_name) {
const auto& config = get_config();
const std::string& dgo_name,
const Config& config) {
if (!config.allowed_objects.empty()) {
if (config.allowed_objects.find(obj_name) == config.allowed_objects.end()) {
return;
@ -390,14 +392,14 @@ std::string ObjectFileDB::generate_obj_listing() {
/*!
* Process all of the linking data of all objects.
*/
void ObjectFileDB::process_link_data() {
void ObjectFileDB::process_link_data(const Config& config) {
lg::info("Processing Link Data...");
Timer process_link_timer;
LinkedObjectFile::Stats combined_stats;
for_each_obj([&](ObjectFileData& obj) {
obj.linked_data = to_linked_object_file(obj.data, obj.record.name, dts);
obj.linked_data = to_linked_object_file(obj.data, obj.record.name, dts, config.game_version);
combined_stats.add(obj.linked_data.stats);
});
@ -454,7 +456,8 @@ void ObjectFileDB::write_object_file_words(const std::string& output_dir,
*/
void ObjectFileDB::write_disassembly(const std::string& output_dir,
bool disassemble_data,
bool disassemble_code) {
bool disassemble_code,
bool print_hex) {
lg::info("- Writing functions...");
Timer timer;
uint32_t total_bytes = 0, total_files = 0;
@ -463,7 +466,7 @@ void ObjectFileDB::write_disassembly(const std::string& output_dir,
for_each_obj([&](ObjectFileData& obj) {
if ((obj.obj_version == 3 && disassemble_code) || (obj.obj_version != 3 && disassemble_data)) {
auto file_text = obj.linked_data.print_disassembly();
auto file_text = obj.linked_data.print_disassembly(print_hex);
asm_functions += obj.linked_data.print_asm_function_disassembly(obj.to_unique_name());
auto file_name = file_util::combine_path(output_dir, obj.to_unique_name() + ".asm");
@ -488,7 +491,7 @@ void ObjectFileDB::write_disassembly(const std::string& output_dir,
/*!
* Find code/data zones, identify functions, and disassemble
*/
void ObjectFileDB::find_code() {
void ObjectFileDB::find_code(const Config& config) {
lg::info("Finding code in object files...");
LinkedObjectFile::Stats combined_stats;
Timer timer;
@ -499,7 +502,7 @@ void ObjectFileDB::find_code() {
obj.linked_data.find_functions();
obj.linked_data.disassemble_functions();
if (get_config().game_version == 1 || obj.to_unique_name() != "effect-control-v0") {
if (config.game_version == 1 || 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());
@ -619,12 +622,11 @@ std::string ObjectFileDB::process_game_count_file() {
/*!
* This is the main decompiler routine which runs after we've identified functions.
*/
void ObjectFileDB::analyze_functions_ir1() {
void ObjectFileDB::analyze_functions_ir1(const Config& config) {
lg::info("- Analyzing Functions...");
Timer timer;
int total_functions = 0;
const auto& config = get_config();
// Step 1 - analyze the "top level" or "login" code for each object file.
// this will give us type definitions, method definitions, and function definitions...
@ -665,7 +667,8 @@ void ObjectFileDB::analyze_functions_ir1() {
unique_names.insert(name);
if (config.asm_functions_by_name.find(name) != config.asm_functions_by_name.end()) {
if (config.hacks.asm_functions_by_name.find(name) !=
config.hacks.asm_functions_by_name.end()) {
func.warnings.info("Flagged as asm by config");
func.suspected_asm = true;
}
@ -735,7 +738,10 @@ void ObjectFileDB::analyze_functions_ir1() {
// if we got an inspect method, inspect it.
if (func.is_inspect_method) {
auto result = inspect_inspect_method(func, func.method_of_type, dts, data.linked_data);
auto result = inspect_inspect_method(
func, func.method_of_type, dts, data.linked_data,
config.hacks.types_with_bad_inspect_methods.find(func.method_of_type) !=
config.hacks.types_with_bad_inspect_methods.end());
all_type_defs += ";; " + data.to_unique_name() + "\n";
all_type_defs += result.print_as_deftype() + "\n";
}

View file

@ -49,32 +49,34 @@ class ObjectFileDB {
ObjectFileDB(const std::vector<std::string>& _dgos,
const std::string& obj_file_name_map_file,
const std::vector<std::string>& object_files,
const std::vector<std::string>& str_files);
const std::vector<std::string>& str_files,
const Config& config);
std::string generate_dgo_listing();
std::string generate_obj_listing();
void process_link_data();
void process_link_data(const Config& config);
void process_labels();
void find_code();
void find_code(const Config& config);
void find_and_write_scripts(const std::string& output_dir);
void dump_raw_objects(const std::string& output_dir);
void write_object_file_words(const std::string& output_dir, bool dump_data, bool dump_code);
void write_disassembly(const std::string& output_dir,
bool disassemble_data,
bool disassemble_code);
bool disassemble_code,
bool print_hex);
void analyze_functions_ir1();
void analyze_functions_ir2(const std::string& output_dir);
void ir2_top_level_pass();
void analyze_functions_ir1(const Config& config);
void analyze_functions_ir2(const std::string& output_dir, const Config& config);
void ir2_top_level_pass(const Config& config);
void ir2_stack_spill_slot_pass();
void ir2_basic_block_pass();
void ir2_atomic_op_pass();
void ir2_type_analysis_pass();
void ir2_atomic_op_pass(const Config& config);
void ir2_type_analysis_pass(const Config& config);
void ir2_register_usage_pass();
void ir2_variable_pass();
void ir2_cfg_build_pass();
void ir2_store_current_forms();
void ir2_build_expressions();
void ir2_build_expressions(const Config& config);
void ir2_insert_lets();
void ir2_rewrite_inline_asm_instructions();
void ir2_insert_anonymous_functions();
@ -94,16 +96,18 @@ class ObjectFileDB {
bool lookup_function_type(const FunctionName& name,
const std::string& obj_name,
const Config& config,
TypeSpec* result);
public:
void load_map_file(const std::string& map_data);
void get_objs_from_dgo(const std::string& filename);
void get_objs_from_dgo(const std::string& filename, const Config& config);
void add_obj_from_dgo(const std::string& obj_name,
const std::string& name_in_dgo,
const uint8_t* obj_data,
uint32_t obj_size,
const std::string& dgo_name);
const std::string& dgo_name,
const Config& config);
/*!
* Apply f to all ObjectFileData's. Does it in the right order.

View file

@ -29,18 +29,18 @@ namespace decompiler {
* At this point, we assume that the files are loaded and we've run find_code to locate all
* functions, but nothing else.
*/
void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) {
void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir, const Config& config) {
lg::info("Using IR2 analysis...");
lg::info("Processing top-level functions...");
ir2_top_level_pass();
ir2_top_level_pass(config);
lg::info("Processing basic blocks and control flow graph...");
ir2_basic_block_pass();
lg::info("Finding stack spills...");
ir2_stack_spill_slot_pass();
lg::info("Converting to atomic ops...");
ir2_atomic_op_pass();
ir2_atomic_op_pass(config);
lg::info("Running type analysis...");
ir2_type_analysis_pass();
ir2_type_analysis_pass(config);
lg::info("Register usage analysis...");
ir2_register_usage_pass();
lg::info("Variable analysis...");
@ -51,7 +51,7 @@ void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) {
lg::info("Storing temporary form result...");
ir2_store_current_forms();
lg::info("Expression building...");
ir2_build_expressions();
ir2_build_expressions(config);
lg::info("Re-writing inline asm instructions...");
ir2_rewrite_inline_asm_instructions();
@ -74,7 +74,7 @@ void ObjectFileDB::analyze_functions_ir2(const std::string& output_dir) {
* - Find method definitions
* - Warn for non-unique function names.
*/
void ObjectFileDB::ir2_top_level_pass() {
void ObjectFileDB::ir2_top_level_pass(const Config& config) {
Timer timer;
int total_functions = 0;
int total_named_global_functions = 0;
@ -134,8 +134,8 @@ void ObjectFileDB::ir2_top_level_pass() {
unique_names.insert(name);
if (get_config().asm_functions_by_name.find(name) !=
get_config().asm_functions_by_name.end()) {
if (config.hacks.asm_functions_by_name.find(name) !=
config.hacks.asm_functions_by_name.end()) {
func.warnings.info("Flagged as asm by config");
func.suspected_asm = true;
}
@ -253,7 +253,7 @@ void ObjectFileDB::ir2_stack_spill_slot_pass() {
* Conversion of MIPS instructions into AtomicOps. The AtomicOps represent what we
* think are IR of the original GOAL compiler.
*/
void ObjectFileDB::ir2_atomic_op_pass() {
void ObjectFileDB::ir2_atomic_op_pass(const Config& config) {
Timer timer;
int total_functions = 0;
int attempted = 0;
@ -266,8 +266,8 @@ void ObjectFileDB::ir2_atomic_op_pass() {
attempted++;
try {
bool inline_asm =
get_config().hint_inline_assembly_functions.find(func.guessed_name.to_string()) !=
get_config().hint_inline_assembly_functions.end();
config.hacks.hint_inline_assembly_functions.find(func.guessed_name.to_string()) !=
config.hacks.hint_inline_assembly_functions.end();
auto ops = convert_function_to_atomic_ops(func, data.linked_data.labels, func.warnings,
inline_asm);
func.ir2.atomic_ops = std::make_shared<FunctionAtomicOps>(std::move(ops));
@ -288,13 +288,23 @@ void ObjectFileDB::ir2_atomic_op_pass() {
100.f * attempted / total_functions, 100.f * successful / attempted);
}
template <typename Key, typename Value>
Value try_lookup(const std::unordered_map<Key, Value>& map, const Key& key) {
auto lookup = map.find(key);
if (lookup == map.end()) {
return Value();
} else {
return lookup->second;
}
}
/*!
* Analyze registers and determine the type in each register at each instruction.
* - Figure out the type of each function, from configs.
* - Propagate types.
* - NOTE: this will update register info usage more accurately for functions.
*/
void ObjectFileDB::ir2_type_analysis_pass() {
void ObjectFileDB::ir2_type_analysis_pass(const Config& config) {
Timer timer;
int total_functions = 0;
int non_asm_functions = 0;
@ -307,21 +317,21 @@ void ObjectFileDB::ir2_type_analysis_pass() {
if (!func.suspected_asm) {
non_asm_functions++;
TypeSpec ts;
if (lookup_function_type(func.guessed_name, data.to_unique_name(), &ts) &&
if (lookup_function_type(func.guessed_name, data.to_unique_name(), config, &ts) &&
func.ir2.atomic_ops_succeeded) {
func.type = ts;
attempted_functions++;
// try type analysis here.
auto func_name = func.guessed_name.to_string();
auto casts = get_config().type_casts_by_function_by_atomic_op_idx[func_name];
auto label_types = get_config().label_types[data.to_unique_name()];
auto casts = try_lookup(config.type_casts_by_function_by_atomic_op_idx, func_name);
auto label_types = try_lookup(config.label_types, data.to_unique_name());
func.ir2.env.set_type_casts(casts);
func.ir2.env.set_label_types(label_types);
if (get_config().pair_functions_by_name.find(func_name) !=
get_config().pair_functions_by_name.end()) {
if (config.hacks.pair_functions_by_name.find(func_name) !=
config.hacks.pair_functions_by_name.end()) {
func.ir2.env.set_sloppy_pair_typing();
}
func.ir2.env.set_stack_var_hints(get_config().stack_var_hints_by_function[func_name]);
func.ir2.env.set_stack_var_hints(try_lookup(config.stack_var_hints_by_function, func_name));
if (run_type_analysis_ir2(ts, dts, func)) {
successful_functions++;
func.ir2.env.types_succeeded = true;
@ -436,7 +446,7 @@ void ObjectFileDB::ir2_store_current_forms() {
lg::info("Stored debug forms for {} functions in {:.2f} ms\n", total, timer.getMs());
}
void ObjectFileDB::ir2_build_expressions() {
void ObjectFileDB::ir2_build_expressions(const Config& config) {
Timer timer;
int total = 0;
int attempted = 0;
@ -449,13 +459,13 @@ void ObjectFileDB::ir2_build_expressions() {
func.ir2.env.types_succeeded) {
attempted++;
auto name = func.guessed_name.to_string();
auto arg_config = get_config().function_arg_names.find(name);
auto var_config = get_config().function_var_overrides.find(name);
auto arg_config = config.function_arg_names.find(name);
auto var_config = config.function_var_overrides.find(name);
if (convert_to_expressions(func.ir2.top_form, *func.ir2.form_pool, func,
arg_config != get_config().function_arg_names.end()
arg_config != config.function_arg_names.end()
? arg_config->second
: std::vector<std::string>{},
var_config != get_config().function_var_overrides.end()
var_config != config.function_var_overrides.end()
? var_config->second
: std::unordered_map<std::string, LocalVarOverride>{},
dts)) {
@ -826,12 +836,11 @@ std::string ObjectFileDB::ir2_function_to_string(ObjectFileData& data, Function&
*/
bool ObjectFileDB::lookup_function_type(const FunctionName& name,
const std::string& obj_name,
const Config& config,
TypeSpec* result) {
auto& cfg = get_config();
// don't return function types that are explictly flagged as bad in config.
if (cfg.no_type_analysis_functions_by_name.find(name.to_string()) !=
cfg.no_type_analysis_functions_by_name.end()) {
if (config.hacks.no_type_analysis_functions_by_name.find(name.to_string()) !=
config.hacks.no_type_analysis_functions_by_name.end()) {
return false;
}
@ -867,7 +876,7 @@ bool ObjectFileDB::lookup_function_type(const FunctionName& name,
return true;
} else if (name.kind == FunctionName::FunctionKind::UNIDENTIFIED) {
// try looking up the object
const auto& map = get_config().anon_function_types_by_obj_by_id;
const auto& map = config.anon_function_types_by_obj_by_id;
auto obj_kv = map.find(obj_name);
if (obj_kv != map.end()) {
auto func_kv = obj_kv->second.find(name.get_anon_id());

View file

@ -6,11 +6,6 @@
#include "decompiler/util/config_parsers.h"
namespace decompiler {
Config gConfig;
Config& get_config() {
return gConfig;
}
namespace {
/*!
@ -25,60 +20,39 @@ nlohmann::json read_json_file_from_config(const nlohmann::json& cfg, const std::
} // namespace
/*!
* Parse the main config file and set the global decompiler configuration.
* Parse the main config file and return decompiler config.
*/
void set_config(const std::string& path_to_config_file) {
Config read_config_file(const std::string& path_to_config_file) {
Config config;
auto config_str = file_util::read_text_file(path_to_config_file);
auto cfg = parse_commented_json(config_str);
gConfig.game_version = cfg.at("game_version").get<int>();
gConfig.dgo_names = cfg.at("dgo_names").get<std::vector<std::string>>();
gConfig.object_file_names = cfg.at("object_file_names").get<std::vector<std::string>>();
gConfig.str_file_names = cfg.at("str_file_names").get<std::vector<std::string>>();
config.game_version = cfg.at("game_version").get<int>();
auto inputs_json = read_json_file_from_config(cfg, "inputs_file");
config.dgo_names = inputs_json.at("dgo_names").get<std::vector<std::string>>();
config.object_file_names = inputs_json.at("object_file_names").get<std::vector<std::string>>();
config.str_file_names = inputs_json.at("str_file_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.disassemble_code = cfg.at("disassemble_code").get<bool>();
gConfig.decompile_code = cfg.at("decompile_code").get<bool>();
gConfig.regenerate_all_types = cfg.at("regenerate_all_types").get<bool>();
gConfig.write_hex_near_instructions = cfg.at("write_hex_near_instructions").get<bool>();
gConfig.write_scripts = cfg.at("write_scripts").get<bool>();
gConfig.disassemble_data = cfg.at("disassemble_data").get<bool>();
gConfig.process_tpages = cfg.at("process_tpages").get<bool>();
gConfig.process_game_text = cfg.at("process_game_text").get<bool>();
gConfig.process_game_count = cfg.at("process_game_count").get<bool>();
gConfig.hexdump_code = cfg.at("hexdump_code").get<bool>();
gConfig.hexdump_data = cfg.at("hexdump_data").get<bool>();
gConfig.dump_objs = cfg.at("dump_objs").get<bool>();
gConfig.hint_inline_assembly_functions =
cfg.at("inline_asm_hint").get<std::unordered_set<std::string>>();
std::vector<std::string> asm_functions_by_name =
cfg.at("asm_functions_by_name").get<std::vector<std::string>>();
for (const auto& x : asm_functions_by_name) {
gConfig.asm_functions_by_name.insert(x);
}
std::vector<std::string> pair_functions_by_name =
cfg.at("pair_functions_by_name").get<std::vector<std::string>>();
for (const auto& x : pair_functions_by_name) {
gConfig.pair_functions_by_name.insert(x);
}
std::vector<std::string> no_type_analysis_functions_by_name =
cfg.at("no_type_analysis_functions_by_name").get<std::vector<std::string>>();
for (const auto& x : no_type_analysis_functions_by_name) {
gConfig.no_type_analysis_functions_by_name.insert(x);
}
auto bad_inspect = cfg.at("types_with_bad_inspect_methods").get<std::vector<std::string>>();
for (const auto& x : bad_inspect) {
gConfig.bad_inspect_types.insert(x);
config.obj_file_name_map_file = cfg.at("obj_file_name_map_file").get<std::string>();
}
config.disassemble_code = cfg.at("disassemble_code").get<bool>();
config.decompile_code = cfg.at("decompile_code").get<bool>();
config.regenerate_all_types = cfg.at("regenerate_all_types").get<bool>();
config.write_hex_near_instructions = cfg.at("write_hex_near_instructions").get<bool>();
config.write_scripts = cfg.at("write_scripts").get<bool>();
config.disassemble_data = cfg.at("disassemble_data").get<bool>();
config.process_tpages = cfg.at("process_tpages").get<bool>();
config.process_game_text = cfg.at("process_game_text").get<bool>();
config.process_game_count = cfg.at("process_game_count").get<bool>();
config.hexdump_code = cfg.at("hexdump_code").get<bool>();
config.hexdump_data = cfg.at("hexdump_data").get<bool>();
config.dump_objs = cfg.at("dump_objs").get<bool>();
auto allowed = cfg.at("allowed_objects").get<std::vector<std::string>>();
for (const auto& x : allowed) {
gConfig.allowed_objects.insert(x);
config.allowed_objects.insert(x);
}
auto type_casts_json = read_json_file_from_config(cfg, "type_casts_file");
@ -92,7 +66,7 @@ void set_config(const std::string& path_to_config_file) {
type_cast.atomic_op_idx = idx;
type_cast.reg = Register(cast.at(1));
type_cast.type_name = cast.at(2).get<std::string>();
gConfig.type_casts_by_function_by_atomic_op_idx[function_name][idx].push_back(type_cast);
config.type_casts_by_function_by_atomic_op_idx[function_name][idx].push_back(type_cast);
}
}
}
@ -104,7 +78,7 @@ void set_config(const std::string& path_to_config_file) {
for (auto& anon_type : anon_types) {
auto id = anon_type.at(0).get<int>();
const auto& type_name = anon_type.at(1).get<std::string>();
gConfig.anon_function_types_by_obj_by_id[obj_file_name][id] = type_name;
config.anon_function_types_by_obj_by_id[obj_file_name][id] = type_name;
}
}
auto var_names_json = read_json_file_from_config(cfg, "var_names_file");
@ -113,7 +87,7 @@ void set_config(const std::string& path_to_config_file) {
auto arg = kv.value().find("args");
if (arg != kv.value().end()) {
for (auto& x : arg.value()) {
gConfig.function_arg_names[function_name].push_back(x);
config.function_arg_names[function_name].push_back(x);
}
}
@ -129,7 +103,7 @@ void set_config(const std::string& path_to_config_file) {
} else {
throw std::runtime_error("Invalid function var override.");
}
gConfig.function_var_overrides[function_name][vkv.first] = override;
config.function_var_overrides[function_name][vkv.first] = override;
}
}
}
@ -142,7 +116,7 @@ void set_config(const std::string& path_to_config_file) {
const auto& name = x.at(0).get<std::string>();
const auto& type_name = x.at(1).get<std::string>();
bool is_const = x.at(2).get<bool>();
auto& config_entry = gConfig.label_types[obj_name][name];
auto& config_entry = config.label_types[obj_name][name];
config_entry = {type_name, is_const, {}};
if (x.size() > 3) {
config_entry.array_size = x.at(3).get<int>();
@ -154,8 +128,21 @@ void set_config(const std::string& path_to_config_file) {
for (auto& kv : stack_vars_json.items()) {
auto& func_name = kv.key();
auto& stack_vars = kv.value();
gConfig.stack_var_hints_by_function[func_name] = parse_stack_var_hints(stack_vars);
config.stack_var_hints_by_function[func_name] = parse_stack_var_hints(stack_vars);
}
auto hacks_json = read_json_file_from_config(cfg, "hacks_file");
config.hacks.hint_inline_assembly_functions =
hacks_json.at("hint_inline_assembly_functions").get<std::unordered_set<std::string>>();
config.hacks.asm_functions_by_name =
hacks_json.at("asm_functions_by_name").get<std::unordered_set<std::string>>();
config.hacks.pair_functions_by_name =
hacks_json.at("pair_functions_by_name").get<std::unordered_set<std::string>>();
config.hacks.no_type_analysis_functions_by_name =
hacks_json.at("no_type_analysis_functions_by_name").get<std::unordered_set<std::string>>();
config.hacks.types_with_bad_inspect_methods =
hacks_json.at("types_with_bad_inspect_methods").get<std::unordered_set<std::string>>();
return config;
}
} // namespace decompiler

View file

@ -42,12 +42,20 @@ struct StackVariableHint {
int stack_offset = 0; // where it's located on the stack (relative to sp after prologue)
};
struct DecompileHacks {
std::unordered_set<std::string> types_with_bad_inspect_methods;
std::unordered_set<std::string> no_type_analysis_functions_by_name;
std::unordered_set<std::string> hint_inline_assembly_functions;
std::unordered_set<std::string> asm_functions_by_name;
std::unordered_set<std::string> pair_functions_by_name;
};
struct Config {
int game_version = -1;
std::vector<std::string> dgo_names;
std::vector<std::string> object_file_names;
std::vector<std::string> str_file_names;
std::unordered_set<std::string> bad_inspect_types;
std::string obj_file_name_map_file;
bool disassemble_code = false;
@ -64,9 +72,6 @@ struct Config {
bool hexdump_data = false;
bool dump_objs = false;
std::unordered_set<std::string> asm_functions_by_name;
std::unordered_set<std::string> pair_functions_by_name;
std::unordered_set<std::string> no_type_analysis_functions_by_name;
std::unordered_set<std::string> allowed_objects;
std::unordered_map<std::string, std::unordered_map<int, std::vector<TypeCast>>>
type_casts_by_function_by_atomic_op_idx;
@ -78,10 +83,9 @@ struct Config {
std::unordered_map<std::string, std::unordered_map<std::string, LabelType>> label_types;
std::unordered_map<std::string, std::vector<StackVariableHint>> stack_var_hints_by_function;
std::unordered_set<std::string> hint_inline_assembly_functions;
DecompileHacks hacks;
};
Config& get_config();
void set_config(const std::string& path_to_config_file);
Config read_config_file(const std::string& path_to_config_file);
} // namespace decompiler

View file

@ -1,68 +1,9 @@
{
"game_version":1,
"game_version": 1,
//////////////////////
// INPUT FILES
//////////////////////
// input is GOAL object files, possibly in containers.
// most objects are part of CGO/DGO files (both go in dgo_names). This includes levels and the engine
// the DGOs will be processed in this order. Usually it's best to have KERNEL, ENGINE, then the levels when
// you want to run on the entire game.
"dgo_names":["CGO/KERNEL.CGO","CGO/ENGINE.CGO", "CGO/GAME.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"
],
// some objects are part of STR files (streaming data). In Jak 1 this is just animations
"str_file_names":["STR/BAFCELL.STR", "STR/SWTE4.STR", "STR/SWTE3.STR", "STR/SWTE2.STR", "STR/SWTE1.STR",
"STR/SNRBSBFC.STR", "STR/SNRBIPFC.STR", "STR/SNRBICFC.STR", "STR/ORR3.STR", "STR/ORR2.STR", "STR/MICANNON.STR",
"STR/BECANNON.STR", "STR/SWTS4.STR", "STR/SWTS3.STR", "STR/SWTS2.STR", "STR/SW4.STR", "STR/SW3.STR", "STR/SW2.STR",
"STR/SWTS1.STR", "STR/ORREYE.STR", "STR/ORLEYE.STR", "STR/SW1.STR", "STR/MAGFCELL.STR", "STR/GNFCELL.STR",
"STR/ORRE3.STR","STR/ORRE2.STR","STR/ORRE1.STR","STR/ORR1.STR","STR/ORLE3.STR","STR/ORLE2.STR","STR/ORI3.STR",
"STR/ORI2.STR","STR/DE0202.STR","STR/RARSANIM.STR","STR/RARANIM.STR","STR/EIFISH.STR","STR/ORLE1.STR",
"STR/SWTEF4.STR","STR/SWTEF3.STR","STR/SWTEF2.STR","STR/SWTEF1.STR","STR/ORI1.STR","STR/EIICE.STR","STR/EIA3.STR",
"STR/DE0191.STR","STR/DE0186.STR","STR/DE0187.STR","STR/EIA4.STR","STR/EIPOLE.STR","STR/RARASECO.STR",
"STR/RARA2.STR","STR/DE0184.STR","STR/DE0181.STR","STR/PESEXT.STR","STR/DE0195.STR","STR/EIA2.STR","STR/FIR1.STR",
"STR/DE0182.STR","STR/BIR1.STR","STR/HAPOPEN.STR","STR/EITUBE.STR","STR/SCR1.STR","STR/DE0197.STR",
"STR/DE0193.STR","STR/EIA1.STR","STR/FAR2.STR","STR/FAR1.STR","STR/DE0199.STR","STR/GERMONEY.STR",
"STR/BIRESOLU.STR","STR/GARMONEY.STR","STR/BIADVENT.STR","STR/FUCRV1.STR","STR/BIREJECT.STR","STR/WAR1.STR",
"STR/BIACCEPT.STR","STR/SA3R1DEC.STR","STR/ASR1GENE.STR","STR/FIREJECT.STR","STR/GARRACE.STR","STR/GEZMONEY.STR",
"STR/LRFALLIN.STR","STR/EXR2.STR","STR/GERMOLES.STR","STR/FUCVICTO.STR","STR/MIR1ORBS.STR","STR/SA3R1RAM.STR",
"STR/AS2R1FLU.STR","STR/FUCV2.STR","STR/MIR1GNAW.STR","STR/GAZMONEY.STR","STR/AS3REMIN.STR","STR/SIHISA.STR",
"STR/FIACCEPT.STR","STR/FIWECO.STR","STR/FARESOLU.STR","STR/ASR1RBIK.STR","STR/MARDONAT.STR","STR/GAZRACE.STR",
"STR/FUCFV1.STR","STR/FUCV5.STR","STR/SABR1CDU.STR","STR/FLLINTRO.STR","STR/SAR1ECOR.STR","STR/AS2R1ROB.STR",
"STR/MIR2ORBS.STR","STR/MARBEAMS.STR","STR/LOI2.STR","STR/SAR1GENE.STR","STR/BILR1.STR","STR/AS2R1ROO.STR",
"STR/ASR1BESW.STR","STR/LOLOOP.STR","STR/FAINTROD.STR","STR/GEZMOLES.STR","STR/V1IN.STR","STR/FUCV4.STR",
"STR/SAIECORO.STR","STR/MIR1SWIT.STR","STR/LOINTRO.STR","STR/SAR2GENE.STR","STR/MUVICTOR.STR","STR/SAR1MCAN.STR",
"STR/FUCV7.STR","STR/MIZ1ORBS.STR","STR/FUCV8.STR","STR/BILR2.STR","STR/FUCV6.STR","STR/FUCV3.STR",
"STR/PLLBLOWU.STR","STR/PLBMAIN.STR","STR/WARESOLU.STR","STR/EIRACER.STR","STR/MAZDONAT.STR","STR/MAZBEAMS.STR",
"STR/MIISWITC.STR","STR/FIBRTVIL.STR","STR/FIBRTMIS.STR","STR/SABR1PAR.STR","STR/NDINTRO.STR","STR/GORDOWN.STR",
"STR/GORUP.STR","STR/SA3IRAMS.STR","STR/YERESOLU.STR","STR/EIFLUT.STR","STR/GRSDSACR.STR","STR/EXR1.STR",
"STR/SCRESOLU.STR","STR/FIRESOLU.STR","STR/SIHITEST.STR","STR/GAI1.STR","STR/EXRESOLU.STR","STR/MIZ2ORBS.STR",
"STR/ASIRBIKE.STR","STR/GRSOBBEC.STR","STR/BIINTROD.STR","STR/GRSOBBNC.STR","STR/AS2IROBB.STR","STR/GRSOBFIN.STR",
"STR/RERESOLU.STR","STR/BLRESOLU.STR","STR/SABIPARM.STR","STR/EVMEND.STR","STR/AS2RESOL.STR","STR/SAIMCANN.STR",
"STR/MIIGNAWE.STR","STR/GRSOBBA.STR","STR/GRSINTRO.STR","STR/SAISE.STR","STR/SA3IDECO.STR","STR/ASFRESOL.STR",
"STR/EXINTROD.STR","STR/BILINTRO.STR","STR/FIINTROD.STR","STR/MAINTROD.STR","STR/SCINTROD.STR","STR/AS2IFLUT.STR",
"STR/ASLERESO.STR","STR/ASLSRESO.STR","STR/AS2IROOM.STR","STR/GRSRESOL.STR","STR/SABICDUS.STR","STR/SIHISB.STR",
"STR/ASIBESWI.STR","STR/BILBRESO.STR","STR/FIBRT1AL.STR","STR/AS2INTRO.STR","STR/GEINTROD.STR","STR/SAISD1.STR",
"STR/SAISA.STR","STR/SIHISC.STR","STR/MIIORBS.STR","STR/WAINTROD.STR","STR/SAISD2.STR","STR/GRSOPREB.STR",
"STR/GRSOBBB.STR","STR/SA3INTRO.STR"
],
// some objects are directly stored as files on the DVD. This is just text files.
"object_file_names":["TEXT/0COMMON.TXT", "TEXT/1COMMON.TXT", "TEXT/2COMMON.TXT", "TEXT/3COMMON.TXT", "TEXT/4COMMON.TXT",
"TEXT/5COMMON.TXT", "TEXT/6COMMON.TXT"],
// if you want to filter to only some object names.
// it will make the decompiler much faster.
"allowed_objects":[],
"allowed_objects": [],
////////////////////////////
// CODE ANALYSIS OPTIONS
@ -70,10 +11,10 @@
// set to true to generate plain .asm files with MIPS disassembly, with no fancy decompilation.
// this is fast and should succeed 100% of the time.
"disassemble_code":false,
"disassemble_code": false,
// Run the decompiler
"decompile_code":true,
"decompile_code": true,
////////////////////////////
// DATA ANALYSIS OPTIONS
@ -82,14 +23,14 @@
// set to true to generate plain .asm files for data files.
// this will display most data as hex, but will add labels/references/type pointers/strings
// this generates a huge amount of output if you run it on the entire game.
"disassemble_data":false,
"disassemble_data": false,
// unpack textures to assets folder
"process_tpages":true,
"process_tpages": true,
// unpack game text to assets folder
"process_game_text":true,
"process_game_text": true,
// unpack game count to assets folder
"process_game_count":true,
"process_game_count": true,
///////////////////////////
// WEIRD OPTIONS
@ -98,464 +39,33 @@
// these options are used rarely and should usually be left at false
// output a file type_defs.gc which is used the types part of all-types.gc
"regenerate_all_types":false,
"regenerate_all_types": false,
// debug option for instruction decoder
"write_hex_near_instructions":false,
"write_hex_near_instructions": false,
// experimental tool to extract linked lists used for region scripting in Jak 2 and Jak 3.
"write_scripts":false,
"write_scripts": false,
// hex dump of code/data files.
"hexdump_code":false,
"hexdump_data":false,
"hexdump_code": false,
"hexdump_data": false,
// dump raw obj files
"dump_objs":false,
"dump_objs": false,
////////////////////////////
// CONFIG FILES
////////////////////////////
"type_casts_file":"decompiler/config/jak1_ntsc_black_label/type_casts.jsonc",
"anonymous_function_types_file":"decompiler/config/jak1_ntsc_black_label/anonymous_function_types.jsonc",
"var_names_file":"decompiler/config/jak1_ntsc_black_label/var_names.jsonc",
"label_types_file":"decompiler/config/jak1_ntsc_black_label/label_types.jsonc",
"stack_vars_file":"decompiler/config/jak1_ntsc_black_label/stack_vars.jsonc",
"type_casts_file": "decompiler/config/jak1_ntsc_black_label/type_casts.jsonc",
"anonymous_function_types_file": "decompiler/config/jak1_ntsc_black_label/anonymous_function_types.jsonc",
"var_names_file": "decompiler/config/jak1_ntsc_black_label/var_names.jsonc",
"label_types_file": "decompiler/config/jak1_ntsc_black_label/label_types.jsonc",
"stack_vars_file": "decompiler/config/jak1_ntsc_black_label/stack_vars.jsonc",
"hacks_file": "decompiler/config/jak1_ntsc_black_label/hacks.jsonc",
"inputs_file": "decompiler/config/jak1_ntsc_black_label/inputs.jsonc",
// optional: a predetermined object file name map from a file.
// this will make decompilation naming consistent even if you only run on some objects.
"obj_file_name_map_file":"goal_src/build/all_objs.json",
////////////////////////////
// HACKS and ASM FUNCTIONS
////////////////////////////
"types_with_bad_inspect_methods":[
"engine",
"bsp-header",
"joint-anim-matrix",
"part-tracker"],
"no_type_analysis_functions_by_name":[],
// this provides a hint to the decompiler that these functions will have a lot of inline assembly.
"inline_asm_hint":["matrix-transpose!"],
"asm_functions_by_name":[
// gcommon
"quad-copy!",
// gkernel
"(method 11 cpu-thread)",
"throw",
"return-from-thread",
"return-from-thread-dead",
"reset-and-call",
"(method 10 cpu-thread)",
"(method 0 catch-frame)",
"throw-dispatch",
"set-to-run-bootstrap",
"run-function-in-process", // not asm, but it uses the stack.
// pskernel
"return-from-exception", // F: eret
"kernel-read-function", // F: delay slot tricks
"kernel-write-function", // F: delay slot tricks
"kernel-copy-function",
"kernel-check-hardwired-addresses",
// math
"rand-uint31-gen",
// bounding box
"(method 9 bounding-box)", // F: asm branching
"(method 14 bounding-box)",
// matrix
"(method 9 matrix)", // F: asm branching
"matrix-axis-sin-cos!", // F: asm branching
"matrix-axis-sin-cos-vu!",
// 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!",
// trigonometry
"exp", // BUG: cfg is wrong.
"atan0", // P: manual use of stack
"sincos!", // P: manual use of stack
"sincos-rad!",
// 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",
// dma
"symlink3", // F: asm branching
"symlink2", // F: asm branching
"dma-sync-hang",
// display
"vblank-handler", // F: weird asm for interrupt handler
"vif1-handler", // F: weird asm for interrupt handler
"vif1-handler-debug",
// vector
"vector=", // asm branching
// 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",
"sp-get-particle",
// 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)",
// not enough type info to decompile these
// (these are NOT actually asm functions)
"(method 15 sync-info)", // NEED *res-static-buf*
"(method 15 sync-info-eased)", // NEED *res-static-buf*
"(method 15 sync-info-paused)" // NEED *res-static-buf*
],
"pair_functions_by_name":["ref", "last", "member", "nmember", "assoc", "assoce", "append!", "delete!", "delete-car!",
"insert-cons!", "sort", "unload-package", "(method 4 pair)", "nassoc", "nassoce", "lookup-level-info", "(method 21 level-group)"]
}
"obj_file_name_map_file": "goal_src/build/all_objs.json"
}

View file

@ -0,0 +1,450 @@
{
////////////////////////////
// HACKS and ASM FUNCTIONS
////////////////////////////
"types_with_bad_inspect_methods": [
"engine",
"bsp-header",
"joint-anim-matrix",
"part-tracker"
],
"no_type_analysis_functions_by_name": [],
// this provides a hint to the decompiler that these functions will have a lot of inline assembly.
"hint_inline_assembly_functions": ["matrix-transpose!"],
"asm_functions_by_name": [
// gcommon
"quad-copy!",
// gkernel
"(method 11 cpu-thread)",
"throw",
"return-from-thread",
"return-from-thread-dead",
"reset-and-call",
"(method 10 cpu-thread)",
"(method 0 catch-frame)",
"throw-dispatch",
"set-to-run-bootstrap",
"run-function-in-process", // not asm, but it uses the stack.
// pskernel
"return-from-exception", // F: eret
"kernel-read-function", // F: delay slot tricks
"kernel-write-function", // F: delay slot tricks
"kernel-copy-function",
"kernel-check-hardwired-addresses",
// math
"rand-uint31-gen",
// bounding box
"(method 9 bounding-box)", // F: asm branching
"(method 14 bounding-box)",
// matrix
"(method 9 matrix)", // F: asm branching
"matrix-axis-sin-cos!", // F: asm branching
"matrix-axis-sin-cos-vu!",
// 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!",
// trigonometry
"exp", // BUG: cfg is wrong.
"atan0", // P: manual use of stack
"sincos!", // P: manual use of stack
"sincos-rad!",
// 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",
// dma
"symlink3", // F: asm branching
"symlink2", // F: asm branching
"dma-sync-hang",
// display
"vblank-handler", // F: weird asm for interrupt handler
"vif1-handler", // F: weird asm for interrupt handler
"vif1-handler-debug",
// vector
"vector=", // asm branching
// 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",
"sp-get-particle",
// 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)",
// not enough type info to decompile these
// (these are NOT actually asm functions)
"(method 15 sync-info)", // NEED *res-static-buf*
"(method 15 sync-info-eased)", // NEED *res-static-buf*
"(method 15 sync-info-paused)" // NEED *res-static-buf*
],
"pair_functions_by_name": [
"ref",
"last",
"member",
"nmember",
"assoc",
"assoce",
"append!",
"delete!",
"delete-car!",
"insert-cons!",
"sort",
"unload-package",
"(method 4 pair)",
"nassoc",
"nassoce",
"lookup-level-info",
"(method 21 level-group)"
]
}

View file

@ -0,0 +1,260 @@
{
//////////////////////
// INPUT FILES
//////////////////////
// input is GOAL object files, possibly in containers.
// most objects are part of CGO/DGO files (both go in dgo_names). This includes levels and the engine
// the DGOs will be processed in this order. Usually it's best to have KERNEL, ENGINE, then the levels when
// you want to run on the entire game.
"dgo_names": [
"CGO/KERNEL.CGO",
"CGO/ENGINE.CGO",
"CGO/GAME.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"
],
// some objects are part of STR files (streaming data). In Jak 1 this is just animations
"str_file_names": [
"STR/BAFCELL.STR",
"STR/SWTE4.STR",
"STR/SWTE3.STR",
"STR/SWTE2.STR",
"STR/SWTE1.STR",
"STR/SNRBSBFC.STR",
"STR/SNRBIPFC.STR",
"STR/SNRBICFC.STR",
"STR/ORR3.STR",
"STR/ORR2.STR",
"STR/MICANNON.STR",
"STR/BECANNON.STR",
"STR/SWTS4.STR",
"STR/SWTS3.STR",
"STR/SWTS2.STR",
"STR/SW4.STR",
"STR/SW3.STR",
"STR/SW2.STR",
"STR/SWTS1.STR",
"STR/ORREYE.STR",
"STR/ORLEYE.STR",
"STR/SW1.STR",
"STR/MAGFCELL.STR",
"STR/GNFCELL.STR",
"STR/ORRE3.STR",
"STR/ORRE2.STR",
"STR/ORRE1.STR",
"STR/ORR1.STR",
"STR/ORLE3.STR",
"STR/ORLE2.STR",
"STR/ORI3.STR",
"STR/ORI2.STR",
"STR/DE0202.STR",
"STR/RARSANIM.STR",
"STR/RARANIM.STR",
"STR/EIFISH.STR",
"STR/ORLE1.STR",
"STR/SWTEF4.STR",
"STR/SWTEF3.STR",
"STR/SWTEF2.STR",
"STR/SWTEF1.STR",
"STR/ORI1.STR",
"STR/EIICE.STR",
"STR/EIA3.STR",
"STR/DE0191.STR",
"STR/DE0186.STR",
"STR/DE0187.STR",
"STR/EIA4.STR",
"STR/EIPOLE.STR",
"STR/RARASECO.STR",
"STR/RARA2.STR",
"STR/DE0184.STR",
"STR/DE0181.STR",
"STR/PESEXT.STR",
"STR/DE0195.STR",
"STR/EIA2.STR",
"STR/FIR1.STR",
"STR/DE0182.STR",
"STR/BIR1.STR",
"STR/HAPOPEN.STR",
"STR/EITUBE.STR",
"STR/SCR1.STR",
"STR/DE0197.STR",
"STR/DE0193.STR",
"STR/EIA1.STR",
"STR/FAR2.STR",
"STR/FAR1.STR",
"STR/DE0199.STR",
"STR/GERMONEY.STR",
"STR/BIRESOLU.STR",
"STR/GARMONEY.STR",
"STR/BIADVENT.STR",
"STR/FUCRV1.STR",
"STR/BIREJECT.STR",
"STR/WAR1.STR",
"STR/BIACCEPT.STR",
"STR/SA3R1DEC.STR",
"STR/ASR1GENE.STR",
"STR/FIREJECT.STR",
"STR/GARRACE.STR",
"STR/GEZMONEY.STR",
"STR/LRFALLIN.STR",
"STR/EXR2.STR",
"STR/GERMOLES.STR",
"STR/FUCVICTO.STR",
"STR/MIR1ORBS.STR",
"STR/SA3R1RAM.STR",
"STR/AS2R1FLU.STR",
"STR/FUCV2.STR",
"STR/MIR1GNAW.STR",
"STR/GAZMONEY.STR",
"STR/AS3REMIN.STR",
"STR/SIHISA.STR",
"STR/FIACCEPT.STR",
"STR/FIWECO.STR",
"STR/FARESOLU.STR",
"STR/ASR1RBIK.STR",
"STR/MARDONAT.STR",
"STR/GAZRACE.STR",
"STR/FUCFV1.STR",
"STR/FUCV5.STR",
"STR/SABR1CDU.STR",
"STR/FLLINTRO.STR",
"STR/SAR1ECOR.STR",
"STR/AS2R1ROB.STR",
"STR/MIR2ORBS.STR",
"STR/MARBEAMS.STR",
"STR/LOI2.STR",
"STR/SAR1GENE.STR",
"STR/BILR1.STR",
"STR/AS2R1ROO.STR",
"STR/ASR1BESW.STR",
"STR/LOLOOP.STR",
"STR/FAINTROD.STR",
"STR/GEZMOLES.STR",
"STR/V1IN.STR",
"STR/FUCV4.STR",
"STR/SAIECORO.STR",
"STR/MIR1SWIT.STR",
"STR/LOINTRO.STR",
"STR/SAR2GENE.STR",
"STR/MUVICTOR.STR",
"STR/SAR1MCAN.STR",
"STR/FUCV7.STR",
"STR/MIZ1ORBS.STR",
"STR/FUCV8.STR",
"STR/BILR2.STR",
"STR/FUCV6.STR",
"STR/FUCV3.STR",
"STR/PLLBLOWU.STR",
"STR/PLBMAIN.STR",
"STR/WARESOLU.STR",
"STR/EIRACER.STR",
"STR/MAZDONAT.STR",
"STR/MAZBEAMS.STR",
"STR/MIISWITC.STR",
"STR/FIBRTVIL.STR",
"STR/FIBRTMIS.STR",
"STR/SABR1PAR.STR",
"STR/NDINTRO.STR",
"STR/GORDOWN.STR",
"STR/GORUP.STR",
"STR/SA3IRAMS.STR",
"STR/YERESOLU.STR",
"STR/EIFLUT.STR",
"STR/GRSDSACR.STR",
"STR/EXR1.STR",
"STR/SCRESOLU.STR",
"STR/FIRESOLU.STR",
"STR/SIHITEST.STR",
"STR/GAI1.STR",
"STR/EXRESOLU.STR",
"STR/MIZ2ORBS.STR",
"STR/ASIRBIKE.STR",
"STR/GRSOBBEC.STR",
"STR/BIINTROD.STR",
"STR/GRSOBBNC.STR",
"STR/AS2IROBB.STR",
"STR/GRSOBFIN.STR",
"STR/RERESOLU.STR",
"STR/BLRESOLU.STR",
"STR/SABIPARM.STR",
"STR/EVMEND.STR",
"STR/AS2RESOL.STR",
"STR/SAIMCANN.STR",
"STR/MIIGNAWE.STR",
"STR/GRSOBBA.STR",
"STR/GRSINTRO.STR",
"STR/SAISE.STR",
"STR/SA3IDECO.STR",
"STR/ASFRESOL.STR",
"STR/EXINTROD.STR",
"STR/BILINTRO.STR",
"STR/FIINTROD.STR",
"STR/MAINTROD.STR",
"STR/SCINTROD.STR",
"STR/AS2IFLUT.STR",
"STR/ASLERESO.STR",
"STR/ASLSRESO.STR",
"STR/AS2IROOM.STR",
"STR/GRSRESOL.STR",
"STR/SABICDUS.STR",
"STR/SIHISB.STR",
"STR/ASIBESWI.STR",
"STR/BILBRESO.STR",
"STR/FIBRT1AL.STR",
"STR/AS2INTRO.STR",
"STR/GEINTROD.STR",
"STR/SAISD1.STR",
"STR/SAISA.STR",
"STR/SIHISC.STR",
"STR/MIIORBS.STR",
"STR/WAINTROD.STR",
"STR/SAISD2.STR",
"STR/GRSOPREB.STR",
"STR/GRSOBBB.STR",
"STR/SA3INTRO.STR"
],
// some objects are directly stored as files on the DVD. This is just text files.
"object_file_names": [
"TEXT/0COMMON.TXT",
"TEXT/1COMMON.TXT",
"TEXT/2COMMON.TXT",
"TEXT/3COMMON.TXT",
"TEXT/4COMMON.TXT",
"TEXT/5COMMON.TXT",
"TEXT/6COMMON.TXT"
]
}

View file

@ -25,20 +25,20 @@ int main(int argc, char** argv) {
}
// collect all files to process
set_config(argv[1]);
auto config = read_config_file(argv[1]);
std::string in_folder = argv[2];
std::string out_folder = argv[3];
std::vector<std::string> dgos, objs, strs;
for (const auto& dgo_name : get_config().dgo_names) {
for (const auto& dgo_name : config.dgo_names) {
dgos.push_back(file_util::combine_path(in_folder, dgo_name));
}
for (const auto& obj_name : get_config().object_file_names) {
for (const auto& obj_name : config.object_file_names) {
objs.push_back(file_util::combine_path(in_folder, obj_name));
}
for (const auto& str_name : get_config().str_file_names) {
for (const auto& str_name : config.str_file_names) {
strs.push_back(file_util::combine_path(in_folder, str_name));
}
@ -46,7 +46,7 @@ int main(int argc, char** argv) {
// build file database
lg::info("Setting up object file DB...");
ObjectFileDB db(dgos, get_config().obj_file_name_map_file, objs, strs);
ObjectFileDB db(dgos, config.obj_file_name_map_file, objs, strs, config);
// write out DGO file info
file_util::write_text_file(file_util::combine_path(out_folder, "dgo.txt"),
@ -56,57 +56,58 @@ int main(int argc, char** argv) {
db.generate_obj_listing());
// dump raw objs
if (get_config().dump_objs) {
if (config.dump_objs) {
auto path = file_util::combine_path(out_folder, "raw_obj");
file_util::create_dir_if_needed(path);
db.dump_raw_objects(path);
}
// process files (required for all analysis)
db.process_link_data();
db.find_code();
db.process_link_data(config);
db.find_code(config);
db.process_labels();
// print disassembly
if (get_config().disassemble_code || get_config().disassemble_data) {
db.write_disassembly(out_folder, get_config().disassemble_data, get_config().disassemble_code);
if (config.disassemble_code || config.disassemble_data) {
db.write_disassembly(out_folder, config.disassemble_data, config.disassemble_code,
config.write_hex_near_instructions);
}
// regenerate all-types if needed
if (get_config().regenerate_all_types) {
db.analyze_functions_ir1();
if (config.regenerate_all_types) {
db.analyze_functions_ir1(config);
file_util::write_text_file(file_util::combine_path(out_folder, "type_defs.gc"),
db.all_type_defs);
}
// main decompile.
if (get_config().decompile_code) {
db.analyze_functions_ir2(out_folder);
if (config.decompile_code) {
db.analyze_functions_ir2(out_folder, config);
}
// write out all symbols TODO - organize by file
file_util::write_text_file(file_util::combine_path(out_folder, "all-syms.gc"),
db.dts.dump_symbol_types());
if (get_config().hexdump_code || get_config().hexdump_data) {
db.write_object_file_words(out_folder, get_config().hexdump_data, get_config().hexdump_code);
if (config.hexdump_code || config.hexdump_data) {
db.write_object_file_words(out_folder, config.hexdump_data, config.hexdump_code);
}
// data stuff
if (get_config().write_scripts) {
if (config.write_scripts) {
db.find_and_write_scripts(out_folder);
}
if (get_config().process_game_text) {
if (config.process_game_text) {
auto result = db.process_game_text_files();
file_util::write_text_file(file_util::get_file_path({"assets", "game_text.txt"}), result);
}
if (get_config().process_tpages) {
if (config.process_tpages) {
db.process_tpages();
}
if (get_config().process_game_count) {
if (config.process_game_count) {
auto result = db.process_game_count_file();
file_util::write_text_file(file_util::get_file_path({"assets", "game_count.txt"}), result);
}

View file

@ -8,7 +8,6 @@ echo "======================================="
echo ""
echo " ================= Cloning..."
cd ../..
ISO_DATA_PATH=${1}
BRANCH_NAME=${2:-master}
# Provide a default location to bind the ISO_DATA_PATH
@ -42,19 +41,22 @@ make -j
echo " ================ Running unit tests..."
../test.sh
echo " ================ Running offline decompiler tests..."
./offline-test
echo " ================ Decompiling..."
../decomp.sh
../scripts/shell/decomp.sh
echo " ================ Building assets..."
../gc.sh -cmd \(build-data\)
../scripts/shell/gc.sh -cmd \(build-data\)
echo " ================ Checking assets..."
../check.sh
../scripts/shell/check.sh
echo " ================ Building game..."
../gc.sh -cmd \(build-game\)
../scripts/shell/gc.sh -cmd \(build-game\)
echo " ================ Booting game..."
../boot_game.sh
../scripts/shell/boot_game.sh
echo "Offline test has completed successfully!"

View file

@ -206,18 +206,19 @@ int main(int argc, char** argv) {
class OfflineDecompilation : public ::testing::Test {
protected:
static std::unique_ptr<decompiler::ObjectFileDB> db;
static std::unique_ptr<decompiler::Config> config;
static void SetUpTestCase() {
// global setup
file_util::init_crc();
decompiler::init_opcode_info();
decompiler::set_config(
file_util::get_file_path({"decompiler", "config", "jak1_ntsc_black_label.jsonc"}));
config = std::make_unique<decompiler::Config>(decompiler::read_config_file(
file_util::get_file_path({"decompiler", "config", "jak1_ntsc_black_label.jsonc"})));
std::unordered_set<std::string> object_files;
for (auto& p : g_object_files_to_decompile_or_ref_check) {
object_files.insert(p.first);
}
decompiler::get_config().allowed_objects = object_files;
config->allowed_objects = object_files;
std::vector<std::string> dgos = {"CGO/KERNEL.CGO", "CGO/ENGINE.CGO"};
std::vector<std::string> dgo_paths;
@ -231,23 +232,27 @@ class OfflineDecompilation : public ::testing::Test {
}
}
db = std::make_unique<decompiler::ObjectFileDB>(
dgo_paths, decompiler::get_config().obj_file_name_map_file, std::vector<std::string>{},
std::vector<std::string>{});
db = std::make_unique<decompiler::ObjectFileDB>(dgo_paths, config->obj_file_name_map_file,
std::vector<std::string>{},
std::vector<std::string>{}, *config);
// basic processing to find functions/data/disassembly
db->process_link_data();
db->find_code();
db->process_link_data(*config);
db->find_code(*config);
db->process_labels();
// fancy decompilation.
db->analyze_functions_ir2({});
db->analyze_functions_ir2({}, *config);
}
static void TearDownTestCase() { db.reset(); }
static void TearDownTestCase() {
db.reset();
config.reset();
}
};
std::unique_ptr<decompiler::ObjectFileDB> OfflineDecompilation::db;
std::unique_ptr<decompiler::Config> OfflineDecompilation::config;
/*!
* Check that the most basic disassembly into files/functions/instructions has succeeded.
@ -263,7 +268,7 @@ TEST_F(OfflineDecompilation, CheckBasicDecode) {
EXPECT_EQ(stats.n_fp_reg_use, stats.n_fp_reg_use_resolved);
});
EXPECT_EQ(obj_count, decompiler::get_config().allowed_objects.size());
EXPECT_EQ(obj_count, config->allowed_objects.size());
}
/*!
@ -302,7 +307,7 @@ TEST_F(OfflineDecompilation, FunctionDetect) {
});
// one login per object file
EXPECT_EQ(decompiler::get_config().allowed_objects.size(), login_count);
EXPECT_EQ(config->allowed_objects.size(), login_count);
// not many lambdas.
EXPECT_TRUE(unknown_count < 10);