public void Update(byte[] data, bool bigEndian) { VersionInfo versionInfo = bigEndian ? BigEndianMarshal.ByteArrayToStructureBigEndian <VersionInfo>(data) : BigEndianMarshal.ByteArrayToStructureLittleEndian <VersionInfo>(data); txtMajorVersion.Text = $"{versionInfo.major}"; txtMiddleVersion.Text = $"{versionInfo.middle}"; txtMinorVersion.Text = $"{versionInfo.minor}"; txtVariety.Text = $"{versionInfo.variety}"; txtInternal.Text = $"{versionInfo.interna1}"; txtShortInfo.Text = StringHandlers.CToString(versionInfo.short_info, Encoding.UTF8); txtLongInfo.Text = StringHandlers.CToString(versionInfo.long_info, Encoding.UTF8); }
static ResourceTypeBlock[] ResourceDecode(byte[] data) { uint pos = 0; byte[] buffer = new byte[Marshal.SizeOf(typeof(ResourcesHeader))]; Array.Copy(data, pos, buffer, 0, buffer.Length); ResourcesHeader header = BigEndianMarshal.ByteArrayToStructureLittleEndian <ResourcesHeader>(buffer); if (header.magic != Consts.RESOURCES_HEADER_MAGIC) { return(null); } pos = header.index_section_offset; buffer = new byte[Marshal.SizeOf(typeof(ResourceIndexSectionHeader))]; if (pos + buffer.Length > data.Length) { return(null); } Array.Copy(data, pos, buffer, 0, buffer.Length); ResourceIndexSectionHeader indexHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian <ResourceIndexSectionHeader>(buffer); pos += (uint)buffer.Length; ResourceIndexEntry[] indexes = new ResourceIndexEntry[(indexHeader.index_section_size - Marshal.SizeOf(typeof(ResourceIndexSectionHeader))) / Marshal.SizeOf(typeof(ResourceIndexEntry))]; for (int i = 0; i < indexes.Length; i++) { buffer = new byte[Marshal.SizeOf(typeof(ResourceIndexEntry))]; Array.Copy(data, pos, buffer, 0, buffer.Length); indexes[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ResourceIndexEntry>(buffer); pos += (uint)buffer.Length; } pos = indexHeader.info_table_offset; string[] types = new string[header.resource_count]; bool terminated = true; string currentType = null; string[] names = new string[header.resource_count]; ResourceInfo[] infos = new ResourceInfo[header.resource_count]; for (int i = 0; i < header.resource_count; i++) { if (terminated) { buffer = new byte[4]; Array.Copy(data, pos, buffer, 0, 4); currentType = Encoding.ASCII.GetString(buffer.Reverse().ToArray()); terminated = false; pos += 4; } buffer = new byte[Marshal.SizeOf(typeof(ResourceInfo))]; Array.Copy(data, pos, buffer, 0, buffer.Length); infos[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <ResourceInfo>(buffer); pos += (uint)buffer.Length; buffer = new byte[infos[i].name_size - 1]; Array.Copy(data, pos, buffer, 0, buffer.Length); names[i] = Encoding.ASCII.GetString(buffer); pos += (uint)(buffer.Length + 1); types[i] = currentType; if (BitConverter.ToInt32(data, (int)pos) != -1 || BitConverter.ToInt32(data, (int)pos + 4) != -1) { continue; } terminated = true; pos += 8; } Dictionary <string, List <Resource> > rezzes = new Dictionary <string, List <Resource> >(); for (int i = 0; i < header.resource_count; i++) { rezzes.TryGetValue(types[i], out List <Resource> thisRezzes); if (thisRezzes == null) { thisRezzes = new List <Resource>(); } Resource rez = new Resource { id = infos[i].id, index = infos[i].index, name = names[i], data = new byte[indexes[infos[i].index - 1].size] }; Array.Copy(data, indexes[infos[i].index - 1].offset, rez.data, 0, rez.data.Length); thisRezzes.Add(rez); rezzes.Remove(types[i]); rezzes.Add(types[i], thisRezzes); } List <ResourceTypeBlock> result = new List <ResourceTypeBlock>(); foreach (KeyValuePair <string, List <Resource> > kvp in rezzes) { ResourceTypeBlock block = new ResourceTypeBlock { type = kvp.Key, resources = kvp.Value.ToArray() }; result.Add(block); } return(result.ToArray()); }
/// <summary> /// This will decode a bitmap array, or if data is not an array, return an array with the single bitmap element /// </summary> /// <param name="data">Data</param> /// <returns>Array of <see cref="DecodedBitmap" />, one per bitmap, null if the bitmap could not be decoded</returns> public static DecodedBitmap[] DecodeBitmap(byte[] data) { long pos = 0; BitmapArrayHeader bitmapArrayHeader; byte[] buffer = new byte[Marshal.SizeOf(typeof(BitmapInfoHeader))]; List <DecodedBitmap> bitmaps = new List <DecodedBitmap>(); do { Array.Copy(data, pos, buffer, 0, buffer.Length); bitmapArrayHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian <BitmapArrayHeader>(buffer); long remaining; if (bitmapArrayHeader.Type == TYPE_BITMAP_ARRAY) { remaining = bitmapArrayHeader.Size - Marshal.SizeOf(typeof(BitmapArrayHeader)); pos += Marshal.SizeOf(typeof(BitmapArrayHeader)); } else { remaining = 1; pos = 0; bitmapArrayHeader.Next = 0; } while (remaining > 0) { buffer = new byte[Marshal.SizeOf(typeof(BitmapInfoHeader))]; Array.Copy(data, pos, buffer, 0, buffer.Length); BitmapInfoHeader bitmapFileHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian <BitmapInfoHeader>(buffer); // Stop at unknown header if (bitmapFileHeader.Fix != 12) { break; } // Multiplanes not supported if (bitmapFileHeader.Planes != 1) { break; } // TODO: Non paletted? pos += Marshal.SizeOf(typeof(BitmapInfoHeader)); Rgb[] palette = new Rgb[1 << bitmapFileHeader.BitsPerPlane]; buffer = new byte[Marshal.SizeOf(typeof(Rgb))]; for (int i = 0; i < palette.Length; i++) { Array.Copy(data, pos, buffer, 0, buffer.Length); pos += buffer.Length; palette[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <Rgb>(buffer); } remaining -= bitmapFileHeader.Fix; // rgb[1]; remaining -= 1; // TODO (Optimize): Calculate real data length considering that every line is word-aligned (2-byte) long dataLength = 0; for (int y = 0; y < bitmapFileHeader.Y; y++) { int x = 0; while (x < bitmapFileHeader.X) { for (int k = 8 - bitmapFileHeader.BitsPerPlane; k >= 0; k -= (int)bitmapFileHeader.BitsPerPlane) { x++; } dataLength++; } dataLength += dataLength % 2; } buffer = new byte[dataLength]; Array.Copy(data, bitmapFileHeader.Offset, buffer, 0, buffer.Length); DecodedBitmap bitmap = DecodeBitmap(bitmapFileHeader, palette, buffer); // Mask palette int[] argbPalette = new int[palette.Length]; for (int c = 0; c < palette.Length; c++) { argbPalette[c] = (palette[c].Red << 16) + (palette[c].Green << 8) + palette[c].Blue; } // First image, then mask if (bitmapFileHeader.Type == TYPE_ICON || bitmapFileHeader.Type == TYPE_POINTER) { int[] icon = new int[bitmap.Width * bitmap.Height / 2]; int[] mask = new int[bitmap.Width * bitmap.Height / 2]; Array.Copy(bitmap.Pixels, 0, icon, 0, icon.Length); Array.Copy(bitmap.Pixels, icon.Length, mask, 0, mask.Length); bitmap.Pixels = new int[bitmap.Width * bitmap.Height / 2]; bitmap.Height /= 2; for (int px = 0; px < bitmap.Pixels.Length; px++) { bitmap.Pixels[px] = icon[px] + (mask[px] == argbPalette[0] ? VISIBLE : 0); } } // We got the mask, now we need to read the color else if (bitmapFileHeader.Type == TYPE_COLOR_ICON || bitmapFileHeader.Type == TYPE_COLOR_POINTER) { DecodedBitmap mask = bitmap; buffer = new byte[Marshal.SizeOf(typeof(BitmapInfoHeader))]; Array.Copy(data, pos, buffer, 0, buffer.Length); bitmapFileHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian <BitmapInfoHeader>(buffer); // Stop at unknown header if (bitmapFileHeader.Size != Marshal.SizeOf(typeof(BitmapInfoHeader))) { break; } // Multiplanes not supported if (bitmapFileHeader.Planes != 1) { break; } // TODO: Non paletted? pos += bitmapFileHeader.Size; palette = new Rgb[1 << bitmapFileHeader.BitsPerPlane]; buffer = new byte[Marshal.SizeOf(typeof(Rgb))]; for (int i = 0; i < palette.Length; i++) { Array.Copy(data, pos, buffer, 0, buffer.Length); pos += buffer.Length; palette[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <Rgb>(buffer); } remaining -= bitmapFileHeader.Fix; // rgb[1]; remaining -= 1; // TODO (Optimize): Calculate real data length considering that every line is word-aligned (2-byte) dataLength = 0; for (int y = 0; y < bitmapFileHeader.Y; y++) { int x = 0; while (x < bitmapFileHeader.X) { for (int k = 8 - bitmapFileHeader.BitsPerPlane; k >= 0; k -= (int)bitmapFileHeader.BitsPerPlane) { x++; } dataLength++; } dataLength += dataLength % 2; } buffer = new byte[dataLength]; Array.Copy(data, bitmapFileHeader.Offset, buffer, 0, buffer.Length); bitmap = DecodeBitmap(bitmapFileHeader, palette, buffer); for (int px = 0; px < bitmap.Pixels.Length; px++) { bitmap.Pixels[px] = bitmap.Pixels[px] + (mask.Pixels[px + bitmapFileHeader.X * bitmapFileHeader.Y] == argbPalette[0] ? VISIBLE : 0); } } // Not an icon, all pixels are visible else { for (int px = 0; px < bitmap.Pixels.Length; px++) { bitmap.Pixels[px] = bitmap.Pixels[px] + VISIBLE; } } // Need to reverse first all pixels then by line int[] pixels = bitmap.Pixels.Reverse().ToArray(); for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { bitmap.Pixels[y * bitmap.Width + (bitmap.Width - x - 1)] = pixels[y * bitmap.Width + x]; } } bitmaps.Add(bitmap); } pos = bitmapArrayHeader.Next; }while(bitmapArrayHeader.Next != 0); return(bitmaps.ToArray()); }
/// <summary> /// This will decode an icon /// </summary> /// <param name="data">Data</param> /// <returns>A <see cref="DecodedBitmap" /> with the icon, null if the icon could not be decoded</returns> public static DecodedBitmap DecodeIcon(byte[] data) { long pos = 0; byte[] buffer = new byte[Marshal.SizeOf(typeof(BitmapInfoHeader))]; Array.Copy(data, pos, buffer, 0, buffer.Length); BitmapInfoHeader bitmapFileHeader = BigEndianMarshal.ByteArrayToStructureLittleEndian <BitmapInfoHeader>(buffer); // Stop at unknown header if (bitmapFileHeader.HeaderSize != 40) { return(null); } // Multiplanes not supported if (bitmapFileHeader.Planes != 1) { return(null); } // TODO: Non paletted? pos += bitmapFileHeader.HeaderSize; Rgb[] palette = new Rgb[1 << bitmapFileHeader.BitsPerPlane]; buffer = new byte[Marshal.SizeOf(typeof(Rgb))]; for (int i = 0; i < palette.Length; i++) { Array.Copy(data, pos, buffer, 0, buffer.Length); pos += buffer.Length; palette[i] = BigEndianMarshal.ByteArrayToStructureLittleEndian <Rgb>(buffer); } // First let's do the icon itself bitmapFileHeader.Height /= 2; long dataLength = 0; for (int y = 0; y < bitmapFileHeader.Height; y++) { int x = 0; while (x < bitmapFileHeader.Width) { for (int k = 8 - bitmapFileHeader.BitsPerPlane; k >= 0; k -= (int)bitmapFileHeader.BitsPerPlane) { x++; } dataLength++; } dataLength += dataLength % 2; } buffer = new byte[dataLength]; Array.Copy(data, pos, buffer, 0, buffer.Length); DecodedBitmap icon = DecodeBitmap(bitmapFileHeader, palette, buffer); // Then the mask pos += dataLength; bitmapFileHeader.BitsPerPlane = 1; dataLength = 0; for (int y = 0; y < bitmapFileHeader.Height; y++) { int x = 0; while (x < bitmapFileHeader.Width) { for (int k = 8 - bitmapFileHeader.BitsPerPlane; k >= 0; k -= (int)bitmapFileHeader.BitsPerPlane) { x++; } dataLength++; } dataLength += dataLength % 2; } buffer = new byte[dataLength]; Array.Copy(data, pos, buffer, 0, buffer.Length); DecodedBitmap mask = DecodeBitmap(bitmapFileHeader, palette, buffer); // Mask palette int[] argbPalette = new int[palette.Length]; for (int c = 0; c < palette.Length; c++) { argbPalette[c] = (palette[c].Red << 16) + (palette[c].Green << 8) + palette[c].Blue; } DecodedBitmap bitmap = new DecodedBitmap { BitsPerPixel = icon.BitsPerPixel, Height = icon.Height, Width = icon.Width, Pixels = new int[icon.Pixels.Length] }; for (int px = 0; px < bitmap.Pixels.Length; px++) { bitmap.Pixels[px] = icon.Pixels[px] + (mask.Pixels[px] == argbPalette[0] ? VISIBLE : 0); } // Need to reverse first all pixels then by line int[] pixels = bitmap.Pixels.Reverse().ToArray(); for (int y = 0; y < bitmap.Height; y++) { for (int x = 0; x < bitmap.Width; x++) { bitmap.Pixels[y * bitmap.Width + (bitmap.Width - x - 1)] = pixels[y * bitmap.Width + x]; } } return(bitmap); }