public override bool Disassemble(Disassembler dis, int idx, out string output)
            {
                output = null;

                var setTimg = GetCmd <GSetTImg>(dis, idx++);

                if (setTimg.fmt != G_IM_FMT.G_IM_FMT_RGBA || setTimg.width != 1)
                {
                    return(false);
                }

                idx++; // G_RDPTILESYNC

                var setTile = GetCmd <GSetTile>(dis, idx++);

                idx++; // G_RDPLOADSYNC

                var loadTlut = GetCmd <GLoadTlut>(dis, idx++);

                idx++; // G_RDPPIPESYNC

                output = $"gsDPLoadTLUT({loadTlut.count + 1}, 0x{setTile.tmem:X}, {dis.DisAddress(setTimg.imgaddr)})";
                return(true);
            }
 protected T GetCmd <T>(Disassembler dis, int idx) => dis._dlist.AtIndex(idx).cmd.Convert <T>();
 public abstract bool Disassemble(Disassembler dis, int idx, out string output);
            public override bool Disassemble(Disassembler dis, int idx, out string output)
            {
                output = null;

                var setTimg = GetCmd <GSetTImg>(dis, idx++);

                if (setTimg.width != 1)
                {
                    return(false);
                }

                var setTile = GetCmd <GSetTile>(dis, idx++);

                idx++; // G_RDPLOADSYNC

                var loadBlock = GetCmd <GLoadBlock>(dis, idx++);

                idx++; // G_RDPPIPESYNC

                var setTile2 = GetCmd <GSetTile>(dis, idx++);

                var setTileSize = GetCmd <GLoadTile>(dis, idx++);

                var       timg   = setTimg.imgaddr;
                var       fmt    = setTile2.fmt;
                var       siz    = setTile2.siz;
                int       width  = (int)(setTileSize.lrs.IntPart() + 1);
                int       height = (int)(setTileSize.lrt.IntPart() + 1);
                var       pal    = setTile2.palette;
                var       cmt    = setTile2.cmT;
                var       maskt  = setTile2.maskT;
                var       shiftt = setTile2.shiftT;
                var       cms    = setTile2.cmS;
                var       masks  = setTile2.maskS;
                var       shifts = setTile2.shiftS;
                int       tmem   = setTile2.tmem;
                G_TX_TILE rtile  = setTile2.tile;

                if (
                    setTimg.fmt == fmt &&
                    setTimg.siz == SizLoadBlock(siz) &&
                    setTimg.width == 1 &&

                    setTile.fmt == fmt &&
                    setTile.siz == SizLoadBlock(siz) &&
                    setTile.line == 0 &&
                    setTile.tmem == tmem &&
                    setTile.tile == G_TX_TILE.G_TX_LOADTILE &&
                    setTile.palette == 0 &&
                    setTile.cmT == cmt && setTile.maskT == maskt && setTile.shiftT == shiftt &&
                    setTile.cmS == cms && setTile.maskS == masks && setTile.shiftS == shifts &&

                    loadBlock.tile == G_TX_TILE.G_TX_LOADTILE &&
                    loadBlock.uls.Raw == 0 && loadBlock.ult.Raw == 0 &&
                    loadBlock.texels == ((width * height + SizIncr(siz)) >> SizShift(siz)) - 1 &&
                    //(loadBlock.dxt.Raw == 0 || loadBlock.dxt.Raw == CalcDxt(width, SizBytes(siz))) &&

                    //setTile2.line == ((width * SizLineBytes(siz)) + 7) >> 3 &&

                    setTileSize.uls.Raw == 0 && setTileSize.ult.Raw == 0
                    )
                {
                    string s = loadBlock.dxt.Raw == 0 ? "S" : "";

                    if (siz == G_IM_SIZ.G_IM_SIZ_4b)
                    {
                        if ((loadBlock.dxt.Raw == 0 || loadBlock.dxt.Raw == CalcDxt_4b(width)) &&
                            setTile2.line == ((width >> 1) + 7) >> 3)
                        {
                            output = (tmem == 0 && rtile == G_TX_TILE.G_TX_RENDERTILE)
                               ? $"gsDPLoadTextureBlock_4b{s}({dis.DisAddress(timg)}, {fmt}, {width}, {height}, {pal}, {DisTexWrap(cms)}, {DisTexWrap(cmt)}, {masks}, {maskt}, {shifts}, {shiftt})"
                               : $"gsDPLoadMultiBlock_4b{s}({dis.DisAddress(timg)}, 0x{tmem:X}, {rtile}, {fmt}, {width}, {height}, {pal}, {DisTexWrap(cms)}, {DisTexWrap(cmt)}, {masks}, {maskt}, {shifts}, {shiftt})";
                        }
                    }
                    else
                    {
                        if ((loadBlock.dxt.Raw == 0 || loadBlock.dxt.Raw == CalcDxt(width, SizBytes(siz))) &&
                            setTile2.line == ((width * SizLineBytes(siz)) + 7) >> 3)
                        {
                            output = (tmem == 0 && rtile == G_TX_TILE.G_TX_RENDERTILE)
                               ? $"gsDPLoadTextureBlock{s}({dis.DisAddress(timg)}, {fmt}, {siz}, {width}, {height}, {pal}, {DisTexWrap(cms)}, {DisTexWrap(cmt)}, {masks}, {maskt}, {shifts}, {shiftt})"
                               : $"gsDPLoadMultiBlock{s}({dis.DisAddress(timg)}, 0x{tmem:X}, {rtile}, {fmt}, {siz}, {width}, {height}, {pal}, {DisTexWrap(cms)}, {DisTexWrap(cmt)}, {masks}, {maskt}, {shifts}, {shiftt})";
                        }
                    }
                }

                if (output == null)
                {
                    Debug.WriteLine("weird LoadTextureBlock detected");
                }

                return(output != null);
            }