예제 #1
0
 /// <summary>从数据流中读取消息头</summary>
 /// <param name="stream"></param>
 public void Read(Stream stream)
 {
     var reader = new BinaryReaderX(stream);
     reader.Settings.EncodeInt = true;
     Flag = (Flags)reader.ReadByte();
     if (HasFlag(Flags.Channel)) Channel = reader.ReadByte();
     if (HasFlag(Flags.SessionID)) SessionID = reader.ReadInt32();
     if (HasFlag(Flags.Length)) Length = reader.ReadInt32();
 }
예제 #2
0
        public G1T(Stream input, Platform platform)
        {
            _platform = platform;

            using (BinaryReaderX br = new BinaryReaderX(input))
            {
                //Deciding on Endianess
                var magic1 = br.ReadString(4);
                br.ByteOrder           = ByteOrder = (magic1 == "GT1G") ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
                br.BaseStream.Position = 0;

                //Header
                header = br.ReadStruct <Header>();

                //OffsetList
                br.BaseStream.Position = header.dataOffset;
                var offsetList = br.ReadMultiple <int>(header.texCount);

                //Meta
                meta = new List <Meta>();
                for (int i = 0; i < header.texCount; i++)
                {
                    br.BaseStream.Position = header.dataOffset + offsetList[i];
                    var metainfo = br.ReadStruct <Meta>();
                    meta.Add(metainfo);
                    byte[] ext = null;
                    if (metainfo.extHeader > 0)
                    {
                        var extSize = br.ReadInt32();
                        ext = br.ReadBytes(extSize - 4);
                    }
                    metaExt.Add(ext);

                    //Check if format exists
                    switch (_platform)
                    {
                    case Platform.N3DS:
                        if (!Support.N3DSFormat.ContainsKey(metainfo.format))
                        {
                            throw new Exception($"Unsupported image format 0x{metainfo.format:X2}.");
                        }
                        break;

                    case Platform.PS:
                        if (!Support.PSFormat.ContainsKey(metainfo.format))
                        {
                            throw new Exception($"Unsupported image format 0x{metainfo.format:X2}.");
                        }
                        break;

                    case Platform.Vita:
                        if (!Support.VitaFormat.ContainsKey(metainfo.format))
                        {
                            throw new Exception($"Unsupported image format 0x{metainfo.format:X2}.");
                        }
                        break;
                    }

                    var format = (_platform == Platform.Vita) ? Support.VitaFormat[meta[i].format] : (_platform == Platform.N3DS) ? Support.N3DSFormat[meta[i].format] : Support.PSFormat[meta[i].format];

                    IImageSwizzle swizzle = null;
                    if (_platform == Platform.Vita)
                    {
                        swizzle = new VitaSwizzle(metainfo.width, metainfo.height, format.FormatName.Contains("DXT"));
                    }
                    else if (_platform == Platform.N3DS)
                    {
                        swizzle = new CTRSwizzle(metainfo.width, metainfo.height, 2);
                    }
                    else if (format.FormatName.Contains("DXT"))
                    {
                        swizzle = new BlockSwizzle(metainfo.width, metainfo.height);
                    }

                    var setting = new ImageSettings
                    {
                        Width   = metainfo.width,
                        Height  = metainfo.height,
                        Swizzle = swizzle,
                        Format  = format
                    };
                    settings.Add(setting);

                    var length = metainfo.width * metainfo.height * format.BitDepth / 8;
                    bmps.Add(Common.Load(br.ReadBytes(length), setting));
                }
            }
        }
예제 #3
0
        public BTXT(string filename)
        {
            using (FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                BinaryReaderX br = new BinaryReaderX(fs);

                // Header
                Header.Identifier = br.ReadBytes(8);
                if (!Header.Identifier.SequenceEqual(new byte[] { 0x0, 0x0, 0x0, 0x0, 0x24, 0x10, 0x12, 0xFF }))
                {
                    throw new InvalidBTXTException("The file provided is not a valid BTXT file.");
                }

                Header.NumberOfLabels  = br.ReadUInt16();
                Header.NumberOfStrings = br.ReadUInt16();

                // Create labels
                for (int i = 0; i < Header.NumberOfLabels; i++)
                {
                    Labels.Add(new Label());
                }

                // Attributes
                for (int i = 0; i < Header.NumberOfLabels; i++)
                {
                    Label label = Labels[i];
                    label.StringCount = br.ReadUInt32();

                    for (int j = 0; j < label.StringCount; j++)
                    {
                        String str = new String();
                        str.ID = br.ReadUInt32();
                        label.Strings.Add(str);
                    }
                }

                // Offsets
                for (int i = 0; i < Header.NumberOfLabels + Header.NumberOfStrings; i++)
                {
                    Offsets.Add(br.ReadUInt32());
                }

                // Set the offset start position
                uint offsetStart = (uint)br.BaseStream.Position;
                Offsets.Add((uint)br.BaseStream.Length - offsetStart);                 // Add an extra offset at the end

                // Labels
                for (int i = 0; i < Header.NumberOfLabels; i++)
                {
                    Label label = Labels[i];
                    label.Name = Encoding.ASCII.GetString(br.ReadBytes((int)(Offsets[i + 1] - Offsets[i]))).TrimEnd('\0');
                }

                // Text
                int index = 0;
                for (int i = 0; i < Header.NumberOfLabels; i++)
                {
                    Label label = Labels[i];

                    for (int j = 0; j < label.StringCount; j++)
                    {
                        String str = label.Strings[j];
                        str.Text = FileEncoding.GetString(br.ReadBytes((int)(Offsets[Header.NumberOfLabels + index + 1] - Offsets[Header.NumberOfLabels + index]))).TrimEnd('\0');
                        index++;
                    }
                }

                br.Close();
            }
        }
예제 #4
0
        public static byte[] Decompress(Stream instream, ByteOrder byteOrder)
        {
            using (var br = new BinaryReaderX(instream, true, byteOrder))
            {
                var         offset = 0;
                List <byte> output = new List <byte>();

                #region 16-byte Header
                if (br.ReadString(4) != "MIO0")
                {
                    throw new Exception("Not a valid MIO0 compressed file!");
                }

                int decompressedLength = br.ReadInt32();
                int compressedOffset   = br.ReadInt32() + offset;
                int uncompressedOffset = br.ReadInt32() + offset;
                #endregion

                int currentOffset;

                while (output.Count < decompressedLength)
                {
                    byte     bits        = br.ReadByte(); //byte of layout bits
                    BitArray arrayOfBits = new BitArray(new byte[1] {
                        bits
                    });

                    for (int i = 7; i > -1 && (output.Count < decompressedLength); i--) //iterate through layout bits
                    {
                        if (arrayOfBits[i] == true)
                        {
                            //non-compressed
                            //add one byte from uncompressedOffset to newFile

                            currentOffset = (int)br.BaseStream.Position;

                            br.BaseStream.Seek(uncompressedOffset, SeekOrigin.Begin);

                            output.Add(br.ReadByte());
                            uncompressedOffset++;

                            br.BaseStream.Seek(currentOffset, SeekOrigin.Begin);
                        }
                        else
                        {
                            //compressed
                            //read 2 bytes
                            //4 bits = length
                            //12 bits = offset

                            currentOffset = (int)br.BaseStream.Position;
                            br.BaseStream.Seek(compressedOffset, SeekOrigin.Begin);

                            byte byte1 = br.ReadByte();
                            byte byte2 = br.ReadByte();
                            compressedOffset += 2;

                            //Note: For Debugging, binary representations can be printed with:  Convert.ToString(numberVariable, 2);

                            byte byte1Upper = (byte)((byte1 & 0x0F));      //offset bits
                            byte byte1Lower = (byte)((byte1 & 0xF0) >> 4); //length bits

                            int combinedOffset = ((byte1Upper << 8) | byte2);

                            int finalOffset = 1 + combinedOffset;
                            int finalLength = 3 + byte1Lower;

                            for (int k = 0; k < finalLength; k++)               //add data for finalLength iterations
                            {
                                output.Add(output[output.Count - finalOffset]); //add byte at offset (fileSize - finalOffset) to file
                            }

                            br.BaseStream.Seek(currentOffset, SeekOrigin.Begin); //return to layout bits
                        }
                    }
                }

                return(output.ToArray());
            }
        }
