// File: Thilotilo[P]DoaERando/Randomizer.cpp
// Function: DoaERando::Randomizer::CaveShuffle()
void Randomizer::CaveShuffle()
{
    // These are world map offsets
    const int XU_ZHE_CAVE_OFFSET = 0x07;
    const int MT_GANG_TAI_ENTRANCE_OFFSET = 0x0B;
    const int MT_GANG_TAI_EXIT_OFFSET = 0x1F;
    const int WU_CAVE_EXIT_OFFSET = 0x26;
    const int WU_CAVE_ENTRANCE_OFFSET = 0x39;
    const int GOLD_KEY_CAVE_OFFSET = 0x46;
    const int CHANG_AN_ENTRANCE_OFFSET = 0x58;
    const int CHANG_AN_EXIT_OFFSET = 0x61;
    const int NAN_YANG_CAVE_OFFSET = 0x63;
    const int WEI_CAVE_2_ENTRANCE_OFFSET = 0x6C;
    const int WEI_CAVE_2_EXIT_OFFSET = 0x7B;
    const int WEI_CAVE_1_EXIT_OFFSET = 0x7E;
    const int WEI_CAVE_1_ENTRANCE_OFFSET = 0x93;
    const int SALTPETER_CAVE_OFFSET = 0x99;

    // Magic numbers are bad, but 8 million consts to start a method are obnoxious.
    vector<vector<BYTE>> CaveWarpOffsets = {
        {XU_ZHE_CAVE_OFFSET,          0x08, 0x09},
        {MT_GANG_TAI_ENTRANCE_OFFSET, 0x0A},
        {MT_GANG_TAI_EXIT_OFFSET,     0x1E},
        {WU_CAVE_EXIT_OFFSET,         0x27},
        {WU_CAVE_ENTRANCE_OFFSET,     0x38},
        {GOLD_KEY_CAVE_OFFSET,        0x47, 0x48},
        {CHANG_AN_ENTRANCE_OFFSET,    0x57, 0x59},
        {CHANG_AN_EXIT_OFFSET,        0x60, 0x62},
        {NAN_YANG_CAVE_OFFSET,        0x64, 0x65},
        {WEI_CAVE_2_ENTRANCE_OFFSET,  0x6D, 0x7D},
        {WEI_CAVE_2_EXIT_OFFSET,      0x7A, 0x7C},
        {WEI_CAVE_1_EXIT_OFFSET,      0x7F, 0x80},
        {WEI_CAVE_1_ENTRANCE_OFFSET,  0x94, 0x95},
        {SALTPETER_CAVE_OFFSET,       0x9A, 0x9B}
    };

    vector<vector<BYTE>> ShuffledOffsets = CaveWarpOffsets;

    for (int i = 0; i < 10000; ++i)
    {
        int location1 = myRNG.GetRandomInt(0, ShuffledOffsets.size() - 1);
        int location2 = myRNG.GetRandomInt(0, ShuffledOffsets.size() - 1);
        swap(ShuffledOffsets[location1], ShuffledOffsets[location2]);
    }

    // Now do sanity checks
    // For now, let's prevent the following:
    // 1) Wu Cave entrance should not be a single-entrance cave to prevent softlocks from canal
    // 2) Mt Gang Tai Exit cannot be a single-entrance cave, and it's other side cannot come to
    //    one of the Wei caves if the other is a Single Exit cave
    // 3) Wei1 Exit & Wei2 Entrance can't be opposite ends of the same cave
    // 4) Wei1 Exit & Wei2 Entrance can't both be single-entrance caves.
    while (IsSingleExitCave(ShuffledOffsets[4][0]) ||
           IsSingleExitCave(ShuffledOffsets[2][0]) ||
           (AreExitsFromSameCave(ShuffledOffsets[2][0], ShuffledOffsets[9][0]) &&
            IsSingleExitCave(ShuffledOffsets[11][0])) ||
           (AreExitsFromSameCave(ShuffledOffsets[2][0], ShuffledOffsets[11][0]) &&
            IsSingleExitCave(ShuffledOffsets[9][0])) ||
           AreExitsFromSameCave(ShuffledOffsets[9][0], ShuffledOffsets[11][0]) ||
           (IsSingleExitCave(ShuffledOffsets[9][0]) && IsSingleExitCave(ShuffledOffsets[11][0])))
    {
        int location1 = myRNG.GetRandomInt(0, ShuffledOffsets.size() - 1);
        int location2 = myRNG.GetRandomInt(0, ShuffledOffsets.size() - 1);
        swap(ShuffledOffsets[location1], ShuffledOffsets[location2]);
    }

    // Collect all the bytes we need to update
    std::vector<std::vector<BYTE>> bytesToWrite;
    for (int i = 0; i < ShuffledOffsets.size(); ++i)
    {
        printf("Putting cave id 0x%02X in the vanilla 0x%02X location\n",
               ShuffledOffsets[i][0], CaveWarpOffsets[i][0]);
        int lsb = myRom->ReadByte(0x1C210 + ShuffledOffsets[i][0]);
        int msb = myRom->ReadByte(0x1C2C0 + ShuffledOffsets[i][0]);
        int shuffledAddressInBank = (msb << 8) | lsb;

        lsb = myRom->ReadByte(0x1C210 + CaveWarpOffsets[i][1]);
        msb = myRom->ReadByte(0x1C2C0 + CaveWarpOffsets[i][1]);
        int caveExitAddressInBank = (msb << 8) | lsb;

        // This puts the destination of the shuffled world map address into the vanilla location
        std::vector<BYTE> updateToWrite;
        updateToWrite.push_back(CaveWarpOffsets[i][0]);
        for (int j = 4; j < 9; ++j)
        {
            updateToWrite.push_back(myRom->ReadByteAtBank(0x7, shuffledAddressInBank + j));
        }

        bytesToWrite.push_back(updateToWrite);

        // This puts the destination of the vanilla cave exits to the shuffled world map location
        for (int j = 1; j < ShuffledOffsets[i].size(); ++j)
        {
            std::vector<BYTE> updatedCaveEntrance;
            updatedCaveEntrance.push_back(ShuffledOffsets[i][j]);
            for (int k = 4; k < 9; ++k)
            {
                updatedCaveEntrance.push_back(myRom->ReadByteAtBank(0x7, caveExitAddressInBank + k));
            }
            bytesToWrite.push_back(updatedCaveEntrance);
        }
    }

    // Now write everything
    for (auto& entry : bytesToWrite)
    {
        int lsb = myRom->ReadByte(0x1C210 + entry[0]);
        int msb = myRom->ReadByte(0x1C2C0 + entry[0]);
        int addressInBank = (msb << 8) | lsb;

        for (int i = 1; i < entry.size(); ++i)
        {
            myRom->WriteByteAtBank(0x7, addressInBank + i + 3, entry[i]);
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x670, %rsp            # imm = 0x670
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x410(%rbp)
movl $0x7, -0xc(%rbp)
movl $0xb, -0x10(%rbp)
movl $0x1f, -0x14(%rbp)
movl $0x26, -0x18(%rbp)
movl $0x39, -0x1c(%rbp)
movl $0x46, -0x20(%rbp)
movl $0x58, -0x24(%rbp)
movl $0x61, -0x28(%rbp)
movl $0x63, -0x2c(%rbp)
movl $0x6c, -0x30(%rbp)
movl $0x7b, -0x34(%rbp)
movl $0x7e, -0x38(%rbp)
movl $0x93, -0x3c(%rbp)
movl $0x99, -0x40(%rbp)
movb $0x1, -0x31d(%rbp)
leaq -0x1b8(%rbp), %rax
movq %rax, -0x408(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x7, -0x1d3(%rbp)
movb $0x8, -0x1d2(%rbp)
movb $0x9, -0x1d1(%rbp)
leaq -0x1d3(%rbp), %rax
movq %rax, -0x1d0(%rbp)
movq $0x3, -0x1c8(%rbp)
leaq -0x1d4(%rbp), %rdi
movq %rdi, -0x400(%rbp)
callq 0x404e70
movq -0x408(%rbp), %rdi
movq -0x400(%rbp), %rcx
movq -0x1d0(%rbp), %rsi
movq -0x1c8(%rbp), %rdx
callq 0x40fb50
jmp 0x40650c
leaq -0x1a0(%rbp), %rax
movq %rax, -0x420(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0xb, -0x1fa(%rbp)
movb $0xa, -0x1f9(%rbp)
leaq -0x1fa(%rbp), %rax
movq %rax, -0x1f8(%rbp)
movq $0x2, -0x1f0(%rbp)
leaq -0x1fb(%rbp), %rdi
movq %rdi, -0x418(%rbp)
callq 0x404e70
movq -0x420(%rbp), %rdi
movq -0x418(%rbp), %rcx
movq -0x1f8(%rbp), %rsi
movq -0x1f0(%rbp), %rdx
callq 0x40fb50
jmp 0x40657e
leaq -0x188(%rbp), %rax
movq %rax, -0x430(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x1f, -0x212(%rbp)
movb $0x1e, -0x211(%rbp)
leaq -0x212(%rbp), %rax
movq %rax, -0x210(%rbp)
movq $0x2, -0x208(%rbp)
leaq -0x213(%rbp), %rdi
movq %rdi, -0x428(%rbp)
callq 0x404e70
movq -0x430(%rbp), %rdi
movq -0x428(%rbp), %rcx
movq -0x210(%rbp), %rsi
movq -0x208(%rbp), %rdx
callq 0x40fb50
jmp 0x4065f0
leaq -0x170(%rbp), %rax
movq %rax, -0x440(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x26, -0x22a(%rbp)
movb $0x27, -0x229(%rbp)
leaq -0x22a(%rbp), %rax
movq %rax, -0x228(%rbp)
movq $0x2, -0x220(%rbp)
leaq -0x22b(%rbp), %rdi
movq %rdi, -0x438(%rbp)
callq 0x404e70
movq -0x440(%rbp), %rdi
movq -0x438(%rbp), %rcx
movq -0x228(%rbp), %rsi
movq -0x220(%rbp), %rdx
callq 0x40fb50
jmp 0x406662
leaq -0x158(%rbp), %rax
movq %rax, -0x450(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x39, -0x242(%rbp)
movb $0x38, -0x241(%rbp)
leaq -0x242(%rbp), %rax
movq %rax, -0x240(%rbp)
movq $0x2, -0x238(%rbp)
leaq -0x243(%rbp), %rdi
movq %rdi, -0x448(%rbp)
callq 0x404e70
movq -0x450(%rbp), %rdi
movq -0x448(%rbp), %rcx
movq -0x240(%rbp), %rsi
movq -0x238(%rbp), %rdx
callq 0x40fb50
jmp 0x4066d4
leaq -0x140(%rbp), %rax
movq %rax, -0x460(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x46, -0x25b(%rbp)
movb $0x47, -0x25a(%rbp)
movb $0x48, -0x259(%rbp)
leaq -0x25b(%rbp), %rax
movq %rax, -0x258(%rbp)
movq $0x3, -0x250(%rbp)
leaq -0x25c(%rbp), %rdi
movq %rdi, -0x458(%rbp)
callq 0x404e70
movq -0x460(%rbp), %rdi
movq -0x458(%rbp), %rcx
movq -0x258(%rbp), %rsi
movq -0x250(%rbp), %rdx
callq 0x40fb50
jmp 0x40674d
leaq -0x128(%rbp), %rax
movq %rax, -0x470(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x58, -0x273(%rbp)
movb $0x57, -0x272(%rbp)
movb $0x59, -0x271(%rbp)
leaq -0x273(%rbp), %rax
movq %rax, -0x270(%rbp)
movq $0x3, -0x268(%rbp)
leaq -0x274(%rbp), %rdi
movq %rdi, -0x468(%rbp)
callq 0x404e70
movq -0x470(%rbp), %rdi
movq -0x468(%rbp), %rcx
movq -0x270(%rbp), %rsi
movq -0x268(%rbp), %rdx
callq 0x40fb50
jmp 0x4067c6
leaq -0x110(%rbp), %rax
movq %rax, -0x480(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x61, -0x28b(%rbp)
movb $0x60, -0x28a(%rbp)
movb $0x62, -0x289(%rbp)
leaq -0x28b(%rbp), %rax
movq %rax, -0x288(%rbp)
movq $0x3, -0x280(%rbp)
leaq -0x28c(%rbp), %rdi
movq %rdi, -0x478(%rbp)
callq 0x404e70
movq -0x480(%rbp), %rdi
movq -0x478(%rbp), %rcx
movq -0x288(%rbp), %rsi
movq -0x280(%rbp), %rdx
callq 0x40fb50
jmp 0x40683f
leaq -0xf8(%rbp), %rax
movq %rax, -0x490(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x63, -0x2a3(%rbp)
movb $0x64, -0x2a2(%rbp)
movb $0x65, -0x2a1(%rbp)
leaq -0x2a3(%rbp), %rax
movq %rax, -0x2a0(%rbp)
movq $0x3, -0x298(%rbp)
leaq -0x2a4(%rbp), %rdi
movq %rdi, -0x488(%rbp)
callq 0x404e70
movq -0x490(%rbp), %rdi
movq -0x488(%rbp), %rcx
movq -0x2a0(%rbp), %rsi
movq -0x298(%rbp), %rdx
callq 0x40fb50
jmp 0x4068b8
leaq -0xe0(%rbp), %rax
movq %rax, -0x4a0(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x6c, -0x2bb(%rbp)
movb $0x6d, -0x2ba(%rbp)
movb $0x7d, -0x2b9(%rbp)
leaq -0x2bb(%rbp), %rax
movq %rax, -0x2b8(%rbp)
movq $0x3, -0x2b0(%rbp)
leaq -0x2bc(%rbp), %rdi
movq %rdi, -0x498(%rbp)
callq 0x404e70
movq -0x4a0(%rbp), %rdi
movq -0x498(%rbp), %rcx
movq -0x2b8(%rbp), %rsi
movq -0x2b0(%rbp), %rdx
callq 0x40fb50
jmp 0x406931
leaq -0xc8(%rbp), %rax
movq %rax, -0x4b0(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x7b, -0x2d3(%rbp)
movb $0x7a, -0x2d2(%rbp)
movb $0x7c, -0x2d1(%rbp)
leaq -0x2d3(%rbp), %rax
movq %rax, -0x2d0(%rbp)
movq $0x3, -0x2c8(%rbp)
leaq -0x2d4(%rbp), %rdi
movq %rdi, -0x4a8(%rbp)
callq 0x404e70
movq -0x4b0(%rbp), %rdi
movq -0x4a8(%rbp), %rcx
movq -0x2d0(%rbp), %rsi
movq -0x2c8(%rbp), %rdx
callq 0x40fb50
jmp 0x4069aa
leaq -0xb0(%rbp), %rax
movq %rax, -0x4c0(%rbp)
movq %rax, -0x1c0(%rbp)
movb $0x7e, -0x2eb(%rbp)
movb $0x7f, -0x2ea(%rbp)
movb $-0x80, -0x2e9(%rbp)
leaq -0x2eb(%rbp), %rax
movq %rax, -0x2e8(%rbp)
movq $0x3, -0x2e0(%rbp)
leaq -0x2ec(%rbp), %rdi
movq %rdi, -0x4b8(%rbp)
callq 0x404e70
movq -0x4c0(%rbp), %rdi
movq -0x4b8(%rbp), %rcx
movq -0x2e8(%rbp), %rsi
movq -0x2e0(%rbp), %rdx
callq 0x40fb50
jmp 0x406a23
leaq -0x98(%rbp), %rax
movq %rax, -0x4d0(%rbp)
movq %rax, -0x1c0(%rbp)
movb $-0x6d, -0x303(%rbp)
movb $-0x6c, -0x302(%rbp)
movb $-0x6b, -0x301(%rbp)
leaq -0x303(%rbp), %rax
movq %rax, -0x300(%rbp)
movq $0x3, -0x2f8(%rbp)
leaq -0x304(%rbp), %rdi
movq %rdi, -0x4c8(%rbp)
callq 0x404e70
movq -0x4d0(%rbp), %rdi
movq -0x4c8(%rbp), %rcx
movq -0x300(%rbp), %rsi
movq -0x2f8(%rbp), %rdx
callq 0x40fb50
jmp 0x406a9c
leaq -0x80(%rbp), %rax
movq %rax, -0x4e0(%rbp)
movq %rax, -0x1c0(%rbp)
movb $-0x67, -0x31b(%rbp)
movb $-0x66, -0x31a(%rbp)
movb $-0x65, -0x319(%rbp)
leaq -0x31b(%rbp), %rax
movq %rax, -0x318(%rbp)
movq $0x3, -0x310(%rbp)
leaq -0x31c(%rbp), %rdi
movq %rdi, -0x4d8(%rbp)
callq 0x404e70
movq -0x4e0(%rbp), %rdi
movq -0x4d8(%rbp), %rcx
movq -0x318(%rbp), %rsi
movq -0x310(%rbp), %rdx
callq 0x40fb50
jmp 0x406b12
movb $0x0, -0x31d(%rbp)
leaq -0x1b8(%rbp), %rax
movq %rax, -0x68(%rbp)
movq $0xe, -0x60(%rbp)
leaq -0x31e(%rbp), %rdi
movq %rdi, -0x4e8(%rbp)
callq 0x40fbd0
movq -0x4e8(%rbp), %rcx
movq -0x68(%rbp), %rsi
movq -0x60(%rbp), %rdx
leaq -0x58(%rbp), %rdi
callq 0x40fbf0
jmp 0x406b59
leaq -0x31e(%rbp), %rdi
callq 0x40fc70
leaq -0x1b8(%rbp), %rax
movq %rax, -0x4f8(%rbp)
addq $0x150, %rax            # imm = 0x150
movq %rax, -0x4f0(%rbp)
movq -0x4f0(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x500(%rbp)
callq 0x404f50
movq -0x4f8(%rbp), %rcx
movq -0x500(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x4f0(%rbp)
jne 0x406b80
leaq -0x31c(%rbp), %rdi
callq 0x404fb0
leaq -0x304(%rbp), %rdi
callq 0x404fb0
leaq -0x2ec(%rbp), %rdi
callq 0x404fb0
leaq -0x2d4(%rbp), %rdi
callq 0x404fb0
leaq -0x2bc(%rbp), %rdi
callq 0x404fb0
leaq -0x2a4(%rbp), %rdi
callq 0x404fb0
leaq -0x28c(%rbp), %rdi
callq 0x404fb0
leaq -0x274(%rbp), %rdi
callq 0x404fb0
leaq -0x25c(%rbp), %rdi
callq 0x404fb0
leaq -0x243(%rbp), %rdi
callq 0x404fb0
leaq -0x22b(%rbp), %rdi
callq 0x404fb0
leaq -0x213(%rbp), %rdi
callq 0x404fb0
leaq -0x1fb(%rbp), %rdi
callq 0x404fb0
leaq -0x1d4(%rbp), %rdi
callq 0x404fb0
leaq -0x338(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x40fc90
jmp 0x406c6b
movl $0x0, -0x33c(%rbp)
cmpl $0x2710, -0x33c(%rbp)   # imm = 0x2710
jge 0x40703b
movq -0x410(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x510(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x40fd80
movq -0x510(%rbp), %rdi
movl %eax, %edx
decl %edx
xorl %esi, %esi
callq 0x41dba0
movl %eax, -0x504(%rbp)
jmp 0x406cbd
movq -0x410(%rbp), %rax
movl -0x504(%rbp), %ecx
movl %ecx, -0x340(%rbp)
addq $0x8, %rax
movq %rax, -0x520(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x40fd80
movq -0x520(%rbp), %rdi
movl %eax, %edx
decl %edx
xorl %esi, %esi
callq 0x41dba0
movl %eax, -0x514(%rbp)
jmp 0x406d01
movl -0x514(%rbp), %eax
movl %eax, -0x344(%rbp)
movslq -0x340(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, -0x528(%rbp)
movslq -0x344(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq -0x528(%rbp), %rdi
movq %rax, %rsi
callq 0x40fdb0
movl -0x33c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x33c(%rbp)
jmp 0x406c75
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406fa4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f98
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f8c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f80
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f74
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f68
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f5c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f50
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f44
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f38
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f2c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f20
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f14
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x406f08
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
leaq -0x31e(%rbp), %rdi
callq 0x40fc70
leaq -0x1b8(%rbp), %rax
movq %rax, -0x538(%rbp)
addq $0x150, %rax            # imm = 0x150
movq %rax, -0x530(%rbp)
movq -0x530(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x540(%rbp)
callq 0x404f50
movq -0x538(%rbp), %rcx
movq -0x540(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x530(%rbp)
jne 0x406ed5
jmp 0x406f08
leaq -0x31c(%rbp), %rdi
callq 0x404fb0
leaq -0x304(%rbp), %rdi
callq 0x404fb0
leaq -0x2ec(%rbp), %rdi
callq 0x404fb0
leaq -0x2d4(%rbp), %rdi
callq 0x404fb0
leaq -0x2bc(%rbp), %rdi
callq 0x404fb0
leaq -0x2a4(%rbp), %rdi
callq 0x404fb0
leaq -0x28c(%rbp), %rdi
callq 0x404fb0
leaq -0x274(%rbp), %rdi
callq 0x404fb0
leaq -0x25c(%rbp), %rdi
callq 0x404fb0
leaq -0x243(%rbp), %rdi
callq 0x404fb0
leaq -0x22b(%rbp), %rdi
callq 0x404fb0
leaq -0x213(%rbp), %rdi
callq 0x404fb0
leaq -0x1fb(%rbp), %rdi
callq 0x404fb0
leaq -0x1d4(%rbp), %rdi
callq 0x404fb0
testb $0x1, -0x31d(%rbp)
jne 0x406fbb
jmp 0x407008
movq -0x1c0(%rbp), %rax
leaq -0x1b8(%rbp), %rcx
cmpq %rax, %rcx
movq %rax, -0x548(%rbp)
je 0x407006
movq -0x548(%rbp), %rdi
addq $-0x18, %rdi
movq %rdi, -0x550(%rbp)
callq 0x404f50
movq -0x550(%rbp), %rax
leaq -0x1b8(%rbp), %rcx
cmpq %rcx, %rax
movq %rax, -0x548(%rbp)
jne 0x406fd5
jmp 0x407008
jmp 0x407b03
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x407afa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x407aee
jmp 0x40703d
leaq -0x338(%rbp), %rdi
movl $0x4, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movzbl (%rax), %edi
callq 0x407b10
movb %al, -0x551(%rbp)
jmp 0x40706a
movb -0x551(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x552(%rbp)
jne 0x40734d
jmp 0x407083
leaq -0x338(%rbp), %rdi
movl $0x2, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movzbl (%rax), %edi
callq 0x407b10
movb %al, -0x553(%rbp)
jmp 0x4070b0
movb -0x553(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x552(%rbp)
jne 0x40734d
jmp 0x4070c9
leaq -0x338(%rbp), %rdi
movq %rdi, -0x568(%rbp)
movl $0x2, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x560(%rbp)
callq 0x405030
movq -0x568(%rbp), %rdi
movzbl (%rax), %eax
movl %eax, -0x558(%rbp)
movl $0x9, %esi
callq 0x40fde0
movq -0x560(%rbp), %rsi
movq %rax, %rdi
callq 0x405030
movl -0x558(%rbp), %edi
movzbl (%rax), %esi
callq 0x407b70
movb %al, -0x554(%rbp)
jmp 0x407133
movb -0x554(%rbp), %al
testb $0x1, %al
jne 0x40713f
jmp 0x407185
leaq -0x338(%rbp), %rdi
movl $0xb, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movzbl (%rax), %edi
callq 0x407b10
movb %al, -0x569(%rbp)
jmp 0x40716c
movb -0x569(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x552(%rbp)
jne 0x40734d
jmp 0x407185
leaq -0x338(%rbp), %rdi
movq %rdi, -0x580(%rbp)
movl $0x2, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x578(%rbp)
callq 0x405030
movq -0x580(%rbp), %rdi
movzbl (%rax), %eax
movl %eax, -0x570(%rbp)
movl $0xb, %esi
callq 0x40fde0
movq -0x578(%rbp), %rsi
movq %rax, %rdi
callq 0x405030
movl -0x570(%rbp), %edi
movzbl (%rax), %esi
callq 0x407b70
movb %al, -0x56a(%rbp)
jmp 0x4071ef
movb -0x56a(%rbp), %al
testb $0x1, %al
jne 0x4071fb
jmp 0x407241
leaq -0x338(%rbp), %rdi
movl $0x9, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movzbl (%rax), %edi
callq 0x407b10
movb %al, -0x581(%rbp)
jmp 0x407228
movb -0x581(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x552(%rbp)
jne 0x40734d
jmp 0x407241
leaq -0x338(%rbp), %rdi
movq %rdi, -0x598(%rbp)
movl $0x9, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
movq %rsi, -0x590(%rbp)
callq 0x405030
movq -0x598(%rbp), %rdi
movzbl (%rax), %eax
movl %eax, -0x588(%rbp)
movl $0xb, %esi
callq 0x40fde0
movq -0x590(%rbp), %rsi
movq %rax, %rdi
callq 0x405030
movl -0x588(%rbp), %edi
movzbl (%rax), %esi
callq 0x407b70
movb %al, -0x582(%rbp)
jmp 0x4072ab
movb -0x582(%rbp), %cl
movb $0x1, %al
testb $0x1, %cl
movb %al, -0x552(%rbp)
jne 0x40734d
jmp 0x4072c4
leaq -0x338(%rbp), %rdi
movl $0x9, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movzbl (%rax), %edi
callq 0x407b10
movb %al, -0x599(%rbp)
jmp 0x4072f1
movb -0x599(%rbp), %cl
xorl %eax, %eax
testb $0x1, %cl
movb %al, -0x59a(%rbp)
jne 0x407306
jmp 0x407341
leaq -0x338(%rbp), %rdi
movl $0xb, %esi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movzbl (%rax), %edi
callq 0x407b10
movb %al, -0x59b(%rbp)
jmp 0x407333
movb -0x59b(%rbp), %al
movb %al, -0x59a(%rbp)
jmp 0x407341
movb -0x59a(%rbp), %al
movb %al, -0x552(%rbp)
movb -0x552(%rbp), %al
testb $0x1, %al
jne 0x40735c
jmp 0x407425
movq -0x410(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x5a8(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x40fd80
movq -0x5a8(%rbp), %rdi
movl %eax, %edx
decl %edx
xorl %esi, %esi
callq 0x41dba0
movl %eax, -0x5a0(%rbp)
jmp 0x407394
movq -0x410(%rbp), %rax
movl -0x5a0(%rbp), %ecx
movl %ecx, -0x348(%rbp)
addq $0x8, %rax
movq %rax, -0x5b8(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x40fd80
movq -0x5b8(%rbp), %rdi
movl %eax, %edx
decl %edx
xorl %esi, %esi
callq 0x41dba0
movl %eax, -0x5ac(%rbp)
jmp 0x4073d8
movl -0x5ac(%rbp), %eax
movl %eax, -0x34c(%rbp)
movslq -0x348(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, -0x5c0(%rbp)
movslq -0x34c(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq -0x5c0(%rbp), %rdi
movq %rax, %rsi
callq 0x40fdb0
jmp 0x40703d
leaq -0x368(%rbp), %rdi
callq 0x40fe00
movl $0x0, -0x36c(%rbp)
movslq -0x36c(%rbp), %rax
movq %rax, -0x5c8(%rbp)
leaq -0x338(%rbp), %rdi
callq 0x40fd80
movq %rax, %rcx
movq -0x5c8(%rbp), %rax
cmpq %rcx, %rax
jae 0x4078f1
movslq -0x36c(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, -0x5cc(%rbp)
movl %eax, %esi
movq %rsi, -0x5d8(%rbp)
callq 0x405030
movzbl (%rax), %eax
movl %eax, -0x5d0(%rbp)
movslq -0x36c(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x40fde0
movq -0x5d8(%rbp), %rsi
movq %rax, %rdi
callq 0x405030
movl -0x5d0(%rbp), %esi
movq %rax, %rcx
movl -0x5cc(%rbp), %eax
movzbl (%rcx), %edx
leaq 0x193bd5(%rip), %rdi    # 0x59b0aa
callq 0x4f06e0
jmp 0x4074dc
movq -0x410(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x5e8(%rbp)
movslq -0x36c(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movq -0x5e8(%rbp), %rdi
movzbl (%rax), %esi
addl $0x1c210, %esi          # imm = 0x1C210
callq 0x404bb0
movb %al, -0x5d9(%rbp)
jmp 0x407529
movq -0x410(%rbp), %rax
movb -0x5d9(%rbp), %cl
movzbl %cl, %ecx
movl %ecx, -0x370(%rbp)
movq (%rax), %rax
movq %rax, -0x5f8(%rbp)
movslq -0x36c(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movq -0x5f8(%rbp), %rdi
movzbl (%rax), %esi
addl $0x1c2c0, %esi          # imm = 0x1C2C0
callq 0x404bb0
movb %al, -0x5e9(%rbp)
jmp 0x407585
movq -0x410(%rbp), %rax
movb -0x5e9(%rbp), %cl
movzbl %cl, %ecx
movl %ecx, -0x374(%rbp)
movl -0x374(%rbp), %ecx
shll $0x8, %ecx
movl -0x370(%rbp), %edx
orl %edx, %ecx
movl %ecx, -0x378(%rbp)
movq (%rax), %rax
movq %rax, -0x608(%rbp)
movslq -0x36c(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
movl $0x1, %esi
callq 0x405030
movq -0x608(%rbp), %rdi
movzbl (%rax), %esi
addl $0x1c210, %esi          # imm = 0x1C210
callq 0x404bb0
movb %al, -0x5f9(%rbp)
jmp 0x4075f6
movq -0x410(%rbp), %rax
movb -0x5f9(%rbp), %cl
movzbl %cl, %ecx
movl %ecx, -0x370(%rbp)
movq (%rax), %rax
movq %rax, -0x618(%rbp)
movslq -0x36c(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
movl $0x1, %esi
callq 0x405030
movq -0x618(%rbp), %rdi
movzbl (%rax), %esi
addl $0x1c2c0, %esi          # imm = 0x1C2C0
callq 0x404bb0
movb %al, -0x609(%rbp)
jmp 0x407650
movb -0x609(%rbp), %al
movzbl %al, %eax
movl %eax, -0x374(%rbp)
movl -0x374(%rbp), %eax
shll $0x8, %eax
movl -0x370(%rbp), %ecx
orl %ecx, %eax
movl %eax, -0x37c(%rbp)
leaq -0x398(%rbp), %rdi
movq %rdi, -0x620(%rbp)
callq 0x40fa90
movslq -0x36c(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movq -0x620(%rbp), %rdi
movq %rax, %rsi
callq 0x40fae0
jmp 0x4076b6
movl $0x4, -0x39c(%rbp)
cmpl $0x9, -0x39c(%rbp)
jge 0x407759
movq -0x410(%rbp), %rax
movq (%rax), %rdi
movl -0x378(%rbp), %edx
movl -0x39c(%rbp), %eax
addl %eax, %edx
movl $0x7, %esi
callq 0x404be0
movb %al, -0x621(%rbp)
jmp 0x4076f7
movb -0x621(%rbp), %al
movb %al, -0x39d(%rbp)
leaq -0x398(%rbp), %rdi
leaq -0x39d(%rbp), %rsi
callq 0x40fab0
jmp 0x407718
jmp 0x40771a
movl -0x39c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x39c(%rbp)
jmp 0x4076c0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x407ae2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
jmp 0x4078e0
leaq -0x368(%rbp), %rdi
leaq -0x398(%rbp), %rsi
callq 0x40fe20
jmp 0x40776e
movl $0x1, -0x3a4(%rbp)
movslq -0x3a4(%rbp), %rax
movq %rax, -0x630(%rbp)
movslq -0x36c(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
callq 0x405010
movq %rax, %rcx
movq -0x630(%rbp), %rax
cmpq %rcx, %rax
jae 0x4078c0
leaq -0x3c0(%rbp), %rdi
movq %rdi, -0x638(%rbp)
callq 0x40fa90
movslq -0x36c(%rbp), %rsi
leaq -0x338(%rbp), %rdi
callq 0x40fde0
movq %rax, %rdi
movslq -0x3a4(%rbp), %rsi
callq 0x405030
movq -0x638(%rbp), %rdi
movq %rax, %rsi
callq 0x40fae0
jmp 0x4077fa
movl $0x4, -0x3c4(%rbp)
cmpl $0x9, -0x3c4(%rbp)
jge 0x40788b
movq -0x410(%rbp), %rax
movq (%rax), %rdi
movl -0x37c(%rbp), %edx
movl -0x3c4(%rbp), %eax
addl %eax, %edx
movl $0x7, %esi
callq 0x404be0
movb %al, -0x639(%rbp)
jmp 0x407837
movb -0x639(%rbp), %al
movb %al, -0x3c5(%rbp)
leaq -0x3c0(%rbp), %rdi
leaq -0x3c5(%rbp), %rsi
callq 0x40fab0
jmp 0x407858
jmp 0x40785a
movl -0x3c4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3c4(%rbp)
jmp 0x407804
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1e0(%rbp)
movl %eax, -0x1e4(%rbp)
leaq -0x3c0(%rbp), %rdi
callq 0x404f50
jmp 0x4078e0
leaq -0x368(%rbp), %rdi
leaq -0x3c0(%rbp), %rsi
callq 0x40fe20
jmp 0x4078a0
leaq -0x3c0(%rbp), %rdi
callq 0x404f50
movl -0x3a4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3a4(%rbp)
jmp 0x407778
leaq -0x398(%rbp), %rdi
callq 0x404f50
movl -0x36c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x36c(%rbp)
jmp 0x40743b
leaq -0x398(%rbp), %rdi
callq 0x404f50
jmp 0x407ae2
leaq -0x368(%rbp), %rax
movq %rax, -0x3d0(%rbp)
movq -0x3d0(%rbp), %rdi
callq 0x40fe90
movq %rax, -0x3d8(%rbp)
movq -0x3d0(%rbp), %rdi
callq 0x40fec0
movq %rax, -0x3e0(%rbp)
leaq -0x3d8(%rbp), %rdi
leaq -0x3e0(%rbp), %rsi
callq 0x40fef0
testb $0x1, %al
jne 0x407941
jmp 0x407ab8
leaq -0x3d8(%rbp), %rdi
callq 0x40ff30
movq %rax, %rcx
movq -0x410(%rbp), %rax
movq %rcx, -0x3e8(%rbp)
movq (%rax), %rax
movq %rax, -0x648(%rbp)
movq -0x3e8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movq -0x648(%rbp), %rdi
movzbl (%rax), %esi
addl $0x1c210, %esi          # imm = 0x1C210
callq 0x404bb0
movb %al, -0x63a(%rbp)
jmp 0x407995
movq -0x410(%rbp), %rax
movb -0x63a(%rbp), %cl
movzbl %cl, %ecx
movl %ecx, -0x3ec(%rbp)
movq (%rax), %rax
movq %rax, -0x658(%rbp)
movq -0x3e8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x405030
movq -0x658(%rbp), %rdi
movzbl (%rax), %esi
addl $0x1c2c0, %esi          # imm = 0x1C2C0
callq 0x404bb0
movb %al, -0x649(%rbp)
jmp 0x4079e2
movb -0x649(%rbp), %al
movzbl %al, %eax
movl %eax, -0x3f0(%rbp)
movl -0x3f0(%rbp), %eax
shll $0x8, %eax
orl -0x3ec(%rbp), %eax
movl %eax, -0x3f4(%rbp)
movl $0x1, -0x3f8(%rbp)
movslq -0x3f8(%rbp), %rax
movq %rax, -0x660(%rbp)
movq -0x3e8(%rbp), %rdi
callq 0x405010
movq %rax, %rcx
movq -0x660(%rbp), %rax
cmpq %rcx, %rax
jae 0x407aa5
movq -0x410(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x670(%rbp)
movl -0x3f4(%rbp), %ecx
movslq -0x3f8(%rbp), %rsi
movl %esi, %edx
movl %ecx, %eax
movl %edx, %ecx
leal 0x3(%rax,%rcx), %eax
movl %eax, -0x664(%rbp)
movq -0x3e8(%rbp), %rdi
callq 0x405030
movq -0x670(%rbp), %rdi
movl -0x664(%rbp), %edx
movzbl (%rax), %ecx
movl $0x7, %esi
callq 0x404c60
jmp 0x407a8f
jmp 0x407a91
movl -0x3f8(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x3f8(%rbp)
jmp 0x407a10
jmp 0x407aa7
leaq -0x3d8(%rbp), %rdi
callq 0x40ff50
jmp 0x407925
leaq -0x368(%rbp), %rdi
callq 0x40ff70
leaq -0x338(%rbp), %rdi
callq 0x40ff70
leaq -0x58(%rbp), %rdi
callq 0x40ff70
addq $0x670, %rsp            # imm = 0x670
popq %rbp
retq
leaq -0x368(%rbp), %rdi
callq 0x40ff70
leaq -0x338(%rbp), %rdi
callq 0x40ff70
leaq -0x58(%rbp), %rdi
callq 0x40ff70
movq -0x1e0(%rbp), %rdi
callq 0x4c9ba0
nop