// File: Thilotilo[P]DoaERando/Randomizer.cpp
// Function: DoaERando::Randomizer::ItemShuffle()
void Randomizer::ItemShuffle()
{
    std::vector<BYTE> chestContentsToRandomize;

    // Grab starting items
    chestContentsToRandomize.push_back(myRom->ReadByte(0x3556C));
    chestContentsToRandomize.push_back(myRom->ReadByte(0x3556D));
    chestContentsToRandomize.push_back(myRom->ReadByte(0x35574));
    chestContentsToRandomize.push_back(myRom->ReadByte(0x35575));
    chestContentsToRandomize.push_back(myRom->ReadByte(0x3557C));
    chestContentsToRandomize.push_back(myRom->ReadByte(0x3557D));

    // Add Zhao Yun's sister's item
    chestContentsToRandomize.push_back(myRom->ReadByte(0x368DC));

    // Add Intro Letr item (We'll put gemsword behind this item)
    chestContentsToRandomize.push_back(myRom->ReadByte(0x366DD));

    // Add Silver Key item
    chestContentsToRandomize.push_back(myRom->ReadByte(0x3680F));

    // Add Gunpowder Item
    chestContentsToRandomize.push_back(myRom->ReadByte(0x368A2));

    // Add Qing Long Item
    chestContentsToRandomize.push_back(myRom->ReadByte(0x37333));

    // Grab hidden items
    const int HIDDEN_ITEM_OFFSET = 0x30B10;
    for (int i = HIDDEN_ITEM_OFFSET; i < HIDDEN_ITEM_OFFSET + 20; ++i)
    {
        BYTE item = myRom->ReadByte(i);
        if (item != 0xFF) // I found a keyhole, i = 2
        {
            chestContentsToRandomize.push_back(item);
        }
    }

    // Grab non-hidden items
    const int ITEMS_OFFSET = 0x30914; // (Every 5th byte is the item ID) - data starts at 30910
    const int ITEMS_OFFSET_END = 0x309E7;
    for (int i = ITEMS_OFFSET; i < ITEMS_OFFSET_END; i += 5)
    {
        chestContentsToRandomize.push_back(myRom->ReadByte(i));
    }

    for (int i = 0; i < 100000; ++i)
    {
        int index1 = myRNG.GetRandomIndexFromByteVector(chestContentsToRandomize);
        int index2 = myRNG.GetRandomIndexFromByteVector(chestContentsToRandomize);

        BYTE item1 = chestContentsToRandomize[index1];
        BYTE item2 = chestContentsToRandomize[index2];

        // 3 Conditions we have to verify
        // 1) Make sure that we're not swapping coins into starting inventory or talk-and-speak inventory
        // 2) Make sure that the Silver Key is not behind Zhao Yun's sister
        // 3) Make sure that the Zhou Letr isn't in Guang Zong.
        if (!((index1 < 11 || index2 < 11) && (item1 < 0x10 || item2 < 0x10)) // 1
            || (index1 == 14 && item2 == 0x22) || (index2 == 14 && item1 == 0x22) // 2
            || (index1 == 8 && item2 == 0x18) || (index2 == 8 && item2 == 0x18)) // 3
        {
            chestContentsToRandomize[index1] = item2;
            chestContentsToRandomize[index2] = item1;
        }
    }

    int index = 0;

    for (int i = 0; i < chestContentsToRandomize.size(); ++i)
    {
        if (i == 0)
        {
            printf ("Starting items:\n");
        }
        if (i == 6)
        {
            printf ("Talk-and-get items:\n");
        }
        if (i == 11)
        {
            printf ("Hidden items:\n");
        }
        if (i == 30)
        {
            printf ("Normal chests:\n");
        }
        printf ("\tChest %d: 0x%02X\n", i, chestContentsToRandomize[i]);
    }

    // Write new starting items
    myRom->WriteByte(0x3556C, chestContentsToRandomize[index++]);
    myRom->WriteByte(0x3556D, chestContentsToRandomize[index++]);
    myRom->WriteByte(0x35574, chestContentsToRandomize[index++]);
    myRom->WriteByte(0x35575, chestContentsToRandomize[index++]);
    myRom->WriteByte(0x3557C, chestContentsToRandomize[index++]);
    myRom->WriteByte(0x3557D, chestContentsToRandomize[index++]);

    // Write new Zhou Letr item
    myRom->WriteByte(0x368DC, chestContentsToRandomize[index++]);

    // Write new Intro Letr item
    myRom->WriteByte(0x366DD, chestContentsToRandomize[index++]);

    // Write new Silver Key item
    myRom->WriteByte(0x3680F, chestContentsToRandomize[index++]);

    // Write new Gunpowder Item
    myRom->WriteByte(0x368A2, chestContentsToRandomize[index++]);

    // Write new Qing Long Item
    myRom->WriteByte(0x37333, chestContentsToRandomize[index++]);

    // Write new hidden items
    for (int i = HIDDEN_ITEM_OFFSET; i < HIDDEN_ITEM_OFFSET + 20; ++i)
    {
        BYTE item = myRom->ReadByte(i);
        if (item != 0xFF) // I found a keyhole, i = 2
        {
            myRom->WriteByte(i, chestContentsToRandomize[index++]);
        }
    }

    for (int i = ITEMS_OFFSET; i < ITEMS_OFFSET_END; i += 5)
    {
        myRom->WriteByte(i, chestContentsToRandomize[index++]);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x130, %rsp            # imm = 0x130
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x90(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x40fa90
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x3556c, %esi          # imm = 0x3556C
callq 0x404bb0
movb %al, -0x81(%rbp)
jmp 0x407ccf
movb -0x81(%rbp), %al
movb %al, -0x21(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x21(%rbp), %rsi
callq 0x40fab0
jmp 0x407ce7
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x3556d, %esi          # imm = 0x3556D
callq 0x404bb0
movb %al, -0x91(%rbp)
jmp 0x407d03
movb -0x91(%rbp), %al
movb %al, -0x35(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x35(%rbp), %rsi
callq 0x40fab0
jmp 0x407d1b
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x35574, %esi          # imm = 0x35574
callq 0x404bb0
movb %al, -0x92(%rbp)
jmp 0x407d37
movb -0x92(%rbp), %al
movb %al, -0x36(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x36(%rbp), %rsi
callq 0x40fab0
jmp 0x407d4f
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x35575, %esi          # imm = 0x35575
callq 0x404bb0
movb %al, -0x93(%rbp)
jmp 0x407d6b
movb -0x93(%rbp), %al
movb %al, -0x37(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x37(%rbp), %rsi
callq 0x40fab0
jmp 0x407d83
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x3557c, %esi          # imm = 0x3557C
callq 0x404bb0
movb %al, -0x94(%rbp)
jmp 0x407d9f
movb -0x94(%rbp), %al
movb %al, -0x38(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x40fab0
jmp 0x407db7
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x3557d, %esi          # imm = 0x3557D
callq 0x404bb0
movb %al, -0x95(%rbp)
jmp 0x407dd3
movb -0x95(%rbp), %al
movb %al, -0x39(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x39(%rbp), %rsi
callq 0x40fab0
jmp 0x407deb
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x368dc, %esi          # imm = 0x368DC
callq 0x404bb0
movb %al, -0x96(%rbp)
jmp 0x407e07
movb -0x96(%rbp), %al
movb %al, -0x3a(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x3a(%rbp), %rsi
callq 0x40fab0
jmp 0x407e1f
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x366dd, %esi          # imm = 0x366DD
callq 0x404bb0
movb %al, -0x97(%rbp)
jmp 0x407e3b
movb -0x97(%rbp), %al
movb %al, -0x3b(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x3b(%rbp), %rsi
callq 0x40fab0
jmp 0x407e53
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x3680f, %esi          # imm = 0x3680F
callq 0x404bb0
movb %al, -0x98(%rbp)
jmp 0x407e6f
movb -0x98(%rbp), %al
movb %al, -0x3c(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x3c(%rbp), %rsi
callq 0x40fab0
jmp 0x407e87
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x368a2, %esi          # imm = 0x368A2
callq 0x404bb0
movb %al, -0x99(%rbp)
jmp 0x407ea3
movb -0x99(%rbp), %al
movb %al, -0x3d(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x3d(%rbp), %rsi
callq 0x40fab0
jmp 0x407ebb
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl $0x37333, %esi          # imm = 0x37333
callq 0x404bb0
movb %al, -0x9a(%rbp)
jmp 0x407ed7
movb -0x9a(%rbp), %al
movb %al, -0x3e(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x3e(%rbp), %rsi
callq 0x40fab0
jmp 0x407eef
movl $0x30b10, -0x44(%rbp)   # imm = 0x30B10
movl $0x30b10, -0x48(%rbp)   # imm = 0x30B10
cmpl $0x30b24, -0x48(%rbp)   # imm = 0x30B24
jge 0x407f6c
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl -0x48(%rbp), %esi
callq 0x404bb0
movb %al, -0x9b(%rbp)
jmp 0x407f20
movb -0x9b(%rbp), %al
movb %al, -0x49(%rbp)
movzbl -0x49(%rbp), %eax
cmpl $0xff, %eax
je 0x407f5f
leaq -0x20(%rbp), %rdi
leaq -0x49(%rbp), %rsi
callq 0x40fae0
jmp 0x407f43
jmp 0x407f5f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x30(%rbp)
movl %eax, -0x34(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x404f50
jmp 0x40855a
jmp 0x407f61
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x407efd
movl $0x30914, -0x50(%rbp)   # imm = 0x30914
movl $0x309e7, -0x54(%rbp)   # imm = 0x309E7
movl $0x30914, -0x58(%rbp)   # imm = 0x30914
cmpl $0x309e7, -0x58(%rbp)   # imm = 0x309E7
jge 0x407fc9
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl -0x58(%rbp), %esi
callq 0x404bb0
movb %al, -0x9c(%rbp)
jmp 0x407fa4
movb -0x9c(%rbp), %al
movb %al, -0x59(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x59(%rbp), %rsi
callq 0x40fab0
jmp 0x407fbc
jmp 0x407fbe
movl -0x58(%rbp), %eax
addl $0x5, %eax
movl %eax, -0x58(%rbp)
jmp 0x407f81
movl $0x0, -0x60(%rbp)
cmpl $0x186a0, -0x60(%rbp)   # imm = 0x186A0
jge 0x4080f1
movq -0x90(%rbp), %rdi
addq $0x8, %rdi
leaq -0x20(%rbp), %rsi
callq 0x41dbe0
movl %eax, -0xa0(%rbp)
jmp 0x407ff9
movq -0x90(%rbp), %rdi
movl -0xa0(%rbp), %eax
movl %eax, -0x64(%rbp)
addq $0x8, %rdi
leaq -0x20(%rbp), %rsi
callq 0x41dbe0
movl %eax, -0xa4(%rbp)
jmp 0x40801e
movl -0xa4(%rbp), %eax
movl %eax, -0x68(%rbp)
movslq -0x64(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0x405030
movb (%rax), %al
movb %al, -0x69(%rbp)
movslq -0x68(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0x405030
movb (%rax), %al
movb %al, -0x6a(%rbp)
cmpl $0xb, -0x64(%rbp)
jl 0x408057
cmpl $0xb, -0x68(%rbp)
jge 0x4080a5
movzbl -0x69(%rbp), %eax
cmpl $0x10, %eax
jl 0x408069
movzbl -0x6a(%rbp), %eax
cmpl $0x10, %eax
jge 0x4080a5
cmpl $0xe, -0x64(%rbp)
jne 0x408078
movzbl -0x6a(%rbp), %eax
cmpl $0x22, %eax
je 0x4080a5
cmpl $0xe, -0x68(%rbp)
jne 0x408087
movzbl -0x69(%rbp), %eax
cmpl $0x22, %eax
je 0x4080a5
cmpl $0x8, -0x64(%rbp)
jne 0x408096
movzbl -0x6a(%rbp), %eax
cmpl $0x18, %eax
je 0x4080a5
cmpl $0x8, -0x68(%rbp)
jne 0x4080e1
movzbl -0x6a(%rbp), %eax
cmpl $0x18, %eax
jne 0x4080e1
movb -0x6a(%rbp), %al
movb %al, -0xa6(%rbp)
movslq -0x64(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0x405030
movb -0xa6(%rbp), %cl
movb %cl, (%rax)
movb -0x69(%rbp), %al
movb %al, -0xa5(%rbp)
movslq -0x68(%rbp), %rsi
leaq -0x20(%rbp), %rdi
callq 0x405030
movb -0xa5(%rbp), %cl
movb %cl, (%rax)
jmp 0x4080e3
movl -0x60(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x60(%rbp)
jmp 0x407fd0
movl $0x0, -0x70(%rbp)
movl $0x0, -0x74(%rbp)
movslq -0x74(%rbp), %rax
movq %rax, -0xb0(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405010
movq %rax, %rcx
movq -0xb0(%rbp), %rax
cmpq %rcx, %rax
jae 0x4081c4
cmpl $0x0, -0x74(%rbp)
jne 0x40813e
leaq 0x192fae(%rip), %rdi    # 0x59b0e1
xorl %eax, %eax
callq 0x4f06e0
jmp 0x40813c
jmp 0x40813e
cmpl $0x6, -0x74(%rbp)
jne 0x408156
leaq 0x192fa7(%rip), %rdi    # 0x59b0f2
xorl %eax, %eax
callq 0x4f06e0
jmp 0x408154
jmp 0x408156
cmpl $0xb, -0x74(%rbp)
jne 0x40816e
leaq 0x192fa4(%rip), %rdi    # 0x59b107
xorl %eax, %eax
callq 0x4f06e0
jmp 0x40816c
jmp 0x40816e
cmpl $0x1e, -0x74(%rbp)
jne 0x408186
leaq 0x192f9b(%rip), %rdi    # 0x59b116
xorl %eax, %eax
callq 0x4f06e0
jmp 0x408184
jmp 0x408186
movl -0x74(%rbp), %eax
movl %eax, -0xb4(%rbp)
movslq %eax, %rsi
leaq -0x20(%rbp), %rdi
callq 0x405030
movl -0xb4(%rbp), %esi
movzbl (%rax), %edx
leaq 0x192f7b(%rip), %rdi    # 0x59b126
xorl %eax, %eax
callq 0x4f06e0
jmp 0x4081b4
jmp 0x4081b6
movl -0x74(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x74(%rbp)
jmp 0x4080ff
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xc0(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xc0(%rbp), %rdi
movzbl (%rax), %edx
movl $0x3556c, %esi          # imm = 0x3556C
callq 0x404c20
jmp 0x4081ff
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xc8(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xc8(%rbp), %rdi
movzbl (%rax), %edx
movl $0x3556d, %esi          # imm = 0x3556D
callq 0x404c20
jmp 0x40823a
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xd0(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xd0(%rbp), %rdi
movzbl (%rax), %edx
movl $0x35574, %esi          # imm = 0x35574
callq 0x404c20
jmp 0x408275
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xd8(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xd8(%rbp), %rdi
movzbl (%rax), %edx
movl $0x35575, %esi          # imm = 0x35575
callq 0x404c20
jmp 0x4082b0
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xe0(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xe0(%rbp), %rdi
movzbl (%rax), %edx
movl $0x3557c, %esi          # imm = 0x3557C
callq 0x404c20
jmp 0x4082eb
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xe8(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xe8(%rbp), %rdi
movzbl (%rax), %edx
movl $0x3557d, %esi          # imm = 0x3557D
callq 0x404c20
jmp 0x408326
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xf0(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xf0(%rbp), %rdi
movzbl (%rax), %edx
movl $0x368dc, %esi          # imm = 0x368DC
callq 0x404c20
jmp 0x408361
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0xf8(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0xf8(%rbp), %rdi
movzbl (%rax), %edx
movl $0x366dd, %esi          # imm = 0x366DD
callq 0x404c20
jmp 0x40839c
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x100(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0x100(%rbp), %rdi
movzbl (%rax), %edx
movl $0x3680f, %esi          # imm = 0x3680F
callq 0x404c20
jmp 0x4083d7
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x108(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0x108(%rbp), %rdi
movzbl (%rax), %edx
movl $0x368a2, %esi          # imm = 0x368A2
callq 0x404c20
jmp 0x408412
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x110(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0x110(%rbp), %rdi
movzbl (%rax), %edx
movl $0x37333, %esi          # imm = 0x37333
callq 0x404c20
jmp 0x40844d
movl $0x30b10, -0x78(%rbp)   # imm = 0x30B10
cmpl $0x30b24, -0x78(%rbp)   # imm = 0x30B24
jge 0x4084e6
movq -0x90(%rbp), %rax
movq (%rax), %rdi
movl -0x78(%rbp), %esi
callq 0x404bb0
movb %al, -0x111(%rbp)
jmp 0x40847b
movb -0x111(%rbp), %al
movb %al, -0x79(%rbp)
movzbl -0x79(%rbp), %eax
cmpl $0xff, %eax
je 0x4084d6
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x120(%rbp)
movl -0x78(%rbp), %eax
movl %eax, -0x118(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0x120(%rbp), %rdi
movl -0x118(%rbp), %esi
movzbl (%rax), %edx
callq 0x404c20
jmp 0x4084d4
jmp 0x4084d6
jmp 0x4084d8
movl -0x78(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x78(%rbp)
jmp 0x408454
movl $0x30914, -0x80(%rbp)   # imm = 0x30914
cmpl $0x309e7, -0x80(%rbp)   # imm = 0x309E7
jge 0x408548
movq -0x90(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x130(%rbp)
movl -0x80(%rbp), %eax
movl %eax, -0x124(%rbp)
movslq -0x70(%rbp), %rsi
movl %esi, %eax
incl %eax
movl %eax, -0x70(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x405030
movq -0x130(%rbp), %rdi
movl -0x124(%rbp), %esi
movzbl (%rax), %edx
callq 0x404c20
jmp 0x40853b
jmp 0x40853d
movl -0x80(%rbp), %eax
addl $0x5, %eax
movl %eax, -0x80(%rbp)
jmp 0x4084ed
leaq -0x20(%rbp), %rdi
callq 0x404f50
addq $0x130, %rsp            # imm = 0x130
popq %rbp
retq
movq -0x30(%rbp), %rdi
callq 0x4c9ba0
nopw %cs:(%rax,%rax)