#pragma once #include #include #include #include #include #include "decompiler/Disasm/Register.h" #include "decompiler/data/game_text.h" namespace decompiler { struct RegisterTypeCast { int atomic_op_idx = -1; Register reg; std::string type_name; }; struct StackTypeCast { int stack_offset = -1; std::string type_name; }; struct LabelConfigInfo { // if the label is a "value" type, it will be loaded directly into a register. // in all cases, this is a constant, either a 64-bit integer or a float. // For example: // ld v1, L346(fp) // lwc1 f0, L345(fp) // lw a0, L41(fp) // if the label is not a value type, it's a reference type, and the GOAL variable is a pointer. bool is_value = false; // the type of the resulting GOAL variable. std::string type_name; // if the type is a (pointer x) or (inline-array x), the size must be specified here. // For a boxed array (array x), the size will be figured out automatically std::optional array_size; }; struct LocalVarOverride { std::string name; // this may be left out, indicating that the variable should use the type determined // by the type analysis pass. std::optional type; }; /*! * Information about a structure on the stack. */ struct StackStructureHint { std::string element_type; // type of the thing stored // todo - is boxed array on the stack supported? enum class ContainerType { NONE, // just store the plain thing. ARRAY, // for refs, array of refs. For values, array of values. INLINE_ARRAY // for refs, array of values, for values, invalid } container_type = ContainerType::NONE; int container_size = -1; // if container other than NONE, the number of elements. int stack_offset = 0; // where it's located on the stack (relative to sp after prologue) }; struct CondWithElseLengthHack { std::unordered_map max_length_by_start_block; }; struct DecompileHacks { std::unordered_set types_with_bad_inspect_methods; std::unordered_set no_type_analysis_functions_by_name; std::unordered_set hint_inline_assembly_functions; std::unordered_set asm_functions_by_name; std::unordered_set pair_functions_by_name; std::unordered_map cond_with_else_len_by_func_name; std::unordered_set reject_cond_to_value; std::unordered_map> blocks_ending_in_asm_branch_by_func_name; std::unordered_map>> format_ops_with_dynamic_string_by_func_name; std::unordered_set mips2c_functions_by_name; std::unordered_map> mips2c_jump_table_functions; std::unordered_map>> missing_textures_by_level; }; struct Config { int game_version = -1; std::vector dgo_names; std::vector object_file_names; std::vector str_file_names; std::string audio_dir_file_name; std::vector streamed_audio_file_names; std::string obj_file_name_map_file; bool disassemble_code = false; bool decompile_code = false; bool write_scripts = false; bool disassemble_data = false; bool process_tpages = false; bool process_game_text = false; bool process_game_count = false; bool rip_levels = false; bool regenerate_all_types = false; bool write_hex_near_instructions = false; bool hexdump_code = false; bool hexdump_data = false; bool dump_objs = false; bool print_cfgs = false; bool generate_symbol_definition_map = false; bool is_pal = false; std::string game_name; std::string expected_elf_name; GameTextVersion text_version = GameTextVersion::JAK1_V1; std::unordered_set allowed_objects; std::unordered_set banned_objects; std::unordered_set merged_objects; std::unordered_map>> register_type_casts_by_function_by_atomic_op_idx; std::unordered_map> stack_type_casts_by_function_by_stack_offset; std::unordered_map> anon_function_types_by_obj_by_id; std::unordered_map> function_arg_names; std::unordered_map> function_var_overrides; std::unordered_map> label_types; std::unordered_map> stack_structure_hints_by_function; std::unordered_map bad_format_strings; std::vector levels_to_extract; bool levels_extract; DecompileHacks hacks; }; Config read_config_file(const std::string& path_to_config_file, const std::map& overrides); } // namespace decompiler