Example #1
0
        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));
                }
            }
        }
Example #2
0
 public static Bitmap EntryDataToBitmap(PegEntry entry)
 {
     if (entry.bitmap_format == PegFormat.PC_DXT1)
     {
         var decompressBuffer = Squish.Decompress(entry.RawData, entry.width, entry.height, Squish.Flags.DXT1);
         return(MakeBitmapFromDXT(entry.width, entry.height, decompressBuffer, true));
     }
     else if (entry.bitmap_format == PegFormat.PC_DXT3)
     {
         var decompressBuffer = Squish.Decompress(entry.RawData, entry.width, entry.height, Squish.Flags.DXT3);
         return(MakeBitmapFromDXT(entry.width, entry.height, decompressBuffer, true));
     }
     else if (entry.bitmap_format == PegFormat.PC_DXT5)
     {
         var decompressBuffer = Squish.Decompress(entry.RawData, entry.width, entry.height, Squish.Flags.DXT5);
         return(MakeBitmapFromDXT(entry.width, entry.height, decompressBuffer, true));
     }
     else
     {
         throw new Exception($"Unsupported PEG data format detected! {entry.bitmap_format.ToString()} is not yet supported.");
     }
 }
Example #3
0
        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));
                }
            }
        }
Example #4
0
        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);
                    }
                }
            }
        }
Example #5
0
        public bool Init(CacheFile target, int selectedIndex, string replacementFilePath)
        {
            //Todo: Make some reuseable helper functions to shorten this up. Ex:
            //Todo:  - Copy file, parent, asm, and cpu/gpu sister file between caches
            //Todo:  - Repack parent with edited file
            //Todo:  - Update asm file with new values

            PegEntry selectedEntry = target.PegData.Entries[selectedIndex];

            PegName        = target.PegData.cpuFileName;
            SubTextureName = selectedEntry.Name;

            //Set TrackedByAsm and find asm name
            CacheFile    asmFile         = null;
            AsmContainer targetContainer = null;
            AsmPrimitive targetPrimitive = null;

            if (target.Parent.PackfileData.ContainsAsmFiles)
            {
                TrackedByAsm = true;
                foreach (var asm in target.Parent.PackfileData.AsmFiles)
                {
                    foreach (var container in asm.Containers)
                    {
                        foreach (var primitive in container.Primitives)
                        {
                            if (primitive.Name != target.Filename)
                            {
                                continue;
                            }

                            AsmName         = primitive.Name;
                            targetContainer = container;
                            targetPrimitive = primitive;
                        }
                    }
                }

                if (AsmName == null || targetContainer == null || targetPrimitive == null)
                {
                    return(false);
                }
            }

            //Copy edited files to project cache
            if (!ProjectManager.CopyFileToProjectCache(target.PegData.cpuFileName, target.Parent, out CacheFile cpuFile))
            {
                return(false);
            }
            if (!ProjectManager.CopyFileToProjectCache(target.PegData.gpuFileName, target.Parent, out CacheFile gpuFile))
            {
                return(false);
            }
            if (TrackedByAsm && !ProjectManager.CopyFileToProjectCache(AsmName, target.Parent, out asmFile) || asmFile == null)
            {
                return(false);
            }

            //Update entry data
            selectedEntry               = cpuFile.PegData.Entries[selectedIndex];
            selectedEntry.Bitmap        = new Bitmap(replacementFilePath);
            selectedEntry.Edited        = true;
            selectedEntry.RawData       = Utility.Helpers.ImageHelpers.ConvertBitmapToByteArray(selectedEntry.Bitmap);
            selectedEntry.width         = (ushort)selectedEntry.Bitmap.Width;
            selectedEntry.height        = (ushort)selectedEntry.Bitmap.Height;
            selectedEntry.source_height = (ushort)selectedEntry.Bitmap.Height;

            //source_width sometimes equals width and sometimes equals 36352. This is a quick hack for now until that behavior is understood.
            //Not properly setting this causes the game to improperly scale the texture
            selectedEntry.source_width = selectedEntry.source_width == selectedEntry.width
                ? (ushort)selectedEntry.Bitmap.Width
                : (ushort)36352;
            cpuFile.PegData.Write(cpuFile.FilePath, gpuFile.FilePath);

            //Update asm data if applicable
            if (TrackedByAsm)
            {
                var cpuFileInfo = new FileInfo(cpuFile.FilePath);
                var gpuFileInfo = new FileInfo(gpuFile.FilePath);

                int sizeDifference = (int)cpuFileInfo.Length - (int)targetPrimitive.HeaderSize;
                sizeDifference += (int)gpuFileInfo.Length - (int)targetPrimitive.DataSize;

                targetPrimitive.HeaderSize = (uint)cpuFileInfo.Length;
                targetPrimitive.DataSize   = (uint)gpuFileInfo.Length;

                //Todo: Finish packfile writing code
                //Todo: Pack str2 and update CompressedSize
                var parentPackfile = cpuFile.Parent.PackfileData;
                parentPackfile.WriteToBinary(Path.GetDirectoryName(asmFile.FilePath),
                                             asmFile.Parent.FilePath, true, true, true);

                if (!cpuFile.Parent.PackfileData.TryGetSubfileEntry(cpuFile.Filename, out var cpuFileEntry))
                {
                    return(false);
                }
                if (!cpuFile.Parent.PackfileData.TryGetSubfileEntry(gpuFile.Filename, out var gpuFileEntry))
                {
                    return(false);
                }

                targetContainer.CompressedSize = parentPackfile.Header.CompressedDataSize;
                targetContainer.DataOffset     = parentPackfile.DataStartOffset;
                targetPrimitive.HeaderSize     = cpuFileEntry.DataSize;
                targetPrimitive.DataSize       = gpuFileEntry.DataSize;

                //Todo: Update primitive sizes
                //Todo: Update DataOffset
                //Todo: Make sure to update other primitives in the same str2 if their offsets/values have changed

                asmFile.AsmData.WriteToBinary();
            }

            //Todo: Generate modinfo.xml data for this

            UpdateDescription();
            return(true);
        }