コード例 #1
0
        public void RebuildPkg(string inputpkg)
        {
            UInt16 blockheader = 8;

            List <FontHeaderInfo> FontInfo  = new List <FontHeaderInfo>();
            List <BlockRange>     BlockInfo = new List <BlockRange>();

            List <charDatum> blockchars     = new List <charDatum>();
            List <int>       blockcharsizes = new List <int>();

            MemoryStream outBlocks = new MemoryStream();
            MemoryStream chartable = new MemoryStream();
            MemoryStream datatable = new MemoryStream();
            BinaryWriter ow        = new BinaryWriter(outBlocks);
            BinaryWriter ctw       = new BinaryWriter(chartable);
            BinaryWriter dw        = new BinaryWriter(datatable);

            UInt16 tempChar;
            UInt16 lastChar = 0;

            int   blockindex    = 0;
            int   blockoffset   = 0;
            Int16 charcount     = 0;
            bool  freshblock    = true;
            int   chartablesize = 0;

            BlockRange blockk = new BlockRange();



            for (int i = 0; i < Fonts.Count; i++)
            {
                FontHeaderInfo fontt = new FontHeaderInfo();

                for (int j = 0; j < Fonts[i].Characters.Count; j++)
                {
                    if (j == 0)
                    {
                        fontt.startBlock = (short)blockindex;
                    }

                    //check if we can fit this character into the current block
                    var tempSize = 20 + Fonts[i].Characters[j].Data.dataSize;

                    if (chartablesize + datatable.Length + tempSize > ChunkSize - 8)
                    {
                        //nope can't fit

                        //build block character table
                        var chartableoffset = 8;
                        for (int k = 0; k < blockchars.Count; k++)
                        {
                            ctw.Write(blockchars[k].characterCode);
                            ctw.Write(blockchars[k].fontIndex);
                            ctw.Write(chartablesize + chartableoffset);
                            chartableoffset += blockcharsizes[k];
                        }

                        blockchars.Clear();
                        blockcharsizes.Clear();

                        //calculate block padding
                        var    blockdiff  = (ChunkSize - 8) - (chartablesize + datatable.Length);
                        byte[] diffBuffer = new byte[blockdiff];

                        //write block
                        ow.Write(blockheader);
                        ow.Write(charcount);
                        ow.Write((Int16)(ctw.BaseStream.Length + 8));
                        ow.Write((Int16)(dw.BaseStream.Length));
                        ow.Write(chartable.ToArray());
                        ow.Write(datatable.ToArray());
                        ow.Write(diffBuffer);

                        //note the last character in the block for header
                        blockk.endIndex = new charDatum()
                        {
                            characterCode = lastChar, fontIndex = (short)i
                        };;

                        BlockInfo.Add(blockk);

                        //clean up and reset stuff
                        blockk     = new BlockRange();
                        freshblock = true;

                        blockindex   += 1;
                        charcount     = 0;
                        blockoffset   = 0;
                        chartablesize = 0;

                        ctw.Close();
                        dw.Close();

                        chartable = new MemoryStream();
                        datatable = new MemoryStream();

                        ctw = new BinaryWriter(chartable);
                        dw  = new BinaryWriter(datatable);
                    }

                    tempChar = Fonts[i].Characters[j].CharCode;

                    //note the first character in the block
                    if (freshblock)
                    {
                        blockk.startIndex = new charDatum()
                        {
                            characterCode = tempChar, fontIndex = (short)i
                        };
                        freshblock = false;
                    }

                    //add character in temp character table
                    blockchars.Add(new charDatum()
                    {
                        characterCode = tempChar, fontIndex = (short)i
                    });

                    //add character data to temp stream
                    dw.Write(Fonts[i].Characters[j].Data.dispWidth);
                    dw.Write(Fonts[i].Characters[j].Data.dataSize);
                    dw.Write(Fonts[i].Characters[j].Data.width);
                    dw.Write(Fonts[i].Characters[j].Data.height);
                    dw.Write(Fonts[i].Characters[j].Data.leftpad);
                    dw.Write(Fonts[i].Characters[j].Data.dispHeight);
                    dw.Write(Fonts[i].Characters[j].Data.compressedData);

                    //calculate character padding
                    var    dataalign = 12 + Fonts[i].Characters[j].Data.dataSize;
                    byte[] alignhelp = new byte[0];

                    if (dataalign % 8 != 0)
                    {
                        var dataalign2 = dataalign / 8;
                        alignhelp = new byte[((dataalign2 * 8) + 8) - dataalign];

                        dw.Write(alignhelp);
                    }

                    //note the size with padding for the character table
                    blockcharsizes.Add(Fonts[i].Characters[j].Data.dataSize + 12 + alignhelp.Length);

                    //clean up and reset stuff
                    blockoffset   += Fonts[i].Characters[j].Data.dataSize + 12 + alignhelp.Length;
                    charcount     += 1;
                    chartablesize += 8;
                    lastChar       = tempChar;
                }

                fontt.blockCount = (short)(blockindex - fontt.startBlock + 1);

                FontInfo.Add(fontt);
            }

            //out of fonts and characters so write the final block
            var chartableoffsetx = 8;

            for (int k = 0; k < blockchars.Count; k++)
            {
                ctw.Write(blockchars[k].characterCode);
                ctw.Write(blockchars[k].fontIndex);
                ctw.Write(chartablesize + chartableoffsetx);
                chartableoffsetx += blockcharsizes[k];
            }

            var blockdiffx = (ChunkSize - 8) - (chartablesize + datatable.Length);

            byte[] diffBufferx = new byte[blockdiffx];

            ow.Write(blockheader);
            ow.Write(charcount);
            ow.Write((Int16)(ctw.BaseStream.Length + 8));
            ow.Write((Int16)(dw.BaseStream.Length));
            ow.Write(chartable.ToArray());
            ow.Write(datatable.ToArray());
            ow.Write(diffBufferx);

            blockk.endIndex = new charDatum()
            {
                characterCode = lastChar, fontIndex = (short)(Fonts.Count - 1)
            };;

            BlockInfo.Add(blockk);

            ow.Close();
            ctw.Close();
            dw.Close();
            chartable.Close();
            datatable.Close();

            //begin writing new stuff to the font package

            FileStream   fs = new FileStream(inputpkg, FileMode.Open, FileAccess.Write);
            BinaryWriter bw = new BinaryWriter(fs);

            //update ordering
            bw.BaseStream.Position = 8 + (maxFontCount * 0xC);

            for (int i = 0; i < OrderList.Count; i++)
            {
                bw.Write(OrderList[i]);
            }

            //update the block info for each font
            bw.BaseStream.Position = 0x8;

            for (int i = 0; i < FontInfo.Count; i++)
            {
                bw.BaseStream.Position += 8;

                bw.Write((short)FontInfo[i].startBlock);
                bw.Write((short)FontInfo[i].blockCount);
            }

            //update the character info for each block
            bw.BaseStream.Position = BlockRangesOffset;

            for (int i = 0; i < BlockInfo.Count; i++)
            {
                bw.Write(BlockInfo[i].startIndex.characterCode);
                bw.Write(BlockInfo[i].startIndex.fontIndex);

                bw.Write(BlockInfo[i].endIndex.characterCode);
                bw.Write(BlockInfo[i].endIndex.fontIndex);
            }

            //clean up any nonexistant block info
            for (int i = 0; i < (maxFontCount - Fonts.Count); i++)
            {
                bw.Write((Int64)0);
            }

            //update block count
            bw.BaseStream.Position = (8 + (maxFontCount * 12) + (maxFontCount * 4) + 12);            //0x114;
            bw.Write((int)BlockInfo.Count);

            //update each font header with new info
            for (int i = 0; i < Fonts.Count; i++)
            {
                bw.BaseStream.Position = FontEntries[i].offset + 0x24;

                bw.Write(Fonts[i].LineHeight);
                bw.Write(Fonts[i].LineTopPad);
                bw.Write(Fonts[i].LineBottomPad);
                bw.Write(Fonts[i].LineIndent);

                var datasize = 0;
                for (int j = 0; j < Fonts[i].Characters.Count; j++)
                {
                    datasize += Fonts[i].Characters[j].Data.dataSize;
                }

                bw.BaseStream.Position = FontEntries[i].offset + 0x13C;

                bw.Write((int)Fonts[i].Characters.Count);

                bw.BaseStream.Position += 0x14;

                bw.Write(datasize);
            }

            //finally write the new blocks
            bw.BaseStream.SetLength(ChunkSize);

            bw.BaseStream.Position = ChunkSize;
            bw.Write(outBlocks.ToArray());

            bw.Close();
            fs.Close();
        }