예제 #5
0
        public BCFNT(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                // @todo: read as sections
                br.ReadStruct <CFNT>();

                if (br.ReadString(4) == "GLGR")
                {
                    _usesGlgr = true;
                    var glgrSize = br.ReadInt32();
                    br.BaseStream.Position -= 8;
                    _glgr = br.ReadBytes(glgrSize);
                }
                else
                {
                    br.BaseStream.Position -= 4;
                }

                finf = br.ReadStruct <FINF>();

                // read TGLP
                br.BaseStream.Position = finf.tglp_offset - 8;
                tglp = br.ReadStruct <TGLP>();

                // read image data
                br.BaseStream.Position = tglp.sheet_data_offset;
                int width  = tglp.sheet_width;
                int height = tglp.sheet_height;
                if (_usesGlgr)
                {
                    bmps = new Bitmap[tglp.num_sheets];
                    for (int i = 0; i < tglp.num_sheets; i++)
                    {
                        var compSize = br.ReadInt32();
                        var decomp   = Huffman.Decompress(new MemoryStream(br.ReadBytes(compSize)), 8);
                        bmps[i] = Image.Common.Load(decomp, new ImageSettings
                        {
                            Width  = width,
                            Height = height,
                            Format = ImageSettings.ConvertFormat(tglp.sheet_image_format & 0x7fff)
                        });
                    }
                }
                else
                {
                    bmps = Enumerable.Range(0, tglp.num_sheets).Select(_ => Image.Common.Load(br.ReadBytes(tglp.sheet_size), new ImageSettings
                    {
                        Width  = width,
                        Height = height,
                        Format = ImageSettings.ConvertFormat(tglp.sheet_image_format)
                    })).ToArray();
                }

                // read CWDH
                for (int offset = finf.cwdh_offset; offset != 0;)
                {
                    br.BaseStream.Position = offset - 8;
                    var cwdh = br.ReadStruct <CWDH>();
                    for (int i = cwdh.start_index; i <= cwdh.end_index; i++)
                    {
                        lstCWDH.Add(br.ReadStruct <CharWidthInfo>());
                    }
                    offset = cwdh.next_offset;
                }

                // read CMAP
                for (int offset = finf.cmap_offset; offset != 0;)
                {
                    br.BaseStream.Position = offset - 8;
                    var cmap = br.ReadStruct <CMAP>();
                    switch (cmap.mapping_method)
                    {
                    case 0:
                        var charOffset = br.ReadUInt16();
                        for (char i = cmap.code_begin; i <= cmap.code_end; i++)
                        {
                            int idx = i - cmap.code_begin + charOffset;
                            dicCMAP[i] = idx < ushort.MaxValue ? idx : 0;
                        }
                        break;

                    case 1:
                        for (char i = cmap.code_begin; i <= cmap.code_end; i++)
                        {
                            int idx = br.ReadInt16();
                            if (idx != -1)
                            {
                                dicCMAP[i] = idx;
                            }
                        }
                        break;

                    case 2:
                        var n = br.ReadUInt16();
                        for (int i = 0; i < n; i++)
                        {
                            char c   = br.ReadChar();
                            int  idx = br.ReadInt16();
                            if (idx != -1)
                            {
                                dicCMAP[c] = idx;
                            }
                        }
                        break;

                    default:
                        throw new Exception("Unsupported mapping method");
                    }
                    offset = cmap.next_offset;
                }
            }
        }
예제 #6
0
        public void extractCfgBin(BinaryReaderX br, string prefix = "")
        {
            long bk;

            //Header
            Header cfgHeader = br.ReadStruct <Header>();

            headerList.Add(cfgHeader);

            List <EditorStruct> editorEntriesLocal = new List <EditorStruct>();

            editorEntriesLocal.Add(br.ReadStruct <EditorStruct>());

            //getting Editor's notes entries
            while (true)
            {
                Label label = new Label();

                EditorStruct entryE = br.ReadStruct <EditorStruct>();
                editorEntriesLocal.Add(entryE);

                label.Name       = prefix + "editor" + (editorEntriesLocal.Count - 1).ToString();
                label.TextID     = entryE.ID;
                label.TextOffset = cfgHeader.dataOffset + entryE.entryOffset;

                bk = br.BaseStream.Position;
                br.BaseStream.Position = label.TextOffset;
                string text = ""; byte part = br.ReadByte();
                while (part != 0)
                {
                    text += Encoding.GetEncoding("ascii").GetString(new byte[] { part });
                    part  = br.ReadByte();
                }
                br.BaseStream.Position = label.TextOffset;
                label.Text             = text;
                br.BaseStream.Position = bk;

                Labels.Add(label);

                if (entryE.endingFlag == 0x0101)
                {
                    break;
                }
            }
            editorEntries.Add(editorEntriesLocal);

            bool found = false;

            bk = br.BaseStream.Position;
            while (br.BaseStream.Position < cfgHeader.dataOffset && found == false)
            {
                if (br.ReadInt32() == (int)(editorEntries[editorEntries.Count - 1][editorEntries[editorEntries.Count - 1].Count - 1].entryOffset + Labels[Labels.Count - 1].Text.Length + 1))
                {
                    found = true;
                }
            }

            br.BaseStream.Position = bk;
            if (found == false)
            {
                editorRest.Add(br.ReadBytes((int)(cfgHeader.dataOffset - br.BaseStream.Position)));
                textRest.Add(null);
                textEntries.Add(null);
            }
            else
            {
                editorRest.Add(null);

                List <TextStruct> textEntriesLocal = new List <TextStruct>();

                textEntriesLocal.Add(br.ReadStruct <TextStruct>());

                //getting text entries
                TextStruct entryT;
                TextStruct entryT2;
                int        entryCount = 1;
                do
                {
                    Label label = new Label();

                    entryT = br.ReadStruct <TextStruct>();
                    textEntriesLocal.Add(entryT);

                    entryT2 = br.ReadStruct <TextStruct>();
                    br.BaseStream.Position -= 0x14;

                    if (entryT.entryOffset != 0xFFFFFFFF)
                    {
                        label.Name       = prefix + "text" + entryCount.ToString(); entryCount++;
                        label.TextID     = entryT.ID;
                        label.TextOffset = cfgHeader.dataOffset + entryT.entryOffset;

                        bk = br.BaseStream.Position;
                        br.BaseStream.Position = label.TextOffset;
                        int count = 0; byte part = br.ReadByte();
                        while (part != 0)
                        {
                            count++;
                            part = br.ReadByte();
                        }
                        count++;
                        br.BaseStream.Position = label.TextOffset;
                        label.Text             = getUnicodeString(new BinaryReaderX(new MemoryStream(br.ReadBytes(count))));
                        br.BaseStream.Position = bk;

                        Labels.Add(label);
                    }
                } while (entryT.unk3 != 0xffffff00 && (entryT2.entryOffset <= br.BaseStream.Length || entryT2.entryOffset == 0xFFFFFFFF));
                textEntries.Add(textEntriesLocal);

                if (br.BaseStream.Position < cfgHeader.dataOffset)
                {
                    textRest.Add(br.ReadBytes((int)cfgHeader.dataOffset - (int)br.BaseStream.Position));
                }
            }
        }
예제 #7
0
        public BXLIM(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                var tex = br.ReadBytes((int)br.BaseStream.Length - 40);
                sections  = br.ReadSections();
                byteOrder = br.ByteOrder;

                switch (sections.Header.magic)
                {
                case "CLIM":
                    BCLIMHeader = sections[0].Data.BytesToStruct <BCLIMImageHeader>(byteOrder);

                    Settings = new Kontract.Image.ImageSettings
                    {
                        Width   = BCLIMHeader.width,
                        Height  = BCLIMHeader.height,
                        Format  = DSFormat[BCLIMHeader.format],
                        Swizzle = new CTRSwizzle(BCLIMHeader.width, BCLIMHeader.height, BCLIMHeader.swizzleTileMode)
                    };
                    Image = Kontract.Image.Common.Load(tex, Settings);
                    break;

                case "FLIM":
                    if (byteOrder == ByteOrder.LittleEndian)
                    {
                        BFLIMHeader = sections[0].Data.BytesToStruct <BFLIMImageHeader>(byteOrder);

                        Settings = new Kontract.Image.ImageSettings
                        {
                            Width   = BFLIMHeader.width,
                            Height  = BFLIMHeader.height,
                            Format  = DSFormat[BFLIMHeader.format],
                            Swizzle = new CTRSwizzle(BFLIMHeader.width, BFLIMHeader.height, BFLIMHeader.swizzleTileMode)
                        };
                        Image = Kontract.Image.Common.Load(tex, Settings);
                    }
                    else
                    {
                        BFLIMHeader = sections[0].Data.BytesToStruct <BFLIMImageHeader>(byteOrder);

                        var format = WiiUFormat[BFLIMHeader.format];
                        var isBlockBased = new[] { 10, 11, 12, 13, 14, 15, 16, 17, 21, 22, 23 }.Contains(BFLIMHeader.format);     // hax

                        Settings = new Kontract.Image.ImageSettings
                        {
                            Width   = BFLIMHeader.width,
                            Height  = BFLIMHeader.height,
                            Format  = format,
                            Swizzle = new WiiUSwizzle(BFLIMHeader.swizzleTileMode, isBlockBased, format.BitDepth, BFLIMHeader.width, BFLIMHeader.height)
                        };

                        // Uncomment the following line to use the padded width/height instead
                        //(Settings.Width, Settings.Height) = (Settings.Swizzle.Width, Settings.Swizzle.Height);

                        Image = Kontract.Image.Common.Load(tex, Settings);
                    }
                    break;

                default:
                    throw new NotSupportedException($"Unknown image format {sections.Header.magic}");
                }
            }
        }
