Example #1
0
        static List <UInt16> ReadFFNT(BinaryReader br)
        {
            UInt16        BOM      = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
            List <UInt16> charList = new List <UInt16>();
            Encoding      encoding = Encoding.Default;

            if (BOM == 0xFEFF)
            {
                //Big endian
                Console.WriteLine("Parsing Big Endian FFNT...");
                br.BaseStream.Position = 0x6;
                br.BaseStream.Position = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()) + 0x13;
                switch (br.ReadByte())
                {
                case 0:
                    encoding = Encoding.UTF8;
                    break;

                case 1:
                    encoding = Encoding.Unicode;
                    break;

                case 2:
                    encoding = Encoding.GetEncoding(932);     //Because Microsoft couldn't add an easier way to pick ShiftJIS
                    break;

                case 3:
                    encoding = Encoding.GetEncoding(1252);     //Again, same as above just for CP1252
                    break;

                default:
                    throw new FormatException("Wrong encoding!!!");
                }
                br.BaseStream.Position += 0x9;
                br.BaseStream.Position  = ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()) - 0x8;
                String MapSignature = new string(br.ReadChars(4));
                if (MapSignature != "CMAP")
                {
                    throw new FormatException("Invalid CMAP section!!!");
                }
                bool             HasNext     = true;
                UInt32           NextPtr     = (uint)br.BaseStream.Position + 0x4;
                List <CMAP>      cmap_Header = new List <CMAP>();
                List <CMAP_Item> cmap        = new List <CMAP_Item>();
                while (HasNext)
                {
                    br.BaseStream.Position = NextPtr - 0x8;
                    cmap_Header.Add(new CMAP(ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()), ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32())));
                    if (cmap_Header[cmap_Header.Count - 1].Signature != 0x434D4150)
                    {
                        throw new FormatException("Invalid CMAP section!!!");
                    }
                    while (br.BaseStream.Position != cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8)
                    {
                        switch (cmap_Header[cmap_Header.Count - 1].MappingMethod) //This is very stupid, but it works
                        {
                        case 0:
                            var IndexOffset = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i <= cmap_Header[cmap_Header.Count - 1].CodeEnd; i++)
                            {
                                cmap.Add(new CMAP_Item(i, IndexOffset));
                                IndexOffset++;
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 1:
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i < cmap_Header[cmap_Header.Count - 1].CodeEnd + 1; i++)
                            {
                                var index = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
                                if (index != 0xFFFF)
                                {
                                    cmap.Add(new CMAP_Item(i, index));
                                }
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 2:
                            var Num = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
                            for (var i = 0; i < Num; i++)
                            {
                                cmap.Add(new CMAP_Item(ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16())));
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;
                        }
                    }
                    NextPtr = cmap_Header[cmap_Header.Count - 1].PtrNext;
                    if (NextPtr == 0x0)
                    {
                        HasNext = false;
                    }
                }
                foreach (CMAP_Item item in cmap)
                {
                    charList.Add(BitConverter.ToUInt16(Encoding.Convert(encoding, Encoding.Unicode, BitConverter.GetBytes(item.Code)), 0));
                }
                charList.Sort();
            }
            else if (BOM == 0xFFFE)
            {
                //Little endian
                Console.WriteLine("Parsing Little Endian FFNT...");
                br.BaseStream.Position = 0x6;
                br.BaseStream.Position = br.ReadUInt16() + 0x13;
                switch (br.ReadByte())
                {
                case 0:
                    encoding = Encoding.UTF8;
                    break;

                case 1:
                    encoding = Encoding.Unicode;
                    break;

                case 2:
                    encoding = Encoding.GetEncoding(932);     //Because Microsoft couldn't add an easier way to pick ShiftJIS
                    break;

                case 3:
                    encoding = Encoding.GetEncoding(1252);     //Again, same as above just for CP1252
                    break;

                default:
                    throw new FormatException("Wrong encoding!!!");
                }
                br.BaseStream.Position += 0x9;
                br.BaseStream.Position  = br.ReadUInt32() - 0x8;
                String MapSignature = new string(br.ReadChars(4));
                if (MapSignature != "CMAP")
                {
                    throw new FormatException("Invalid CMAP section!!!");
                }
                bool             HasNext     = true;
                UInt32           NextPtr     = (uint)br.BaseStream.Position + 0x4;
                List <CMAP>      cmap_Header = new List <CMAP>();
                List <CMAP_Item> cmap        = new List <CMAP_Item>();
                while (HasNext)
                {
                    br.BaseStream.Position = NextPtr - 0x8;
                    cmap_Header.Add(new CMAP(br.ReadUInt32(), br.ReadUInt32(), br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt32()));
                    if (cmap_Header[cmap_Header.Count - 1].Signature != 0x50414D43)
                    {
                        throw new FormatException("Invalid CMAP section!!!");
                    }
                    while (br.BaseStream.Position != cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8)
                    {
                        switch (cmap_Header[cmap_Header.Count - 1].MappingMethod) //This is very stupid, but it works
                        {
                        case 0:
                            var IndexOffset = br.ReadUInt16();
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i <= cmap_Header[cmap_Header.Count - 1].CodeEnd; i++)
                            {
                                cmap.Add(new CMAP_Item(i, IndexOffset));
                                IndexOffset++;
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 1:
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i < cmap_Header[cmap_Header.Count - 1].CodeEnd + 1; i++)
                            {
                                var index = br.ReadUInt16();
                                if (index != 0xFFFF)
                                {
                                    cmap.Add(new CMAP_Item(i, index));
                                }
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 2:
                            var Num = br.ReadUInt16();
                            for (var i = 0; i < Num; i++)
                            {
                                cmap.Add(new CMAP_Item(br.ReadUInt16(), br.ReadUInt16()));
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;
                        }
                    }
                    NextPtr = cmap_Header[cmap_Header.Count - 1].PtrNext;
                    if (NextPtr == 0x0)
                    {
                        HasNext = false;
                    }
                }
                foreach (CMAP_Item item in cmap)
                {
                    charList.Add(BitConverter.ToUInt16(Encoding.Convert(encoding, Encoding.Unicode, BitConverter.GetBytes(item.Code)), 0));
                }
                charList.Sort();
            }
            else
            {
                throw new FormatException("Wrong BOM!!!");
            }
            Console.WriteLine("Parsed " + charList.Count + " charcters from FFNT");
            return(charList);
        }
