public static void ParseEntries(XmlNode entriesNode, PegFile pegFile) { foreach (XmlNode entryNode in entriesNode.ChildNodes) { switch (entryNode.Name) { case "Entry": PegEntry entry = new PegEntry(); foreach (XmlNode node in entryNode.ChildNodes) { switch (node.Name) { case "Name": entry.Name = node.InnerText; break; case "Frames": ParseFrames(node, entry); break; //default: //throw new Exception(String.Format("Encountered unknown XML element: {0}", node.Name)); } } pegFile.Entries.Add(entry); break; //default: //throw new Exception(String.Format("Encountered unknown XML element: {0}", entryNode.Name)); } } }
static Stream ProcessPeg(IPackfileEntry pegEntry, string newName) { textureNameMap.Clear(); using (Stream pegStream = pegEntry.GetStream()) { PegFile peg = new PegFile(pegStream); string sharedPrefix = FilterPegEntryFilename(peg.Entries[0].Filename); foreach (PegEntry entry in peg.Entries) { while (!FilterPegEntryFilename(entry.Filename).StartsWith(sharedPrefix)) { sharedPrefix = sharedPrefix.Substring(0, sharedPrefix.Length - 1); } } foreach (PegEntry entry in peg.Entries) { string newFilename = null; if (sharedPrefix == "") { newFilename = newName + "_" + entry.Filename; } else { newFilename = entry.Filename.Replace(sharedPrefix, newName + "_").ToLowerInvariant(); if (newFilename.StartsWith("cf_cf_") || newFilename.StartsWith("cf_cm_") || newFilename.StartsWith("cm_cf_") || newFilename.StartsWith("cm_cm_")) { newFilename = newFilename.Remove(3, 3); } } if (!textureNameMap.ContainsKey(entry.Filename)) { textureNameMap.Add(entry.Filename, newFilename); } entry.Filename = newFilename; } MemoryStream outStream = new MemoryStream(); peg.Save(outStream); return(outStream); } }
public static void Unpack(string pegFilePath) { Console.WriteLine("Unpacking {0}:", pegFilePath); if (!File.Exists(pegFilePath)) { Console.WriteLine("peg_pc file does not exist: {0}", pegFilePath); return; } string extension = Path.GetExtension(pegFilePath).ToLower(); bool xbox = (extension == ".peg_xbox2"); if (!(extension == ".peg_pc" || extension == ".peg_xbox2")) { Console.WriteLine("File is not a peg_pc file: {0}", pegFilePath); return; } string pegDataFilePath = xbox ? Path.ChangeExtension(pegFilePath, "g_peg_xbox2") : Path.ChangeExtension(pegFilePath, "g_peg_pc"); string pegDescFilePath = Path.ChangeExtension(pegFilePath, "peg_desc"); if (!File.Exists(pegDataFilePath)) { Console.WriteLine("g_peg_pc file does not exist: {0}", pegDataFilePath); Console.WriteLine("Did you copy it into the same directory as {0}?", pegFilePath); return; } PegFile pegFile = new PegFile(xbox); FileStream pegFileStream = new FileStream(pegFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); FileStream pegDataFileStream = new FileStream(pegDataFilePath, FileMode.Open, FileAccess.Read, FileShare.Read); pegFile.Read(pegFileStream); string extractionPath = Path.GetDirectoryName(pegFilePath); Console.Write("Writing peg description to: {0}... ", pegDescFilePath); Console.WriteLine(" done."); WritePegDescription(pegFile, pegDescFilePath); Console.WriteLine("Unpacking images:"); UnpackImages(pegFile, extractionPath, pegDataFileStream); pegFileStream.Close(); pegDataFileStream.Close(); Console.WriteLine(); Console.WriteLine("Finished unpacking."); }
public void ReadFormatData() { switch (FileType) { case RfgFileTypes.None: return; case RfgFileTypes.Packfile: PackfileData = new Packfile(false); PackfileData.ReadMetadata(FilePath); PackfileData.DirectoryEntries.Sort((entry1, entry2) => string.Compare(entry1.FileName, entry2.FileName, StringComparison.Ordinal)); PackfileData.ParseAsmFiles($"{CachePath}{Filename}\\"); break; case RfgFileTypes.Container: PackfileData = new Packfile(false); PackfileData.ReadMetadata(FilePath); break; case RfgFileTypes.Primitive: string extension = Path.GetExtension(Filename); if (extension == ".cpeg_pc" || extension == ".cvbm_pc") { if (!PathHelpers.TryGetGpuFileNameFromCpuFile(FilePath, out string gpuFileName)) { return; } string basePath = Path.GetDirectoryName(FilePath); string gpuFilePath = $"{basePath}\\{gpuFileName}"; //Todo: Change this to check editor or project cache depending on CacheFile location //Ensure gpu file is extracted if (!ProjectManager.TryGetCacheFile(gpuFileName, ParentName, out _, true)) { return; } PegData = new PegFile(); PegData.Read(FilePath, gpuFilePath); } //Todo: Add checks for primitive type, and primitive handling code break; } }
private void OpenTextureFile_OnClick(object sender, RoutedEventArgs e) { _fileBrowser.IsFolderPicker = false; if (_fileBrowser.ShowDialog() == CommonFileDialogResult.Ok) { string cpuFilePath = _fileBrowser.FileName; if (!File.Exists(cpuFilePath)) { return; } var cpuFileInfo = new FileInfo(cpuFilePath); if (cpuFileInfo.Extension == ".cpeg_pc") { var gpuFileInfo = new FileInfo(cpuFileInfo.DirectoryName + "\\" + Path.GetFileNameWithoutExtension(cpuFilePath) + ".gpeg_pc"); _peg = new PegFile(cpuFilePath, gpuFileInfo.FullName); _peg.Read(); } else if (cpuFileInfo.Extension == ".cvbm_pc") { var gpuFileInfo = new FileInfo(cpuFileInfo.DirectoryName + "\\" + Path.GetFileNameWithoutExtension(cpuFilePath) + ".gvbm_pc"); _peg = new PegFile(cpuFilePath, gpuFileInfo.FullName); _peg.Read(); } else { throw new Exception($"{cpuFileInfo.Extension} is an invalid file extension for peg files!"); } UpdateWindowTitle(); PopulateTreeView(); SetSelectedTexture(0); UpdateInfoPanel(); } }
private void GenerateTextureData(PegFile pegData) { //Add peg info DataPanel.Children.Add(new TextBlock { Inlines = { new Run { Text = "Peg info", FontWeight = FontWeights.Bold, FontSize = 14 }, new LineBreak(), new Run { Text = "Name: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.cpuFileName }, new LineBreak(), new Run { Text = "Version: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.Version.ToString() }, new LineBreak(), new Run { Text = "Platform: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.Platform.ToString() }, new LineBreak(), new Run { Text = "Cpeg size: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.DirectoryBlockSize.ToString() }, new LineBreak(), new Run { Text = "Gpeg size: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.DataBlockSize.ToString() }, new LineBreak(), new Run { Text = "Number of sub-textures: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.NumberOfBitmaps.ToString() }, new LineBreak(), new Run { Text = "Flags: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.Flags.ToString() }, new LineBreak(), new Run { Text = "Total entries: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.TotalEntries.ToString() }, new LineBreak(), new Run { Text = "Align value: ", FontWeight = FontWeights.Bold }, new Run { Text = pegData.AlignValue.ToString() }, new LineBreak() }, TextWrapping = TextWrapping.Wrap }); //Add sub-texture info var subTextures = new TreeView(); var rootNode = new TreeViewItem { Header = "Texture info", IsExpanded = true }; foreach (var entry in pegData.Entries) { var entryNode = new TreeViewItem { Header = entry.Name, IsExpanded = true }; //Add basic values entryNode.Items.Add(new TextBlock { Margin = new Thickness(0.0, 0.0, 0.0, -15.0), Inlines = { new Run { Text = "Width: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.width.ToString() }, new LineBreak(), new Run { Text = "Height: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.height.ToString() }, new LineBreak(), new Run { Text = "Format: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.bitmap_format.ToString() }, new LineBreak() } }); //Add advanced values //Todo: Add some helpers to shorten this code entryNode.Items.Add(new TreeViewItem { Header = "Advanced values", Items = { new TextBlock { Inlines = { new Run { Text = "Data offset: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.data.ToString() }, new LineBreak(), new Run { Text = "Source width: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.source_width.ToString() }, new LineBreak(), new Run { Text = "Source height: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.source_height.ToString() }, new LineBreak(), new Run { Text = "Anim tiles width: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.anim_tiles_width.ToString() }, new LineBreak(), new Run { Text = "Anim tiles height: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.anim_tiles_height.ToString() }, new LineBreak(), new Run { Text = "Number of frames: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.num_frames.ToString() }, new LineBreak(), new Run { Text = "Flags: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.flags.ToString() }, new LineBreak(), new Run { Text = "Filename hash: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.filename.ToString() }, new LineBreak(), new Run { Text = "FPS: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.fps.ToString() }, new LineBreak(), new Run { Text = "Mip levels: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.mip_levels.ToString() }, new LineBreak(), new Run { Text = "Frame size: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.frame_size.ToString() }, new LineBreak(), new Run { Text = "Next: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.next.ToString() }, new LineBreak(), new Run { Text = "Previous: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.previous.ToString() }, new LineBreak(), new Run { Text = "Cache 0: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.cache0.ToString() }, new LineBreak(), new Run { Text = "Cache 1: ", FontWeight = FontWeights.Bold }, new Run { Text = entry.cache1.ToString() }, new LineBreak(), } } } }); rootNode.Items.Add(entryNode); } subTextures.Items.Add(rootNode); DataPanel.Children.Add(subTextures); }
public static void Main(string[] args) { var fullAlpha = false; var showHelp = false; var mode = Mode.Unknown; var options = new OptionSet() { // ReSharper disable AccessToModifiedClosure { "full-alpha", "when decoding textures, don't force 1-bit alpha", v => fullAlpha = v != null }, { "a|assemble", "assemble PEG file", v => mode = v != null ? Mode.Assemble : mode }, { "d|disassemble", "disassemble PEG file", v => mode = v != null ? Mode.Disassemble : mode }, { "h|help", "show this message and exit", v => showHelp = v != null }, // ReSharper restore AccessToModifiedClosure }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (mode == Mode.Unknown && extras.Count > 0) { // detect mode if (Directory.Exists(extras[0]) == true) { mode = Mode.Assemble; } else if (File.Exists(extras[0]) == true) { mode = Mode.Disassemble; } } if (extras.Count < 1 || extras.Count > 2 || showHelp == true || mode == Mode.Unknown) { Console.WriteLine("Usage: {0} [OPTIONS]+ [-a|-d] input [output]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } if (mode == Mode.Assemble) { throw new NotImplementedException(); } else if (mode == Mode.Disassemble) { var inputPath = Path.GetFullPath(extras[0]); var outputBasePath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null); using (var input = File.OpenRead(inputPath)) { var peg = new PegFile(); peg.Deserialize(input); if (peg.Textures.Count == 0) { return; } var info = new PegFileInfo() { Endian = peg.Endian, Version = peg.Version, Textures = new List <PegTextureInfo>(), }; Directory.CreateDirectory(outputBasePath); for (int i = 0; i < peg.Textures.Count; i++) { var nextDataOffset = i + 1 >= peg.Textures.Count ? input.Length : peg.Textures[i + 1].DataOffset; var texture = peg.Textures[i]; var rawTextureSize = nextDataOffset - texture.DataOffset; var frameSize = ComputeFrameSize(texture); var textureSize = frameSize * texture.FrameCount; if (rawTextureSize < textureSize) { throw new FormatException(); } input.Position = texture.DataOffset; var textureInfo = new PegTextureInfo() { Width = texture.Width, Height = texture.Height, Format = texture.Format, FormatArgument = texture.FormatArgument, Flags = texture.Flags, AnimationDelay = texture.AnimationDelay, MipCount = texture.MipCount, UnknownA = texture.UnknownA, UnknownB = texture.UnknownB, Name = texture.Name, }; if (texture.FrameCount == 1) { textureInfo.Path = texture.Name + ".png"; var outputPath = Path.Combine(outputBasePath, textureInfo.Path); var bytes = input.ReadBytes(textureSize); using (var bitmap = ExportTexture(texture, bytes, fullAlpha == false)) { bitmap.Save(outputPath, ImageFormat.Png); } } else { textureInfo.FramePaths = new List <string>(); for (int j = 0; j < texture.FrameCount; j++) { var texturePath = texture.Name + "_" + j + ".png"; textureInfo.FramePaths.Add(texturePath); var outputPath = Path.Combine(outputBasePath, texturePath); var bytes = input.ReadBytes(frameSize); using (var bitmap = ExportTexture(texture, bytes, fullAlpha == false)) { bitmap.Save(outputPath, ImageFormat.Png); } } } info.Textures.Add(textureInfo); } using (var output = File.Create(Path.Combine(outputBasePath, "@peg.json"))) using (var textWriter = new StreamWriter(output, Encoding.UTF8)) using (var writer = new JsonTextWriter(textWriter)) { writer.Formatting = Newtonsoft.Json.Formatting.Indented; writer.Indentation = 2; writer.IndentChar = ' '; var serializer = new JsonSerializer(); serializer.Serialize(writer, info); } } } }
public static PegFile ParseFile(string descFilePath) { XmlDocument document = new XmlDocument(); document.Load(descFilePath); PegFile pegFile = new PegFile(false); XmlNode rootNode = null; foreach (XmlNode childNode in document.ChildNodes) { if (childNode.Name == "PegDescription") { rootNode = childNode; break; } } if (rootNode == null) { Console.WriteLine("This is not a valid peg_desc file: {0}", descFilePath); Console.WriteLine("Unable to find PegDescription node.", document.ChildNodes[1].Name); return(null); } foreach (XmlNode node in rootNode.ChildNodes) { switch (node.Name) { case "BigEndian": bool.TryParse(node.InnerText, out pegFile.BigEndian); break; case "Magic": if (node.InnerText != "GEKV") { Console.WriteLine("This is not a valid peg_desc file: {0}", descFilePath); Console.WriteLine("Bad magic value. Got: {0}, expected: GEKV", node.InnerText); return(null); } break; case "Version": int version = 0; int.TryParse(node.InnerText, out version); if (version != 10) { Console.WriteLine("This is not a valid peg_desc file: {0}", descFilePath); Console.WriteLine("Bad version value. Got: {0}, expected: 10", node.InnerText); return(null); } break; case "Unknown06": ushort.TryParse(node.InnerText, out pegFile.Unknown06); break; case "Unknown12": ushort.TryParse(node.InnerText, out pegFile.Unknown12); break; case "Unknown16": ushort.TryParse(node.InnerText, out pegFile.Unknown16); break; case "Entries": ParseEntries(node, pegFile); break; //default: //throw new Exception(String.Format("Encountered unknown XML element: {0}", node.Name)); } } return(pegFile); }
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 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."); } } }
public static void WritePegDescription(PegFile pegFile, string pegDescFilePath) { XmlTextWriter writer = new XmlTextWriter(pegDescFilePath, Encoding.UTF8); writer.Formatting = Formatting.Indented; writer.IndentChar = '\t'; writer.Indentation = 1; writer.WriteStartDocument(); writer.WriteStartElement("PegDescription"); // Header data writer.WriteElementString("BigEndian", pegFile.BigEndian.ToString()); writer.WriteElementString("Magic", "GEKV"); writer.WriteElementString("Version", "10"); writer.WriteElementString("Unknown06", pegFile.Unknown06.ToString()); writer.WriteElementString("FileSize", pegFile.FileSize.ToString()); writer.WriteElementString("DataFileSize", pegFile.DataFileSize.ToString()); writer.WriteElementString("EntryCount", pegFile.Entries.Count.ToString()); writer.WriteElementString("Unknown12", pegFile.Unknown12.ToString()); int frameCount = 0; foreach (PegEntry entry in pegFile.Entries) { frameCount += entry.Frames.Count; } writer.WriteElementString("FrameCount", frameCount.ToString()); writer.WriteElementString("Unknown16", pegFile.Unknown16.ToString()); writer.WriteStartElement("Entries"); foreach (PegEntry entry in pegFile.Entries) { writer.WriteStartElement("Entry"); writer.WriteElementString("Name", entry.Name); writer.WriteStartElement("Frames"); foreach (PegFrame frame in entry.Frames) { writer.WriteStartElement("Frame"); writer.WriteElementString("Offset", frame.Offset.ToString()); writer.WriteElementString("Width", frame.Width.ToString()); writer.WriteElementString("Height", frame.Height.ToString()); PegFormat frameFormat = (PegFormat)frame.Format; writer.WriteElementString("Format", frameFormat.ToString()); writer.WriteElementString("Unknown0A", frame.Unknown0A.ToString()); writer.WriteElementString("Unknown0C", frame.Unknown0C.ToString()); writer.WriteElementString("Frames", frame.Frames.ToString()); writer.WriteElementString("Unknown12", frame.Unknown12.ToString()); writer.WriteElementString("Unknown16", frame.Unknown16.ToString()); writer.WriteElementString("UnknownFlags1A", frame.UnknownFlags1A.ToString("X4")); writer.WriteElementString("Size", frame.Size.ToString()); writer.WriteElementString("Unknown20", frame.Unknown20.ToString()); writer.WriteElementString("Unknown24", frame.Unknown24.ToString()); writer.WriteElementString("Unknown28", frame.Unknown28.ToString()); writer.WriteElementString("Unknown2C", frame.Unknown2C.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndElement(); writer.WriteEndDocument(); writer.Close(); }
static void Main(string[] args) { Options options = null; try { options = CommandLine.Parse <Options>(); } catch (CommandLineException exception) { Console.WriteLine(exception.ArgumentHelp.Message); Console.WriteLine(); Console.WriteLine(exception.ArgumentHelp.GetHelpText(Console.BufferWidth)); #if DEBUG Console.ReadLine(); #endif return; } if (options.Output == null) { options.Output = "output"; } if (!Directory.Exists(options.Output)) { Directory.CreateDirectory(options.Output); } FontFile font = null; using (Stream s = File.OpenRead(options.Source)) { font = new FontFile(s); } Dictionary <char, char> charMap = new Dictionary <char, char>(); using (Stream s = File.OpenRead(options.Charmap)) { charMap = LanguageUtility.GetDecodeCharMapFromStream(s); } string indicatedPegPath = Path.Combine(Path.GetDirectoryName(options.Source), font.Header.BitmapName); string[] pegExtensions = new string[] { ".cpeg_pc", ".cvbm_pc" }; string[] gpegExtensions = new string[] { ".gpeg_pc", ".gvbm_pc" }; bool foundPeg = false; string pegPath = null; string gpegPath = null; for (int i = 0; i < pegExtensions.Length; i++) { string pegExtension = pegExtensions[i]; string gpegExtension = gpegExtensions[i]; string candidatePath = Path.ChangeExtension(indicatedPegPath, pegExtension); if (File.Exists(candidatePath)) { foundPeg = true; pegPath = candidatePath; gpegPath = Path.ChangeExtension(pegPath, gpegExtension); break; } } if (!foundPeg) { Console.WriteLine("Couldn't find {0}! Extension may be \".cpeg_pc\" or \".cvbm_pc\".", indicatedPegPath); return; } Bitmap fontBitmap = null; using (Stream pegStream = File.OpenRead(pegPath)) { PegFile peg = new PegFile(pegStream); PegEntry entry = null; foreach (PegEntry e in peg.Entries) { if (e.Filename == font.Header.BitmapName) { entry = e; break; } } if (entry == null) { Console.WriteLine("Couldn't find bitmap {0} in font peg!", font.Header.BitmapName); return; } byte[] bitmapData = null; using (Stream gpegStream = File.OpenRead(gpegPath)) { bitmapData = entry.GetData(gpegStream); } byte[] uncompressed = null; switch (entry.Data.BitmapFormat) { case PegBitmapFormat.D3DFMT_DXT3: uncompressed = ManagedSquish.Squish.DecompressImage(bitmapData, entry.Data.Width, entry.Data.Height, ManagedSquish.SquishFlags.Dxt3); break; case PegBitmapFormat.D3DFMT_DXT5: uncompressed = ManagedSquish.Squish.DecompressImage(bitmapData, entry.Data.Width, entry.Data.Height, ManagedSquish.SquishFlags.Dxt5); break; default: throw new Exception(); } fontBitmap = new Bitmap(entry.Data.Width, entry.Data.Height, PixelFormat.Format32bppArgb); BitmapData data = fontBitmap.LockBits(new Rectangle(0, 0, fontBitmap.Width, fontBitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); Marshal.Copy(uncompressed, 0, data.Scan0, uncompressed.Length); fontBitmap.UnlockBits(data); } using (StreamWriter sw = new StreamWriter(Path.Combine(options.Output, "out.txt"))) { for (int i = 0; i < font.Characters.Count; i++) { FontCharacter c = font.Characters[i]; int u = font.U[i]; int v = font.V[i]; int charValue = font.Header.FirstAscii + i; if (c.ByteWidth == 0) { continue; } char actualChar = '\0'; char rawChar = (char)charValue; if (charMap.ContainsKey(rawChar)) { actualChar = charMap[rawChar]; sw.WriteLine("{0} \"{1}\"", charValue, actualChar); } else { sw.WriteLine("{0} \"\"", charValue); } using (Bitmap bm = new Bitmap(c.ByteWidth, font.Header.RenderHeight)) { using (Graphics g = Graphics.FromImage(bm)) { g.Clear(Color.Black); g.DrawImage(fontBitmap, 0, 0, new Rectangle(u, v, c.ByteWidth, font.Header.RenderHeight), GraphicsUnit.Pixel); g.Flush(); } string bmName = String.Format("{0}.png", charValue); string bmPath = Path.Combine(options.Output, bmName); bm.Save(bmPath, ImageFormat.Png); } } } }