예제 #8
0
파일: Yay0.cs 프로젝트: SeeMirra/Kuriimu
        public static byte[] Compress(Stream input, ByteOrder byteOrder)
        {
            using (var br = new BinaryReaderX(input, true))
            {
                var cap = 0x111;
                var sz  = input.Length;

                var cmds = new List <byte>();
                var ctrl = new List <byte>();
                var raws = new List <byte>();

                var cmdpos = 0;
                cmds.Add(0);

                var  pos  = 0;
                byte flag = 0x80;

                while (pos < sz)
                {
                    var hitp = 0;
                    var hitl = 0;
                    _search(input, pos, sz, cap, ref hitp, ref hitl);

                    if (hitl < 3)
                    {
                        raws.Add(br.ScanBytes(pos)[0]);
                        cmds[cmdpos] |= flag;
                        pos          += 1;
                    }
                    else
                    {
                        var tstp = 0;
                        var tstl = 0;
                        _search(input, pos + 1, sz, cap, ref tstp, ref tstl);

                        if ((hitl + 1) < tstl)
                        {
                            raws.Add(br.ScanBytes(pos)[0]);
                            cmds[cmdpos] |= flag;
                            pos          += 1;
                            flag        >>= 1;
                            if (flag == 0)
                            {
                                flag   = 0x80;
                                cmdpos = cmds.Count();
                                cmds.Add(0);
                            }

                            hitl = tstl;
                            hitp = tstp;
                        }

                        var e = pos - hitp - 1;
                        pos += hitl;

                        if (hitl < 0x12)
                        {
                            hitl -= 2;
                            ctrl.AddRange(BitConverter.GetBytes((ushort)((hitl << 12) | e)).Reverse());
                        }
                        else
                        {
                            ctrl.AddRange(BitConverter.GetBytes((ushort)(e)).Reverse());
                            raws.Add((byte)(hitl - 0x12));
                        }
                    }

                    flag >>= 1;
                    if (flag == 0)
                    {
                        flag   = 0x80;
                        cmdpos = cmds.Count();
                        cmds.Add(0);
                    }
                }

                if (flag == 0x80)
                {
                    cmds.RemoveAt(cmdpos);
                }

                var v = 4 - (cmds.Count() & 3);
                cmds.AddRange(new byte[v & 3]);
                var l = cmds.Count() + 16;
                var o = ctrl.Count() + l;

                List <byte> header = new List <byte>();
                header.AddRange(Encoding.ASCII.GetBytes("Yay0"));
                header.AddRange((byteOrder == ByteOrder.LittleEndian) ? BitConverter.GetBytes((int)sz) : BitConverter.GetBytes((int)sz).Reverse());
                header.AddRange((byteOrder == ByteOrder.LittleEndian) ? BitConverter.GetBytes(l) : BitConverter.GetBytes(l).Reverse());
                header.AddRange((byteOrder == ByteOrder.LittleEndian) ? BitConverter.GetBytes(o) : BitConverter.GetBytes(o).Reverse());
                header.AddRange(cmds);
                header.AddRange(ctrl);
                header.AddRange(raws);

                return(header.ToArray());
            }
        }
예제 #9
0
        private void btnLookup_Click(object sender, EventArgs e)
        {
            Encoding enc  = Encoding.Unicode;
            FileInfo file = new FileInfo(txtFile.Text.Trim());

            if (file.Exists)
            {
                using (FileStream fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    BinaryReaderX br = new BinaryReaderX(fs, ByteOrder.LittleEndian);

                    txtResults.Text = string.Empty;
                    uint offset   = Convert.ToUInt32(txtOffset.Text.Trim(), 16);
                    uint leneance = Convert.ToUInt32(txtLeneance.Text.Trim());

                    uint        value    = 0;
                    List <uint> pointers = new List <uint>();

                    while (br.BaseStream.Position < br.BaseStream.Length - 4)
                    {
                        bool found   = false;
                        uint pointer = (uint)br.BaseStream.Position;
                        value = br.ReadUInt32();

                        if (value < br.BaseStream.Length - 4)
                        {
                            uint shift = 0;
                            uint.TryParse(Settings.Default.DirectorShift, out shift);

                            if (value == (offset + shift))
                            {
                                found = true;
                            }
                            else if (value >= (offset + shift - leneance) && value < offset + shift)
                            {
                                found = true;
                            }
                            else if (value <= (offset + shift + leneance) && value > offset + shift)
                            {
                                found = true;
                            }

                            if (found)
                            {
                                pointers.Add(pointer);
                            }
                        }
                    }

                    if (pointers.Count > 0)
                    {
                        List <byte> result = new List <byte>();
                        br.BaseStream.Seek(offset, SeekOrigin.Begin);
                        while (br.BaseStream.Position < br.BaseStream.Length)
                        {
                            byte[] unichar = br.ReadBytes(2);

                            if (unichar[0] != 0x0 || unichar[1] != 0x0)
                            {
                                result.AddRange(unichar);
                            }
                            else
                            {
                                break;
                            }
                        }

                        string strResult = enc.GetString(result.ToArray());

                        txtResults.AppendText("<entry encoding=\"" + enc.EncodingName + "\" name=\"\" offset=\"" + offset.ToString("X2") + "\" relocatable=\"true\" max_length=\"0\">");
                        txtResults.AppendText("\r\n");

                        foreach (uint p in pointers)
                        {
                            txtResults.AppendText("\t<pointer address=\"" + p.ToString("X2") + "\" />");
                            txtResults.AppendText("\r\n");
                        }

                        txtResults.AppendText("\t<original>" + strResult + "</original>");
                        txtResults.AppendText("\r\n");
                        txtResults.AppendText("\t<edited>" + strResult + "</edited>");
                        txtResults.AppendText("\r\n");
                        txtResults.AppendText("</entry>");
                    }
                    else
                    {
                        txtResults.Text = "No pointers found...";
                    }

                    br.Close();
                }
            }
        }
예제 #10
0
        // Dumper
        private void workerDumper_DoWork(object sender, DoWorkEventArgs e)
        {
            FileStream    fs = new FileStream(txtFilename.Text, FileMode.Open, FileAccess.Read, FileShare.Read);
            BinaryReaderX br = new BinaryReaderX(fs, ByteOrder.LittleEndian);

            // Pointer Tables
            _pointers = new Dictionary <long, long>();

            _workerDumper.ReportProgress(0, "STATUS|Dumping pointers...");
            foreach (Bound pointerBound in _kup.PointerTables)
            {
                long end = Math.Max(4, pointerBound.EndLong);

                if (end == 4)
                {
                    end += pointerBound.StartLong;
                }

                br.BaseStream.Seek(pointerBound.StartLong, SeekOrigin.Begin);
                while (br.BaseStream.Position < end)
                {
                    uint offset = br.ReadUInt32() - _kup.RamOffsetUInt;
                    if (offset < br.BaseStream.Length)
                    {
                        _pointers.Add(br.BaseStream.Position - sizeof(uint), offset); // AAAHAAAAARRRRRRGGRGGGGHHHHHHH
                    }
                    _workerDumper.ReportProgress((int)(((double)br.BaseStream.Position - pointerBound.StartLong) / ((double)pointerBound.EndLong - pointerBound.StartLong) * prgBottom.Maximum), "BOTTOM");
                }
            }
            _workerDumper.ReportProgress(0, "STATUS|Found " + _pointers.Count + " pointers...");

            _workerDumper.ReportProgress(0, "STATUS|Dumping strings...");
            for (int i = 0; i < _kup.StringBounds.Count; i++)
            {
                Bound stringBound = _kup.StringBounds[i];

                _workerDumper.ReportProgress((int)(((double)i + 1 / (double)_kup.StringBounds.Count) * prgBottom.Maximum), "BOTTOM");

                if (stringBound.Dumpable)
                {
                    var  result   = new List <byte>();
                    var  offset   = stringBound.StartLong;
                    long jumpBack = 0;

                    br.BaseStream.Seek(stringBound.StartLong, SeekOrigin.Begin);
                    while (br.BaseStream.Position < stringBound.EndLong)
                    {
                        var unichar = br.ReadBytes(_kup.Encoding.IsSingleByte ? 1 : 2);
                        result.AddRange(unichar);

                        if (stringBound.Injectable)
                        {
                            if (jumpBack == 0 && (_pointers.Values.Contains(br.BaseStream.Position) || br.BaseStream.Position == stringBound.EndLong))
                            {
                                jumpBack = br.BaseStream.Position;
                            }

                            if ((_pointers.Values.Contains(br.BaseStream.Position) || br.BaseStream.Position == stringBound.EndLong) && (result[result.Count - 1] == 0x00 && (_kup.Encoding.IsSingleByte || result[result.Count - 2] == 0x00)))
                            {
                                if (result[result.Count - 1] == 0x00 && (_kup.Encoding.IsSingleByte || result[result.Count - 2] == 0x00))
                                {
                                    result.RemoveAt(result.Count - 1);
                                    if (!_kup.Encoding.IsSingleByte)
                                    {
                                        result.RemoveAt(result.Count - 1);
                                    }
                                }

                                var entry = new Entry {
                                    OffsetLong = offset
                                };

                                // Merging
                                var matched = false;
                                foreach (var ent in _kup.Entries)
                                {
                                    if (ent.Offset == entry.Offset)
                                    {
                                        entry   = ent;
                                        matched = true;
                                        break;
                                    }
                                }

                                // Pointers
                                foreach (var key in _pointers.Keys)
                                {
                                    if (_pointers[key] == offset)
                                    {
                                        entry.AddPointer(key);
                                    }
                                }

                                // Text
                                if (Equals(_kup.Encoding, Encoding.ASCII))
                                {
                                    var parsed = new StringBuilder();
                                    foreach (var b in result)
                                    {
                                        parsed.Append((char)b);
                                    }
                                    entry.OriginalText = _gameHandler.GetKuriimuString(parsed.ToString()).Replace("\0", "<null>").Replace("\n", "\r\n");;
                                }
                                else
                                {
                                    entry.OriginalText = _gameHandler.GetKuriimuString(_kup.Encoding.GetString(result.ToArray())).Replace("\0", "<null>").Replace("\n", "\r\n");
                                }

                                // Not Matched
                                if (!matched)
                                {
                                    entry.Relocatable = stringBound.Injectable;
                                    entry.Name        = Regex.Match(entry.OriginalText, @"\w+", RegexOptions.IgnoreCase).Value;
                                    entry.EditedText  = entry.OriginalText;
                                    _kup.Entries.Add(entry);
                                }

                                if (entry.OriginalText.Contains("<null>"))
                                {
                                    _workerDumper.ReportProgress(0, "STATUS|Found a potentially broken string at " + entry.Offset + ": " + entry.Name + "|" + entry.Offset);
                                }

                                if (jumpBack > 0)
                                {
                                    br.BaseStream.Seek(jumpBack, SeekOrigin.Begin);
                                    jumpBack = 0;
                                }

                                offset = br.BaseStream.Position;
                                result.Clear();
                            }
                        }
                        else
                        {
                            if (br.BaseStream.Position == stringBound.EndLong)
                            {
                                if (result.Count >= (_kup.Encoding.IsSingleByte ? 1 : 2))
                                {
                                    if (result[result.Count - 1] == 0x00 && (_kup.Encoding.IsSingleByte || result[result.Count - 2] == 0x00))
                                    {
                                        result.RemoveAt(result.Count - 1);
                                        if (!_kup.Encoding.IsSingleByte)
                                        {
                                            result.RemoveAt(result.Count - 1);
                                        }
                                    }

                                    var entry = new Entry {
                                        OffsetLong = stringBound.StartLong
                                    };

                                    // Merging
                                    var matched = false;
                                    foreach (var ent in _kup.Entries)
                                    {
                                        if (ent.Offset == entry.Offset)
                                        {
                                            entry   = ent;
                                            matched = true;
                                            break;
                                        }
                                    }

                                    // Text
                                    if (Equals(_kup.Encoding, Encoding.ASCII))
                                    {
                                        var parsed = new StringBuilder();
                                        foreach (var b in result)
                                        {
                                            parsed.Append((char)b);
                                        }
                                        entry.OriginalText = _gameHandler.GetKuriimuString(parsed.ToString()).Replace("\0", "<null>").Replace("\n", "\r\n");;
                                    }
                                    else
                                    {
                                        entry.OriginalText = _gameHandler.GetKuriimuString(_kup.Encoding.GetString(result.ToArray())).Replace("\0", "<null>").Replace("\n", "\r\n");
                                    }

                                    // Not Matched
                                    if (!matched)
                                    {
                                        entry.Relocatable = stringBound.Injectable;
                                        entry.Name        = Regex.Match(entry.OriginalText, @"\w+", RegexOptions.IgnoreCase).Value;
                                        entry.EditedText  = entry.OriginalText;
                                        entry.MaxLength   = entry.EditedText.Length;
                                        _kup.Entries.Add(entry);
                                    }
                                }

                                result.Clear();
                            }
                        }

                        _workerDumper.ReportProgress((int)(((double)br.BaseStream.Position - stringBound.StartLong) / ((double)stringBound.EndLong - stringBound.StartLong) * prgTop.Maximum), "TOP");
                    }
                }
            }
            _workerDumper.ReportProgress(0, "STATUS|Dumped " + _kup.Entries.Count + " strings...");

            br.Close();
        }
