public static byte[] Compress(ByteArrayStream target)
        {
            var commands = new List <byte>();
            var data     = new List <byte>();
            var copyData = 0;

            while (!target.AtEnd)
            {
                var term       = target.GetBytes(0x11);
                var copyOutput = 0;
                var copyOffset = -1;

                while (term.Length >= 3)
                {
                    var(found, address) = target.FindLastInWindow(term, target.Address - 256, target.Address + term.Length - 1);

                    if (found)
                    {
                        copyOutput = term.Length - 2;
                        copyOffset = target.Address - address - 1;
                        break;
                    }

                    term = target.GetBytes(term.Length - 1);
                }

                if (copyOutput == 0)
                {
                    if (copyData == 0xf)
                    {
                        commands.Add((byte)copyData);
                        copyData = 1;
                    }
                    else
                    {
                        copyData++;
                    }
                    data.Add(target.Byte());
                }
                else
                {
                    commands.Add((byte)((copyOutput << 4) + copyData));
                    commands.Add((byte)copyOffset);
                    copyData        = 0;
                    target.Address += term.Length;
                }
            }

            // Add last copy data command
            if (copyData != 0)
            {
                commands.Add((byte)copyData);
            }

            // Add terminating command
            commands.Add(0);

            var output = new ByteArrayStream(commands.Count + data.Count + 2);

            var dataOffset = commands.Count;

            if (dataOffset > 0xffff)
            {
                throw new Exception($"{nameof(dataOffset)} cannot be larger than 0xffff. {nameof(commands)} is too large");
            }

            output.Word((ushort)dataOffset);
            output.Write(commands);
            output.Write(data);

            return(output.Buffer);
        }