Exemplo n.º 1
0
def sub_80E72C8_fix_extra_vars_0x74_read(opcode_params, funcstate, src_file,
                                         fileline):
    if opcode_params[0] == "r0" and opcode_params[1] == "r5":
        funcstate.regs["r0"].set_new_reg(
            analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
        return False
    return True
Exemplo n.º 2
0
def sub_80103F8_hack_battle_obj_null(opcode_params, funcstate, src_file,
                                     fileline):
    if opcode_params[0] != "r7":
        return True
    funcstate.regs["r7"].set_new_reg(
        analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
    return False
Exemplo n.º 3
0
def hack_battle_state_field_0x80_object_read(opcode_params, funcstate,
                                             src_file, fileline):
    if opcode_params[0] == "r7" and opcode_params[1] == "r4":
        funcstate.regs["r7"].set_new_reg(
            analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
        return False
    return True
Exemplo n.º 4
0
def check_sub_802EF74_tst(opcode_params, funcstate, src_file, fileline):
    if opcode_params[0] == "r7":
        funcstate.regs["r7"].set_new_reg(
            analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
        return False

    return True
Exemplo n.º 5
0
def check_stored_functions(opcode_params, funcstate, src_file, fileline):
    if opcode_params.startswith("nullsub"):
        return False
    elif opcode_params not in analyzer.template_functions:
        return True

    return_values = analyzer.template_functions[opcode_params]
    for return_value in return_values:
        funcstate.regs[return_value.regname].set_new_reg(analyzer.RegisterInfo(return_value.datatype().wrap(), fileline))

    fileline_msg("Called stored function \"%s\"." % opcode_params, fileline)
    return False
Exemplo n.º 6
0
def sub_80E1566_fix_sub_80E1670_return_value(opcode_params, funcstate,
                                             src_file, fileline):
    funcstate.regs["r0"].set_new_reg(
        analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
    return True
Exemplo n.º 7
0
def sub_80DCA38_fix_uninitialized_stack_read(opcode_params, funcstate,
                                             src_file, fileline):
    if opcode_params[1] == "r6":
        funcstate.regs["r6"].set_new_reg(
            analyzer.RegisterInfo(datatypes.Primitive().wrap(), fileline))
    return True
Exemplo n.º 8
0
def sub_80BC670_set_r0_battle_object(opcode_params, funcstate, src_file,
                                     fileline):
    funcstate.regs["r0"].set_new_reg(
        analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
    return True
Exemplo n.º 9
0
def object_get_panel_region_set_correct_return_value(opcode_params, funcstate,
                                                     src_file, fileline):
    funcstate.regs["r0"].set_new_reg(
        analyzer.RegisterInfo(datatypes.Primitive().wrap(), fileline))
    return True
Exemplo n.º 10
0
def check_bl_sub_80BC3B8(opcode_params, funcstate, src_file, fileline):
    if opcode_params == "sub_80BC3B8":
        funcstate.regs["r0"].set_new_reg(
            analyzer.RegisterInfo(datatypes.BattleObject().wrap(), fileline))
    return True
Exemplo n.º 11
0
def sub_8109D08_bx_callback_fix(opcode_params, funcstate, src_file, fileline):
    funcstate.regs["r1"].set_new_reg(
        analyzer.RegisterInfo(
            datatypes.ROMPointer([syms["sub_810A21A"], syms["sub_810A254"]],
                                 syms["off_810A2B0"]).wrap(), fileline))
    return True
Exemplo n.º 12
0
def check_sub_8013892_push_r7(opcode_params, funcstate, src_file, fileline):
    if opcode_params == "{r7}":
        funcstate.regs["r4"].set_new_reg(
            analyzer.RegisterInfo(datatypes.AIData().wrap(), fileline))
    return True
Exemplo n.º 13
0
def check_sub_80127C0(opcode_params, funcstate, src_file, fileline):
    funcstate.regs["r6"].set_new_reg(
        analyzer.RegisterInfo(datatypes.Primitive(Size.BYTE).wrap(), fileline))
    funcstate.regs["r4"].set_new_reg(
        analyzer.RegisterInfo(datatypes.Primitive().wrap(), fileline))
    return False
Exemplo n.º 14
0
def check_loc_800EA38(opcode_params, funcstate, src_file, fileline):
    funcstate.regs["r3"].set_new_reg(
        analyzer.RegisterInfo(
            datatypes.Primitive(Size.BYTE, 0x8c).wrap(), fileline))
    return True
Exemplo n.º 15
0
def run_analyzer_common(src_file, funcstate, function_start_time):
    function_total_time = 0
    return_lr = funcstate.regs["lr"].data
    base_stack_offset = funcstate.regs["sp"].data.ref.offset
    function_name = funcstate.function.name
    function_filename = funcstate.function.filename
    #function_tree = collections.OrderedDict()

    debug_print("funcstart: base stack offset: %s, function: %s (%s:%s)" %
                (base_stack_offset, function_name, function_filename,
                 funcstate.function.line_num + 1))
    return_regs = None
    return_pc = None
    return_stack = None

    funcstate.regs["pc"].set_new_reg(
        RegisterInfo(
            datatypes.ProgramCounter(src_file.filename,
                                     src_file.line_num).wrap(),
            FileLine(src_file.filename, src_file.line_num)))

    add_function_specific_callbacks(funcstate.function.value)

    while True:
        debug_print("start src_file: %s:%s" %
                    (src_file.filename, src_file.line_num + 1))
        for line in src_file:
            #if funcstate.function.value == 0x80BE8AE: # sub_80BE8AE
            #    debug_print("cur src_file: %s:%s" % (src_file.filename, src_file.line_num + 1))
            if not line.startswith("\t"):
                split_line = line.split(":", 1)
                # if we're currently in an unconditional branch, don't read opcodes until we find the label
                if funcstate.uncond_branch != "":
                    if funcstate.uncond_branch != split_line[0]:
                        continue
                    funcstate.uncond_branch = ""
                funcstate.found_labels[split_line[0]] = FileLine(
                    src_file.filename, src_file.line_num)
                if len(split_line) > 1:
                    line = split_line[1]
                else:
                    continue

            if line.strip() == "":
                continue
            elif funcstate.uncond_branch != "":
                continue

            funcstate.regs["pc"].data.ref.line_num = src_file.line_num
            pc_fileline = funcstate.regs["pc"][-1].fileline

            fileline = FileLine(src_file.filename, src_file.line_num)
            analyze_source.global_fileline = fileline
            if opcodes.read_opcode(line, funcstate, src_file, fileline):
                new_pc_fileline = funcstate.regs["pc"][-1].fileline
                if new_pc_fileline.line_num != pc_fileline.line_num or new_pc_fileline.filename != pc_fileline.filename:
                    sp_datatype_ref = funcstate.regs["sp"].data.ref
                    pc_datatype_ref = funcstate.regs["pc"].data.ref
                    try:
                        possible_syms = pc_datatype_ref.possible_syms
                    except AttributeError:
                        # need to fundamentally rethink how to parse variable callbacks, for now just hope that they don't do anything significant
                        fileline_msg(
                            "VariableCallbackWarning: Skipped bad callback of type \"%s\"!"
                            % type(pc_datatype_ref).__name__, fileline)
                        funcstate.regs["r0"].set_new_reg(
                            analyzer.RegisterInfo(
                                datatypes.UnknownDataType().wrap(), fileline))
                        funcstate.regs["r1"].set_new_reg(
                            analyzer.RegisterInfo(
                                datatypes.UnknownDataType().wrap(), fileline))
                        funcstate.regs["r2"].set_new_reg(
                            analyzer.RegisterInfo(
                                datatypes.UnknownDataType().wrap(), fileline))
                        funcstate.regs["r3"].set_new_reg(
                            analyzer.RegisterInfo(
                                datatypes.UnknownDataType().wrap(), fileline))
                        possible_syms = None

                    if possible_syms is not None:
                        if len(possible_syms) > 1:
                            #debug_print("sp offset: %s" % sp_datatype_ref.offset)
                            if sp_datatype_ref.offset == base_stack_offset:
                                fileline_error(
                                    "Tried performing jumptable at base stack offset!",
                                    fileline)

                            remove_function_specific_callbacks(
                                funcstate.function.value)
                            jumptable_already_executed = pc_datatype_ref.original_sym.value in already_executed_jumptables
                            debug_print("Jumptable found: name: %s" %
                                        pc_datatype_ref.original_sym.name)
                            #if funcstate.function.value == 0x801B9E6: # sub_801B9E6, runs jumptables
                            #    dumb_hack_please_remove_function_memory = datatypes.Struct.dumb_hack_basic_struct_fields[datatypes.AIData][0xc8][Size.WORD].memory
                            #    dumb_hack_please_remove_function_memory.function = None
                            #    dumb_hack_please_remove_function_memory.dumb_hack_please_remove_in_sub_801B9E6 = True
                            already_executed_jumptables.add(
                                pc_datatype_ref.original_sym.value)
                            for sym in possible_syms:
                                if sym.type != "F":
                                    fileline_msg(
                                        "BadFunctionDefinitionWarning: Tried executing jumptable non-function symbol \"%s\"!"
                                        % sym.name, fileline)
                                if sym.name not in problem_functions:
                                    debug_print(
                                        "Start of jumptable function called from \"%s\" (%s:%s)"
                                        % (function_name, src_file.filename,
                                           src_file.line_num + 1))
                                    function_total_time += time.time(
                                    ) - function_start_time
                                    #subroutine_return_regs, function_tree["!" + sym.name] = run_analyzer_from_sym(sym, funcstate.regs, time.time())
                                    subroutine_return_regs = run_analyzer_from_sym(
                                        sym, funcstate.regs, time.time())
                                    function_start_time = time.time()
                                    debug_print(
                                        "End of jumptable function called from \"%s\" (%s:%s)"
                                        % (function_name, src_file.filename,
                                           src_file.line_num + 1))
                                    if jumptable_already_executed:
                                        break
                                else:
                                    debug_print(
                                        "Skipped problem function \"%s\" called from \"%s\" (%s:%s)"
                                        % (sym.name, function_name,
                                           src_file.filename,
                                           src_file.line_num + 1))
                            #if funcstate.function.value == 0x801B9E6: # sub_801B9E6
                            #    dumb_hack_please_remove_function_memory.dumb_hack_please_remove_in_sub_801B9E6 = False
                            add_function_specific_callbacks(
                                funcstate.function.value)
                        elif len(possible_syms) == 1:
                            if sp_datatype_ref.offset == base_stack_offset:
                                # returning from function
                                if return_lr.ref.filename == pc_datatype_ref.filename and return_lr.ref.line_num == pc_datatype_ref.line_num:
                                    if return_regs is None:
                                        # just use first return regs found for now
                                        return_regs = funcstate.regs
                                        return_stack = datatypes.Stack.datatypes
                                    break
                                # not returning from function, then this is a noreturn bx or something similar
                                # I think this only happens when performing an interwork return
                                else:
                                    fileline_error(
                                        "Tried performing noreturn branch!",
                                        fileline)
                            else:
                                if possible_syms[0].type != "F":
                                    fileline_msg(
                                        "BadFunctionDefinitionWarning: Tried executing regular non-function symbol \"%s\"!"
                                        % possible_syms[0].name, fileline)
                                debug_print(
                                    "Start of regular function called from \"%s\" (%s:%s)"
                                    % (function_name, src_file.filename,
                                       src_file.line_num + 1))
                                remove_function_specific_callbacks(
                                    funcstate.function.value)
                                function_total_time = time.time(
                                ) - function_start_time
                                #subroutine_return_regs, function_tree[possible_syms[0].name] = run_analyzer_from_sym(possible_syms[0], funcstate.regs, time.time())
                                subroutine_return_regs = run_analyzer_from_sym(
                                    possible_syms[0], funcstate.regs,
                                    time.time())
                                function_start_time = time.time()
                                debug_print(
                                    "End of regular function called from \"%s\" (%s:%s)"
                                    % (function_name, src_file.filename,
                                       src_file.line_num + 1))
                                add_function_specific_callbacks(
                                    funcstate.function.value)
                                #debug_print("return regs: %s" % subroutine_return_regs)
                        else:
                            fileline_error(
                                "Tried executing function but there was none!",
                                fileline)

                        funcstate.set_registers(subroutine_return_regs)
                        src_file.line_num = funcstate.regs[
                            "pc"].data.ref.line_num - 1
                elif funcstate.uncond_branch != "":
                    debug_print("uncond branch: %s" % funcstate.uncond_branch)
                    if funcstate.uncond_branch in funcstate.found_labels:
                        # TODO: potential for loop detection here
                        funcstate.uncond_branch = ""
                        break
                    elif funcstate.uncond_branch in syms:
                        if src_file.filename != syms[
                                funcstate.uncond_branch].filename:
                            global_fileline_error(
                                "Unconditional branch jumps to other file!")
                        src_file.line_num = syms[
                            funcstate.uncond_branch].line_num - 1
            else:
                stripped_line = line.strip()
                if stripped_line.startswith(
                        "thumb_func") or stripped_line.startswith(
                            ".align 1, 0"):
                    continue
                fileline_error("Unknown directive \"%s\"!" % stripped_line,
                               fileline)
        else:
            global_fileline_error("Reached end of file while parsing!")

        # don't attempt to run any conditional branches if this function already had its conditional branches executed
        # unless the function is forced to run all paths each time
        if function_name in function_trackers and return_regs is not None and funcstate.function.value not in force_all_paths_functions:
            break

        # sub_801AF44
        if funcstate.function.value == 0x801AF44 and "loc_801B18E" in funcstate.found_labels:
            break

        # now check if we have any conditional labels left
        for cond_branch_info in funcstate.cond_branches:
            if cond_branch_info.branch_name not in funcstate.found_labels:
                #debug_print("found labels: %s\nbranch name: %s" % (funcstate.found_labels, cond_branch_info.branch_name))
                funcstate.set_registers(cond_branch_info.registers)
                src_file.line_num = parser.find_label_line_num(
                    cond_branch_info.branch_name, funcstate)
                datatypes.Stack.datatypes = cond_branch_info.stack
                break
        else:
            if return_regs is not None:
                #debug_print("about to return regs: %s" % return_regs)
                # return_regs["pc"].append(RegisterInfo(copy.deepcopy(return_pc), fileline))
                break
            else:
                fileline_error("Did not find a return point in function!",
                               fileline)

    remove_function_specific_callbacks(funcstate.function.value)
    if funcstate.function.value == 0x8019892:  # object_createCollisionData
        return_regs = funcstate.regs

    datatypes.Stack.datatypes = return_stack

    debug_print("funcend: base stack offset: %s, function: %s (%s:%s)" %
                (base_stack_offset, function_name, function_filename,
                 funcstate.function.line_num + 1))

    if function_name in function_trackers:
        function_trackers[function_name].count += 1
        function_total_time += time.time() - function_start_time
        function_trackers[function_name].time += function_total_time
    else:
        function_total_time += time.time() - function_start_time
        function_trackers[function_name] = FunctionTracker(function_total_time)

    #return (return_regs, function_tree)
    return return_regs
Exemplo n.º 16
0
def chatbox_8041964_skip_flag_call(opcode_params, funcstate, src_file, fileline):
    if opcode_params == "TestEventFlagRange":
        funcstate.regs["r0"].set_new_reg(analyzer.RegisterInfo(datatypes.Primitive().wrap(), fileline))
    return True