예제 #11
0
        public XF(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                //load files
                xpck = new XPCK(input);

                //get xi image to bmp
                xi  = new IMGC(xpck.Files[0].FileData);
                bmp = xi.Image;

                //decompress fnt.bin
                var tempCharSizeInfo = new List <CharSizeInfo>();
                var largeChars       = new List <CharacterMap>();
                var smallChars       = new List <CharacterMap>();
                using (var fntR = new BinaryReaderX(xpck.Files[1].FileData, true))
                {
                    Header = fntR.ReadType <XFHeader>();

                    fntR.BaseStream.Position = Header.table0Offset << 2;
                    t0Comp = (Level5.Method)(fntR.ReadInt32() & 0x7);
                    fntR.BaseStream.Position -= 4;
                    tempCharSizeInfo          = new BinaryReaderX(new MemoryStream(Level5.Decompress(fntR.BaseStream))).ReadMultiple <CharSizeInfo>(Header.table0EntryCount);

                    fntR.BaseStream.Position = Header.table1Offset << 2;
                    t1Comp = (Level5.Method)(fntR.ReadInt32() & 0x7);
                    fntR.BaseStream.Position -= 4;
                    largeChars = new BinaryReaderX(new MemoryStream(Level5.Decompress(fntR.BaseStream))).ReadMultiple <CharacterMap>(Header.table1EntryCount);

                    fntR.BaseStream.Position = Header.table2Offset << 2;
                    t2Comp = (Level5.Method)(fntR.ReadInt32() & 0x7);
                    fntR.BaseStream.Position -= 4;
                    smallChars = new BinaryReaderX(new MemoryStream(Level5.Decompress(fntR.BaseStream))).ReadMultiple <CharacterMap>(Header.table2EntryCount);
                }

                Textures = new List <Bitmap>();
                var bmpInfo = new BitmapInfo(bmp);
                Textures.Add(bmpInfo.CreateChannelBitmap(BitmapInfo.Channel.Red));
                Textures.Add(bmpInfo.CreateChannelBitmap(BitmapInfo.Channel.Green));
                Textures.Add(bmpInfo.CreateChannelBitmap(BitmapInfo.Channel.Blue));

                //Add Characters
                Characters = new List <XFCharacter>();
                foreach (var glyph in largeChars)
                {
                    var newChar = new XFCharacter
                    {
                        Character      = glyph.code_point,
                        TextureID      = (int)glyph.ColorChannel,
                        GlyphX         = (int)glyph.ImageOffsetX,
                        GlyphY         = (int)glyph.ImageOffsetY,
                        GlyphWidth     = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].glyph_width,
                        GlyphHeight    = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].glyph_height,
                        CharacterWidth = (int)glyph.CharWidth,
                        OffsetX        = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].offset_x,
                        OffsetY        = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].offset_y,
                    };
                    Characters.Add(newChar);
                }

                /*foreach (var glyph in smallChars)
                 *  Characters.Add(new XFCharacter
                 *  {
                 *      Character = glyph.code_point,
                 *      TextureID = (int)glyph.ColorChannel,
                 *      GlyphX = (int)glyph.ImageOffsetX,
                 *      GlyphY = (int)glyph.ImageOffsetY,
                 *      GlyphWidth = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].glyph_width,
                 *      GlyphHeight = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].glyph_height,
                 *      CharacterWidth = (int)glyph.CharWidth,
                 *      OffsetX = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].offset_x,
                 *      OffsetY = tempCharSizeInfo[(int)glyph.CharSizeInfoIndex].offset_y,
                 *  });*/

                //Add Textures
            }
        }
예제 #12
0
        public GFDv2(FileStream input)
        {
            _sourceFile = input.Name;

            if (_texAdapters == null || _texAdapters.Count == 0)
            {
                _texAdapters = PluginLoader.Instance.GetAdapters <IMtFrameworkTextureAdapter>();
            }

            using (var br = new BinaryReaderX(input))
            {
                // Set endianess
                if (br.PeekString(4, Encoding.ASCII) == "\0DFG")
                {
                    br.ByteOrder = ByteOrder = ByteOrder.BigEndian;
                    br.BitOrder  = BitOrder = BitOrder.LSBFirst;
                }

                // Header
                Header  = br.ReadType <FileHeader>();
                HeaderF = br.ReadMultiple <float>(Header.FCount);

                // Name
                br.ReadInt32();
                Name = br.ReadCStringASCII();

                // Characters
                Characters = br.ReadMultiple <CharacterInfo>(Header.CharacterCount).Select(ci => new GFDv2Character
                {
                    Character = ci.Character,

                    TextureID = (int)ci.Block1.TextureIndex,
                    GlyphX    = (int)ci.Block1.GlyphX,
                    GlyphY    = (int)ci.Block1.GlyphY,

                    Block2Trailer = (int)ci.Block2.Block2Trailer,
                    GlyphWidth    = (int)ci.Block2.GlyphWidth,
                    GlyphHeight   = (int)ci.Block2.GlyphHeight,

                    CharacterWidth  = (int)ci.Block3.CharacterWidth,
                    CharacterHeight = (int)ci.Block3.CharacterHeight,

                    XAdjust = ci.XAdjust,
                    YAdjust = ci.YAdjust
                }).ToList();

                // Textures
                Textures = new List <Bitmap>();
                for (var i = 0; i < Header.FontTexCount; i++)
                {
                    IMtFrameworkTextureAdapter texAdapter = _texAdapters.Where(adapter => adapter is IIdentifyFiles).
                                                            FirstOrDefault(adapter => ((IIdentifyFiles)adapter).
                                                                           Identify(new StreamInfo(File.OpenRead(GetTexName(_sourceFile, i)), GetTexName(_sourceFile, i)), null));
                    if (texAdapter == null)
                    {
                        continue;
                    }
                    ((ILoadFiles)texAdapter).Load(new StreamInfo(File.OpenRead(GetTexName(_sourceFile, i)), GetTexName(_sourceFile, i)), null);
                    Textures.Add(((IImageAdapter)texAdapter).BitmapInfos[0].Image);
                }
            }
        }
