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); }