示例#1
0
def create_remote_execution_body(
        patch_addresses: StringDisplayPatchAddresses,
        instructions: List[BaseInstruction]) -> Tuple[int, bytes]:
    """
    Return the address and the bytes for executing the given instructions via remote code execution.
    """
    update_hint_state = patch_addresses.update_hint_state

    remote_start_instructions = remote_execution_patch_start()
    remote_start_byte_count = assembler.byte_count(remote_start_instructions)

    body_address = update_hint_state + remote_start_byte_count
    body_instructions = list(instructions)
    body_instructions.extend(remote_execution_patch_end())
    body_bytes = bytes(
        assembler.assemble_instructions(body_address, body_instructions))

    if len(body_bytes
           ) > _remote_execution_max_byte_count - remote_start_byte_count:
        raise ValueError(
            f"Received {len(body_instructions)} instructions with total {len(body_bytes)} bytes, "
            f"but limit is {_remote_execution_max_byte_count - remote_start_byte_count}."
        )

    return body_address, body_bytes
def set_artifact_layer_active_patch(addresses: Prime1DolVersion, layer_id: int, active: bool,
                                    ) -> List[assembler.BaseInstruction]:
    # g_GameState->StateForWorld(0x39F2DE28)->GetLayerState()->SetLayerActive(templeAreaIndex, artifactLayer, true)
    result = []

    for_another_world = [
        # Get the LayerState via the CGameState
        lwz(r3, addresses.game_state_pointer - addresses.sda13_base, r13),  # get g_GameState
        # r4 already have the asset id
        bl(addresses.state_for_world),  # CGameState::StateForWorld
        lwz(r3, 0x14, r3),  # worldState->layerState
    ]

    result.extend([
        # Get the LayerState of current world. We'll overwrite if it's another world, it's just 1 instruction bigger
        lwz(r3, 0x8c8, r31),  # mgr->worldLayerState

        # Tallon Overworld asset id
        custom_ppc.load_unsigned_32bit(r4, 0x39f2de28),

        # Load current asset id in r5
        lwz(r5, 0x850, r31),  # mgr->world
        lwz(r5, 0x8, r5),  # world->mlvlId

        cmpw(0, r4, r5),  # compare asset ids
        beq(4 + assembler.byte_count(for_another_world), relative=True),
        *for_another_world,
        lwz(r3, 0x0, r3),

        # Set layer
        li(r4, 16),  # Artifact Layer
        stw(r4, 0x10, r1),

        # Set layer
        li(r5, layer_id),  # Artifact Layer
        stw(r5, 0x14, r1),

        # Make the layer change via SetLayerActive
        addi(r4, r1, 0x10),
        addi(r5, r1, 0x14),
        li(r6, int(active)),
        bl(addresses.set_layer_active),  # CWorldLayerState::SetLayerActive
    ])

    return result
示例#3
0
def remote_execution_patch_start() -> List[BaseInstruction]:
    return_code = remote_execution_patch_end()
    intro = [
        # se(r1tup stack
        stwu(r1, -(_remote_execution_stack_size - 4), r1),
        mfspr(r0, LR),
        stw(r0, _remote_execution_stack_size, r1),
        stmw(GeneralRegister(32 - _registers_to_save),
             _remote_execution_stack_size - 4 - _registers_to_save * 4, r1),
        or_(r31, r3, r3),

        # return if displayed
        lbz(r4, 0x2, r31),
        cmpwi(r4, 0x0),
        bne((len(return_code) + 1) * 4, relative=True),

        # clean return if flag is not set
        *return_code,

        # set displayed
        li(r6, 0x0),
        stb(r6, 0x2, r31),
    ]

    num_bytes_to_invalidate = _remote_execution_max_byte_count - assembler.byte_count(
        intro)
    # Our loop end condition depends on this value being a multiple of 32, greater than 0
    num_bytes_to_invalidate = ((num_bytes_to_invalidate // 32) + 1) * 32

    return [
        *intro,

        # fetch the instructions again, since they're being overwritten externally
        # this clears Dolphin's JIT cache
        custom_ppc.load_current_address(r30, 8),
        li(r4, num_bytes_to_invalidate),
        icbi(4, 30),  # invalidate using r30 + r4
        cmpwi(r4, 0x0),
        addi(r4, r4, -32),
        bne(-3 * 4, relative=True),
        sync(),
        isync(),
    ]