private void Randomize(object sender, RoutedEventArgs e)
        {
            if (file == null)
            {
                ShowNotification("Error!", "Please select a ROM before applying.");
                return;
            }

            //////////////////////////////////////////////////////
            /// SETUP RANDOMIZER AND SEED
            //////////////////////////////////////////////////////
            string seedtext  = (seed_input.Text != "") ? seed_input.Text : Utils.RandomString(12);
            MD5    md5Hasher = MD5.Create();

            byte[] hashed = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(seedtext));
            int    ivalue = BitConverter.ToInt32(hashed, 0);

            Random rng = new Random(ivalue);

            randomizer = new Randomizer(allBattles, allEncounters, allParts, rng);

            if (chk_enable_randomizer.IsOn)
            {
                //////////////////////////////////////////////////////
                /// RANDOMIZE CHARACTERS
                //////////////////////////////////////////////////////
                if (chk_randomize_characters.IsOn)
                {
                    randomizer.RandomizeCharacters(chk_character_continuity.IsOn);
                }

                //////////////////////////////////////////////////////
                /// RANDOMIZE BATTLES
                //////////////////////////////////////////////////////
                if (chk_randomize_battles.IsOn)
                {
                    float mixedchance            = chk_allow_mixed_bots.IsOn ? (float)(sl_mixed_bots.Value / 100) : 0;
                    bool  keep_team_structure    = chk_keep_battle_structure.IsOn;
                    bool  balanced_medal_level   = chk_balanced_bot_levels.IsOn;
                    bool  keep_battle_continuity = chk_battle_continuity.IsOn;

                    randomizer.RandomizeBattles(keep_team_structure, balanced_medal_level, mixedchance, keep_battle_continuity);
                }

                randomizer.fixSoftlock();
                int amount_of_battles = 0xf5;
                int battle_size       = 0x28;

                for (int i = 0; i <= amount_of_battles; i++)
                {
                    int    battle_address = Utils.GetAdressAtPosition(file, memory_offsets[game_id]["Battles"] + 4 * i);
                    byte[] battle         = StructUtils.getBytes(allBattles[i].content);
                    Array.Copy(battle, 0, file, battle_address, battle_size);
                }
                //////////////////////////////////////////////////////
                /// RANDOM SHOPS
                //////////////////////////////////////////////////////
                if (chk_random_shops.IsOn)
                {
                    for (int i = 0; i <= 0x3B; i++)
                    {
                        if (file[memory_offsets[game_id]["ShopContents"] + i] != 0xff)
                        {
                            file[memory_offsets[game_id]["ShopContents"] + i] = (byte)rng.Next(0, 0x78);
                        }
                    }
                }

                //////////////////////////////////////////////////////
                /// RANDOM STARTER
                //////////////////////////////////////////////////////
                byte[] blacklist = new byte[] { 1, 3, 6, 7, 8,
                                                14, 15, 17, 18,
                                                19, 20, 22, 23,
                                                25, 26, 27, 28,
                                                39, 40, 45, 50,
                                                57, 66, 72, 75,
                                                77, 80, 81, 82,
                                                84, 90, 91, 92,
                                                96, 100, 101, 104,
                                                110, 115, 117, 118 };

                if (chk_randomize_starter.IsOn)
                {
                    byte part;

                    if ((string)cmb_starter.SelectedItem == "Random")
                    {
                        part = (byte)rng.Next(0, 0x78);
                        while (blacklist.Contains(part))
                        {
                            part = (byte)rng.Next(0, 0x78);
                        }
                    }
                    else
                    {
                        part = (byte)(cmb_starter.SelectedIndex - 1);
                    }

                    byte medal = IdTranslator.botMedal(part);

                    randomizer.starterMedal = medal;

                    int  offset     = memory_offsets[game_id]["Starter"];
                    uint funcOffset = 0x044b58;

                    for (int i = 0; i < 4; i++)
                    {
                        file[offset + 4 * i] = part;
                    }

                    if (IdTranslator.isFemale(part))
                    {
                        file[offset + 16] = 1;
                    }

                    file[memory_offsets[game_id]["StartMedal"]] = medal;

                    ushort[] replacedFunction = new ushort[]
                    {
                        //Equip_parts
                        0x4a0e,                          //ldr        r2,[PTR_DAT_]
                        0x7811,                          //ldrb       r1,[r2,#0x0 ]=>DAT_03000be0
                        0x20c0,                          //mov        r0,#0xc0
                        (ushort)(0x2300 + medal),        //mov        r3,#medal
                        0x4308,                          //orr        r0, r1
                        0x7010,                          //strb       r0,[r2,#0x0 ]=>DAT_03000be0
                        0x490c,                          //ldr        r1,[PTR_DAT_]
                        0x2003,                          //mov        r0,#0x3
                        0x7008,                          //strb       r0,[r1,#0x0 ]=>DAT_030017a0
                        0x708b,                          //strb       r3,[r1,#0x2 ]=>DAT_030017a2
                        (ushort)(0x2000 + part),         //mov        r0,#part
                        0x70c8,                          //strb       r0,[r1,#0x3 ]=>DAT_030017a3
                        0x7108,                          //strb       r0,[r1,#0x4 ]=>DAT_030017a4
                        0x7148,                          //strb       r0,[r1,#0x5 ]=>DAT_030017a5
                        0x7188,                          //strb       r0,[r1,#0x6 ]=>DAT_030017a6
                        0x4909,                          //ldr        r1,[->parts_in_inventory]
                        0x1c08,                          //add        r0, r1,#0x0
                        (ushort)(0x3000 + part * 2 + 1), //add        r0,#part_offset
                        0x2201,                          //mov        r2,#0x1
                        0x7002,                          //strb       r2,[r0,#0x0 ]=>DAT_03004c95
                        0x4b07,                          //ldr        r3,[DAT_]
                        0x18c8,                          //add        r0, r1, r3
                        0x7002,                          //strb       r2,[r0,#0x0 ]=>DAT_03004d85
                        0x33f0,                          //add        r3,#0xf0
                        0x18c8,                          //add        r0, r1, r3
                        0x7002,                          //strb       r2,[r0,#0x0 ]=>DAT_03004e75
                        0x4805,                          //ldr        r0,[DAT_]
                        0x1809,                          //add        r1, r1, r0
                        0x700a,                          //strb       r2,[r1,#0x0 ]=>DAT_03004f65
                        0x4770,                          //bx         lr
                        // Data and pointers
                        0x0be0,
                        0x0300,
                        0x17a0,
                        0x0300,
                        0x4c40,
                        0x0300,
                        (ushort)(part * 2 + 1 + 0xf0),
                        0x0000,
                        (ushort)(part * 2 + 1 + 3 * 0xf0),
                        0x0000
                    };

                    Utils.WritePayload(file, funcOffset, replacedFunction);
                }

                //////////////////////////////////////////////////////
                /// RANDOM MEDALS
                //////////////////////////////////////////////////////
                if (chk_random_medal.IsOn)
                {
                    for (int i = memory_offsets[game_id]["Events"]; i < memory_offsets[game_id]["Events"] + 0x18000;)
                    {
                        byte op = file[i];
                        if (op == 0x3C)
                        {
                            Trace.WriteLine("Get Medal: " + IdTranslator.IdToMedal(file[i + 1]));
                            if (i + 1 == memory_offsets[game_id]["StartMedal"])
                            {
                                Trace.WriteLine("Is random starter, skipping...");
                            }
                            else
                            {
                                var randomMedal = randomizer.GetRandomMedal(file[i + 1]);

                                file[i + 1] = randomMedal;
                                Trace.WriteLine("Set Medal to: " + IdTranslator.IdToMedal(file[i + 1]));
                            }
                        }

                        if (op == 0x2F)
                        {
                            //multiconditional jump
                            i += file[i + 1] + 1;
                        }
                        else
                        {
                            i += IdTranslator.operationBytes[op];
                        }
                    }
                    //////////////////////////////////////////////////////
                    /// FIX MESSAGES
                    //////////////////////////////////////////////////////
                    List <byte> origMedals = new List <byte> {
                        15, 16, 17, 18, 19, 20
                    };
                    List <byte> replacedMedals = origMedals.Select(x => randomizer.medalExchanges[x]).ToList();

                    List <Medal> medals = loadFile <List <Medal> >("./Medals.json");
                    List <((int, int), (int, int))> messages = new List <((int, int), (int, int))>();
                    messages.Add(((0x00, 0x6b), (0x00, 0x68)));
                    messages.Add(((0x00, 0x6f), (0x00, 0x6c)));
                    messages.Add(((0x00, 0x73), (0x00, 0x70)));
                    messages.Add(((0x00, 0x77), (0x00, 0x74)));
                    messages.Add(((0x00, 0x7b), (0x00, 0x78)));
                    messages.Add(((0x00, 0x7f), (0x00, 0x7c)));

                    TextParser textParser = new TextParser(file, memory_offsets[game_id]["Text"]);
                    for (int i = 0; i < replacedMedals.Count; i++)
                    {
                        textParser.addMessage(messages[i].Item1, medals[replacedMedals[i]].ikki_text);
                        textParser.addMessage(messages[i].Item2, medals[replacedMedals[i]].collect_text);
                    }
                }
            }
            //////////////////////////////////////////////////////
            /// CODE PATCHES
            //////////////////////////////////////////////////////
            if (chk_code_patches.IsOn)
            {
                uint jumpOffset    = 0x104;
                uint hookOffset    = 0x7f4500;
                uint trainerOffset = hookOffset + 0xD0;

                uint instr1 = (uint)Utils.GetIntAtPosition(file, (int)jumpOffset);
                uint instr2 = (uint)Utils.GetIntAtPosition(file, (int)jumpOffset + 4);
                uint instr3 = (uint)Utils.GetIntAtPosition(file, (int)jumpOffset + 8);

                uint[] jumpPayload = new uint[]
                {
                    0xE92D8000,                         // push r15
                    0xE51FF004,                         // ldr r15, traineraddr
                    0x08000000 + hookOffset             // hookOffset
                };

                uint[] hookPayload = new uint[]
                {
                    0xE92D4000,                         // push r14
                    0xE3A0E402,                         // mov r14, #0x2000000
                    0xE28EE701,                         // add r14, #40000
                    0xE24EE004,                         // sub r14, #28
                    0xE90E08FF,                         // stmdb [r14], r0-r7, r11
                    0xEB00002D,                         // bl trainerfunc
                    0xE3A0E402,                         // mov r14, #0x2000000
                    0xE28EE701,                         // add r14, #40000
                    0xE24EE028,                         // sub r14, #28
                    0xE89E08FF,                         // ldmia [r14], r0-r7, r11
                    0xE8BD4000,                         // pop r14
                    instr1,                             // --- original instruction #1 ---
                    instr2,                             // --- original instruction #2 ---
                    instr3,                             // --- original instruction #3 ---
                    0xE8BD8000                          // pop r15
                };

                List <uint> trainerPayloadList        = new List <uint>();
                Dictionary <uint, ushort> codePatches = new Dictionary <uint, ushort>();

                if (chk_instant_text.IsOn)
                {
                    trainerPayloadList.AddRange(new uint[] {
                        // Set text_speed to instant
                        0xE3A01403,                         // mov r1, #0x3000000
                        0xE3A000FF,                         // mov r0, #0xFF
                        0xE5C1045A,                         // strb r0, [r1, #0x45A]
                    });
                    codePatches = codePatches.Union(new Dictionary <uint, ushort>
                    {
                        // Instant Character Popup
                        { 0x3F5F6, 0x3008 },
                        { 0x3F600, 0xDC08 }
                    }).ToDictionary(k => k.Key, v => v.Value);
                }

                if (chk_encounters.IsOn)
                {
                    trainerPayloadList.AddRange(new uint[] {
                        // Allow encounters
                        0xE3A01403,                         // mov r1, #0x3000000
                        0xE2811B19,                         // add r1, #0x6400
                        0xE3A00000,                         // mov r0, #0x0
                        0xE5C1000C,                         // strb r0, [r1, #0xc]
                    });
                }

                trainerPayloadList.Add(
                    // Return
                    0xE12FFF1E                          // bx r15
                    );

                uint[] trainerPayload = trainerPayloadList.ToArray();

                Utils.WritePayload(file, jumpOffset, jumpPayload);
                Utils.WritePayload(file, hookOffset, hookPayload);
                Utils.WritePayload(file, trainerOffset, trainerPayload);
                Utils.WritePatches(file, codePatches);
            }

            //////////////////////////////////////////////////////
            /// ADD MESSAGES
            //////////////////////////////////////////////////////
            TextParser     textParser2     = new TextParser(file, memory_offsets[game_id]["Text"]);
            List <Message> patchedMessages = loadFile <List <Message> >("./Patched_Messages.json");

            foreach (Message message in patchedMessages)
            {
                textParser2.addMessage((message.id[0], message.id[1]), message.message);
            }

            TextPatcher textPatcher = new TextPatcher(ref file, memory_offsets[game_id]["Text"], 0x7f5500, textParser2.getEncodedMessages());

            textPatcher.PatchText();

            //////////////////////////////////////////////////////
            /// WRITE TO FILE
            //////////////////////////////////////////////////////
            File.WriteAllBytes(seedtext + ".gba", file);
            ShowNotification("Done!", "The ROM has been converted and is saved with seed: \"" + seedtext + "\" as \"" + seedtext + ".gba\"");
        }