예제 #13
0
        public BCH(string filename)
        {
            using (BinaryReaderX br = new BinaryReaderX(File.OpenRead(filename)))
            {
                _file = br.ReadAllBytes();

                //Header
                header = new Header(br.BaseStream);

                if (header.dataSize != 0)
                {
                    //get entryCount
                    br.BaseStream.Position = header.gpuCommandsOffset;
                    int         entryCount = 0;
                    List <uint> wordCount  = new List <uint>();
                    wordCount.Add(0);
                    using (var br2 = new BinaryReaderX(new MemoryStream(br.ReadBytes((int)header.gpuCommandsSize))))
                    {
                        while (br2.BaseStream.Position < br2.BaseStream.Length - 2)
                        {
                            br2.BaseStream.Position += 4;
                            var comp = br2.ReadUInt16();
                            wordCount[wordCount.Count - 1] += 2;
                            if (comp == 0x23d)
                            {
                                entryCount++;
                                wordCount.Add(0);
                            }
                            br2.BaseStream.Position += 2;
                        }
                    }

                    //get commands
                    br.BaseStream.Position = header.gpuCommandsOffset;
                    for (int i = 0; i < entryCount; i++)
                    {
                        picaEntries.Add(new PICACommandReader(br.BaseStream, wordCount[i]));
                    }

                    //loop through commandReaders to get textures
                    for (int i = 0; i < entryCount; i++)
                    {
                        var size = picaEntries[i].getTexUnit0Size();
                        if (size.Height != 0 && size.Width != 0)
                        {
                            br.BaseStream.Position = header.dataOffset + picaEntries[i].getTexUnit0Address();
                            var format   = (byte)picaEntries[i].getTexUnit0Format();
                            int bitDepth = Support.CTRFormat[format].BitDepth;

                            //for (int j = 0; j <= picaEntries[i].getTexUnit0LoD(); j++)
                            //{
                            origValues.Add(new TexEntry(size.Width, size.Height, format));

                            var settings = new ImageSettings
                            {
                                Width   = size.Width,
                                Height  = size.Height,
                                Format  = Support.CTRFormat[format],
                                Swizzle = new CTRSwizzle(size.Width, size.Height)
                            };

                            _settings.Add(settings);
                            //    bmps.Add(Common.Load(br.ReadBytes((((size.Width >> j) * (size.Height >> j)) * bitDepth) / 8), settings));
                            //}

                            bmps.Add(Common.Load(br.ReadBytes((((size.Width) * (size.Height)) * bitDepth) / 8), settings));

                            br.BaseStream.Position = (br.BaseStream.Position + 0x7f) & ~0x7f;
                        }
                    }
                }
            }
        }
예제 #14
0
        public static void Decrypt(object sender, EventArgs e)
        {
            var tsi  = sender as ToolStripMenuItem;
            var name = (tsi.Tag.ToString() == "normal") ? "3DS" : tsi.Tag.ToString();

            FileStream openFile;
            FileStream saveFile = null;

            if ((Types)tsi.Tag != Types.NSW_XCI && (Types)tsi.Tag != Types.NSW_NCA)
            {
                if (!Shared.PrepareFiles("Open an encrypted " + name + " file...", "Save your decrypted file...", ".dec", out openFile, out saveFile))
                {
                    return;
                }
            }
            else
            {
                var ofd = new OpenFileDialog
                {
                    Title  = "Open an encrypted " + name + " file...",
                    Filter = "All Files (*.*)|*.*"
                };
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    openFile = File.Open(ofd.FileName, FileMode.Open, FileAccess.ReadWrite);
                }
                else
                {
                    return;
                }
            }

            bool show = true;

            try
            {
                using (var openBr = new BinaryReaderX(openFile))
                {
                    switch (tsi.Tag)
                    {
                    case Types.BlowFishCBC:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var key = InputBox.Show("Input decryption key:", "Decrypt Blowfish");

                            if (key == String.Empty)
                            {
                                throw new Exception("Key can't be empty!");
                            }
                            var bf = new BlowFish(key);
                            outFs.Write(bf.Decrypt_CBC(openBr.ReadAllBytes()));
                        }
                        break;

                    case Types.BlowFishECB:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var key = InputBox.Show("Input decryption key:", "Decrypt Blowfish");

                            if (key == String.Empty)
                            {
                                throw new Exception("Key can't be empty!");
                            }
                            var bf = new BlowFish(key);
                            outFs.Write(bf.Decrypt_ECB(openBr.ReadAllBytes()));
                        }
                        break;

                    case Types.MTMobile:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var key1 = InputBox.Show("Input 1st decryption key:", "Decrypt MTMobile");
                            var key2 = InputBox.Show("Input 2nd decryption key:", "Decrypt MTMobile");

                            if (key1 == String.Empty || key2 == String.Empty)
                            {
                                throw new Exception("Keys can't be empty!");
                            }
                            outFs.Write(MTFramework.Decrypt(openBr.BaseStream, key1, key2));
                        }
                        break;

                    case Types.Normal:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var engine = new AesEngine();
                            openBr.BaseStream.CopyTo(outFs.BaseStream);
                            openBr.BaseStream.Position = 0;
                            outFs.BaseStream.Position  = 0;
                            engine.DecryptGameNCSD(openBr.BaseStream, outFs.BaseStream);
                        }
                        break;

                    case Types.CIA_shallow:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var engine = new AesEngine();
                            openBr.BaseStream.CopyTo(outFs.BaseStream);
                            openBr.BaseStream.Position = 0;
                            outFs.BaseStream.Position  = 0;
                            engine.DecryptCIA(openBr.BaseStream, outFs.BaseStream, true);
                        }
                        break;

                    case Types.CIA_deep:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var engine = new AesEngine();
                            openBr.BaseStream.CopyTo(outFs.BaseStream);
                            openBr.BaseStream.Position = 0;
                            outFs.BaseStream.Position  = 0;
                            engine.DecryptCIA(openBr.BaseStream, outFs.BaseStream, false);
                        }
                        break;

                    case Types.NCCH:
                        using (var outFs = new BinaryWriterX(saveFile))
                        {
                            var engine = new AesEngine();
                            openBr.BaseStream.CopyTo(outFs.BaseStream);
                            openBr.BaseStream.Position = 0;
                            outFs.BaseStream.Position  = 0;
                            engine.DecryptNCCH(openBr.BaseStream, outFs.BaseStream);
                        }
                        break;

                    /*case Types.BOSS:
                     *  outFs.Write(engine.DecryptBOSS(openBr.ReadBytes((int)openBr.BaseStream.Length)));
                     *  break;*/

                    case Types.NSW_XCI:
                        openBr.BaseStream.Position = 0;

                        var xci_header_key = InputBox.Show("Input XCI Header Key:", "Decrypt XCI").Hexlify();
                        Switch.DecryptXCI(openBr.BaseStream, xci_header_key);

                        MessageBox.Show("XCI Header and all NCA's were decrypted successfully!", "Decryption Success", MessageBoxButtons.OK);
                        show = false;
                        break;

                    case Types.NSW_NCA:
                        openBr.BaseStream.Position = 0;

                        Switch.DecryptNCA(openBr.BaseStream, 0);

                        MessageBox.Show("NCA was decrypted successfully!", "Decryption Success", MessageBoxButtons.OK);
                        show = false;
                        break;
                    }
                }

                if (show)
                {
                    MessageBox.Show($"Successfully decrypted {Path.GetFileName(openFile.Name)}.", tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                File.Delete(saveFile.Name);
            }
        }
예제 #15
0
 public bool Identify(StreamInfo file, BaseReadOnlyDirectoryNode fileSystem)
 {
     using (var br = new BinaryReaderX(file.FileData, LeaveOpen))
         return(br.ReadString(8) == "ARC TEST");
 }
예제 #16
0
파일: G1T.cs 프로젝트: mhdasding/Kuriimu
        public G1T(Stream input, bool vita = false)
        {
            this.vita = vita;

            using (BinaryReaderX br = new BinaryReaderX(input))
            {
                //Deciding on Endianess
                var magic1 = br.ReadString(4);
                br.ByteOrder           = ByteOrder = (magic1 == "GT1G") ? ByteOrder.LittleEndian : ByteOrder.BigEndian;
                br.BaseStream.Position = 0;

                //Header
                header = br.ReadStruct <Header>();

                //OffsetList
                br.BaseStream.Position = header.dataOffset;
                var offsetList = br.ReadMultiple <int>(header.texCount);

                //Meta
                meta = new List <Meta>();
                for (int i = 0; i < header.texCount; i++)
                {
                    br.BaseStream.Position = header.dataOffset + offsetList[i];
                    var metainfo = br.ReadStruct <Meta>();
                    meta.Add(metainfo);
                    byte[] ext = null;
                    if (metainfo.extHeader > 0)
                    {
                        var extSize = br.ReadInt32();
                        ext = br.ReadBytes(extSize - 4);
                    }
                    metaExt.Add(ext);

                    //Check if format exists
                    if (!Support.Format.ContainsKey(metainfo.format))
                    {
                        throw new Exception($"Unsupported image format 0x{metainfo.format:X2}.");
                    }

                    IImageSwizzle swizzle = null;
                    if (vita)
                    {
                        swizzle = new VitaSwizzle(metainfo.width, metainfo.height, Support.Format[metainfo.format].FormatName.Contains("DXT"));
                    }
                    else if (Support.Format[metainfo.format].FormatName.Contains("DXT"))
                    {
                        swizzle = new BlockSwizzle(metainfo.width, metainfo.height);
                    }

                    var setting = new ImageSettings
                    {
                        Width   = metainfo.width,
                        Height  = metainfo.height,
                        Swizzle = swizzle,
                        Format  = Support.Format[metainfo.format]
                    };
                    settings.Add(setting);

                    bmps.Add(Common.Load(br.ReadBytes(metainfo.width * metainfo.height * Support.Format[metainfo.format].BitDepth / 8), setting));
                }
            }
        }
