2020-08-22 23:30:17 -04:00
|
|
|
#include "config.h"
|
|
|
|
#include "third-party/json.hpp"
|
2021-02-09 20:59:14 -05:00
|
|
|
#include "third-party/fmt/core.h"
|
2020-09-10 20:03:31 -04:00
|
|
|
#include "common/util/FileUtil.h"
|
2021-03-13 16:10:39 -05:00
|
|
|
#include "common/util/json_util.h"
|
2021-03-27 15:18:59 -04:00
|
|
|
#include "decompiler/util/config_parsers.h"
|
2020-08-22 23:30:17 -04:00
|
|
|
|
2021-01-06 20:04:15 -05:00
|
|
|
namespace decompiler {
|
2020-08-22 23:30:17 -04:00
|
|
|
|
2020-12-26 11:09:59 -05:00
|
|
|
namespace {
|
|
|
|
/*!
|
|
|
|
* Read an entry from cfg containing the name of a json file, and parse that file.
|
|
|
|
* Relative to jak-project directory.
|
|
|
|
*/
|
|
|
|
nlohmann::json read_json_file_from_config(const nlohmann::json& cfg, const std::string& file_key) {
|
|
|
|
auto file_name = cfg.at(file_key).get<std::string>();
|
|
|
|
auto file_txt = file_util::read_text_file(file_util::get_file_path({file_name}));
|
2021-05-11 21:57:05 -04:00
|
|
|
return parse_commented_json(file_txt, file_name);
|
2020-12-26 11:09:59 -05:00
|
|
|
}
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
/*!
|
2021-05-11 20:49:54 -04:00
|
|
|
* Parse the main config file and return decompiler config.
|
2020-12-26 11:09:59 -05:00
|
|
|
*/
|
2021-05-11 20:49:54 -04:00
|
|
|
Config read_config_file(const std::string& path_to_config_file) {
|
|
|
|
Config config;
|
2020-09-10 20:03:31 -04:00
|
|
|
auto config_str = file_util::read_text_file(path_to_config_file);
|
2021-05-11 21:57:05 -04:00
|
|
|
auto cfg = parse_commented_json(config_str, path_to_config_file);
|
2020-08-22 23:30:17 -04:00
|
|
|
|
2021-05-11 20:49:54 -04:00
|
|
|
config.game_version = cfg.at("game_version").get<int>();
|
2020-08-22 23:30:17 -04:00
|
|
|
|
2021-05-11 20:49:54 -04:00
|
|
|
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>>();
|
2020-10-24 22:51:40 -04:00
|
|
|
|
2021-05-11 20:49:54 -04:00
|
|
|
if (cfg.contains("obj_file_name_map_file")) {
|
|
|
|
config.obj_file_name_map_file = cfg.at("obj_file_name_map_file").get<std::string>();
|
2020-10-24 22:51:40 -04:00
|
|
|
}
|
2021-05-11 20:49:54 -04:00
|
|
|
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>();
|
2021-05-24 19:52:19 -04:00
|
|
|
config.print_cfgs = cfg.at("print_cfgs").get<bool>();
|
2020-12-17 15:48:07 -05:00
|
|
|
|
2021-02-01 20:41:37 -05:00
|
|
|
auto allowed = cfg.at("allowed_objects").get<std::vector<std::string>>();
|
|
|
|
for (const auto& x : allowed) {
|
2021-05-11 20:49:54 -04:00
|
|
|
config.allowed_objects.insert(x);
|
2021-02-01 20:41:37 -05:00
|
|
|
}
|
|
|
|
|
2021-03-13 16:10:39 -05:00
|
|
|
auto type_casts_json = read_json_file_from_config(cfg, "type_casts_file");
|
|
|
|
for (auto& kv : type_casts_json.items()) {
|
2020-12-17 15:48:07 -05:00
|
|
|
auto& function_name = kv.key();
|
2021-03-13 16:10:39 -05:00
|
|
|
auto& casts = kv.value();
|
|
|
|
for (auto& cast : casts) {
|
|
|
|
auto idx_range = parse_json_optional_integer_range(cast.at(0));
|
|
|
|
for (auto idx : idx_range) {
|
|
|
|
TypeCast type_cast;
|
|
|
|
type_cast.atomic_op_idx = idx;
|
|
|
|
type_cast.reg = Register(cast.at(1));
|
|
|
|
type_cast.type_name = cast.at(2).get<std::string>();
|
2021-05-11 20:49:54 -04:00
|
|
|
config.type_casts_by_function_by_atomic_op_idx[function_name][idx].push_back(type_cast);
|
2020-12-17 15:48:07 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-12-26 11:09:59 -05:00
|
|
|
|
|
|
|
auto anon_func_json = read_json_file_from_config(cfg, "anonymous_function_types_file");
|
|
|
|
for (auto& kv : anon_func_json.items()) {
|
|
|
|
auto& obj_file_name = kv.key();
|
|
|
|
auto& anon_types = kv.value();
|
|
|
|
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>();
|
2021-05-11 20:49:54 -04:00
|
|
|
config.anon_function_types_by_obj_by_id[obj_file_name][id] = type_name;
|
2020-12-26 11:09:59 -05:00
|
|
|
}
|
|
|
|
}
|
2021-02-09 20:59:14 -05:00
|
|
|
auto var_names_json = read_json_file_from_config(cfg, "var_names_file");
|
|
|
|
for (auto& kv : var_names_json.items()) {
|
|
|
|
auto& function_name = kv.key();
|
|
|
|
auto arg = kv.value().find("args");
|
|
|
|
if (arg != kv.value().end()) {
|
|
|
|
for (auto& x : arg.value()) {
|
2021-05-11 20:49:54 -04:00
|
|
|
config.function_arg_names[function_name].push_back(x);
|
2021-02-09 20:59:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
auto var = kv.value().find("vars");
|
|
|
|
if (var != kv.value().end()) {
|
2021-03-13 16:10:39 -05:00
|
|
|
for (auto& vkv : var->get<std::unordered_map<std::string, nlohmann::json>>()) {
|
|
|
|
LocalVarOverride override;
|
|
|
|
if (vkv.second.is_string()) {
|
|
|
|
override.name = vkv.second.get<std::string>();
|
|
|
|
} else if (vkv.second.is_array()) {
|
|
|
|
override.name = vkv.second[0].get<std::string>();
|
|
|
|
override.type = vkv.second[1].get<std::string>();
|
|
|
|
} else {
|
|
|
|
throw std::runtime_error("Invalid function var override.");
|
|
|
|
}
|
2021-05-11 20:49:54 -04:00
|
|
|
config.function_var_overrides[function_name][vkv.first] = override;
|
2021-02-09 20:59:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-02-20 11:42:46 -05:00
|
|
|
|
|
|
|
auto label_types_json = read_json_file_from_config(cfg, "label_types_file");
|
|
|
|
for (auto& kv : label_types_json.items()) {
|
|
|
|
auto& obj_name = kv.key();
|
|
|
|
auto& types = kv.value();
|
|
|
|
for (auto& x : types) {
|
|
|
|
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>();
|
2021-05-11 20:49:54 -04:00
|
|
|
auto& config_entry = config.label_types[obj_name][name];
|
2021-02-27 14:40:18 -05:00
|
|
|
config_entry = {type_name, is_const, {}};
|
|
|
|
if (x.size() > 3) {
|
|
|
|
config_entry.array_size = x.at(3).get<int>();
|
|
|
|
}
|
2021-02-20 11:42:46 -05:00
|
|
|
}
|
|
|
|
}
|
2021-03-27 15:18:59 -04:00
|
|
|
|
|
|
|
auto stack_vars_json = read_json_file_from_config(cfg, "stack_vars_file");
|
|
|
|
for (auto& kv : stack_vars_json.items()) {
|
|
|
|
auto& func_name = kv.key();
|
|
|
|
auto& stack_vars = kv.value();
|
2021-05-11 20:49:54 -04:00
|
|
|
config.stack_var_hints_by_function[func_name] = parse_stack_var_hints(stack_vars);
|
2021-03-27 15:18:59 -04:00
|
|
|
}
|
2021-05-11 20:49:54 -04:00
|
|
|
|
|
|
|
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>>();
|
2021-05-30 19:57:11 -04:00
|
|
|
config.hacks.reject_cond_to_value = hacks_json.at("aggressively_reject_cond_to_value_rewrite")
|
|
|
|
.get<std::unordered_set<std::string>>();
|
2021-05-24 19:52:19 -04:00
|
|
|
|
|
|
|
for (auto& entry : hacks_json.at("cond_with_else_max_lengths")) {
|
|
|
|
auto func_name = entry.at(0).get<std::string>();
|
|
|
|
auto cond_name = entry.at(1).get<std::string>();
|
|
|
|
auto max_len = entry.at(2).get<int>();
|
|
|
|
config.hacks.cond_with_else_len_by_func_name[func_name].max_length_by_start_block[cond_name] =
|
|
|
|
max_len;
|
|
|
|
}
|
2021-05-11 20:49:54 -04:00
|
|
|
return config;
|
2020-10-15 20:59:30 -04:00
|
|
|
}
|
2021-03-27 15:18:59 -04:00
|
|
|
|
2021-01-06 20:04:15 -05:00
|
|
|
} // namespace decompiler
|