mirror of
https://github.com/open-goal/jak-project
synced 2026-08-22 07:04:29 -04:00
add types
This commit is contained in:
@@ -239,7 +239,13 @@ StructureDefResult parse_structure_def(StructureType* type,
|
||||
result.generate_runtime_type = false;
|
||||
} else if (opt_name == ":pack-me") {
|
||||
result.pack_me = true;
|
||||
} else {
|
||||
} else if (opt_name == ":heap-base") {
|
||||
u16 hb = get_int(car(rest));
|
||||
rest = cdr(rest);
|
||||
flags.heap_base = hb;
|
||||
}
|
||||
|
||||
else {
|
||||
throw std::runtime_error("Invalid option in field specification: " + opt_name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,10 +312,13 @@ bool get_ptr_offset(IR* ir, Register dst, Register base, int* result) {
|
||||
get_ptr_offset_zero(as_math, base, result);
|
||||
}
|
||||
|
||||
bool is_weird(Function& function, LinkedObjectFile& file, TypeInspectorResult* result) {
|
||||
int get_start_idx(Function& function,
|
||||
LinkedObjectFile& file,
|
||||
TypeInspectorResult* result,
|
||||
const std::string& parent_type) {
|
||||
if (function.basic_blocks.size() > 1) {
|
||||
result->warnings += " too many basic blocks";
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -341,64 +344,94 @@ bool is_weird(Function& function, LinkedObjectFile& file, TypeInspectorResult* r
|
||||
// check size
|
||||
if (function.basic_ops.size() < 7) {
|
||||
result->warnings += " not enough basic ops";
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& move_op = function.basic_ops.at(0);
|
||||
if (!is_reg_reg_move(move_op.get(), make_gpr(Reg::GP), make_gpr(Reg::A0))) {
|
||||
result->warnings += "bad first move";
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& get_format_op = function.basic_ops.at(1);
|
||||
if (!is_get_sym_value(get_format_op.get(), make_gpr(Reg::T9), "format")) {
|
||||
result->warnings += "bad get format";
|
||||
return true;
|
||||
|
||||
if (is_get_sym_value(get_format_op.get(), make_gpr(Reg::T9), "format")) {
|
||||
|
||||
auto& get_true = function.basic_ops.at(2);
|
||||
if (!is_get_sym(get_true.get(), make_gpr(Reg::A0), "#t")) {
|
||||
result->warnings += "bad get true";
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& get_str = function.basic_ops.at(3);
|
||||
if (!is_get_label(get_str.get(), make_gpr(Reg::A1))) {
|
||||
result->warnings += "bad get label";
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto str = file.get_goal_string_by_label(file.labels.at(get_label_id_of_set(get_str.get())));
|
||||
if (str != "[~8x] ~A~%") {
|
||||
result->warnings += "bad type dec string: " + str;
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& move2_op = function.basic_ops.at(4);
|
||||
if (!is_reg_reg_move(move2_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP))) {
|
||||
result->warnings += "bad second move";
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& load_op = function.basic_ops.at(5);
|
||||
bool is_basic_load = is_get_load_with_offset(load_op.get(), make_gpr(Reg::A3),
|
||||
IR_Load::UNSIGNED, 4, make_gpr(Reg::GP), -4);
|
||||
result->is_basic = is_basic_load;
|
||||
|
||||
bool is_struct_load = is_get_sym(load_op.get(), make_gpr(Reg::A3), function.method_of_type);
|
||||
|
||||
if (!is_basic_load && !is_struct_load) {
|
||||
result->warnings += "bad load";
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& call = function.basic_ops.at(6);
|
||||
if (!dynamic_cast<IR_Call*>(call.get())) {
|
||||
result->warnings += "bad call";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// okay!
|
||||
return 7;
|
||||
} else {
|
||||
if (is_get_sym_value(get_format_op.get(), make_gpr(Reg::V1), parent_type)) {
|
||||
// now get the inspect method.
|
||||
auto& get_method_op = function.basic_ops.at(2);
|
||||
if (!is_get_load_with_offset(get_method_op.get(), make_gpr(Reg::T9), IR_Load::UNSIGNED, 4,
|
||||
make_gpr(Reg::V1), 28)) {
|
||||
result->warnings += "bad get method op " + get_method_op->print(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& move2_op = function.basic_ops.at(3);
|
||||
if (!is_reg_reg_move(move2_op.get(), make_gpr(Reg::A0), make_gpr(Reg::GP))) {
|
||||
result->warnings += "bad move2 op " + move2_op->print(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto& call_op = function.basic_ops.at(4);
|
||||
if (!dynamic_cast<IR_Call*>(call_op.get())) {
|
||||
result->warnings += "bad call op " + call_op->print(file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
result->warnings += "inherited inpspect of " + parent_type;
|
||||
result->is_basic = true;
|
||||
return 5;
|
||||
|
||||
} else {
|
||||
result->warnings += "unrecognized get op: " + get_format_op->print(file) + " parent was " + parent_type;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
auto& get_true = function.basic_ops.at(2);
|
||||
if (!is_get_sym(get_true.get(), make_gpr(Reg::A0), "#t")) {
|
||||
result->warnings += "bad get true";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& get_str = function.basic_ops.at(3);
|
||||
if (!is_get_label(get_str.get(), make_gpr(Reg::A1))) {
|
||||
result->warnings += "bad get label";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto str = file.get_goal_string_by_label(file.labels.at(get_label_id_of_set(get_str.get())));
|
||||
if (str != "[~8x] ~A~%") {
|
||||
result->warnings += "bad type dec string: " + str;
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& move2_op = function.basic_ops.at(4);
|
||||
if (!is_reg_reg_move(move2_op.get(), make_gpr(Reg::A2), make_gpr(Reg::GP))) {
|
||||
result->warnings += "bad second move";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& load_op = function.basic_ops.at(5);
|
||||
bool is_basic_load = is_get_load_with_offset(load_op.get(), make_gpr(Reg::A3), IR_Load::UNSIGNED,
|
||||
4, make_gpr(Reg::GP), -4);
|
||||
result->is_basic = is_basic_load;
|
||||
|
||||
bool is_struct_load = is_get_sym(load_op.get(), make_gpr(Reg::A3), function.method_of_type);
|
||||
|
||||
if (!is_basic_load && !is_struct_load) {
|
||||
result->warnings += "bad load";
|
||||
return true;
|
||||
}
|
||||
|
||||
auto& call = function.basic_ops.at(6);
|
||||
if (!dynamic_cast<IR_Call*>(call.get())) {
|
||||
result->warnings += "bad call";
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int identify_basic_field(int idx,
|
||||
@@ -706,11 +739,11 @@ TypeInspectorResult inspect_inspect_method(Function& inspect,
|
||||
assert(flags.pad == 0);
|
||||
|
||||
auto& bad_set = get_config().bad_inspect_types;
|
||||
if (is_weird(inspect, file, &result) || bad_set.find(type_name) != bad_set.end()) {
|
||||
int idx = get_start_idx(inspect, file, &result, result.parent_type_name);
|
||||
if (idx == 0 || bad_set.find(type_name) != bad_set.end()) {
|
||||
// printf("was weird: %s\n", result.warnings.c_str());
|
||||
return result;
|
||||
}
|
||||
int idx = 7;
|
||||
while (idx < int(inspect.basic_ops.size()) - 1 && idx != -1) {
|
||||
idx = detect(idx, inspect, file, &result);
|
||||
}
|
||||
|
||||
+28953
-133
File diff suppressed because it is too large
Load Diff
@@ -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,
|
||||
@@ -34,7 +34,8 @@
|
||||
"types_with_bad_inspect_methods":[
|
||||
"engine",
|
||||
"bsp-header",
|
||||
"joint-anim-matrix"
|
||||
"joint-anim-matrix",
|
||||
"part-tracker"
|
||||
],
|
||||
|
||||
"asm_functions_by_name":[
|
||||
|
||||
@@ -58,6 +58,19 @@ void DecompilerTypeSystem::parse_type_defs(const std::vector<std::string>& file_
|
||||
|
||||
} else if (car(o).as_symbol()->name == "deftype") {
|
||||
parse_deftype(cdr(o), &ts);
|
||||
} else if (car(o).as_symbol()->name == "declare-type") {
|
||||
auto* rest = &cdr(o);
|
||||
auto type_name = car(*rest);
|
||||
rest = &cdr(*rest);
|
||||
auto type_kind = car(*rest);
|
||||
if (!cdr(*rest).is_empty_list()) {
|
||||
throw std::runtime_error("malformed declare-type");
|
||||
}
|
||||
if (type_kind.as_symbol()->name == "basic") {
|
||||
ts.forward_declare_type_as_basic(type_name.as_symbol()->name);
|
||||
} else {
|
||||
throw std::runtime_error("bad declare-type");
|
||||
}
|
||||
} else {
|
||||
throw std::runtime_error("Decompiler cannot parse " + car(o).print());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user