예제 #17
0
파일: LZ77.cs 프로젝트: wabberz/Kuriimu
        public static byte[] Compress(Stream input)
        {
            using (BinaryReaderX br = new BinaryReaderX(input))
            {
                List <bool> result = new List <bool>();

                List <byte> searchBuffer = new List <byte>();
                for (int i = 0; i < searchBufferSize; i++)
                {
                    searchBuffer.Add(0x00);
                }
                List <byte> NonePlaceholder = new List <byte>();
                for (int i = 0; i < searchBufferSize; i++)
                {
                    NonePlaceholder.Add(0x00);
                }

                List <byte> lookAheadBuffer = br.ReadBytes(lookAheadBufferSize).ToList();

                int bk;
                int count = 0;

                while (lookAheadBuffer.Count() != 0)
                {
                    byte length; byte offset; byte symbol;
                    Search(lookAheadBuffer, searchBuffer, NonePlaceholder, out length, out offset);
                    count++;

                    try
                    {
                        symbol = lookAheadBuffer[length];
                    }
                    catch
                    {
                        symbol = 0x24;
                    }

                    if (length > 0)
                    {
                        if (symbol == 0x24 && br.BaseStream.Length - br.BaseStream.Position > 0)
                        {
                            symbol = br.ReadByte();

                            searchBuffer.AddRange(lookAheadBuffer); searchBuffer.Add(symbol);
                            for (int i = 0; i < lookAheadBuffer.Count(); i++)
                            {
                                NonePlaceholder.Add(1);
                            }
                            NonePlaceholder.Add(1);

                            bk              = searchBuffer.Count();
                            searchBuffer    = GetLastElements(searchBuffer, bk - (length + 1));
                            NonePlaceholder = GetLastElements(NonePlaceholder, bk - (length + 1));

                            lookAheadBuffer.AddRange(br.ReadBytes(length + 1));
                            lookAheadBuffer = GetLastElements(lookAheadBuffer, lookAheadBuffer.Count() - (length + 1));
                        }
                        else
                        {
                            searchBuffer.AddRange(GetFirstElements(lookAheadBuffer, length + 1));
                            for (int i = 0; i < length + 1; i++)
                            {
                                NonePlaceholder.Add(1);
                            }

                            bk              = searchBuffer.Count();
                            searchBuffer    = GetLastElements(searchBuffer, bk - (length + 1));
                            NonePlaceholder = GetLastElements(NonePlaceholder, bk - (length + 1));

                            lookAheadBuffer.AddRange(br.ReadBytes(length + 1));
                            lookAheadBuffer = GetLastElements(lookAheadBuffer, lookAheadBuffer.Count() - (length + 1));
                        }
                    }
                    else
                    {
                        bk              = searchBuffer.Count();
                        searchBuffer    = GetLastElements(searchBuffer, bk - 1);
                        NonePlaceholder = GetLastElements(NonePlaceholder, bk - 1);

                        byte e = lookAheadBuffer[0]; lookAheadBuffer = GetLastElements(lookAheadBuffer, lookAheadBuffer.Count() - 1);

                        searchBuffer.Add(e);
                        NonePlaceholder.Add(1);

                        try
                        {
                            e = br.ReadByte();
                            lookAheadBuffer.Add(e);
                        }
                        catch
                        {
                        }
                    }

                    if (offset != 0)
                    {
                        result.Add(true);
                        result.AddRange(GetBoolArray(offset));
                        result.AddRange(GetBoolArray(length));
                        result.AddRange(GetBoolArray(symbol));
                    }
                    else
                    {
                        result.Add(false);
                        result.AddRange(GetBoolArray(symbol));
                    }
                }

                while (result.Count() % 8 != 0)
                {
                    result.Add(false);
                }

                return(GetByteArray(result));
            }
        }
예제 #18
0
        public SERIParameter ParseSERIParameter(Stream fileData, Stream names, byte[] pointers, string type, string name, int valueOffset, int valuesOffset)
        {
            switch (type)
            {
            case "s":     //String
                names.Position = valueOffset;
                using (var namesB = new BinaryReaderX(names, true))
                    return(new String(name, namesB.ReadCStringA()));

            case "i":     //Integer
                using (var br = new BinaryReaderX(fileData, true))
                {
                    var bk = br.BaseStream.Position;
                    br.BaseStream.Position = valuesOffset + valueOffset;
                    int IntValue = br.ReadInt32();
                    br.BaseStream.Position = bk;

                    switch (name)
                    {
                    case "bone":
                    case "smes":
                    case "smat":
                    case "tex":
                    case "hair_length":
                        using (var pointersB = new BinaryReaderX(new MemoryStream(pointers)))
                            using (var namesB = new BinaryReaderX(names, true))
                            {
                                pointersB.BaseStream.Position = (IntValue - 1) * 4;
                                var tmp = pointersB.ReadInt32();

                                namesB.BaseStream.Position = tmp;
                                return(new String(name, namesB.ReadCStringA()));
                            }

                    default:
                        return(new Integer(name, IntValue));
                    }
                }

            case "b":     //Boolean
                using (var br = new BinaryReaderX(fileData, true))
                {
                    var bk = br.BaseStream.Position;
                    br.BaseStream.Position = valuesOffset + valueOffset;
                    bool BooleanValue = br.ReadByte() == 1;
                    br.BaseStream.Position = bk;

                    return(new Boolean(name, BooleanValue));
                }

            case "f":     //Float
                using (var br = new BinaryReaderX(fileData, true))
                {
                    var bk = br.BaseStream.Position;
                    br.BaseStream.Position = valuesOffset + valueOffset;
                    float FloatValue = br.ReadSingle();
                    br.BaseStream.Position = bk;

                    return(new Float(name, FloatValue));
                }

            case "a":     //Array
                throw new Exception($"Type {type} isn't supported!");

            /*using (var br = new BinaryReaderX(fileData, true))
             * {
             *  var bk = br.BaseStream.Position;
             *  br.BaseStream.Position = valuesOffset + valueOffset;
             *
             *  var array = ParseSERIArray(
             *      br.BaseStream,
             *      names,
             *      pointers,
             *      valuesOffset,
             *      name);
             *
             *  br.BaseStream.Position = bk;
             *  return array;
             * }*/
            default:
                throw new Exception($"Type {type} is unknown!");
            }
        }
예제 #19
0
파일: Yay0.cs 프로젝트: SeeMirra/Kuriimu
        public static byte[] Decompress(Stream instream, ByteOrder byteOrder)
        {
            using (var br = new BinaryReaderX(instream, true, byteOrder))
            {
                #region 16-byte Header
                if (br.ReadString(4) != "Yay0") // "Yay0" Magic
                {
                    throw new InvalidDataException("Invalid Magic, not a Yay0 File");
                }

                int uncompressedSize = br.ReadInt32();
                int linkTableOffset  = br.ReadInt32();
                int byteChunkAndCountModifiersOffset = br.ReadInt32();
                #endregion

                int maskBitCounter            = 0;
                int currentOffsetInDestBuffer = 0;
                int currentMask = 0;

                byte[] uncompressedData = new byte[uncompressedSize];

                br.ByteOrder = ByteOrder.BigEndian;
                do
                {
                    // If we're out of bits, get the next mask.
                    if (maskBitCounter == 0)
                    {
                        currentMask    = br.ReadInt32();
                        maskBitCounter = 32;
                    }

                    // If the next bit is set, the chunk is non-linked and just copy it from the non-link table.
                    if (((uint)currentMask & (uint)0x80000000) == 0x80000000)
                    {
                        var offsetT = br.BaseStream.Position;
                        br.BaseStream.Position = byteChunkAndCountModifiersOffset;
                        uncompressedData[currentOffsetInDestBuffer] = br.ReadByte();
                        br.BaseStream.Position = offsetT;
                        currentOffsetInDestBuffer++;
                        byteChunkAndCountModifiersOffset++;
                    }
                    // Do a copy otherwise.
                    else
                    {
                        // Read 16-bit from the link table
                        var offsetT = br.BaseStream.Position;
                        br.BaseStream.Position = linkTableOffset;
                        ushort link = br.ReadUInt16();
                        br.BaseStream.Position = offsetT;
                        linkTableOffset       += 2;

                        // Calculate the offset
                        int offset = currentOffsetInDestBuffer - (link & 0xfff);

                        // Calculate the count
                        int count = link >> 12;

                        if (count == 0)
                        {
                            byte countModifier;
                            offsetT = br.BaseStream.Position;
                            br.BaseStream.Position = byteChunkAndCountModifiersOffset;
                            countModifier          = br.ReadByte();
                            br.BaseStream.Position = offsetT;
                            byteChunkAndCountModifiersOffset++;
                            count = countModifier + 18;
                        }
                        else
                        {
                            count += 2;
                        }

                        // Copy the block
                        int blockCopy = offset;

                        for (int i = 0; i < count; i++)
                        {
                            uncompressedData[currentOffsetInDestBuffer] = uncompressedData[blockCopy - 1];
                            currentOffsetInDestBuffer++;
                            blockCopy++;
                        }
                    }

                    // Get the next bit in the mask.
                    currentMask <<= 1;
                    maskBitCounter--;
                } while (currentOffsetInDestBuffer < uncompressedSize);

                return(uncompressedData);
            }
        }
