public static void Repack(string descFilePath) { Console.WriteLine("Repacking {0}:", descFilePath); if (!File.Exists(descFilePath)) { Console.WriteLine("peg_desc file does not exist: {0}", descFilePath); return; } string extension = Path.GetExtension(descFilePath); if (!(extension == ".peg_desc")) { Console.WriteLine("File is not a peg_desc file: {0}", descFilePath); return; } string descFolder = Path.GetDirectoryName(descFilePath); Console.Write("Loading Peg Description... "); PegFile pegFile = XmlParser.ParseFile(descFilePath); if (pegFile == null) { Console.WriteLine("An error occurred while loading the peg_desc file."); return; } Console.WriteLine("done."); Console.WriteLine("Loading texture data, performing colour space conversions and compressing data:"); Dictionary <PegFrame, byte[]> rawFrameData = new Dictionary <PegFrame, byte[]>(); uint totalSize = 0; ushort totalFrames = 0; foreach (PegEntry entry in pegFile.Entries) { for (int i = 0; i < entry.Frames.Count; i++) { PegFrame frame = entry.Frames[i]; Console.Write(" - {0} (frame {1})... ", entry.Name, i); frame.Frames = (ushort)((i == 0) ? entry.Frames.Count : 1); frame.Offset = totalSize; PegFormat format = (PegFormat)frame.Format; byte[] rawData = null; string rawFilePath = Path.Combine(descFolder, String.Format("{0}_{1}.raw", entry.Name, i)); string filePath = Path.Combine(descFolder, String.Format("{0}_{1}.png", entry.Name, i)); if (File.Exists(rawFilePath)) { Console.Write("loading from {0}... ", rawFilePath); FileStream rawFileStream = new FileStream(rawFilePath, FileMode.Open, FileAccess.Read, FileShare.None); rawData = new byte[rawFileStream.Length]; rawFileStream.Read(rawData, 0, rawData.Length); rawFileStream.Close(); Console.WriteLine("done."); } else { Console.Write("importing from {0}... ", filePath); if (!File.Exists(filePath)) { Console.WriteLine("Unable to find file: {0}", filePath); Console.WriteLine("Make sure all your texture files are in the correct location and correctly named."); return; } Bitmap srcBitmap = new Bitmap(filePath); switch (format) { case PegFormat.DXT1: case PegFormat.DXT3: case PegFormat.DXT5: rawData = GetRawA8R8G8B8DataFromBitmap(srcBitmap); ImageFormats.SwapRedAndBlue((uint)srcBitmap.Width, (uint)srcBitmap.Height, ref rawData); rawData = ImageFormats.Compress(rawData, (uint)srcBitmap.Width, (uint)srcBitmap.Height, format); break; case PegFormat.A8R8G8B8: rawData = GetRawA8R8G8B8DataFromBitmap(srcBitmap); break; case PegFormat.R5G6B5: Bitmap outBitmap = new Bitmap(srcBitmap.Width, srcBitmap.Height, PixelFormat.Format16bppRgb565); srcBitmap.SetResolution(96, 96); Graphics g = Graphics.FromImage(outBitmap); g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy; g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; g.DrawImage(srcBitmap, 0, 0, srcBitmap.Width, srcBitmap.Height); g.Dispose(); Rectangle lockArea = new Rectangle(0, 0, outBitmap.Width, outBitmap.Height); BitmapData bitmapData = outBitmap.LockBits(lockArea, ImageLockMode.ReadOnly, outBitmap.PixelFormat); rawData = new byte[srcBitmap.Width * srcBitmap.Height * 2]; Marshal.Copy(bitmapData.Scan0, rawData, 0, rawData.Length); outBitmap.UnlockBits(bitmapData); outBitmap.Dispose(); break; default: throw new Exception("Unhandled format: " + format.ToString()); } srcBitmap.Dispose(); Console.WriteLine("done."); } frame.Size = (uint)rawData.Length; totalSize += frame.Size; if (totalSize % 16 != 0) { uint difference = (uint)(Math.Ceiling((float)totalSize / 16f) * 16) - totalSize; totalSize += difference; } totalFrames++; entry.Frames[i] = frame; rawFrameData.Add(frame, rawData); } } pegFile.DataFileSize = totalSize; Console.WriteLine("Finished loading texture data."); Console.Write("Writing peg_pc and g_peg_pc files..."); string pegFilePath = Path.ChangeExtension(descFilePath, "peg_pc"); string pegDataFilePath = Path.ChangeExtension(descFilePath, "g_peg_pc"); FileStream pegFileStream = new FileStream(pegFilePath, FileMode.Create, FileAccess.Write, FileShare.None); FileStream pegDataFileStream = new FileStream(pegDataFilePath, FileMode.Create, FileAccess.Write, FileShare.None); pegFileStream.WriteU32(0x564B4547); // GEKV pegFileStream.WriteU16(10); // Version pegFileStream.WriteU16(pegFile.Unknown06); pegFileStream.WriteU32(pegFile.FileSize); // Length - we come back and fill this in later pegFileStream.WriteU32(pegFile.DataFileSize); pegFileStream.WriteU16((ushort)pegFile.Entries.Count); pegFileStream.WriteU16(pegFile.Unknown12); pegFileStream.WriteU16(totalFrames); pegFileStream.WriteU16(pegFile.Unknown16); // Write entries pegFileStream.Seek(0x18, SeekOrigin.Begin); foreach (PegEntry entry in pegFile.Entries) { for (int i = 0; i < entry.Frames.Count; i++) { PegFrame frame = entry.Frames[i]; byte[] frameData = StructureToByteArray(frame); pegFileStream.Write(frameData, 0, frameData.Length); } } // Write names pegFileStream.Seek(0x18 + (0x30 * totalFrames), SeekOrigin.Begin); foreach (PegEntry entry in pegFile.Entries) { pegFileStream.WriteASCIIZ(entry.Name); } pegFileStream.Seek(0x08, SeekOrigin.Begin); pegFileStream.WriteU32((uint)pegFileStream.Length); pegFileStream.Flush(); pegFileStream.Close(); pegDataFileStream.SetLength(pegFile.DataFileSize); foreach (PegEntry entry in pegFile.Entries) { foreach (PegFrame frame in entry.Frames) { pegDataFileStream.Seek(frame.Offset, SeekOrigin.Begin); pegDataFileStream.Write(rawFrameData[frame], 0, (int)frame.Size); } } pegDataFileStream.Flush(); pegDataFileStream.Close(); Console.WriteLine("done."); Console.WriteLine(); Console.WriteLine("Finished repacking."); }
public static void ParseFrames(XmlNode framesNode, PegEntry entry) { foreach (XmlNode frameNode in framesNode.ChildNodes) { switch (frameNode.Name) { case "Frame": PegFrame frame = new PegFrame(); foreach (XmlNode node in frameNode.ChildNodes) { switch (node.Name) { case "Width": ushort.TryParse(node.InnerText, out frame.Width); break; case "Height": ushort.TryParse(node.InnerText, out frame.Height); break; case "Format": PegFormat format = (PegFormat)Enum.Parse(typeof(PegFormat), node.InnerText, true); frame.Format = (ushort)format; break; case "Unknown0A": ushort.TryParse(node.InnerText, out frame.Unknown0A); break; case "Unknown0C": uint.TryParse(node.InnerText, out frame.Unknown0C); break; case "Unknown12": uint.TryParse(node.InnerText, out frame.Unknown12); break; case "Unknown16": uint.TryParse(node.InnerText, out frame.Unknown16); break; case "UnknownFlags1A": ushort.TryParse(node.InnerText, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out frame.UnknownFlags1A); break; case "Size": uint.TryParse(node.InnerText, out frame.Size); break; case "Unknown20": uint.TryParse(node.InnerText, out frame.Unknown20); break; case "Unknown24": uint.TryParse(node.InnerText, out frame.Unknown24); break; case "Unknown28": uint.TryParse(node.InnerText, out frame.Unknown28); break; case "Unknown2C": uint.TryParse(node.InnerText, out frame.Unknown2C); break; //default: //throw new Exception(String.Format("Encountered unknown XML element: {0}", node.Name)); } } entry.Frames.Add(frame); break; default: throw new Exception(String.Format("Encountered unknown XML element: {0}", frameNode.Name)); } } }
public static void UnpackImages(PegFile pegFile, string path, Stream pegDataFileStream) { foreach (PegEntry entry in pegFile.Entries) { Console.WriteLine("Extracting {0} ({1} frame{2}):", entry.Name, entry.Frames.Count, (entry.Frames.Count == 1 ? "" : "s")); for (int i = 0; i < entry.Frames.Count; i++) { string filePath = Path.Combine(path, String.Format("{0}_{1}.png", entry.Name, i)); string rawFilePath = Path.Combine(path, String.Format("{0}_{1}.raw", entry.Name, i)); Console.Write(" - Extracting {0}... ", filePath); PegFrame frame = entry.Frames[i]; pegDataFileStream.Seek(frame.Offset, SeekOrigin.Begin); byte[] rawData = new byte[frame.Size]; pegDataFileStream.Read(rawData, 0, (int)frame.Size); PegFormat format = (PegFormat)frame.Format; FileStream rawFileStream = new FileStream(rawFilePath, FileMode.Create, FileAccess.Write, FileShare.None); rawFileStream.Write(rawData, 0, rawData.Length); rawFileStream.Flush(); rawFileStream.Close(); Bitmap bitmap = null; switch (format) { case PegFormat.A8R8G8B8: if (pegFile.BigEndian) { rawData = ImageFormats.ByteSwap(rawData, format); } bitmap = ImageFormats.MakeBitmapFromA8R8G8B8(frame.Width, frame.Height, rawData); break; case PegFormat.R5G6B5: if (pegFile.BigEndian) { rawData = ImageFormats.ByteSwap(rawData, format); } bitmap = ImageFormats.MakeBitmapFromR5G6B5(frame.Width, frame.Height, rawData); break; case PegFormat.DXT1: if (pegFile.BigEndian) { rawData = ImageFormats.ByteSwap(rawData, format); } byte[] decompressedDXT1 = ImageFormats.Decompress(rawData, frame.Width, frame.Height, format); bitmap = ImageFormats.MakeBitmapFromDXT(frame.Width, frame.Height, decompressedDXT1, false); break; case PegFormat.DXT3: case PegFormat.DXT5: byte[] decompressed = ImageFormats.Decompress(rawData, frame.Width, frame.Height, format); bitmap = ImageFormats.MakeBitmapFromDXT(frame.Width, frame.Height, decompressed, true); break; default: throw new Exception("Unhandled format: " + format.ToString()); } bitmap.Save(filePath, ImageFormat.Png); bitmap.Dispose(); Console.WriteLine("done."); } } }