Example #2
0
        static List <UInt16> ReadRFNT(BinaryReader br)
        {
            //Sidenote: only Big Endian variant of this code has a kinda in-depth explanation of how the code works, I was just lazy enogh to copy-paste that into other code sections)
            //Read Byte Order Mark to determine how to further process the file
            UInt16 BOM = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
            //Initialize some variables
            List <UInt16> charList = new List <UInt16>();
            Encoding      encoding = Encoding.Default;

            //Do the thing, split by endianess
            if (BOM == 0xFEFF)
            {
                //Big endian
                Console.WriteLine("Parsing Big Endian RFNT...");
                br.BaseStream.Position = 0xC;                                                               //Goto position of FINF offset
                br.BaseStream.Position = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()) + 0xf; //Go to character encoding offset
                //Read character encoding
                switch (br.ReadByte())
                {
                case 0:
                    encoding = Encoding.UTF8;
                    break;

                case 1:
                    encoding = Encoding.Unicode;
                    break;

                case 2:
                    encoding = Encoding.GetEncoding(932);     //Because Microsoft couldn't add an easier way to pick ShiftJIS
                    break;

                case 3:
                    encoding = Encoding.GetEncoding(1252);     //Again, same as above just for CP1252
                    break;

                default:
                    throw new FormatException("Wrong encoding!!!");
                }
                br.BaseStream.Position += 0x8;                                                               //Go to CMAP pointer position
                br.BaseStream.Position  = ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()) - 0x8; //Go to first CMAP section
                //Read first CMAP header
                String MapSignature = new string(br.ReadChars(4));
                if (MapSignature != "CMAP")
                {
                    throw new FormatException("Invalid CMAP section!!!");
                }
                bool             HasNext     = true;
                UInt32           NextPtr     = (uint)br.BaseStream.Position + 0x4;
                List <CMAP>      cmap_Header = new List <CMAP>();
                List <CMAP_Item> cmap        = new List <CMAP_Item>();
                //Parse all CMAP data
                while (HasNext)
                {
                    br.BaseStream.Position = NextPtr - 0x8;                                                                                                                                                                                                                                                                                                                                                                                                                               //Go to offset of next CMAP section
                    cmap_Header.Add(new CMAP(ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()), ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt32_ReverseEndianness(br.ReadUInt32()))); //Read the header
                    if (cmap_Header[cmap_Header.Count - 1].Signature != 0x434D4150)
                    {
                        throw new FormatException("Invalid CMAP section!!!");                                                             //Validate CMAP by checking it's signaure
                    }
                    //And here goes the main CMAP parsing thing which I won't explain, since it should be quite obvious
                    while (br.BaseStream.Position != cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8)
                    {
                        switch (cmap_Header[cmap_Header.Count - 1].MappingMethod)
                        {
                        case 0:
                            //Direct mapping method parser
                            var IndexOffset = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i <= cmap_Header[cmap_Header.Count - 1].CodeEnd; i++)
                            {
                                cmap.Add(new CMAP_Item(i, IndexOffset));
                                IndexOffset++;
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 1:
                            //Table mapping method
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i < cmap_Header[cmap_Header.Count - 1].CodeEnd + 1; i++)
                            {
                                var index = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
                                if (index != 0xFFFF)
                                {
                                    cmap.Add(new CMAP_Item(i, index));
                                }
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 2:
                            //Scan mapping method
                            var Num = ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16());
                            for (var i = 0; i < Num; i++)
                            {
                                cmap.Add(new CMAP_Item(ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16()), ReverseEndianness.UInt16_ReverseEndianness(br.ReadUInt16())));
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;
                        }
                    }
                    NextPtr = cmap_Header[cmap_Header.Count - 1].PtrNext; //Save pointer to the next CMAP section
                    if (NextPtr == 0x0)
                    {
                        HasNext = false;                 //If NextPtr == 0x0 then we should stop parsing
                    }
                }
                foreach (CMAP_Item item in cmap)
                {
                    charList.Add(BitConverter.ToUInt16(Encoding.Convert(encoding, Encoding.Unicode, BitConverter.GetBytes(item.Code)), 0));
                }
                charList.Sort();
            }
            else if (BOM == 0xFFFE)
            {
                //Little endian
                Console.WriteLine("Parsing Little Endian RFNT...");
                br.BaseStream.Position = 0xC;
                br.BaseStream.Position = br.ReadUInt16() + 0xf;
                switch (br.ReadByte())
                {
                case 0:
                    encoding = Encoding.UTF8;
                    break;

                case 1:
                    encoding = Encoding.Unicode;
                    break;

                case 2:
                    encoding = Encoding.GetEncoding(932);     //Because Microsoft couldn't add an easier way to pick ShiftJIS
                    break;

                case 3:
                    encoding = Encoding.GetEncoding(1252);     //Again, same as above just for CP1252
                    break;

                default:
                    throw new FormatException("Wrong encoding!!!");
                }
                br.BaseStream.Position += 0x8;
                br.BaseStream.Position  = br.ReadUInt32() - 0x8;
                String MapSignature = new string(br.ReadChars(4));
                if (MapSignature != "CMAP")
                {
                    throw new FormatException("Invalid CMAP section!!!");
                }
                bool             HasNext     = true;
                UInt32           NextPtr     = (uint)br.BaseStream.Position + 0x4;
                List <CMAP>      cmap_Header = new List <CMAP>();
                List <CMAP_Item> cmap        = new List <CMAP_Item>();
                while (HasNext)
                {
                    br.BaseStream.Position = NextPtr - 0x8;
                    cmap_Header.Add(new CMAP(br.ReadUInt32(), br.ReadUInt32(), br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt32()));
                    if (cmap_Header[cmap_Header.Count - 1].Signature != 0x50414D43)
                    {
                        throw new FormatException("Invalid CMAP section!!!");
                    }
                    while (br.BaseStream.Position != cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8)
                    {
                        switch (cmap_Header[cmap_Header.Count - 1].MappingMethod)
                        {
                        case 0:
                            var IndexOffset = br.ReadUInt16();
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i <= cmap_Header[cmap_Header.Count - 1].CodeEnd; i++)
                            {
                                cmap.Add(new CMAP_Item(i, IndexOffset));
                                IndexOffset++;
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 1:
                            for (var i = cmap_Header[cmap_Header.Count - 1].CodeBegin; i < cmap_Header[cmap_Header.Count - 1].CodeEnd + 1; i++)
                            {
                                var index = br.ReadUInt16();
                                if (index != 0xFFFF)
                                {
                                    cmap.Add(new CMAP_Item(i, index));
                                }
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;

                        case 2:
                            var Num = br.ReadUInt16();
                            for (var i = 0; i < Num; i++)
                            {
                                cmap.Add(new CMAP_Item(br.ReadUInt16(), br.ReadUInt16()));
                            }
                            br.BaseStream.Position = cmap_Header[cmap_Header.Count - 1].PtrNext - 0x8;
                            break;
                        }
                    }
                    NextPtr = cmap_Header[cmap_Header.Count - 1].PtrNext;
                    if (NextPtr == 0x0)
                    {
                        HasNext = false;
                    }
                }
                foreach (CMAP_Item item in cmap)
                {
                    charList.Add(BitConverter.ToUInt16(Encoding.Convert(encoding, Encoding.Unicode, BitConverter.GetBytes(item.Code)), 0));
                }
                charList.Sort();
            }
            else
            {
                throw new FormatException("Wrong BOM!!!");
            }
            Console.WriteLine("Parsed " + charList.Count + " charcters from RFNT");
            return(charList);
        }