Beispiel #1
0
        public static bool parseBCH(string path)
        {
            // goto 0x80 (skip the PT container header and go straight to the BCH data
            // srcdata[:]=srcdata[0x80:len(srcdata)]
            byte[] input = File.ReadAllBytes(path);
            if (input.Length == 0)
            {
                return(false);
            }
            if (BitConverter.ToUInt32(input, 0) != 0x484342) // BCH
            {
                return(false);
            }

            // BCH should now be in our data array.
            BCH bch = analyze(path, input);

            if (bch.TextureCount > 0)
            {
                Directory.CreateDirectory(bch.FilePath + "\\" + bch.FileName + "_\\");
            }
            for (int i = 0; i < bch.TextureCount; i++)
            {
                string texname = bch.TexNames[i];
                Bitmap img     = parseEntry(bch.Textures[i], bch.data); //pass in texture desc, data

                using (MemoryStream ms = new MemoryStream())
                {
                    //error will throw from here
                    img.Save(ms, ImageFormat.Png);
                    byte[] data = ms.ToArray();
                    File.WriteAllBytes(bch.FilePath + "\\" + bch.FileName + "_\\" + texname + ".png", data);
                }
            }
            return(true);
        }
Beispiel #2
0
        public static BCH analyze(string path, byte[] input)
        {
            BCH bch = new BCH
            {
                FileName  = Path.GetFileNameWithoutExtension(path),
                FilePath  = Path.GetDirectoryName(path),
                Extension = Path.GetExtension(path)
            };

            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    bw.Write(input);
                    using (BinaryReader br = new BinaryReader(ms))
                    {
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        long bchlength = br.BaseStream.Length;
                        bch.Magic = br.ReadUInt32();            //0x00 [4]byte        "BCH\x00"
                        br.ReadUInt32();                        //0x04 [4]byte        07 07 0D 97
                        bch.InfoOffset   = br.ReadUInt32();     //0x08 InfoTable Offset
                        bch.SymbolOffset = br.ReadUInt32();     //0x0C SymbTable Offset
                        bch.DescOffset   = br.ReadUInt32();     //0x10 DescTable Offset
                        bch.DataOffset   = br.ReadUInt32();     //0x14 DataTable Offset
                        uint AfterDataOffset = br.ReadUInt32(); //0x18 UnknTable offset
                        uint AADP            = br.ReadUInt32(); //0x1C InfoTable size
                        uint SymbSize        = br.ReadUInt32(); //0x20 SymbTable Size
                        uint DescSize        = br.ReadUInt32(); //0x24 DescTable Size
                        bch.DataLength = br.ReadUInt32();       //0x28 DataTable Size
                        uint dumb = br.ReadUInt32();            //0x2C UnknTable Size
                        if (bch.InfoOffset == 0x44)
                        {
                            SymbSize       = DescSize;
                            bch.DataLength = Math.Max(dumb, Math.Max(AADP, AfterDataOffset) - bch.DataOffset);
                        }
                        br.BaseStream.Seek(bch.InfoOffset + 0x24, SeekOrigin.Begin);
                        bch.TableOffset  = br.ReadUInt32() + bch.InfoOffset; //info+0x24
                        bch.TextureCount = br.ReadUInt32();                  //info+0x28
                        bch.TexNames     = new List <String>();
                        bch.RawNames     = new Dictionary <int, string>();
                        br.BaseStream.Seek((bch.SymbolOffset), SeekOrigin.Begin);
                        int  ofs = 0;
                        uint ind = 0;
                        while (ind < SymbSize)
                        {
                            string curname = "";
                            byte   b       = br.ReadByte();
                            ind++;
                            while (b != 0)
                            {
                                curname = curname + (char)b;
                                b       = br.ReadByte();
                                ind++;
                            }
                            bch.RawNames.Add(ofs, curname);
                            ofs += curname.Length + 1;
                        }
                        bch.Textures = new List <BCHTexture>();

                        for (int i = 0; i < bch.TextureCount; i++)
                        {
                            BCHTexture CurTexture = new BCHTexture();
                            br.BaseStream.Seek(bch.TableOffset + i * 0x4, SeekOrigin.Begin);
                            uint CurTexInfoOffset = br.ReadUInt32();
                            br.BaseStream.Seek(bch.InfoOffset + CurTexInfoOffset, SeekOrigin.Begin);
                            CurTexture.DescOffset = br.ReadUInt32() + bch.DescOffset; //0x0  Location within Desc
                            br.ReadUInt32();                                          //0x4  unk
                            br.ReadUInt32();                                          //0x8  unk
                            br.ReadUInt32();                                          //0xC  unk
                            br.ReadUInt32();                                          //0x10 unk
                            br.ReadUInt32();                                          //0x14 unk
                            br.ReadUInt32();                                          //0x18 unk;
                            int key = (int)br.ReadUInt32();                           //0x1C Name offset; not useful because we already parsed
                            if (bch.InfoOffset == 0x44)
                            {
                                // key--;
                            }
                            string name;
                            bch.RawNames.TryGetValue(key, out name);
                            bch.TexNames.Add(name);
                            br.BaseStream.Seek(CurTexture.DescOffset, SeekOrigin.Begin);
                            CurTexture.Height = br.ReadUInt16();     //0x0 height
                            CurTexture.Width  = br.ReadUInt16();     //0x2 width
                            br.ReadUInt32();                         //0x4, unk
                            CurTexture.DataOffset = br.ReadUInt32(); //0x8 DataOffset
                            br.ReadUInt32();                         //0xC unk
                            CurTexture.Format = br.ReadUInt32();     //0x10 Format
                            if (bch.InfoOffset == 0x44 || bch.InfoOffset == 0x3C)
                            {
                                CurTexture.DataOffset = CurTexture.Format;
                                br.ReadUInt32();
                                CurTexture.Format = br.ReadUInt32();
                            }
                            bch.Textures.Add(CurTexture); //OKAY DONE
                        }
                        for (int i = 0; i < bch.Textures.Count - 1; i++)
                        {
                            BCHTexture bchtex = bch.Textures[i];
                            bchtex.Length = bch.Textures[i + 1].DataOffset - bch.Textures[i].DataOffset;
                            if (bch.InfoOffset == 0x44)
                            {
                                bchtex.Length = (uint)(FormatToBPP((int)bchtex.Format) * bchtex.Width * bchtex.Height);
                            }
                            bch.Textures[i] = bchtex;
                        }
                        if (bch.TextureCount > 0)
                        {
                            BCHTexture bchtex1 = bch.Textures[bch.Textures.Count - 1];
                            bchtex1.Length = bch.DataLength - bchtex1.DataOffset;
                            if (bch.InfoOffset == 0x44)
                            {
                                bchtex1.Length = (uint)(FormatToBPP((int)bchtex1.Format) * bchtex1.Width * bchtex1.Height);
                            }
                            bch.Textures[bch.Textures.Count - 1] = bchtex1;
                        }
                        br.BaseStream.Seek(bch.DataOffset, SeekOrigin.Begin);
                        byte[] data = new byte[bch.DataLength];
                        br.Read(data, 0, (int)bch.DataLength);
                        bch.data = data;
                    }
                }
            }
            return(bch);
        }
