private void PatchRELEntries(byte[] File_Buffer)
        {
            List <Relocation_Entry> Relocation_Entries_List = new List <Relocation_Entry>();
            List <string>           Relocated_Output        = new List <string>();

            for (int i = 0; i < Import_Entries.Length; i++)
            {
                Import_Entry Current_Import_Entry = Import_Entries[i];
                uint         Current_Section      = 0;
                uint         Current_Offset       = 0;
                uint         Value = 0;
                uint         Where = 0;
                uint         Orig  = 0;
                int          Index = 0;

                if (Current_Import_Entry.Module_Id == Header.Id) // These relocations are inside our own file
                {
                    while (true)
                    {
                        int Rel_Offset         = (int)(Current_Import_Entry.Offset + Index * 8);
                        Relocation_Entry Entry = new Relocation_Entry(BitConverter.ToUInt16(File_Buffer, Rel_Offset).Reverse(),
                                                                      File_Buffer[Rel_Offset + 2], File_Buffer[Rel_Offset + 3], BitConverter.ToUInt32(File_Buffer, Rel_Offset + 4).Reverse());
                        Relocation_Entries_List.Add(Entry);
                        //Debug.WriteLine(Entry.Offset.ToString("X4") + " | " + Entry.Type_Value.ToString());

                        if (Entry.IsEnd())
                        {
                            break;
                        }

                        Current_Offset += Entry.Offset;
                        uint OverwriteAddress = 0;
                        uint OverwriteValue   = 0;
                        switch (Entry.Type)
                        {
                        case RelocationType.R_DOLPHIN_SECTION:
                            Current_Section = Entry.Section;
                            Current_Offset  = 0;
                            //Debug.WriteLine("DOLPHIN_SECTION Set Section to " + Current_Section);
                            //Relocated_Output.Add("DOLPHIN_SECTION Set Section to " + Current_Section);
                            break;

                        case RelocationType.R_DOLPHIN_NOP:
                            break;

                        case RelocationType.R_PPC_ADDR32:
                            OverwriteAddress = GetSectionAddress(Current_Section, Current_Offset);
                            OverwriteValue   = GetSectionAddress(Entry.Section, Entry.Addend);
                            //Debug.WriteLine(string.Format("ADDR32 Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X")));
                            //Relocated_Output.Add(string.Format("ADDR32 Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X")));
                            break;

                        case RelocationType.R_PPC_ADDR16_LO:
                            OverwriteAddress = GetSectionAddress(Current_Section, Current_Offset);
                            OverwriteValue   = GetSectionAddress(Entry.Section, Entry.Addend) & 0xFFFF;
                            //Debug.WriteLine(string.Format("ADDR16_LO Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X")));
                            //Relocated_Output.Add(string.Format("ADDR16_LO Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X")));
                            break;

                        case RelocationType.R_PPC_ADDR16_HA:
                            OverwriteAddress = GetSectionAddress(Current_Section, Current_Offset);
                            OverwriteValue   = GetSectionAddress(Entry.Section, Entry.Addend);
                            if ((OverwriteValue & 0x8000) == 0x8000)
                            {
                                OverwriteValue += 0x00010000;
                            }
                            //OverwriteValue += 0x80000000;
                            OverwriteValue = (OverwriteValue >> 16) & 0xFFFF;
                            //Debug.WriteLine(string.Format("ADDR16_HA Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X")));
                            //Relocated_Output.Add(string.Format("ADDR16_HA Offset 0x{0} had its value patched to address 0x{1}", OverwriteAddress.ToString("X"), OverwriteValue.ToString("X")));
                            break;

                        case RelocationType.R_PPC_REL24:
                            Where  = GetSectionAddress(Current_Section, Current_Offset);
                            Value  = GetSectionAddress(Entry.Section, Entry.Addend);
                            Value -= Where;
                            Orig   = BitConverter.ToUInt32(File_Buffer, (int)Where).Reverse();
                            Orig  &= 0xFC000003;
                            Orig  |= Value & 0x03FFFFFC;
                            //Debug.WriteLine("REL24 Offset 0x{0} is now 0x{1}", Where.ToString("X"), Orig.ToString("X"));
                            //Relocated_Output.Add(string.Format("REL24 Offset 0x{0} is now 0x{1}", Where.ToString("X"), Orig.ToString("X")));
                            break;

                        default:
                            Debug.WriteLine(string.Format("Unsupported Relocation Type: {0}", Entry.Type));
                            break;
                        }
                        Index++;
                    }
                }
                else // Move on to external relocations
                {
                    /*while (true)
                     * {
                     *  int Rel_Offset = (int)(Current_Import_Entry.Offset + Index * 8);
                     *  Relocation_Entry Entry = new Relocation_Entry(BitConverter.ToUInt16(File_Buffer.Skip(Rel_Offset).Take(2).Reverse().ToArray(), 0),
                     *      File_Buffer[Rel_Offset + 2], File_Buffer[Rel_Offset + 3], BitConverter.ToUInt32(File_Buffer.Skip(Rel_Offset + 4).Take(4).Reverse().ToArray(), 0));
                     *  Relocation_Entries_List.Add(Entry);
                     *
                     *  if (Entry.IsEnd())
                     *      break;
                     *
                     *  //if (Entry.Type == RelocationType.R_DOLPHIN_SECTION || Entry.Type == RelocationType.R_DOLPHIN_NOP)
                     *      //Debug.WriteLine("Extenral Entry called an unneeded opcode: " + Entry.Type.ToString());
                     *
                     *  Index++;
                     * }*/
                }
            }

            using (TextWriter Writer = File.CreateText(Path.GetDirectoryName(Location) + "\\Relocation_Output.txt"))
            {
                foreach (string s in Relocated_Output)
                {
                    Writer.WriteLine(s);
                }

                Writer.Flush();
            }
        }
        public REL(byte[] Rel_Buffer, string Rel_Location, bool Load_Externals = true)
        {
            Debug.WriteLine(string.Format("============= Loading REL {0} =============", Path.GetFileNameWithoutExtension(Rel_Location)));
            Header   = new REL_Header(Rel_Buffer);
            Location = Rel_Location;

            // Load Section Entries
            Section_Entries = new Section_Entry[Header.Section_Count];
            for (int i = 0; i < Header.Section_Count; i++)
            {
                int Section_Offset = (int)(Header.Section_Table_Offset + i * 8);
                if (Section_Offset >= Rel_Buffer.Length)
                {
                    Debug.WriteLine(string.Format("Section {0} could not be loaded as the file ended while parsing it!", i));
                    continue;
                }

                Section_Entry Entry = new Section_Entry(BitConverter.ToUInt32(Rel_Buffer, Section_Offset).Reverse(),
                                                        BitConverter.ToUInt32(Rel_Buffer, Section_Offset + 4).Reverse());

                // Sanity Checks
                if (Entry.Offset == 0 && Entry.Size != 0) // .bss Section
                {
                    // Set .bss offset
                    if (i > 0)
                    {
                        Entry.Offset = Section_Entries[i - 1].Offset + Section_Entries[i - 1].Size;
                    }

                    if (Entry.Size != Header.BSS_Size)
                    {
                        Debug.WriteLine(string.Format("Section {0} seems to be the .bss section, but its size does not match the header's size. This size: 0x{1} | Header size: 0x{2}",
                                                      i, Entry.Size.ToString("X"), Header.BSS_Size.ToString("X")));
                    }
                    else if (Entry.Offset == Header.Import_Offset || Entry.Offset == Header.Relocation_Offset)
                    {
                        Debug.WriteLine(string.Format("Section {0} seemst o be the .bss section, but it overlaps with the import or relocation section. It's likely not in the file.",
                                                      i));
                    }
                    else
                    {
                        Debug.WriteLine(string.Format("Successfully loaded the .bss Section: {0} | Offset: {1} | Size: {2}", i, Entry.Offset.ToString("X"), Entry.Size.ToString("X")));
                    }
                }
                else if (Entry.Offset != 0 && Entry.Size != 0)
                {
                    if (Entry.Offset < Header.GetHeaderSize())
                    {
                        Debug.WriteLine("Section {0} seems to be inside the REL header! Offset: 0x{1} | Expected Minimum Offset: 0x{2}", i, Entry.Offset.ToString("X"),
                                        Header.GetHeaderSize().ToString("X"));
                    }
                    else if (Entry.Offset + Entry.Size >= Rel_Buffer.Length)
                    {
                        Debug.WriteLine("Section {0} seems to go past the end of the file! End Offset: 0x{1} | Maximum End Offset: 0x{2}", i,
                                        (Entry.Offset + Entry.Size).ToString("X"), Rel_Buffer.Length.ToString("X"));
                    }
                    else
                    {
                        Debug.WriteLine(string.Format("Successfully loaded Section {0}! Offset: 0x{1} | Size: 0x{2} | End Offset: 0x{3}",
                                                      i, Entry.Offset.ToString("X"), Entry.Size.ToString("X"), (Entry.Offset + Entry.Size).ToString("X")));
                    }
                }
                else
                {
                    Debug.WriteLine(string.Format("Section {0} has a zeroed Offset and Size! It's probably an unused section.", i));
                }

                //Debug.WriteLine(string.Format("Added section #{0} with a start address of 0x{1}", i, Entry.Offset.ToString("X8")));
                Section_Entries[i] = Entry;
            }

            // Load Import Table Entries
            LoadModuleNames(Rel_Location, Load_Externals);
            int Import_Table_Count = (int)(Header.Import_Size / 8); //(int)(Header.Relocation_Offset - Header.Import_Offset) / 8;

            Import_Entries = new Import_Entry[Import_Table_Count];

            for (int i = 0; i < Import_Table_Count; i++)
            {
                int  Current_Offset = (int)(Header.Import_Offset + i * 8);
                uint Id             = BitConverter.ToUInt32(Rel_Buffer, Current_Offset).Reverse();
                Import_Entries[i] = new Import_Entry(Id,
                                                     BitConverter.ToUInt32(Rel_Buffer, Current_Offset + 4).Reverse(), Module_Names.ContainsKey(Id) ? Module_Names[Id] : null);
            }

            // Load and Patch Relocation Table Entries
            //PatchRELEntries(Rel_Buffer);
        }