private MEinfo GetMEFileInfo(Stream stream, string path, uint startoffset = 0, uint endoffset = 0)
        {
            stream.Seek(startoffset, SeekOrigin.Begin);
            var meinfo = new MEinfo();

            var handle       = GCHandle.Alloc(new BinaryReader(stream).ReadBytes(Marshal.SizeOf(typeof(FptPreHeader))), GCHandleType.Pinned);
            var fptPreHeader = (FptPreHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(FptPreHeader));

            handle.Free();

            handle = GCHandle.Alloc(new BinaryReader(stream).ReadBytes(Marshal.SizeOf(typeof(FptHeader))), GCHandleType.Pinned);
            var fptHeader = (FptHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(FptHeader));

            handle.Free();

            var fptEntries = new List <FptEntry>();

            for (var i = 0; i < fptHeader.NumPartitions; i++)
            {
                handle = GCHandle.Alloc(new BinaryReader(stream).ReadBytes(Marshal.SizeOf(typeof(FptEntry))), GCHandleType.Pinned);
                var fptEntry = (FptEntry)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(FptEntry));
                handle.Free();

                fptEntries.Add(fptEntry);
            }

            var mn2Manifests = new List <Mn2Manifest>();

            //foreach (var fptEntry in fptEntries.Where(fptEntry => (fptEntry.Flags & 0x00FF) == 0x80))
            foreach (var fptEntry in fptEntries.Where(fptEntry => (new string(fptEntry.Name) == "FTPR")))
            {
                stream.Seek(fptEntry.Offset + startoffset, SeekOrigin.Begin);

                var o = 0;
                if (new string(new BinaryReader(stream).ReadChars(4)) == "$CPD")
                {
                    o = new BinaryReader(stream).ReadByte() * 0x18 + 0x10;
                }
                stream.Seek(fptEntry.Offset + startoffset + o, SeekOrigin.Begin);

                handle = GCHandle.Alloc(new BinaryReader(stream).ReadBytes(Marshal.SizeOf(typeof(Mn2Manifest))), GCHandleType.Pinned);
                mn2Manifests.Add((Mn2Manifest)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(Mn2Manifest)));
                handle.Free();
            }
            if (mn2Manifests.Count < 1)
            {
                throw new Exception($@"Unsupported ME version: {path.SafeFileName()}");
            }
            var manifest = mn2Manifests.First();

            meinfo.Size   = endoffset == 0 ? (uint)stream.Length : endoffset - startoffset;
            meinfo.Path   = path;
            meinfo.Major  = manifest.Major;
            meinfo.Minor  = manifest.Minor;
            meinfo.Hotfix = manifest.Hotfix;
            meinfo.Build  = manifest.Build;
            return(meinfo);
        }
        private void LoadBIOS(string path)
        {
            Log("----------------------------------------", LogLevel.Default);
            BIOSfile = File.ReadAllBytes(path);
            var stream = File.Open(path, FileMode.Open);

            stream.Seek(0x10, SeekOrigin.Begin);

            var magic = new BinaryReader(stream).ReadBytes(4);

            if (magic.SequenceEqual(new byte[] { 0x5A, 0xA5, 0xF0, 0x0F })) // Flas descriptor sign. BIOS file
            {
                stream.Seek(0x14, SeekOrigin.Begin);
                var flmap0 = new BinaryReader(stream).ReadUInt32();
                var flmap1 = new BinaryReader(stream).ReadUInt32();
                var nr     = flmap0 >> 24 & 0x7;
                var frba   = flmap0 >> 12 & 0xff0;
                //var fmba = (flmap1 & 0xff) << 4;
                if (nr >= 2 || true)
                {
                    Log("Intel BIOS image detected! :D", LogLevel.Info);
                    stream.Seek(frba, SeekOrigin.Begin);
                    //FLREG0 = Flash Descriptor
                    //FLREG1 = BIOS
                    //FLREG2 = ME
                    var flreg0 = new BinaryReader(stream).ReadUInt32();
                    var flreg1 = new BinaryReader(stream).ReadUInt32();
                    var flreg2 = new BinaryReader(stream).ReadUInt32();
                    //var fd_start = (flreg0 & 0x1fff) << 12;
                    //var fd_end = flreg0 >> 4 & 0x1fff000 | 0xfff + 1;
                    BIOS_ME_start_offset = (flreg2 & 0x1fff) << 12;
                    BIOS_ME_end_offset   = flreg2 >> 4 & 0x1fff000 | 0xfff + 1;
                    if (BIOS_ME_start_offset >= BIOS_ME_end_offset)
                    {
                        throw new Exception("The ME/TXE region in this image has been disabled");
                    }
                    stream.Seek(BIOS_ME_start_offset + 0x10, SeekOrigin.Begin);

                    if (new string(new BinaryReader(stream).ReadChars(4)) != "$FPT")
                    {
                        throw new Exception("The ME/TXE region is corrupted or missing");
                    }


                    BIOS_ME_info = GetMEFileInfo(stream, path, BIOS_ME_start_offset, BIOS_ME_end_offset);

                    _mode = BIOS_ME_info.Major < 4 ? Mode.TXE : Mode.ME;
                    UpdateGUI();

                    Log("BIOS read successful! " + path.SafeFileName(), LogLevel.Info);
                    Log($"The {_mode} region goes from {BIOS_ME_start_offset:X8} to {BIOS_ME_end_offset:X8}", LogLevel.Info);

                    UpdateComboBox();

                    var offset = Find(BIOSfile, MSDM_table_pattern) + MSDM_offset;
                    if (offset - MSDM_offset != -1)
                    {
                        stream.Seek(offset, SeekOrigin.Begin);
                        var handle = GCHandle.Alloc(new BinaryReader(stream).ReadBytes(Marshal.SizeOf(typeof(MSDM))), GCHandleType.Pinned);
                        var MSDM   = (MSDM)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(MSDM));
                        handle.Free();
                        WinKeyTextBox.Text = new string(MSDM.WinKey);
                    }
                    else
                    {
                        WinKeyTextBox.Text = @"none";
                    }
                    stream.Close();
                    return;
                }

                MessageBox.Show(flmap0 + " " + flmap1);

                stream.Close();
                throw new Exception("Number of partitions in file is less than 2! " + path.SafeFileName());
            }
            stream.Close();
            ClearGUI();
            BIOSfile = null;
            throw new Exception("Invalid input file " + path.SafeFileName());
        }