コード例 #2
0
        /// <summary>
        /// Loads a font package from the given file.
        /// </summary>
        /// <returns>0 = success, 1 = bad header version, 2 = font count is zero</returns>
        public int Load(string filename)
        {
            FileStream   fs = new FileStream(filename, FileMode.Open);
            BinaryReader br = new BinaryReader(fs);

            ms = new MemoryStream(br.ReadBytes((int)br.BaseStream.Length));
            fs.Close();
            br = new BinaryReader(ms);

            br.BaseStream.Position = 0;

            //Make sure this is a font package
            var fileMagic = br.ReadUInt32();

            if (fileMagic != 0xC0000003)
            {
                ms.Close();
                br.Close();
                return(1);
            }

            int fontCount = br.ReadInt32();

            if (fontCount <= 0)
            {
                ms.Close();
                br.Close();
                return(2);
            }

            maxFontCount = 16;

            //check to see if package belongs to Halo 4
            var maxcounthack = br.ReadInt32();

            if (maxcounthack == 1048)
            {
                maxFontCount = 64;
            }

            //get the font headers info
            br.BaseStream.Position -= 4;
            for (int i = 0; i < maxFontCount; i++)
            {
                FontEntries.Add(new FontHeaderInfo()
                {
                    offset     = br.ReadInt32(),
                    size       = br.ReadInt32(),
                    startBlock = br.ReadInt16(),
                    blockCount = br.ReadInt16()
                });
            }

            //read engine ordering
            for (int i = 0; i < maxFontCount; i++)
            {
                OrderList.Add(br.ReadInt32());
            }

            int headerTableOffset = br.ReadInt32();
            int headerTableSize   = br.ReadInt32();

            BlockRangesOffset = br.ReadInt32();
            int blockCount = br.ReadInt32();

            br.BaseStream.Position = BlockRangesOffset;

            for (int i = 0; i < blockCount; i++)
            {
                var startchar = br.ReadUInt16();
                var startfont = br.ReadInt16();

                var endchar = br.ReadUInt16();
                var endfont = br.ReadInt16();

                charDatum start = new charDatum()
                {
                    characterCode = startchar, fontIndex = startfont
                };
                charDatum end = new charDatum()
                {
                    characterCode = endchar, fontIndex = endfont
                };

                BlockRange range = new BlockRange()
                {
                    startIndex = start, endIndex = end
                };

                BlockRanges.Add(range);
            }

            //read data blocks

            //set position for hax to check for h4b
            br.BaseStream.Position = 0x8000;

            ChunkSize = 0x8000;

            if (maxFontCount == 64 & br.ReadInt16() != 8)            //blocks seem to have a short value of 8 as some header or version
            {
                ChunkSize = 0xC000;
            }

            for (int i = 0; i < blockCount; i++)
            {
                Block dataBlock = new Block();
                dataBlock.Read(br, ChunkSize + (i * ChunkSize));

                Blocks.Add(dataBlock);
            }

            //read font headers and find its characters
            for (int i = 0; i < fontCount; i++)
            {
                var tempfont = new PackageFont();
                br.BaseStream.Position = FontEntries[i].offset;
                tempfont.ReadHeader(br);

                for (int bl = FontEntries[i].startBlock; bl < (FontEntries[i].startBlock + FontEntries[i].blockCount); bl++)
                {
                    for (int ch = 0; ch < Blocks[bl].charCount; ch++)
                    {
                        if (Blocks[bl].charTable[ch].index.fontIndex == i)
                        {
                            var tempchar = new FontCharacter(Blocks[bl].charTable[ch].index.characterCode, Blocks[bl].charData[ch]);

                            tempfont.Characters.Add(tempchar);
                        }
                    }
                }
                Fonts.Add(tempfont);
            }

            br.Close();
            ms.Close();
            return(0);
        }