// File: ruankotovich[P]B-Tree/src/primarybtree.cpp
// Function: PrimaryBTree::insertRecursive(int, PrimaryBTreeNodeReinterpret*, int, _IO_FILE*)
PrimaryBTreeRecursionResponse PrimaryBTree::insertRecursive(int key, PrimaryBTreeNodeReinterpret* nodeReinterpretation, int offset, FILE* indexFile)
{
    if (nodeReinterpretation->node.isLeaf()) {

        if (nodeReinterpretation->node.hasRoom()) {
            nodeReinterpretation->node.insert(key);
            writeBackNode(&nodeReinterpretation->node, offset, indexFile);
            return SUCCESSFUL_TREE_INSERTION;
        }

        PrimaryBTreeNode* splitLeaf = new PrimaryBTreeNode(PRIMARY_MAX_KEYS);
        int promoted;

        // elege o promoted e manipula os vetores resultantes da operação do splitLeaf.
        int leftMiddleKey = nodeReinterpretation->node.keys[PRIMARY_LEFT_MIDDLE_KEY];
        int rightMiddleKey = nodeReinterpretation->node.keys[PRIMARY_RIGHT_MIDDLE_KEY];

        splitLeaf->count = nodeReinterpretation->node.count = PRIMARY_HALF_MAX_KEYS;

        switch (relativeKeyPosition(key, leftMiddleKey, rightMiddleKey)) {
        case RELATIVE_LEFT: {
            promoted = leftMiddleKey;
            --nodeReinterpretation->node.count;

            nodeReinterpretation->node.insert(key);

            for (int i = PRIMARY_HALF_MAX_KEYS, j = 0; i < PRIMARY_MAX_KEYS; ++i, ++j) {
                splitLeaf->keys[j] = nodeReinterpretation->node.keys[i];
            }
        } // não esquecer de manipular os blockPointes para nós não-folha
        break;

        case RELATIVE_RIGHT: {
            promoted = rightMiddleKey;
            --splitLeaf->count;

            for (int i = PRIMARY_RIGHT_MIDDLE_KEY + 1, j = 0; i < PRIMARY_MAX_KEYS; ++i, ++j) {
                splitLeaf->keys[j] = nodeReinterpretation->node.keys[i];
            } // não esquecer de manipular os blockPointes para nós não-folha

            splitLeaf->insert(key);
        } break;

        case RELATIVE_MIDDLE: {
            promoted = key;

            for (int i = PRIMARY_HALF_MAX_KEYS, j = 0; i < PRIMARY_MAX_KEYS; ++i, ++j) {
                splitLeaf->keys[j] = nodeReinterpretation->node.keys[i];
            }
        } // não esquecer de manipular os blockPointes para nós não-folha

        break;
        }

        writeBackNode(&nodeReinterpretation->node, offset, indexFile);
        int offset = writeNewNode(splitLeaf, indexFile);

        delete splitLeaf; // deleta da memória principal pois já foi salvo no disco

        // return { true, { promoted, offset } };
        return PrimaryBTreeRecursionResponse(true, promoted, offset);
    }

    int result = upperBound(nodeReinterpretation->node.keys, nodeReinterpretation->node.count, key); // [TROCAR]

    unsigned short childNodeOffset;

    if (result >= nodeReinterpretation->node.count) {
        childNodeOffset = result;
        result = nodeReinterpretation->node.count - 1;
    }

    childNodeOffset = ((key < nodeReinterpretation->node.keys[result]) ? nodeReinterpretation->node.blockPointers[result] : nodeReinterpretation->node.blockPointers[result + 1]);

    PrimaryBTreeNodeReinterpret* retrieveNode = new PrimaryBTreeNodeReinterpret();
    fseek(indexFile, sizeof(AbstractBlock_t) * childNodeOffset, SEEK_SET);
    fread(&retrieveNode->block, sizeof(AbstractBlock_t), 1, indexFile);

    auto resultRecursion = insertRecursive(key, retrieveNode, childNodeOffset, indexFile);
    delete retrieveNode;

    if (resultRecursion.hasBeenSplit) { // caso em que veio um valor promovido e um blockPointer
        //caso 1 - tem espaço para inserir o promovido
        if (nodeReinterpretation->node.hasRoom()) {
            //o + 1 é para não realizar essa soma em toda iteração do for logo abaixo
            unsigned short rightIndexInserted = nodeReinterpretation->node.insert(resultRecursion.promotedKey) + 1;

            for (unsigned short i = nodeReinterpretation->node.countPointers; i > rightIndexInserted; --i) {
                nodeReinterpretation->node.blockPointers[i] = nodeReinterpretation->node.blockPointers[i - 1];
            }

            nodeReinterpretation->node.blockPointers[rightIndexInserted] = resultRecursion.newBlockOffset;
            ++nodeReinterpretation->node.countPointers;

            writeBackNode(&nodeReinterpretation->node, offset, indexFile);
        } else { // caso 2 - não tem espaço para inserir o promovido -> fazer o split com remanejamento de chaves
            PrimaryBTreeNodeReinterpret* split = new PrimaryBTreeNodeReinterpret();
            int promoted;

            // elege o promoted e manipula os vetores resultantes da operação do split.
            int leftMiddleKey = nodeReinterpretation->node.keys[PRIMARY_LEFT_MIDDLE_KEY];
            int rightMiddleKey = nodeReinterpretation->node.keys[PRIMARY_RIGHT_MIDDLE_KEY];

            split->node.count = nodeReinterpretation->node.count = PRIMARY_HALF_MAX_KEYS; // remoção lógica exatamente na metade

            //como está cheio, vai metade dos elementos para cada bloco, contnado com o split.
            // se vai metade, haverá metade + 1 ponteiros para bloco preenchidos.
            split->node.countPointers = nodeReinterpretation->node.countPointers = PRIMARY_HALF_MAX_KEYS + 1;

            switch (relativeKeyPosition(resultRecursion.promotedKey, leftMiddleKey, rightMiddleKey)) {
            case RELATIVE_LEFT: {
                promoted = leftMiddleKey;

                --nodeReinterpretation->node.count;

                // índice do ponteiro mais à direita do vetor blockPointers
                unsigned short greaterNodeBlockPointer = nodeReinterpretation->node.blockPointers[nodeReinterpretation->node.countPointers - 1]; // a subtração tem a ver com índice

                //índice em que foi inserido o promovido no nó já existente
                unsigned short rightIndexInserted = nodeReinterpretation->node.insert(resultRecursion.promotedKey) + 1;

                //remanejar os blockPoints
                for (unsigned short i = nodeReinterpretation->node.countPointers - 1; i > rightIndexInserted; --i) {
                    nodeReinterpretation->node.blockPointers[i] = nodeReinterpretation->node.blockPointers[i - 1];
                }

                nodeReinterpretation->node.blockPointers[rightIndexInserted] = resultRecursion.newBlockOffset;

                for (int i = PRIMARY_HALF_MAX_KEYS, j = 0; i < PRIMARY_MAX_KEYS; ++i, ++j) {
                    split->node.keys[j] = nodeReinterpretation->node.keys[i];
                    split->node.blockPointers[j + 1] = nodeReinterpretation->node.blockPointers[i + 1];
                } // não esquecer de manipular os blockPointes para nós não-folha

                split->node.blockPointers[0] = greaterNodeBlockPointer;
            } break;

            case RELATIVE_RIGHT: {
                promoted = rightMiddleKey;
                --split->node.count;
                // não é preciso modificar o countPointers nem o count do node aqui porque eles já foram atribuidos ali em cima,
                // então a remoção lógica já foi feita

                for (int i = PRIMARY_RIGHT_MIDDLE_KEY + 1, j = 0; i < PRIMARY_MAX_KEYS; ++i, ++j) {
                    split->node.keys[j] = nodeReinterpretation->node.keys[i];
                    split->node.blockPointers[j] = nodeReinterpretation->node.blockPointers[i];
                } // não esquecer de manipular os blockPointes para nós não-folha/

                split->node.blockPointers[PRIMARY_HALF_MAX_KEYS - 1] = nodeReinterpretation->node.blockPointers[PRIMARY_MAX_KEYS];
                unsigned short rightIndexInserted = split->node.insert(resultRecursion.promotedKey) + 1;

                //remanejar os blockPoints
                for (unsigned short i = split->node.countPointers - 1; i > rightIndexInserted; --i) {
                    split->node.blockPointers[i] = split->node.blockPointers[i - 1];
                }

                split->node.blockPointers[rightIndexInserted] = resultRecursion.newBlockOffset;
            } break;

            case RELATIVE_MIDDLE: {
                promoted = resultRecursion.promotedKey;

                for (int i = PRIMARY_HALF_MAX_KEYS, j = 0; i < PRIMARY_MAX_KEYS; ++i, ++j) {
                    split->node.keys[j] = nodeReinterpretation->node.keys[i];
                    split->node.blockPointers[j + 1] = nodeReinterpretation->node.blockPointers[i + 1];
                } // não esquecer de manipular os blockPointes para nós não-folha
                split->node.blockPointers[0] = resultRecursion.newBlockOffset;
            } break;
            }

            writeBackNode(&nodeReinterpretation->node, offset, indexFile);
            int offset = writeNewNode(&split->node, indexFile);
            delete split; // deleta da memória principal pois já foi salvo no disco
            return PrimaryBTreeRecursionResponse(true, promoted, offset);
        }
    }

    return SUCCESSFUL_TREE_INSERTION;
    // return PrimaryBTreeRecursionResponse(false, 0, 0);
    // return { false, { 0, 0 } };
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x150, %rsp            # imm = 0x150
movq %rdi, -0x18(%rbp)
movl %esi, -0x1c(%rbp)
movq %rdx, -0x28(%rbp)
movl %ecx, -0x2c(%rbp)
movq %r8, -0x38(%rbp)
movq -0x18(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x28(%rbp), %rdi
callq 0x3620
testb $0x1, %al
jne 0x38aa
jmp 0x3b22
movq -0x28(%rbp), %rdi
callq 0x3640
testb $0x1, %al
jne 0x38b9
jmp 0x38ee
movq -0x28(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x3660
movq -0x28(%rbp), %rdi
movl -0x2c(%rbp), %esi
movq -0x38(%rbp), %rdx
callq 0x4720
movq -0x108(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0xc(%rbp)
movl 0x8(%rax), %eax
movl %eax, -0x4(%rbp)
jmp 0x427e
movl $0xff8, %edi            # imm = 0xFF8
callq 0x10b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x110(%rbp)
movl $0x2a8, %esi            # imm = 0x2A8
callq 0x3600
jmp 0x3911
movq -0x110(%rbp), %rax
movq %rax, -0x40(%rbp)
movq -0x28(%rbp), %rax
movl 0x550(%rax), %eax
movl %eax, -0x54(%rbp)
movq -0x28(%rbp), %rax
movl 0x554(%rax), %eax
movl %eax, -0x58(%rbp)
movq -0x28(%rbp), %rax
movw $0x154, (%rax)          # imm = 0x154
movq -0x40(%rbp), %rax
movw $0x154, (%rax)          # imm = 0x154
movl -0x1c(%rbp), %edi
movl -0x54(%rbp), %esi
movl -0x58(%rbp), %edx
callq 0x4770
movsbl %al, %eax
movl %eax, -0x114(%rbp)
subl $-0x1, %eax
je 0x39ac
jmp 0x3966
movl -0x114(%rbp), %eax
testl %eax, %eax
je 0x3a79
jmp 0x3976
movl -0x114(%rbp), %eax
subl $0x1, %eax
je 0x3a14
jmp 0x3ac4
movq -0x110(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
movl $0xff8, %esi            # imm = 0xFF8
callq 0x10c0
jmp 0x42a9
movl -0x54(%rbp), %eax
movl %eax, -0x50(%rbp)
movq -0x28(%rbp), %rax
movw (%rax), %cx
addw $-0x1, %cx
movw %cx, (%rax)
movq -0x28(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x3660
movl $0x154, -0x5c(%rbp)     # imm = 0x154
movl $0x0, -0x60(%rbp)
cmpl $0x2a8, -0x5c(%rbp)     # imm = 0x2A8
jge 0x3a0f
movq -0x28(%rbp), %rax
movslq -0x5c(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %edx
movq -0x40(%rbp), %rax
movslq -0x60(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x39da
jmp 0x3ac4
movl -0x58(%rbp), %eax
movl %eax, -0x50(%rbp)
movq -0x40(%rbp), %rax
movw (%rax), %cx
addw $-0x1, %cx
movw %cx, (%rax)
movl $0x155, -0x64(%rbp)     # imm = 0x155
movl $0x0, -0x68(%rbp)
cmpl $0x2a8, -0x64(%rbp)     # imm = 0x2A8
jge 0x3a6b
movq -0x28(%rbp), %rax
movslq -0x64(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %edx
movq -0x40(%rbp), %rax
movslq -0x68(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movl -0x64(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x64(%rbp)
movl -0x68(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x68(%rbp)
jmp 0x3a36
movq -0x40(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x3660
jmp 0x3ac4
movl -0x1c(%rbp), %eax
movl %eax, -0x50(%rbp)
movl $0x154, -0x6c(%rbp)     # imm = 0x154
movl $0x0, -0x70(%rbp)
cmpl $0x2a8, -0x6c(%rbp)     # imm = 0x2A8
jge 0x3ac2
movq -0x28(%rbp), %rax
movslq -0x6c(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %edx
movq -0x40(%rbp), %rax
movslq -0x70(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movl -0x6c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x6c(%rbp)
movl -0x70(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x70(%rbp)
jmp 0x3a8d
jmp 0x3ac4
movq -0x28(%rbp), %rdi
movl -0x2c(%rbp), %esi
movq -0x38(%rbp), %rdx
callq 0x4720
movq -0x40(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x47b0
movl %eax, -0x74(%rbp)
movq -0x40(%rbp), %rax
movq %rax, -0x120(%rbp)
cmpq $0x0, %rax
je 0x3b06
movq -0x120(%rbp), %rdi
movl $0xff8, %esi            # imm = 0xFF8
callq 0x10c0
movl -0x50(%rbp), %edx
movl -0x74(%rbp), %eax
leaq -0xc(%rbp), %rdi
movl $0x1, %esi
movzwl %ax, %ecx
callq 0x35c0
jmp 0x427e
movq -0x28(%rbp), %rdi
addq $0x4, %rdi
movq -0x28(%rbp), %rax
movzwl (%rax), %esi
movl -0x1c(%rbp), %edx
callq 0x42c0
movl %eax, -0x78(%rbp)
movl -0x78(%rbp), %eax
movq -0x28(%rbp), %rcx
movzwl (%rcx), %ecx
cmpl %ecx, %eax
jl 0x3b5e
movl -0x78(%rbp), %eax
movw %ax, -0x7a(%rbp)
movq -0x28(%rbp), %rax
movzwl (%rax), %eax
subl $0x1, %eax
movl %eax, -0x78(%rbp)
movl -0x1c(%rbp), %eax
movq -0x28(%rbp), %rcx
movslq -0x78(%rbp), %rdx
cmpl 0x4(%rcx,%rdx,4), %eax
jge 0x3b88
movq -0x28(%rbp), %rax
movslq -0x78(%rbp), %rcx
movw 0xaa4(%rax,%rcx,2), %ax
movw %ax, -0x122(%rbp)
jmp 0x3ba4
movq -0x28(%rbp), %rax
movl -0x78(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %ax
movw %ax, -0x122(%rbp)
movw -0x122(%rbp), %ax
movw %ax, -0x7a(%rbp)
movl $0x1000, %edi           # imm = 0x1000
callq 0x10b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x130(%rbp)
callq 0x4700
jmp 0x3bcd
movq -0x130(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x38(%rbp), %rdi
movzwl -0x7a(%rbp), %eax
shll $0xc, %eax
movl %eax, %esi
xorl %edx, %edx
callq 0x10d0
movq -0x88(%rbp), %rdi
movq -0x38(%rbp), %rcx
movl $0x1000, %esi           # imm = 0x1000
movl $0x1, %edx
callq 0x1100
movq -0x108(%rbp), %rdi
movl -0x1c(%rbp), %esi
movq -0x88(%rbp), %rdx
movzwl -0x7a(%rbp), %ecx
movq -0x38(%rbp), %r8
callq 0x3870
movw %dx, -0xa0(%rbp)
movq %rax, -0xa8(%rbp)
movq -0xa8(%rbp), %rax
movq %rax, -0x94(%rbp)
movw -0xa0(%rbp), %ax
movw %ax, -0x8c(%rbp)
movq -0x88(%rbp), %rax
movq %rax, -0x138(%rbp)
cmpq $0x0, %rax
je 0x3c76
movq -0x138(%rbp), %rdi
movl $0x1000, %esi           # imm = 0x1000
callq 0x10c0
testb $0x1, -0x94(%rbp)
je 0x426a
movq -0x28(%rbp), %rdi
callq 0x3640
testb $0x1, %al
jne 0x3c95
jmp 0x3d73
movq -0x28(%rbp), %rdi
movl -0x90(%rbp), %esi
callq 0x3660
movzwl %ax, %eax
addl $0x1, %eax
movw %ax, -0xaa(%rbp)
movq -0x28(%rbp), %rax
movw 0x2(%rax), %ax
movw %ax, -0xac(%rbp)
movzwl -0xac(%rbp), %eax
movzwl -0xaa(%rbp), %ecx
cmpl %ecx, %eax
jle 0x3d34
movq -0x28(%rbp), %rax
movzwl -0xac(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %dx
movq -0x28(%rbp), %rax
movzwl -0xac(%rbp), %ecx
movw %dx, 0xaa4(%rax,%rcx,2)
movw -0xac(%rbp), %ax
addw $-0x1, %ax
movw %ax, -0xac(%rbp)
jmp 0x3cc0
movq -0x130(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
movl $0x1000, %esi           # imm = 0x1000
callq 0x10c0
jmp 0x42a9
movw -0x8c(%rbp), %dx
movq -0x28(%rbp), %rax
movzwl -0xaa(%rbp), %ecx
movw %dx, 0xaa4(%rax,%rcx,2)
movq -0x28(%rbp), %rax
movw 0x2(%rax), %cx
addw $0x1, %cx
movw %cx, 0x2(%rax)
movq -0x28(%rbp), %rdi
movl -0x2c(%rbp), %esi
movq -0x38(%rbp), %rdx
callq 0x4720
jmp 0x4268
movl $0x1000, %edi           # imm = 0x1000
callq 0x10b0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x140(%rbp)
callq 0x4700
jmp 0x3d91
movq -0x140(%rbp), %rax
movq %rax, -0xb8(%rbp)
movq -0x28(%rbp), %rax
movl 0x550(%rax), %eax
movl %eax, -0xc0(%rbp)
movq -0x28(%rbp), %rax
movl 0x554(%rax), %eax
movl %eax, -0xc4(%rbp)
movq -0x28(%rbp), %rax
movw $0x154, (%rax)          # imm = 0x154
movq -0xb8(%rbp), %rax
movw $0x154, (%rax)          # imm = 0x154
movq -0x28(%rbp), %rax
movw $0x155, 0x2(%rax)       # imm = 0x155
movq -0xb8(%rbp), %rax
movw $0x155, 0x2(%rax)       # imm = 0x155
movl -0x90(%rbp), %edi
movl -0xc0(%rbp), %esi
movl -0xc4(%rbp), %edx
callq 0x4770
movsbl %al, %eax
movl %eax, -0x144(%rbp)
subl $-0x1, %eax
je 0x3e58
jmp 0x3e12
movl -0x144(%rbp), %eax
testl %eax, %eax
je 0x4149
jmp 0x3e22
movl -0x144(%rbp), %eax
subl $0x1, %eax
je 0x3fdb
jmp 0x41fe
movq -0x140(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
movl $0x1000, %esi           # imm = 0x1000
callq 0x10c0
jmp 0x42a9
movl -0xc0(%rbp), %eax
movl %eax, -0xbc(%rbp)
movq -0x28(%rbp), %rax
movw (%rax), %cx
addw $-0x1, %cx
movw %cx, (%rax)
movq -0x28(%rbp), %rax
movq -0x28(%rbp), %rcx
movzwl 0x2(%rcx), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %ax
movw %ax, -0xc6(%rbp)
movq -0x28(%rbp), %rdi
movl -0x90(%rbp), %esi
callq 0x3660
movzwl %ax, %eax
addl $0x1, %eax
movw %ax, -0xc8(%rbp)
movq -0x28(%rbp), %rax
movzwl 0x2(%rax), %eax
subl $0x1, %eax
movw %ax, -0xca(%rbp)
movzwl -0xca(%rbp), %eax
movzwl -0xc8(%rbp), %ecx
cmpl %ecx, %eax
jle 0x3f13
movq -0x28(%rbp), %rax
movzwl -0xca(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %dx
movq -0x28(%rbp), %rax
movzwl -0xca(%rbp), %ecx
movw %dx, 0xaa4(%rax,%rcx,2)
movw -0xca(%rbp), %ax
addw $-0x1, %ax
movw %ax, -0xca(%rbp)
jmp 0x3ec1
movw -0x8c(%rbp), %dx
movq -0x28(%rbp), %rax
movzwl -0xc8(%rbp), %ecx
movw %dx, 0xaa4(%rax,%rcx,2)
movl $0x154, -0xd0(%rbp)     # imm = 0x154
movl $0x0, -0xd4(%rbp)
cmpl $0x2a8, -0xd0(%rbp)     # imm = 0x2A8
jge 0x3fc1
movq -0x28(%rbp), %rax
movslq -0xd0(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %edx
movq -0xb8(%rbp), %rax
movslq -0xd4(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movq -0x28(%rbp), %rax
movl -0xd0(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %dx
movq -0xb8(%rbp), %rax
movl -0xd4(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movw %dx, 0xaa4(%rax,%rcx,2)
movl -0xd0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd0(%rbp)
movl -0xd4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd4(%rbp)
jmp 0x3f41
movw -0xc6(%rbp), %cx
movq -0xb8(%rbp), %rax
movw %cx, 0xaa4(%rax)
jmp 0x41fe
movl -0xc4(%rbp), %eax
movl %eax, -0xbc(%rbp)
movq -0xb8(%rbp), %rax
movw (%rax), %cx
addw $-0x1, %cx
movw %cx, (%rax)
movl $0x155, -0xd8(%rbp)     # imm = 0x155
movl $0x0, -0xdc(%rbp)
cmpl $0x2a8, -0xd8(%rbp)     # imm = 0x2A8
jge 0x4082
movq -0x28(%rbp), %rax
movslq -0xd8(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %edx
movq -0xb8(%rbp), %rax
movslq -0xdc(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movq -0x28(%rbp), %rax
movslq -0xd8(%rbp), %rcx
movw 0xaa4(%rax,%rcx,2), %dx
movq -0xb8(%rbp), %rax
movslq -0xdc(%rbp), %rcx
movw %dx, 0xaa4(%rax,%rcx,2)
movl -0xd8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xd8(%rbp)
movl -0xdc(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xdc(%rbp)
jmp 0x400c
movq -0x28(%rbp), %rax
movw 0xff4(%rax), %cx
movq -0xb8(%rbp), %rax
movw %cx, 0xd4a(%rax)
movq -0xb8(%rbp), %rdi
movl -0x90(%rbp), %esi
callq 0x3660
movzwl %ax, %eax
addl $0x1, %eax
movw %ax, -0xde(%rbp)
movq -0xb8(%rbp), %rax
movzwl 0x2(%rax), %eax
subl $0x1, %eax
movw %ax, -0xe0(%rbp)
movzwl -0xe0(%rbp), %eax
movzwl -0xde(%rbp), %ecx
cmpl %ecx, %eax
jle 0x4127
movq -0xb8(%rbp), %rax
movzwl -0xe0(%rbp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %dx
movq -0xb8(%rbp), %rax
movzwl -0xe0(%rbp), %ecx
movw %dx, 0xaa4(%rax,%rcx,2)
movw -0xe0(%rbp), %ax
addw $-0x1, %ax
movw %ax, -0xe0(%rbp)
jmp 0x40cf
movw -0x8c(%rbp), %dx
movq -0xb8(%rbp), %rax
movzwl -0xde(%rbp), %ecx
movw %dx, 0xaa4(%rax,%rcx,2)
jmp 0x41fe
movl -0x90(%rbp), %eax
movl %eax, -0xbc(%rbp)
movl $0x154, -0xe4(%rbp)     # imm = 0x154
movl $0x0, -0xe8(%rbp)
cmpl $0x2a8, -0xe4(%rbp)     # imm = 0x2A8
jge 0x41e9
movq -0x28(%rbp), %rax
movslq -0xe4(%rbp), %rcx
movl 0x4(%rax,%rcx,4), %edx
movq -0xb8(%rbp), %rax
movslq -0xe8(%rbp), %rcx
movl %edx, 0x4(%rax,%rcx,4)
movq -0x28(%rbp), %rax
movl -0xe4(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movw 0xaa4(%rax,%rcx,2), %dx
movq -0xb8(%rbp), %rax
movl -0xe8(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movw %dx, 0xaa4(%rax,%rcx,2)
movl -0xe4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe4(%rbp)
movl -0xe8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xe8(%rbp)
jmp 0x4169
movw -0x8c(%rbp), %cx
movq -0xb8(%rbp), %rax
movw %cx, 0xaa4(%rax)
movq -0x28(%rbp), %rdi
movl -0x2c(%rbp), %esi
movq -0x38(%rbp), %rdx
callq 0x4720
movq -0xb8(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x47b0
movl %eax, -0xec(%rbp)
movq -0xb8(%rbp), %rax
movq %rax, -0x150(%rbp)
cmpq $0x0, %rax
je 0x4249
movq -0x150(%rbp), %rdi
movl $0x1000, %esi           # imm = 0x1000
callq 0x10c0
movl -0xbc(%rbp), %edx
movl -0xec(%rbp), %eax
leaq -0xc(%rbp), %rdi
movl $0x1, %esi
movzwl %ax, %ecx
callq 0x35c0
jmp 0x427e
jmp 0x426a
movq -0x108(%rbp), %rax
movq (%rax), %rcx
movq %rcx, -0xc(%rbp)
movl 0x8(%rax), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
movl %eax, -0xf8(%rbp)
movq -0xc(%rbp), %rax
movq %rax, -0x100(%rbp)
movq -0x100(%rbp), %rax
movw -0xf8(%rbp), %dx
addq $0x150, %rsp            # imm = 0x150
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x1140
nopw %cs:(%rax,%rax)