Exemple #1
0
        public BMG(string filename)
        {
            using (BinaryReaderX br = new BinaryReaderX(File.OpenRead(filename)))
            {
                br.BaseStream.Position = 8;
                if (br.ReadInt32() == br.BaseStream.Length)
                {
                    br.ByteOrder = byteOrder = ByteOrder.LittleEndian;
                }
                else
                {
                    br.ByteOrder = byteOrder = ByteOrder.BigEndian;
                }
                br.BaseStream.Position = 0;

                header = br.ReadStruct <MESGHeader>();
                br.BaseStream.Position = 0x20;

                var strs = new List <string>();
                for (int i = 0; i < header.sectionCount; i++)
                {
                    br.BaseStream.Position = (br.BaseStream.Position + align - 1) & ~(align - 1);

                    var magic   = br.ReadString(4);
                    var secSize = br.ReadInt32();
                    switch (magic)
                    {
                    //Text Index Table
                    case "INF1":
                        var itemCount  = br.ReadInt16();
                        var itemLength = br.ReadInt16();
                        br.BaseStream.Position += 4;

                        for (int j = 0; j < itemCount; j++)
                        {
                            items.Add(new Item {
                                strOffset = br.ReadInt32(), attr = br.ReadBytes(itemLength - 4)
                            });
                        }
                        break;

                    case "DAT1":
                        if (items[0].strOffset == 2)
                        {
                            usedEncoding = Enc.UTF16;
                        }
                        else if (items[0].strOffset == 1)
                        {
                            usedEncoding = Enc.SJIS;
                        }

                        using (var br2 = new BinaryReaderX(new MemoryStream(br.ReadBytes(secSize - 8))))
                        {
                            for (int j = 0; j < items.Count; j++)
                            {
                                br2.BaseStream.Position = items[j].strOffset;
                                var str = GetString(br2.ReadBytes((j == items.Count - 1) ?
                                                                  (int)(br2.BaseStream.Length - br2.BaseStream.Position) :
                                                                  (int)(items[j + 1].strOffset - br2.BaseStream.Position)));

                                strs.Add(str);
                            }
                            break;
                        }

                    case "MID1":
                        midUsed = true;
                        var idCount = br.ReadInt16();
                        midUnk1 = br.ReadInt16();
                        br.BaseStream.Position += 4;

                        for (int j = 0; j < idCount; j++)
                        {
                            var id = br.ReadInt32();
                            Labels.Add(new Label
                            {
                                Name   = "Entry" + id,
                                Text   = strs[j],
                                TextID = id
                            });
                        }
                        break;
                    }
                }

                if (Labels.Count <= 0)
                {
                    for (int i = 0; i < strs.Count; i++)
                    {
                        Labels.Add(new Label
                        {
                            Name   = "Entry" + i,
                            Text   = strs[i],
                            TextID = i
                        });
                    }
                }
            }
        }
Exemple #2
0
        public BMG(string filename)
        {
            using (BinaryReaderX br = new BinaryReaderX(File.OpenRead(filename)))
            {
                header = br.ReadStruct <MESGHeader>();
                if (header.fileSize == br.BaseStream.Length)
                {
                    br.ByteOrder = byteOrder = ByteOrder.LittleEndian;
                }
                else
                {
                    br.ByteOrder           = byteOrder = ByteOrder.BigEndian;
                    br.BaseStream.Position = 0;
                    header = br.ReadStruct <MESGHeader>(); // Reload the header now that the byte order is set.
                }

                br.BaseStream.Position = headerSize;

                switch (header.encoding)
                {
                case BmgEncoding.ASCII:
                    encoding = Encoding.ASCII;
                    break;

                case BmgEncoding.ShiftJIS:
                    encoding = Encoding.GetEncoding("shift-jis");
                    break;

                case BmgEncoding.UTF16:
                    encoding = byteOrder == ByteOrder.BigEndian ? Encoding.BigEndianUnicode : Encoding.Unicode;
                    break;

                default:
                    encoding = Encoding.Unicode;
                    break;
                }

                // INF1 (Info) section must be loaded first to properly calculate the size of each DAT1 (data) entry.
                // I'm fairly certain the specification guarantees that the INF1 section will immediately follow the BMG header,
                // but better safe than sorry. It won't cause performance issues for files that follow the specification.

                do
                {
                    // Since sections are 32-byte aligned, we can just search in 32 byte increments.
                    if (br.ReadString(4) != "INF1")
                    {
                        br.BaseStream.Position += 0x1C;
                    }
                    else
                    {
                        break;
                    }
                } while (br.BaseStream.Position < br.BaseStream.Length);

                // Parse the INF1 items.
                var infSectionSize = br.ReadUInt32();
                var itemCount      = br.ReadUInt16();
                var itemSize       = br.ReadUInt16();
                br.BaseStream.Position += 4;

                for (var i = 0; i < itemCount; i++)
                {
                    items.Add(new Item {
                        strOffset = br.ReadInt32(), attr = br.ReadBytes(itemSize - 4)
                    });
                }

                // Reset the stream position to immediately after the header.
                br.BaseStream.Position = headerSize;

                var strs = new List <string>();
                for (var i = 0; i < header.sectionCount - 1; i++)
                {
                    br.BaseStream.Position = (br.BaseStream.Position + align) & ~align;

                    var magic   = br.ReadString(4);
                    var secSize = br.ReadInt32();
                    switch (magic)
                    {
                    case "DAT1":
                        using (var br2 = new BinaryReaderX(new MemoryStream(br.ReadBytes(secSize - 8))))
                        {
                            for (var j = 0; j < items.Count; j++)
                            {
                                br2.BaseStream.Position = items[j].strOffset;
                                var  currentItem = items[j];
                                Item nextItem    = null;

                                // Skip any 0 offset entries.
                                var idx = j + 1;
                                while (idx++ < items.Count)
                                {
                                    nextItem = items[j + 1];

                                    if (nextItem.strOffset != 0)
                                    {
                                        break;
                                    }
                                    nextItem = null;
                                }

                                var size = (nextItem?.strOffset ?? (int)br.BaseStream.Length) - currentItem.strOffset;
                                strs.Add(GetString(br2.ReadBytes(size)));
                            }
                        }

                        break;

                    case "MID1":
                        midUsed = true;
                        var idCount = br.ReadInt16();
                        midUnk1 = br.ReadInt16();
                        br.BaseStream.Position += 4;

                        for (var j = 0; j < idCount; j++)
                        {
                            var id = br.ReadInt32();
                            Labels.Add(new Label
                            {
                                Name   = "Entry" + id,
                                Text   = strs[j],
                                TextID = id
                            });
                        }

                        break;
                    }
                }

                if (Labels.Count <= 0)
                {
                    for (int i = 0; i < strs.Count; i++)
                    {
                        Labels.Add(new Label
                        {
                            Name   = "Entry" + i,
                            Text   = strs[i],
                            TextID = i
                        });
                    }
                }
            }
        }