예제 #20
0
        public SERIParameter ParseSERIArray(Stream fileData, Stream names, byte[] pointers, int valuesOffset, string name)
        {
            using (var br = new BinaryReaderX(fileData, true))
            {
                var arrayDataType = br.ReadString(1);
                br.BaseStream.Position += 1;
                var     arrayLength = br.ReadInt16();
                short[] pointersA   = br.ReadMultiple <short>(arrayLength).ToArray();

                switch (arrayDataType)
                {
                case "s":      //Of String
                    string[] StringArray = new string[arrayLength];

                    for (int i = 0; i < pointersA.Length; i++)
                    {
                        using (var namesB = new BinaryReaderX(names, true))
                        {
                            namesB.BaseStream.Position = pointersA[i];
                            string ItemName = namesB.ReadCStringA();
                            StringArray[i] = ItemName;
                        }
                    }

                    return(new StringArray(name, StringArray));

                case "i":     //Of Integer
                    switch (name)
                    {
                    case "texi":
                    case "model":
                    case "cloth":
                    case "list":
                        string[] NameArray = new string[arrayLength];

                        for (int i = 0; i < pointersA.Length; i++)
                        {
                            using (var namesB = new BinaryReaderX(names, true))
                                using (var pointersB = new BinaryReaderX(new MemoryStream(pointers)))
                                {
                                    br.BaseStream.Position        = valuesOffset + pointersA[i];
                                    pointersB.BaseStream.Position = (br.ReadInt32() - 1) * 4;
                                    namesB.BaseStream.Position    = pointersB.ReadInt32();
                                    string ItemName = namesB.ReadCStringA();
                                    NameArray[i] = ItemName;
                                }
                        }

                        return(new StringArray(name, NameArray));

                    default:
                        int[] IntArray = new int[arrayLength];

                        for (int i = 0; i < pointersA.Length; i++)
                        {
                            br.BaseStream.Position = valuesOffset + pointersA[i];
                            IntArray[i]            = br.ReadInt32();
                        }

                        return(new IntegerArray(name, IntArray));
                    }

                case "b":     //Of Boolean
                    bool[] BooleanArray = new bool[arrayLength];

                    for (int i = 0; i < pointersA.Length; i++)
                    {
                        br.BaseStream.Position = valuesOffset + pointersA[i];
                        BooleanArray[i]        = br.ReadByte() == 1;
                    }

                    return(new BooleanArray(name, BooleanArray));

                case "f":     //Of Float
                    float[] FloatArray = new float[arrayLength];

                    for (int i = 0; i < pointersA.Length; i++)
                    {
                        br.BaseStream.Position = valuesOffset + pointersA[i];
                        FloatArray[i]          = br.ReadSingle();
                    }

                    return(new FloatArray(name, FloatArray));

                case "h":     //Of Array
                    SERIParameter[] NestedArray = new SERIParameter[arrayLength];

                    for (int i = 0; i < pointersA.Length; i++)
                    {
                        br.BaseStream.Position = valuesOffset + pointersA[i];
                        ushort          Count            = br.ReadUInt16();
                        long            TypesTableOffset = valuesOffset + pointersA[i] + 2 + Count * 4;
                        SERIParameter[] Arrays           = new SERIParameter[Count];
                        for (int Index = 0; Index < Count; Index++)
                        {
                            using (var namesB = new BinaryReaderX(names, true))
                            {
                                br.BaseStream.Position = valuesOffset + pointersA[i] + 2 + Index * 4;
                                ushort NameOffset  = br.ReadUInt16();
                                ushort ValueOffset = br.ReadUInt16();

                                namesB.BaseStream.Position = NameOffset;
                                string ArrayName = namesB.ReadCStringA();

                                br.BaseStream.Seek(TypesTableOffset + Index, SeekOrigin.Begin);
                                string ValueType = br.ReadString(1);

                                Arrays[Index] = ParseSERIParameter(
                                    br.BaseStream,
                                    names,
                                    pointers,
                                    ValueType,
                                    name,
                                    ValueOffset,
                                    valuesOffset);
                            }
                        }

                        NestedArray[i] = new NestedArray(null, Arrays);
                    }

                    return(new NestedArray(name, NestedArray));

                default:
                    throw new Exception($"Type {arrayDataType} is unknown!");
                }
            }
        }
예제 #21
0
파일: Pck.cs 프로젝트: cinnature/Kuriimu2
        public IList <ArchiveFileInfo> Load(Stream input)
        {
            using var br = new BinaryReaderX(input, true);

            // Read file infos
            var fileCount = br.ReadInt32();
            var entries   = br.ReadMultiple <PckFileInfo>(fileCount);

            // Add files
            var result = new List <ArchiveFileInfo>();

            foreach (var entry in entries)
            {
                br.BaseStream.Position = entry.fileOffset;

                // Read hash block before the file data
                var blockOffset = 0;
                var entryHashes = (List <uint>)null;
                var hashIdent   = br.ReadInt16();
                if (hashIdent == 0x64)
                {
                    var hashCount = br.ReadInt16();
                    entryHashes = br.ReadMultiple <uint>(hashCount);

                    blockOffset = (hashCount + 1) * 4;
                }

                // Decide filename
                var fileName = $"{entry.hash:X8}.bin";

                // Add file
                var fileStream = new SubStream(input, entry.fileOffset + blockOffset, entry.fileLength - blockOffset);
                result.Add(new PckArchiveFileInfo(fileStream, fileName, entry, entryHashes));
            }

            return(result);

            //using (var br = new BinaryReaderX(input, true))
            //{
            //    var entries = br.ReadMultiple<Entry>(br.ReadInt32()).ToList();

            //    var dict = (dicts != null) ? dicts.Where(d => d.pckName == Path.GetFileNameWithoutExtension(filename)).ToList() : new List<Dict>();
            //    Files = entries.Select(entry =>
            //    {
            //        br.BaseStream.Position = entry.fileOffset;
            //        var hashes = (br.ReadInt16() == 0x64) ? br.ReadMultiple<uint>(br.ReadInt16()).ToList() : null;
            //        int blockOffset = hashes?.Count + 1 ?? 0;

            //        return new PckFileInfo
            //        {
            //            FileData = new SubStream(
            //                input,
            //                entry.fileOffset + blockOffset * 4,
            //                entry.fileLength - blockOffset * 4),
            //            FileName = (dict.Count > 0) ?
            //                (dict[0].keyValuePairs.Find(kvp => kvp.key == entry.hash) != null ?
            //                    dict[0].keyValuePairs.Find(kvp => kvp.key == entry.hash).value :
            //                    $"0x{entry.hash:X8}.bin") :
            //                $"0x{entry.hash:X8}.bin",
            //            State = ArchiveFileState.Archived,
            //            Entry = entry,
            //            Hashes = hashes
            //        };
            //    }).ToList();
            //}
        }
