// File: /workspace/github_cpp_makefile_star2_O2/gulamf[P]NRF24LE1Flash/main.cpp
// Function: ProgramUC()
bool ProgramUC()
{
    string debugInfo = "";
    vector<HexRecord> *hexRecords;
    BLCommandReturnType blCommandReturnVal;
    uint8_t readData[512] ;
    bool pageErased[31];
    bool dataInPage[31];
    uint8_t ucFlash [0x4000];
    uint8_t jumpInstruction[] = {0x02, 0x3E, 0x00};

    ucFlash[0] = jumpInstruction[0];
    ucFlash[1] = jumpInstruction[1];
    ucFlash[2] = jumpInstruction[2];

    #if DEBUG_MSG_BOX_ENABLED
    outputString = "";
    #endif


    cout << "Initiating program/verify sequence...\r\n";

    if (resetpin == blenabled)
    {
        cout << "Reset and bootloader enable pins cannot be the same!";
        return false;
    }

    cout << "Parsing hex file...\r\n";

    //begin parse hex file
    hexRecords = HexUtils::ParseHexFile(hexfile, debugInfo);

    //If hexRecords is null, then the file could not be found
    if (hexRecords == NULL)
    {
        cout << "Could not open hex file!";
        return false;
    }

    for (unsigned int  x = 0; x < sizeof(pageErased); x++)
    {
        pageErased[x] = false;
        dataInPage[x] = false;
    }

    for (unsigned int x = 0; x < sizeof(ucFlash); x++)
    {
        ucFlash[x] = 0xFF;
    }

    //Loop through each of the individual hex records to build the complete flash image
    for (unsigned int x = 0; x < hexRecords->size(); x++)
    {
        HexRecord curHexRecord = (HexRecord)hexRecords->at((int)x);

        //If an address is found that is in the bootloader's address space, then throw an error
        if ((curHexRecord.address + curHexRecord.len) >= 0x3E00)
        {
            cout << "Attempting to program address in bootloader's address space (0x3E00 through 0x3FFF)!";
            return false;
        }

        //Loop through the data in the hex record to build the flash image
        for (unsigned int y = 0; y < curHexRecord.len; y++)
        {
            uint8_t curPage = (uint8_t)((curHexRecord.address + y) / 512);

            uint8_t data = curHexRecord.data[y];
            int addr = curHexRecord.address;
            ucFlash[ addr + y] = data;

            if (!dataInPage[curPage] && (ucFlash[curHexRecord.address + y] != 0xFF))
                dataInPage[curPage] = true;
        }
    }
    //end parse hex file

    cout << "Parsing hex file complete!\r\n";
    cout << "Programming device flash...\r\n";

    //begin start bootloader
    blCommandReturnVal = ExecuteCommandStartBootloader();

    if (blCommandReturnVal == BLCommandReturnType_SerialPortFailure)
    {
        cout << "Could not open COM port!";
        return false;
    }
    else if (blCommandReturnVal != BLCommandReturnType_OK)
    {
        cout << "Device not connected!\n";
        return false;
    }
    //end start	bootloader

    //begin device id check
    uint16_t devId = 0;

    blCommandReturnVal = ExecuteCommandGetDevID(&devId);

    if (blCommandReturnVal != BLCommandReturnType_OK)
    {
        cout << "Lost communications with device!";
        return false;
    }
    //end device id check

    //begin bootloader version check
    uint8_t blVersion = 0;

    blCommandReturnVal = ExecuteCommandGetBLVersion(&blVersion);

    if (blCommandReturnVal != BLCommandReturnType_OK)
    {
        cout << "Lost communications with device!";
        return false;
    }
    //end device id check

    cout << ConvertBLDevIDToString(devId);

    //begin write hex file data
    for (uint8_t curPage = 0; curPage < 31; curPage++)
    {
        unsigned int writeStartAddress = 0;
        unsigned int writeEndAddress = 0;
        unsigned int curPageStartAddress = (unsigned int )curPage * 512;
        unsigned int curPageEndAddress = curPageStartAddress + 512 - 1;
        unsigned int curRWAddress = 0;

        //If there is data in the page, then we will do some writing
        if (dataInPage[curPage])
        {
            //Page 0 is a special case because it contains the jump to bootloader code
            if (curPage == 0)
            {
                //Erase page 0 here
                if (ExecuteCommandErasePage(0) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Mark page erased
                pageErased[0] = true;

                //Set the RW address so we can write the jump instruction
                if (ExecuteCommandSetRWAddress(0) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Update our shadow copy of the chip's RW address
                curRWAddress = 0;

                //Write the jump instruction
                if (ExecuteCommandWrite(jumpInstruction, 0, 3) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Update our shadow copy of the chip's RW address
                curRWAddress += 3;

                //Set the user main address that lived in the jump instruction of the user's hex file (bytes 1 (MSB) and 2 (LSB))
                if (ExecuteCommandSetUsrMainAddress((uint16_t)(ucFlash[1] << 8) + ucFlash[2]) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Since we've already written the first 3 bytes in the page, update the start address for the rest of the page accordingly
                writeStartAddress = 3;
            }
            else
            {
                //Erase the page if it hasn't been erased
                if (!pageErased[curPage])
                {
                    if (ExecuteCommandErasePage(curPage) != BLCommandReturnType_OK)
                    {
                        cout << "Lost communications with device!";
                        return false;
                    }

                    pageErased[curPage] = true;
                }

                //We haven't written any data, so the start address is just the first address of the page
                writeStartAddress = curPageStartAddress;
            }

            //Loop through this page
            while (writeStartAddress <= curPageEndAddress)
            {
                //Check to see if the current byte is 0xFF or not (FLASH erases to 0xFF, so we do not have to write that value)
                if (ucFlash[writeStartAddress] != 0xFF)
                {
                    uint endFFhCount = 0; //Counter for number of 0xFF values seen after the last non-0xFF value

                    //We have found a non-0xFF value, so now we will try to find where we will end this write operation
                    writeEndAddress = writeStartAddress;

                    //curViewingAddress is the address we're inspecting to see if we want to write the value or not
                    uint curViewingAddress = writeEndAddress + 1;

                    //Check if curViewingAddress is within the current page boundary
                    while (curViewingAddress <= curPageEndAddress)
                    {
                        //We're in the current page boundary, so check if the next value in the flash image is non-0xFF
                        if (ucFlash[writeEndAddress + 1] != 0xFF)
                        {
                            //The next value is non-0xFF, so set writeEndAddress to curViewingAddress and zero out endFFhCount
                            writeEndAddress = curViewingAddress;
                            endFFhCount = 0;
                        }
                        else
                        {
                            //The next value is 0xFF, so increment endFFhCount
                            endFFhCount++;

                            //We have to write at least 8 0xFF values before it makes sense to break a single write into two
                            if (endFFhCount >= 8)
                            {
                                //We are on our 8th 0xFF, so we will break this write
                                break;
                            }
                        }

                        //curViewingAddress is always one location ahead of writeEndAddress plus endFFhCount
                        curViewingAddress = writeEndAddress + endFFhCount + 1;
                    }

                    //Update the chip's RW address if it isn't equal to writeStartAddress
                    if (curRWAddress != writeStartAddress)
                    {
                        if (ExecuteCommandSetRWAddress((uint16_t)writeStartAddress) != BLCommandReturnType_OK)
                        {
                            cout << "Lost communications with device!";
                            return false;
                        }
                    }

                    //Update our shadow copy of the chip's RW address
                    curRWAddress = writeStartAddress;

                    //Write the curent block to the chip
                    uint numBytesToWrite = writeEndAddress - writeStartAddress + 1;

                    if (ExecuteCommandWrite(ucFlash, (uint16_t)curRWAddress, (uint16_t)numBytesToWrite) != BLCommandReturnType_OK)
                    {
                        cout << "Lost communications with device!";
                        return false;
                    }

                    //Update shadow copy of chip's RW address
                    curRWAddress += numBytesToWrite;

                    //Update writeStartAddress
                    writeStartAddress = writeEndAddress + 1;
                }
                else
                {
                    //The value was 0xFF, so look at the next value to try to start the write
                    writeStartAddress++;
                }
            }
        }
        else
        {
            //There is no data in the page, so erase it if it hasn't already been erased
            if (!pageErased[curPage])
            {
                //Erase current page
                if (ExecuteCommandErasePage(curPage) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Mark page erased
                pageErased[curPage] = true;
            }
        }
        //Update the progress bar
        //cout << (((curPage + 1) * 100) / 32) << "% complete\n";
    }
    //end write hex file data

    cout << "Programming device flash complete!\r\n";
    cout << "Verifying device flash...\r\n";

    //begin verify hex file data
    for (uint8_t curPage = 0; curPage < 31; curPage++)
    {
        uint readStartAddress = 0;
        uint readEndAddress = 0;
        uint curPageStartAddress = (uint)curPage * 512;
        uint curPageEndAddress = curPageStartAddress + 512 - 1;
        uint curRWAddress = 0;
        uint userMainJumpInstLoc = 0x3E09;

        //If there is data in the page, then we will do some writing
        if (dataInPage[curPage])
        {
            //Page 0 is a special case because it contains the jump to user code
            if (curPage == 0)
            {
                //Set the RW address so we can read the jump to user main instruction
                if (ExecuteCommandSetRWAddress((uint16_t)userMainJumpInstLoc) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                curRWAddress = userMainJumpInstLoc;

                //Read the jump to user main instruction from the chip
                if (ExecuteCommandRead(readData, 0, 3) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Update our shadow copy of the chip's RW address
                curRWAddress += 3;

                //Verify jump to user main instruction
                if ((readData[0] != 0x02) || (readData[1] != ucFlash[1]) || (readData[2] != ucFlash[2]))
                {
                    cout << "Programming error in jump to user main instruction starting at 0x" + ToHexString(userMainJumpInstLoc) + ": expected [0x02 0x" + ToHexString(ucFlash[1]) + " 0x" + ToHexString(ucFlash[2]) + "], zzbut received [0x" + ToHexString(readData[0]) + " 0x" + ToHexString(readData[1])+ " 0x" + ToHexString(readData[2]) + "]!";
                    return false;
                }

                //Set the RW address so we can read the jump to bootloader instruction
                if (ExecuteCommandSetRWAddress(0) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Update our shadow copy of the chip's RW address
                curRWAddress = 0;

                //Read the jump instruction
                if (ExecuteCommandRead(readData, 0, 3) != BLCommandReturnType_OK)
                {
                    cout << "Lost communications with device!";
                    return false;
                }

                //Update our shadow copy of the chip's RW address
                curRWAddress += 3;

                //Verify jump to bootloader instruction
                if ((readData[0] != jumpInstruction[0]) || (readData[1] != jumpInstruction[1]) || (readData[2] != jumpInstruction[2]))
                {
                    cout << "Programming error in jump to bootloader instruction starting at 0x0000: expected [0x" + ToHexString(jumpInstruction[0]) + " 0x" + ToHexString(jumpInstruction[1]) + " 0x" + ToHexString(jumpInstruction[2]) + "], xxbut received [0x" + ToHexString(readData[0]) + " 0x" + ToHexString(readData[1]) + " 0x" + ToHexString(readData[2]) + "]!";
                    return false;
                }

                //Since we've already read the first 3 bytes in the page, update the start address for the rest of the page accordingly
                readStartAddress = 3;
            }
            else
            {
                //We haven't read any data, so the start address is just the first address of the page
                readStartAddress = curPageStartAddress;
            }

            //Loop through this page
            while (readStartAddress <= curPageEndAddress)
            {
                //Check to see if the current byte is 0xFF or not (FLASH erases to 0xFF, so we do not have to read that value since it automatically matches)
                if (ucFlash[readStartAddress] != 0xFF)
                {
                    uint endFFhCount = 0; //Counter for number of 0xFF values seen after the last non-0xFF value

                    //We have found a non-0xFF value, so now we will try to find where we will end this read operation
                    readEndAddress = readStartAddress;

                    //curViewingAddress is the address we're inspecting to see if we want to read the value or not
                    uint curViewingAddress = readEndAddress + 1;

                    //Check if curViewingAddress is within the current page boundary
                    while (curViewingAddress <= curPageEndAddress)
                    {
                        //We're in the current page boundary, so check if the next value in the flash image is non-0xFF
                        if (ucFlash[readEndAddress + 1] != 0xFF)
                        {
                            //The next value is non-0xFF, so set readEndAddress to curViewingAddress and zero out endFFhCount
                            readEndAddress = curViewingAddress;
                            endFFhCount = 0;
                        }
                        else
                        {
                            //The next value is 0xFF, so increment endFFhCount
                            endFFhCount++;

                            //We have to read at least 8 0xFF values before it makes sense to break a single read into two
                            if (endFFhCount >= 8)
                            {
                                //We are on our 8th 0xFF, so we will break this read
                                break;
                            }
                        }

                        //curViewingAddress is always one location ahead of readEndAddress plus endFFhCount
                        curViewingAddress = readEndAddress + endFFhCount + 1;
                    }

                    //Update the chip's RW address if it isn't equal to readStartAddress
                    if (curRWAddress != readStartAddress)
                    {
                        if (ExecuteCommandSetRWAddress((uint16_t)(readStartAddress)) != BLCommandReturnType_OK)
                        {
                            cout << "Lost communications with device!";
                            return false;
                        }
                    }

                    //Update our shadow copy of the chip's RW address
                    curRWAddress = readStartAddress;

                    //Read the curent block to the chip
                    uint numBytesToRead = readEndAddress - readStartAddress + 1;


                    if (ExecuteCommandRead(readData, readStartAddress, (uint16_t)numBytesToRead) != BLCommandReturnType_OK)
                    {
                        cout << "Lost communications with device!";
                        return false;
                    }

                    //Verify read data
                    for (unsigned int x = 0; x < numBytesToRead; x++)
                    {
                        //Check the current byte against the flash image
                        if (readData[readStartAddress + x] != ucFlash[curRWAddress])
                        {
                            cout << "Programming error at address 0x";
                            cout << ToHexString(curRWAddress);
                            cout << ": expected 0x";
                            cout << ToHexString(ucFlash[curRWAddress]);
                            cout << " but received 0x";
                            cout << ToHexString(readData[x])+ "!";
                            return false;
                        }

                        //Increment shadow copy of chip's RW address
                        curRWAddress++;
                    }

                    //Update readStartAddress
                    readStartAddress = readEndAddress + 1;
                }
                else
                {
                    //The value was 0xFF, so look at the next value to try to start the write
                    readStartAddress++;
                }
            }
        }
        //Update the progress bar
        //cout << (((curPage + 1) * 100) / 32) << "% complete\n";
    }
    //end verify hex file data


    //begin exit bootloader
    if (ExecuteCommandExitBootloader() != BLCommandReturnType_OK)
    {
        cout << "Lost communications with device!";
        return false;
    }
    //end exit bootloader

    cout << "Verifying device flash complete!\r\n";
    cout << "Program/verify sequence completed successfully!\n";

    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4508, %rsp           # imm = 0x4508
leaq 0x2f82(%rip), %rsi      # 0x6a51
leaq -0x330(%rbp), %rdi
leaq -0x4530(%rbp), %rbx
movq %rbx, %rdx
callq 0x4942
movw $0x3e02, (%rbx)         # imm = 0x3E02
movb $0x0, 0x2(%rbx)
movq 0x54e3(%rip), %rdi      # 0x8fd8
leaq 0x2a70(%rip), %rsi      # 0x656c
callq 0x2200
movl 0x56fd(%rip), %eax      # 0x9204
cmpl 0x5803(%rip), %eax      # 0x9310
jne 0x3b1b
leaq 0x2a7e(%rip), %rsi      # 0x6594
jmp 0x3cda
movq 0x54b6(%rip), %rdi      # 0x8fd8
leaq 0x2aa0(%rip), %rsi      # 0x65c9
callq 0x2200
leaq 0x579b(%rip), %rsi      # 0x92d0
leaq -0x310(%rbp), %rdi
callq 0x22a0
leaq -0x310(%rbp), %rdi
leaq -0x330(%rbp), %rsi
callq 0x4c76
movq %rax, %rbx
leaq -0x310(%rbp), %rdi
callq 0x23e8
testq %rbx, %rbx
je 0x3c67
xorl %eax, %eax
xorl %ecx, %ecx
cmpq $0x1f, %rcx
je 0x3b89
movb %al, -0x2d0(%rbp,%rcx)
movb %al, -0x2f0(%rbp,%rcx)
incq %rcx
jmp 0x3b70
xorl %eax, %eax
cmpq $0x4000, %rax           # imm = 0x4000
je 0x3ba0
movb $-0x1, -0x4530(%rbp,%rax)
incq %rax
jmp 0x3b8b
xorl %r15d, %r15d
leaq -0x80(%rbp), %r14
pushq $0x1
popq %r13
movl %r15d, %ecx
movq 0x8(%rbx), %rax
subq (%rbx), %rax
cqto
pushq $0x38
popq %rsi
idivq %rsi
cmpq %rcx, %rax
jbe 0x3c70
movslq %r15d, %rsi
movq %rbx, %rdi
callq 0x4acc
movq %r14, %rdi
movq %rax, %rsi
callq 0x4aea
movzwl -0x5e(%rbp), %eax
movzwl -0x60(%rbp), %ecx
leal (%rcx,%rax), %r12d
cmpl $0x3dff, %r12d          # imm = 0x3DFF
ja 0x3c3a
movq -0x58(%rbp), %rdx
subq $0x1, %rcx
jb 0x3c4d
movl %eax, %esi
shrl $0x9, %esi
movb (%rdx), %dil
movzbl %sil, %esi
movzbl -0x2f0(%rbp,%rsi), %r8d
cmpb $-0x1, %dil
movl %r13d, %r9d
cmovel %r8d, %r9d
testb %r8b, %r8b
cmovnel %r8d, %r9d
movb %dil, -0x4530(%rbp,%rax)
movb %r9b, -0x2f0(%rbp,%rsi)
incq %rax
incq %rdx
jmp 0x3bf5
movq 0x5397(%rip), %rdi      # 0x8fd8
leaq 0x29b0(%rip), %rsi      # 0x65f8
callq 0x2200
movq %r14, %rdi
callq 0x23e8
incl %r15d
cmpl $0x3e00, %r12d          # imm = 0x3E00
jb 0x3bab
jmp 0x3ce6
leaq 0x2971(%rip), %rsi      # 0x65df
jmp 0x3cda
movq 0x5361(%rip), %rdi      # 0x8fd8
leaq 0x29cf(%rip), %rsi      # 0x664d
callq 0x2200
movq 0x534e(%rip), %rdi      # 0x8fd8
leaq 0x29d9(%rip), %rsi      # 0x666a
callq 0x2200
callq 0x35a4
testl %eax, %eax
je 0x3cad
cmpl $0x3, %eax
jne 0x3cd3
leaq 0x29dd(%rip), %rsi      # 0x6688
jmp 0x3cda
leaq -0x2a(%rbp), %rdi
andw $0x0, (%rdi)
callq 0x35d0
testl %eax, %eax
je 0x3d08
movq 0x5313(%rip), %rdi      # 0x8fd8
leaq 0x29d5(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
leaq 0x2847(%rip), %rsi      # 0x6521
movq 0x52f7(%rip), %rdi      # 0x8fd8
callq 0x2200
xorl %ebx, %ebx
leaq -0x330(%rbp), %rdi
callq 0x23e8
movl %ebx, %eax
addq $0x4508, %rsp           # imm = 0x4508
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq -0x2b(%rbp), %rdi
movb $0x0, (%rdi)
callq 0x363e
testl %eax, %eax
je 0x3d2d
movq 0x52b9(%rip), %rdi      # 0x8fd8
leaq 0x297b(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
movzwl -0x2a(%rbp), %esi
leaq -0x80(%rbp), %rdi
callq 0x3699
movq 0x5297(%rip), %rdi      # 0x8fd8
leaq -0x80(%rbp), %rsi
callq 0x21e0
leaq -0x80(%rbp), %rdi
callq 0x23e8
leaq -0x4530(%rbp), %rcx
movzbl 0x1(%rcx), %eax
movl %eax, -0x40(%rbp)
shll $0x8, %eax
movzbl 0x2(%rcx), %ecx
movl %ecx, -0x3c(%rbp)
orl %ecx, %eax
xorl %ebx, %ebx
movzwl %ax, %eax
movl %eax, -0x84(%rbp)
cmpq $0x1f, %rbx
je 0x3f2e
cmpb $0x1, -0x2f0(%rbp,%rbx)
movq %rbx, -0x48(%rbp)
jne 0x3dc9
movl %ebx, %r15d
shll $0x9, %r15d
testq %rbx, %rbx
je 0x3df8
xorl %r12d, %r12d
cmpb $0x0, -0x2d0(%rbp,%rbx)
jne 0x3dc1
movzbl %bl, %edi
callq 0x38b8
testl %eax, %eax
jne 0x3f16
movb $0x1, -0x2d0(%rbp,%rbx)
movl %r15d, %r14d
jmp 0x3e52
cmpb $0x0, -0x2d0(%rbp,%rbx)
jne 0x3def
movq -0x48(%rbp), %rbx
movzbl %bl, %edi
callq 0x38b8
testl %eax, %eax
jne 0x3f16
movb $0x1, -0x2d0(%rbp,%rbx)
movq -0x48(%rbp), %rbx
incq %rbx
jmp 0x3d78
xorl %edi, %edi
callq 0x38b8
testl %eax, %eax
jne 0x3f16
movb $0x1, -0x2d0(%rbp)
xorl %edi, %edi
callq 0x38f0
testl %eax, %eax
jne 0x3f16
leaq 0x2745(%rip), %rdi      # 0x6569
xorl %esi, %esi
pushq $0x3
popq %rdx
callq 0x3937
testl %eax, %eax
jne 0x3f16
movl -0x84(%rbp), %edi
callq 0x39d5
pushq $0x3
popq %rcx
movl %ecx, %r14d
movl %ecx, %r12d
testl %eax, %eax
jne 0x3f16
movq %r12, %rdx
orl $0x1ff, %r15d           # imm = 0x1FF
movl %r14d, %ebx
leaq (%rbx,%rbp), %rax
addq $-0x4530, %rax          # imm = 0xBAD0
xorl %r12d, %r12d
leal (%rbx,%r12), %ecx
cmpl %r15d, %ecx
ja 0x3def
cmpb $-0x1, (%rax,%r12)
jne 0x3e85
incq %r12
jmp 0x3e6c
leaq (%rbx,%r12), %rsi
negl %edx
addq %rsi, %rdx
movq %rdx, %rdi
xorl %eax, %eax
movl %esi, %r8d
movl %esi, %ecx
movl %r8d, %r14d
incl %ecx
cmpl %r15d, %ecx
ja 0x3ec8
leal 0x1(%r14), %r8d
xorl %edx, %edx
cmpb $-0x1, -0x4530(%rbp,%r8)
jne 0x3ebf
cmpl $0x6, %eax
ja 0x3ec8
incl %eax
movl %r14d, %ecx
movl %eax, %edx
movl %ecx, %r8d
addl %edx, %ecx
movl %edx, %eax
jmp 0x3e98
testl %edi, %edi
je 0x3ee4
movq %rsi, -0x38(%rbp)
movzwl %si, %edi
callq 0x38f0
testl %eax, %eax
movq -0x38(%rbp), %rsi
jne 0x4220
movl %r14d, %edx
subl %ebx, %edx
subl %r12d, %edx
incl %edx
movl $0xffff, %eax           # imm = 0xFFFF
andl %eax, %esi
andl %eax, %edx
leaq -0x4530(%rbp), %rdi
callq 0x3937
testl %eax, %eax
jne 0x4208
incl %r14d
movl %r14d, %edx
jmp 0x3e5c
movq 0x50bb(%rip), %rdi      # 0x8fd8
leaq 0x277d(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
movq 0x50a3(%rip), %rdi      # 0x8fd8
leaq 0x2786(%rip), %rsi      # 0x66c2
callq 0x2200
movq 0x5090(%rip), %rdi      # 0x8fd8
leaq 0x2798(%rip), %rsi      # 0x66e7
callq 0x2200
xorl %edx, %edx
cmpq $0x1f, %rdx
je 0x4238
cmpb $0x1, -0x2f0(%rbp,%rdx)
jne 0x4128
movl %edx, %ecx
shll $0x9, %ecx
xorl %eax, %eax
movl %ecx, %ebx
movq %rdx, -0x48(%rbp)
testq %rdx, %rdx
jne 0x4046
movl $0x3e09, %edi           # imm = 0x3E09
callq 0x38f0
testl %eax, %eax
jne 0x4272
leaq -0x530(%rbp), %rdi
xorl %esi, %esi
pushq $0x3
popq %rdx
callq 0x3a18
testl %eax, %eax
jne 0x4272
movzbl -0x530(%rbp), %r12d
movb -0x52f(%rbp), %r14b
movb -0x52e(%rbp), %r15b
cmpl $0x2, %r12d
jne 0x42a2
cmpb -0x40(%rbp), %r14b
jne 0x42a2
cmpb -0x3c(%rbp), %r15b
jne 0x42a2
xorl %edi, %edi
callq 0x38f0
testl %eax, %eax
jne 0x4272
leaq -0x530(%rbp), %rdi
xorl %esi, %esi
pushq $0x3
popq %rdx
callq 0x3a18
testl %eax, %eax
jne 0x4272
movzbl -0x530(%rbp), %r12d
movb -0x52f(%rbp), %r14b
movb -0x52e(%rbp), %al
movb %al, -0x38(%rbp)
cmpl $0x2, %r12d
jne 0x444a
cmpb $0x3e, %r14b
jne 0x444a
pushq $0x3
popq %rax
movl %eax, %ecx
cmpb $0x0, -0x38(%rbp)
jne 0x444a
movl %ebx, %r8d
orl $0x1ff, %r8d            # imm = 0x1FF
movl %r13d, %r15d
subl %ecx, %r15d
movl %ecx, %r12d
movq -0x48(%rbp), %rdx
cmpl %r8d, %r12d
ja 0x4128
movl %r12d, %ecx
cmpb $-0x1, -0x4530(%rbp,%rcx)
jne 0x407b
incl %r12d
decl %r15d
jmp 0x405d
xorl %ecx, %ecx
movl %r12d, %ebx
movl %r12d, %edx
incl %edx
cmpl %r8d, %edx
ja 0x40ac
leal 0x1(%rbx), %edi
xorl %esi, %esi
cmpb $-0x1, -0x4530(%rbp,%rdi)
jne 0x40a4
cmpl $0x6, %ecx
ja 0x40ac
incl %ecx
movl %ebx, %edx
movl %ecx, %esi
movl %edx, %ebx
addl %esi, %edx
movl %esi, %ecx
jmp 0x4083
movl %r8d, -0x38(%rbp)
movzwl %r12w, %r14d
cmpl %eax, %r12d
je 0x40c9
movl %r14d, %edi
callq 0x38f0
testl %eax, %eax
jne 0x46bf
movl %ebx, %eax
subl %r12d, %eax
incl %eax
movzwl %ax, %edx
leaq -0x530(%rbp), %rdi
movl %r14d, %esi
callq 0x3a18
testl %eax, %eax
jne 0x428a
addl %ebx, %r15d
incl %ebx
movq %rbx, %rcx
xorl %eax, %eax
cmpq %rax, %r15
je 0x411d
movq %rax, %rbx
movl %r12d, %eax
movzbl -0x4530(%rbp,%rax), %r14d
cmpb %r14b, -0x530(%rbp,%rax)
jne 0x4130
incl %r12d
movq %rbx, %rax
incq %rax
jmp 0x40f4
movl %ecx, %eax
movl -0x38(%rbp), %r8d
jmp 0x4050
incq %rdx
jmp 0x3f56
movq 0x4ea1(%rip), %rdi      # 0x8fd8
leaq 0x269f(%rip), %rsi      # 0x67dd
callq 0x2200
leaq -0x80(%rbp), %rdi
movl %r12d, %esi
callq 0x569c
movq 0x4e82(%rip), %rdi      # 0x8fd8
leaq -0x80(%rbp), %rsi
callq 0x21e0
leaq -0x80(%rbp), %rdi
callq 0x23e8
movq 0x4e69(%rip), %rdi      # 0x8fd8
leaq 0x2687(%rip), %rsi      # 0x67fd
callq 0x2200
leaq -0x80(%rbp), %rdi
movl %r14d, %esi
callq 0x569c
movq 0x4e4a(%rip), %rdi      # 0x8fd8
leaq -0x80(%rbp), %rsi
callq 0x21e0
leaq -0x80(%rbp), %rdi
callq 0x23e8
movq 0x4e31(%rip), %rdi      # 0x8fd8
leaq 0x265d(%rip), %rsi      # 0x680b
callq 0x2200
movzbl -0x530(%rbp,%rbx), %esi
leaq -0xa8(%rbp), %rdi
callq 0x569c
leaq 0x247d(%rip), %rdx      # 0x664b
leaq -0x80(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x49f3
movq 0x4df3(%rip), %rdi      # 0x8fd8
leaq -0x80(%rbp), %rsi
callq 0x21e0
leaq -0x80(%rbp), %rdi
callq 0x23e8
leaq -0xa8(%rbp), %rdi
callq 0x23e8
jmp 0x3ce6
movq 0x4dc9(%rip), %rdi      # 0x8fd8
leaq 0x248b(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
movq 0x4db1(%rip), %rdi      # 0x8fd8
leaq 0x2473(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
callq 0x367b
testl %eax, %eax
jne 0x3d18
movq 0x4d8c(%rip), %rdi      # 0x8fd8
leaq 0x25c9(%rip), %rsi      # 0x681c
callq 0x2200
movb $0x1, %bl
movq 0x4d77(%rip), %rdi      # 0x8fd8
leaq 0x25d7(%rip), %rsi      # 0x683f
callq 0x2200
jmp 0x3ce8
movq 0x4d5f(%rip), %rdi      # 0x8fd8
leaq 0x2421(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
movq 0x4d47(%rip), %rdi      # 0x8fd8
leaq 0x2409(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
leaq -0x168(%rbp), %rdi
movl $0x3e09, %esi           # imm = 0x3E09
callq 0x569c
leaq 0x2449(%rip), %rsi      # 0x6703
leaq -0x188(%rbp), %rdi
leaq -0x168(%rbp), %rdx
callq 0x4a2a
leaq 0x2471(%rip), %rdx      # 0x6745
leaq -0x1a8(%rbp), %rdi
leaq -0x188(%rbp), %rsi
callq 0x49f3
leaq -0x148(%rbp), %rdi
movl -0x40(%rbp), %esi
callq 0x569c
leaq -0x1c8(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
leaq -0x148(%rbp), %rdx
callq 0x4b11
leaq 0x243e(%rip), %rdx      # 0x6755
leaq -0x1e8(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x49f3
leaq -0x128(%rbp), %rdi
movl -0x3c(%rbp), %esi
callq 0x569c
leaq -0x208(%rbp), %rdi
leaq -0x1e8(%rbp), %rsi
leaq -0x128(%rbp), %rdx
callq 0x4b11
leaq 0x23ff(%rip), %rdx      # 0x6759
leaq -0x228(%rbp), %rdi
leaq -0x208(%rbp), %rsi
callq 0x49f3
leaq -0x108(%rbp), %rdi
movl %r12d, %esi
callq 0x569c
leaq -0x248(%rbp), %rdi
leaq -0x228(%rbp), %rsi
leaq -0x108(%rbp), %rdx
callq 0x4b11
leaq 0x23b8(%rip), %rdx      # 0x6755
leaq -0x268(%rbp), %rdi
leaq -0x248(%rbp), %rsi
callq 0x49f3
movzbl %r14b, %esi
leaq -0xe8(%rbp), %rdi
callq 0x569c
leaq -0x288(%rbp), %rdi
leaq -0x268(%rbp), %rsi
leaq -0xe8(%rbp), %rdx
callq 0x4b11
leaq 0x2374(%rip), %rdx      # 0x6755
leaq -0x2a8(%rbp), %rdi
leaq -0x288(%rbp), %rsi
callq 0x49f3
movzbl %r15b, %esi
leaq -0xc8(%rbp), %rdi
callq 0x569c
leaq -0xa8(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
callq 0x4b11
leaq 0x234a(%rip), %rdx      # 0x676f
leaq -0x80(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x49f3
movq 0x4b9c(%rip), %rdi      # 0x8fd8
leaq -0x80(%rbp), %rsi
callq 0x21e0
jmp 0x45ea
leaq -0x168(%rbp), %rdi
pushq $0x2
popq %rsi
callq 0x569c
leaq 0x2312(%rip), %rsi      # 0x6772
leaq -0x188(%rbp), %rdi
leaq -0x168(%rbp), %rdx
callq 0x4a2a
leaq 0x22db(%rip), %rdx      # 0x6755
leaq -0x1a8(%rbp), %rdi
leaq -0x188(%rbp), %rsi
callq 0x49f3
leaq -0x148(%rbp), %rdi
pushq $0x3e
popq %rsi
callq 0x569c
leaq -0x1c8(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
leaq -0x148(%rbp), %rdx
callq 0x4b11
leaq 0x2298(%rip), %rdx      # 0x6755
leaq -0x1e8(%rbp), %rdi
leaq -0x1c8(%rbp), %rsi
callq 0x49f3
leaq -0x128(%rbp), %rdi
xorl %esi, %esi
callq 0x569c
leaq -0x208(%rbp), %rdi
leaq -0x1e8(%rbp), %rsi
leaq -0x128(%rbp), %rdx
callq 0x4b11
leaq 0x22c8(%rip), %rdx      # 0x67c7
leaq -0x228(%rbp), %rdi
leaq -0x208(%rbp), %rsi
callq 0x49f3
leaq -0x108(%rbp), %rdi
movl %r12d, %esi
callq 0x569c
leaq -0x248(%rbp), %rdi
leaq -0x228(%rbp), %rsi
leaq -0x108(%rbp), %rdx
callq 0x4b11
leaq 0x2213(%rip), %rdx      # 0x6755
leaq -0x268(%rbp), %rdi
leaq -0x248(%rbp), %rsi
callq 0x49f3
movzbl %r14b, %esi
leaq -0xe8(%rbp), %rdi
callq 0x569c
leaq -0x288(%rbp), %rdi
leaq -0x268(%rbp), %rsi
leaq -0xe8(%rbp), %rdx
callq 0x4b11
leaq 0x21cf(%rip), %rdx      # 0x6755
leaq -0x2a8(%rbp), %rdi
leaq -0x288(%rbp), %rsi
callq 0x49f3
movzbl -0x38(%rbp), %esi
leaq -0xc8(%rbp), %rdi
callq 0x569c
leaq -0xa8(%rbp), %rdi
leaq -0x2a8(%rbp), %rsi
leaq -0xc8(%rbp), %rdx
callq 0x4b11
leaq 0x21a5(%rip), %rdx      # 0x676f
leaq -0x80(%rbp), %rdi
leaq -0xa8(%rbp), %rsi
callq 0x49f3
movq 0x49f7(%rip), %rdi      # 0x8fd8
leaq -0x80(%rbp), %rsi
callq 0x21e0
leaq -0x80(%rbp), %rdi
callq 0x23e8
leaq -0xa8(%rbp), %rdi
callq 0x23e8
leaq -0xc8(%rbp), %rdi
callq 0x23e8
leaq -0x2a8(%rbp), %rdi
callq 0x23e8
leaq -0x288(%rbp), %rdi
callq 0x23e8
leaq -0xe8(%rbp), %rdi
callq 0x23e8
leaq -0x268(%rbp), %rdi
callq 0x23e8
leaq -0x248(%rbp), %rdi
callq 0x23e8
leaq -0x108(%rbp), %rdi
callq 0x23e8
leaq -0x228(%rbp), %rdi
callq 0x23e8
leaq -0x208(%rbp), %rdi
callq 0x23e8
leaq -0x128(%rbp), %rdi
callq 0x23e8
leaq -0x1e8(%rbp), %rdi
callq 0x23e8
leaq -0x1c8(%rbp), %rdi
callq 0x23e8
leaq -0x148(%rbp), %rdi
callq 0x23e8
leaq -0x1a8(%rbp), %rdi
callq 0x23e8
leaq -0x188(%rbp), %rdi
callq 0x23e8
leaq -0x168(%rbp), %rdi
jmp 0x41fe
movq 0x4912(%rip), %rdi      # 0x8fd8
leaq 0x1fd4(%rip), %rsi      # 0x66a1
callq 0x2200
jmp 0x3ce6
jmp 0x48d9
jmp 0x472f
jmp 0x473d
jmp 0x474e
jmp 0x475f
jmp 0x4770
jmp 0x481b
jmp 0x4823
jmp 0x482b
jmp 0x4833
jmp 0x483b
jmp 0x4843
jmp 0x484b
jmp 0x4853
jmp 0x485b
jmp 0x4863
jmp 0x4868
jmp 0x486d
jmp 0x4872
jmp 0x48d9
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x23e8
jmp 0x4740
movq %rax, %rbx
leaq -0xa8(%rbp), %rdi
callq 0x23e8
jmp 0x4751
movq %rax, %rbx
leaq -0xc8(%rbp), %rdi
callq 0x23e8
jmp 0x4762
movq %rax, %rbx
leaq -0x2a8(%rbp), %rdi
callq 0x23e8
jmp 0x4773
movq %rax, %rbx
leaq -0x288(%rbp), %rdi
callq 0x23e8
leaq -0xe8(%rbp), %rdi
callq 0x23e8
leaq -0x268(%rbp), %rdi
callq 0x23e8
leaq -0x248(%rbp), %rdi
callq 0x23e8
leaq -0x108(%rbp), %rdi
callq 0x23e8
leaq -0x228(%rbp), %rdi
callq 0x23e8
leaq -0x208(%rbp), %rdi
callq 0x23e8
leaq -0x128(%rbp), %rdi
callq 0x23e8
leaq -0x1e8(%rbp), %rdi
callq 0x23e8
leaq -0x1c8(%rbp), %rdi
callq 0x23e8
leaq -0x148(%rbp), %rdi
callq 0x23e8
leaq -0x1a8(%rbp), %rdi
callq 0x23e8
leaq -0x188(%rbp), %rdi
callq 0x23e8
leaq -0x168(%rbp), %rdi
jmp 0x48d0
movq %rax, %rbx
jmp 0x477f
movq %rax, %rbx
jmp 0x478b
movq %rax, %rbx
jmp 0x4797
movq %rax, %rbx
jmp 0x47a3
movq %rax, %rbx
jmp 0x47af
movq %rax, %rbx
jmp 0x47bb
movq %rax, %rbx
jmp 0x47c7
movq %rax, %rbx
jmp 0x47d3
movq %rax, %rbx
jmp 0x47df
movq %rax, %rbx
jmp 0x47eb
movq %rax, %rbx
jmp 0x47f7
movq %rax, %rbx
jmp 0x4803
movq %rax, %rbx
jmp 0x480f
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x23e8
jmp 0x4892
movq %rax, %rbx
leaq -0xa8(%rbp), %rdi
jmp 0x48d0
jmp 0x48d9
jmp 0x48c9
jmp 0x48d9
jmp 0x48c9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48c9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
jmp 0x48d9
movq %rax, %rbx
leaq -0x310(%rbp), %rdi
jmp 0x48d0
movq %rax, %rbx
leaq -0x80(%rbp), %rdi
callq 0x23e8
jmp 0x48dc
jmp 0x48d9
movq %rax, %rbx
leaq -0x330(%rbp), %rdi
callq 0x23e8
movq %rbx, %rdi
callq 0x2370