Beispiel #3
0
        public static BCH analyze(string path, byte[] input)
        {
            BCH bch = new BCH
            {
                FileName = Path.GetFileNameWithoutExtension(path),
                FilePath = Path.GetDirectoryName(path),
                Extension = Path.GetExtension(path)
            };
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter bw = new BinaryWriter(ms))
                {
                    bw.Write(input);
                    using (BinaryReader br = new BinaryReader(ms))
                    {
                        br.BaseStream.Seek(0, SeekOrigin.Begin);
                        long bchlength = br.BaseStream.Length;
                        bch.Magic = br.ReadUInt32();          //0x00 [4]byte        "BCH\x00"
                        br.ReadUInt32();                      //0x04 [4]byte        07 07 0D 97
                        bch.InfoOffset = br.ReadUInt32();     //0x08 InfoTable Offset
                        bch.SymbolOffset = br.ReadUInt32();   //0x0C SymbTable Offset
                        bch.DescOffset = br.ReadUInt32();     //0x10 DescTable Offset
                        bch.DataOffset = br.ReadUInt32();     //0x14 DataTable Offset
                        uint AfterDataOffset = br.ReadUInt32();                      //0x18 UnknTable offset
                        uint AADP = br.ReadUInt32();                      //0x1C InfoTable size
                        uint SymbSize = br.ReadUInt32();                      //0x20 SymbTable Size
                        uint DescSize = br.ReadUInt32();                      //0x24 DescTable Size
                        bch.DataLength = br.ReadUInt32();                      //0x28 DataTable Size
                        uint dumb = br.ReadUInt32();                      //0x2C UnknTable Size
                        if (bch.InfoOffset == 0x44)
                        {
                            SymbSize = DescSize;
                            bch.DataLength = Math.Max(dumb, Math.Max(AADP, AfterDataOffset) - bch.DataOffset);
                        }
                        br.BaseStream.Seek(bch.InfoOffset + 0x24, SeekOrigin.Begin);
                        bch.TableOffset = br.ReadUInt32() + bch.InfoOffset; //info+0x24
                        bch.TextureCount = br.ReadUInt32(); //info+0x28
                        bch.TexNames = new List<String>();
                        bch.RawNames = new Dictionary<int, string>();
                        br.BaseStream.Seek((bch.SymbolOffset), SeekOrigin.Begin);
                        int ofs = 0;
                        uint ind = 0;
                        while (ind < SymbSize)
                        {
                            string curname = "";
                            byte b = br.ReadByte();
                            ind++;
                            while (b != 0)
                            {
                                curname = curname + (char)b;
                                b = br.ReadByte();
                                ind++;
                            }
                            bch.RawNames.Add(ofs, curname);
                            ofs += curname.Length + 1;
                        }
                        bch.Textures = new List<BCHTexture>();

                        for (int i = 0; i < bch.TextureCount; i++)
                        {
                            BCHTexture CurTexture = new BCHTexture();
                            br.BaseStream.Seek(bch.TableOffset + i * 0x4, SeekOrigin.Begin);
                            uint CurTexInfoOffset = br.ReadUInt32();
                            br.BaseStream.Seek(bch.InfoOffset + CurTexInfoOffset, SeekOrigin.Begin);
                            CurTexture.DescOffset = br.ReadUInt32() + bch.DescOffset; //0x0  Location within Desc
                            br.ReadUInt32();                   //0x4  unk
                            br.ReadUInt32();                   //0x8  unk
                            br.ReadUInt32();                   //0xC  unk
                            br.ReadUInt32();                   //0x10 unk
                            br.ReadUInt32();                   //0x14 unk
                            br.ReadUInt32(); //0x18 unk;
                            int key = (int)br.ReadUInt32(); //0x1C Name offset; not useful because we already parsed
                            if (bch.InfoOffset == 0x44)
                            {
                                // key--;
                            }
                            string name;
                            bch.RawNames.TryGetValue(key, out name);
                            bch.TexNames.Add(name);
                            br.BaseStream.Seek(CurTexture.DescOffset, SeekOrigin.Begin);
                            CurTexture.Height = br.ReadUInt16(); //0x0 height
                            CurTexture.Width = br.ReadUInt16(); //0x2 width
                            br.ReadUInt32(); //0x4, unk
                            CurTexture.DataOffset = br.ReadUInt32(); //0x8 DataOffset
                            br.ReadUInt32(); //0xC unk
                            CurTexture.Format = br.ReadUInt32(); //0x10 Format
                            if (bch.InfoOffset == 0x44 || bch.InfoOffset == 0x3C)
                            {
                                CurTexture.DataOffset = CurTexture.Format;
                                br.ReadUInt32();
                                CurTexture.Format = br.ReadUInt32();
                            }
                            bch.Textures.Add(CurTexture); //OKAY DONE

                        }
                        for (int i = 0; i < bch.Textures.Count - 1; i++)
                        {
                            BCHTexture bchtex = bch.Textures[i];
                            bchtex.Length = bch.Textures[i + 1].DataOffset - bch.Textures[i].DataOffset;
                            if (bch.InfoOffset == 0x44)
                            {
                                bchtex.Length = (uint)(FormatToBPP((int)bchtex.Format) * bchtex.Width * bchtex.Height);
                            }
                            bch.Textures[i] = bchtex;
                        }
                        if (bch.TextureCount > 0)
                        {
                            BCHTexture bchtex1 = bch.Textures[bch.Textures.Count - 1];
                            bchtex1.Length = bch.DataLength - bchtex1.DataOffset;
                            if (bch.InfoOffset == 0x44)
                            {
                                bchtex1.Length = (uint)(FormatToBPP((int)bchtex1.Format) * bchtex1.Width * bchtex1.Height);
                            }
                            bch.Textures[bch.Textures.Count - 1] = bchtex1;
                        }
                        br.BaseStream.Seek(bch.DataOffset, SeekOrigin.Begin);
                        byte[] data = new byte[bch.DataLength];
                        br.Read(data, 0, (int)bch.DataLength);
                        bch.data = data;
                    }
                }
            }
            return bch;
        }