예제 #22
0
        /// <summary>
        /// Read an MTPA file into memory.
        /// </summary>
        /// <param name="input">A readable stream of an MTPA file.</param>
        public MTPA(Stream input)
        {
            using (var br = new BinaryReaderX(input))
            {
                // Packet Header
                _packetHeader = br.ReadType <PacketHeaderX>();

                // MTPA Header
                _mtpaHeader = br.ReadType <MTPAHeader>();
                var metadataSize = _mtpaHeader.MetadataSize;

                // Unknown MTPA Data
                _mtpaHeaderData = br.ReadMultiple <int>(_mtpaHeader.MetadataSize);

                // Text Metadata Pointers
                _mtpaTextMetadataPointers = br.ReadMultiple <int>(_mtpaHeader.PointerCount);

                // Text Metadata
                if (metadataSize == 2)
                {
                    _mtpaTextMetadata = br.ReadMultiple <TextMetadata>(_mtpaHeader.MetadataCount).ToList <ITextMetadata>();
                }
                else if (metadataSize == 4)
                {
                    _mtpaTextMetadata = br.ReadMultiple <TextMetadataX>(_mtpaHeader.MetadataCount).ToList <ITextMetadata>();
                }

                // Text
                var textStart = (int)br.BaseStream.Position;
                var textEnd   = _packetHeader.DataSize + _packetHeader.HeaderSize;

                for (var i = 0; i < _mtpaHeader.MetadataCount; i++)
                {
                    var offset = textStart;
                    var unused = false;

                    offset += _mtpaTextMetadata[i].Offset;

                    br.BaseStream.Position = offset;
                    var length = br.ReadROTnInt32();

                    if (length == 0)
                    {
                        var currentOffset = _mtpaTextMetadata[i].Offset;
                        unused = true;

                        if (i != _mtpaHeader.MetadataCount - 1)
                        {
                            length = _mtpaTextMetadata[i + 1].Offset - currentOffset - 4;
                        }
                        else
                        {
                            length = textEnd - currentOffset - 4;
                        }
                    }

                    var str = br.ReadROTnBytes(length);

                    Entries.Add(new TextEntry
                    {
                        Name       = _mtpaTextMetadata[i].ID.ToString(),
                        EditedText = Encoding.GetEncoding("shift-jis").GetString(str).Trim('\0'),
                        Notes      = unused ? "Text length was set to zero. This line might be unused." : string.Empty
                    });
                }

                br.BaseStream.Position = textEnd;

                // ENRS
                _enrs = br.ReadType <PacketHeaderX>();
                if (br.BaseStream.Position + _enrs.DataSize + Common.PacketHeaderXSize * 2 <= br.BaseStream.Length)
                {
                    _enrsData   = br.ReadBytes(_enrs.DataSize);
                    _enrsFooter = br.ReadType <PacketHeaderX>();
                }
                else
                {
                    br.BaseStream.Position = br.BaseStream.Length - Common.PacketHeaderXSize;
                }

                // MTPA Footer
                _mtpaFooter = br.ReadType <PacketHeaderX>();
            }
        }
예제 #23
0
        public static FabNode Read(BinaryReaderX br)
        {
            // Read header
            var header = br.ReadType <FabNodeHeader>();

            var result = new FabNode {
                _header = header
            };

            switch (header.magic)
            {
            case "FBRC":
                switch (header.description)
                {
                case "BNDL":
                    var numNode = Read(br);
                    var count   = numNode.AsInt32();

                    result.Nodes.Add(numNode);
                    for (var i = 0; i < count; i++)
                    {
                        result.Nodes.Add(Read(br));
                    }
                    break;

                case "TXTR":
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    break;
                }
                break;

            case "USER":
                var offset1 = br.BaseStream.Position;
                br.BaseStream.Position += (header.size - 4 + 1) & ~1;
                result.Data             = new SubStream(br.BaseStream, offset1, header.size - 4);
                break;

            case "LIST":
                switch (header.description)
                {
                case "FILE":
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    break;

                case "META":
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    result.Nodes.Add(Read(br));
                    break;

                case "DATA":
                    var nextHeader = br.ReadType <FabNodeHeader>();
                    br.BaseStream.Position -= 0xC;

                    // Specially handle USER node to unwrap the "actual" file data from it
                    if (nextHeader.magic == "USER")
                    {
                        result.Nodes.Add(Read(br));
                    }
                    else
                    {
                        var offset2 = br.BaseStream.Position;
                        br.BaseStream.Position += (header.size - 4 + 1) & ~1;
                        result.Data             = new SubStream(br.BaseStream, offset2, header.size - 4);
                    }
                    break;
                }
                break;

            // By default treat content as data
            default:
                var offset = br.BaseStream.Position - 4;
                br.BaseStream.Position += (header.size - 4 + 1) & ~1;

                result._headerLength = 0x8;
                result.Data          = new SubStream(br.BaseStream, offset, header.size);
                break;
            }

            return(result);
        }
예제 #24
0
 public static byte[] Decomp(BinaryReaderX br)
 {
     // above to be restored eventually with some changes to Cetera
     return(Level5.Decompress(br.BaseStream));
 }
예제 #25
0
파일: Cpk.cs 프로젝트: obluda3/Kuriimu2
 private void ReadEtocTable(BinaryReaderX br, long etocOffset)
 {
     _etocTable = CpkTable.Create(br.BaseStream, etocOffset);
 }
예제 #26
0
        static IEnumerable <Color> GetColorsFromTexture(byte[] tex, ImageSettings settings)
        {
            var format = settings.Format;

            using (var br = new BinaryReaderX(new MemoryStream(tex), settings.ByteOrder))
            {
                var etc1decoder = new ETC1.Decoder();

                Enum.TryParse <DXT.Formats>(format.ToString(), false, out var dxtFormat);
                var dxtdecoder = new DXT.Decoder(dxtFormat);

                Enum.TryParse <ATI.Formats>(format.ToString(), false, out var atiFormat);
                var atidecoder = new ATI.Decoder(atiFormat);

                while (true)
                {
                    int a = 255, r = 255, g = 255, b = 255;
                    switch (format)
                    {
                    case Format.L8:
                        b = g = r = br.ReadByte();
                        break;

                    case Format.A8:
                        a = br.ReadByte();
                        break;

                    case Format.LA44:
                        a = br.ReadNibble() * 17;
                        b = g = r = br.ReadNibble() * 17;
                        break;

                    case Format.LA88:
                        if (settings.ByteOrder == ByteOrder.LittleEndian)
                        {
                            a = br.ReadByte();
                            b = g = r = br.ReadByte();
                        }
                        else
                        {
                            b = g = r = br.ReadByte();
                            a = br.ReadByte();
                        }
                        break;

                    case Format.HL88:
                        g = br.ReadByte();
                        r = br.ReadByte();
                        break;

                    case Format.RGB565:
                        var s = br.ReadUInt16();
                        b = (s % 32) * 33 / 4;
                        g = (s >> 5) % 64 * 65 / 16;
                        r = (s >> 11) * 33 / 4;
                        break;

                    case Format.RGB888:
                        b = br.ReadByte();
                        g = br.ReadByte();
                        r = br.ReadByte();
                        break;

                    case Format.RGBA5551:
                        var s2 = br.ReadUInt16();
                        a = (s2 & 1) * 255;
                        b = (s2 >> 1) % 32 * 33 / 4;
                        g = (s2 >> 6) % 32 * 33 / 4;
                        r = (s2 >> 11) % 32 * 33 / 4;
                        break;

                    case Format.RGBA4444:
                        a = br.ReadNibble() * 17;
                        b = br.ReadNibble() * 17;
                        g = br.ReadNibble() * 17;
                        r = br.ReadNibble() * 17;
                        break;

                    case Format.RGBA8888:
                        if (settings.ByteOrder == ByteOrder.LittleEndian)
                        {
                            a = br.ReadByte();
                            b = br.ReadByte();
                            g = br.ReadByte();
                            r = br.ReadByte();
                        }
                        else
                        {
                            r = br.ReadByte();
                            g = br.ReadByte();
                            b = br.ReadByte();
                            a = br.ReadByte();
                        }
                        break;

                    case Format.RGBA1010102:
                        var pack = br.ReadUInt32();
                        r = (int)((pack >> 22) / 4);
                        g = (int)(((pack >> 12) & 0x3FF) / 4);
                        b = (int)(((pack >> 2) & 0x3FF) / 4);
                        a = (int)((pack & 0x3) * 85);
                        break;

                    case Format.ETC1:
                    case Format.ETC1A4:
                        yield return(etc1decoder.Get(() =>
                        {
                            var etc1Alpha = format == Format.ETC1A4 ? br.ReadUInt64() : ulong.MaxValue;
                            return new ETC1.PixelData {
                                Alpha = etc1Alpha, Block = br.ReadStruct <ETC1.Block>()
                            };
                        }));

                        continue;

                    case Format.DXT1:
                    case Format.DXT3:
                    case Format.DXT5:
                        yield return(dxtdecoder.Get(() =>
                        {
                            if (br.BaseStream.Position == br.BaseStream.Length)
                            {
                                return (0, 0);
                            }
                            var dxt5Alpha = format == Format.DXT3 || format == Format.DXT5 ? br.ReadUInt64() : 0;
                            return (dxt5Alpha, br.ReadUInt64());
                        }));

                        continue;

                    case Format.ATI1L:
                    case Format.ATI1A:
                    case Format.ATI2:
                        yield return(atidecoder.Get(() =>
                        {
                            if (br.BaseStream.Position == br.BaseStream.Length)
                            {
                                return (0, 0);
                            }
                            return (br.ReadUInt64(), format == Format.ATI2 ? br.ReadUInt64() : 0);
                        }));

                        continue;

                    case Format.L4:
                        b = g = r = br.ReadNibble() * 17;
                        break;

                    case Format.A4:
                        a = br.ReadNibble() * 17;
                        break;

                    case Format.PVRTC:
                        var bmp = PVRTC.PvrtcDecompress.DecodeRgb4Bpp(tex, settings.Width);
                        for (int y = 0; y < settings.Height; y++)
                        {
                            for (int x = 0; x < settings.Width; x++)
                            {
                                yield return(bmp.GetPixel(x, y));
                            }
                        }
                        continue;

                    case Format.PVRTCA:
                        bmp = PVRTC.PvrtcDecompress.DecodeRgba4Bpp(tex, settings.Width);
                        for (int y = 0; y < settings.Height; y++)
                        {
                            for (int x = 0; x < settings.Width; x++)
                            {
                                yield return(bmp.GetPixel(x, y));
                            }
                        }
                        continue;

                    default:
                        throw new NotSupportedException($"Unknown image format {format}");
                    }
                    yield return(Color.FromArgb(a, r, g, b));
                }
            }
        }