add types

This commit is contained in:
water
2020-10-25 12:07:10 -04:00
parent b56025412b
commit 15a66d9c62
5 changed files with 29064 additions and 191 deletions
+7 -1
View File
@@ -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);
}
}
+86 -53
View File
@@ -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);
}
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":[
+13
View File
@@ -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());
}