public PigFile(byte [] buffer, Palette palette) { int offset = BitConverter.ToInt32(buffer, 0); TotalTextures = BitConverter.ToInt32(buffer, offset); offset += 4; TotalSounds = BitConverter.ToInt32(buffer, offset); offset += 4; for (var i = 0; i < TotalTextures; i++) { var pigTexture = new PigTexture(); pigTexture.Name = buffer.ByteArrayToString(offset, 8).Trim(); offset += 8; pigTexture.DFlags = buffer[offset++]; pigTexture.Width = buffer[offset++]; pigTexture.Height = buffer[offset++]; pigTexture.Flags = buffer[offset++]; pigTexture.AveColor = buffer[offset++]; pigTexture.Offset = BitConverter.ToInt32(buffer, offset); offset += 4; if ((pigTexture.DFlags & 128) != 0) { //pigTexture.Width += 256; } Textures.Add(pigTexture); } for (var i = 0; i < TotalSounds; i++) { var pigSound = new PigSound(); pigSound.Name = buffer.ByteArrayToString(offset, 8).Trim(); offset += 8; pigSound.Length = BitConverter.ToInt32(buffer, offset); offset += 4; pigSound.DataLength = BitConverter.ToInt32(buffer, offset); offset += 4; pigSound.Offset = BitConverter.ToInt32(buffer, offset); offset += 4; Sounds.Add(pigSound); } var pigDataStart = offset; // read all the texture data foreach (var texture in Textures) { offset = texture.Offset + pigDataStart; if (texture.RunLengthEncoded) { var size = BitConverter.ToInt32(buffer, offset); offset += 4; offset += texture.Height; if ((texture.DFlags & 32) != 0) { offset += texture.Height; } texture.Data = new byte[size]; for (var i = 0; i < size; i++) { texture.Data[i] = buffer[i + offset]; } // uncompress var result = new List <byte>(); int j = 0; while (j < size - 5) { var color = texture.Data[j++]; if (color == 0xe0) { continue; } if ((color & 0xe0) == 0xe0) { var count = color & 0x1f; color = texture.Data[j++]; for (var k = 0; k < count; k++) { result.Add(color); } } else { result.Add(color); } } // replace with decoded data texture.Data = result.ToArray(); } else { var size = texture.Height * texture.Width; texture.Data = new byte[size]; for (var i = 0; i < size; i++) { texture.Data[i] = buffer[i + offset]; } } //TODO: need to convert indexed data into 32 bit per pixel true color var endResults = new List <byte>(); for (var i = 0; i < texture.Data.Length; i++) { var color = palette.paletteColors[texture.Data[i]]; endResults.Add(color.R); endResults.Add(color.G); endResults.Add(color.B); } texture.Data = endResults.ToArray(); } }
static void Main(string[] args) { var assembly = Assembly.GetExecutingAssembly(); using (var stream = assembly.GetManifestResourceStream("DescentHogFileReader.DESCENT.HOG")) { byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); char[] sig = { (char)buffer[0], (char)buffer[1], (char)buffer[2] }; int index = 3; var fileData = new List <HogFile>(); int totalFiles = 0; while (index < buffer.Length) { fileData.Add(new HogFile(buffer, index)); index += fileData[fileData.Count - 1].FileSize + 13 + 4; // write file to output directory File.WriteAllBytes(_outputDirectory + fileData[fileData.Count - 1].FileName, fileData[fileData.Count - 1].Data); Console.WriteLine(fileData[fileData.Count - 1].FileName + " (" + fileData[fileData.Count - 1].FileSize.ToString("N0") + ")"); totalFiles++; } } // read the palette Palette paletteData; using (var stream = assembly.GetManifestResourceStream("DescentHogFileReader.palette.256")) { byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); paletteData = new Palette(buffer); } // read the textures using (var stream = assembly.GetManifestResourceStream("DescentHogFileReader.DESCENT.PIG")) { byte[] buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); // read the textures and sounds var pigData = new PigFile(buffer, paletteData); // dump all the textures if (!Directory.Exists(_textureOutputDirectory)) { Directory.CreateDirectory(_textureOutputDirectory); } File.Delete(_textureOutputDirectory + "texture_list.txt"); foreach (var texture in pigData.Textures) { if ((texture.DFlags & 63) == 0) { try { var bitmap = new Bitmap(texture.Width, texture.Height, PixelFormat.Format24bppRgb); var bmData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); var pNative = bmData.Scan0; Marshal.Copy(texture.Data, 0, pNative, texture.Width * texture.Height * 3); bitmap.UnlockBits(bmData); bitmap.Save(_textureOutputDirectory + texture.Name.Trim() + ".png", ImageFormat.Png); } catch (Exception e) { } } File.AppendAllText(_textureOutputDirectory + "texture_list.txt", texture.Name + " (" + texture.Width + " x " + texture.Height + $", Frame:{texture.DFlags & 63}{(texture.RunLengthEncoded ? " RLE" : "")})" + Environment.NewLine); } } Console.ReadKey(); }