def crc_step(crc_in: int, data: int) -> int:
    """
    CRC polynomial: x^24 + x^23 + x^6 + x^5 + x + 1 (0x800063)
    Width: 24 bits, shift direction: left (big endian), input: 8 bits
    Note: bit invert CRC if calculating OS9 CRC bytes, if checking whole module with CRC bytes
    don't invert and CRC value should be 0x800FE3 if things match, initial crc value is 0xFFFFFF
    Translation from Verilog module
    """
    # Extract individual bits from crc_in
    c = [(crc_in >> i) & 1 for i in range(24)]
    # Extract individual bits from data
    d = [(data >> i) & 1 for i in range(8)]

    crc_out = [0] * 24

    crc_out[0]  = c[16]^c[17]^c[18]^c[19]^c[20]^c[21]^c[22]^c[23]^d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]
    crc_out[1]  = c[16]^d[0]
    crc_out[2]  = c[17]^d[1]
    crc_out[3]  = c[18]^d[2]
    crc_out[4]  = c[19]^d[3]
    crc_out[5]  = c[16]^c[17]^c[18]^c[19]^c[21]^c[22]^c[23]^d[0]^d[1]^d[2]^d[3]^d[5]^d[6]^d[7]
    crc_out[6]  = c[16]^c[21]^d[0]^d[5]
    crc_out[7]  = c[17]^c[22]^d[1]^d[6]
    crc_out[8]  = c[0]^c[18]^c[23]^d[2]^d[7]
    crc_out[9]  = c[1]^c[19]^d[3]
    crc_out[10] = c[2]^c[20]^d[4]
    crc_out[11] = c[3]^c[21]^d[5]
    crc_out[12] = c[4]^c[22]^d[6]
    crc_out[13] = c[5]^c[23]^d[7]
    crc_out[14] = c[6]
    crc_out[15] = c[7]
    crc_out[16] = c[8]
    crc_out[17] = c[9]
    crc_out[18] = c[10]
    crc_out[19] = c[11]
    crc_out[20] = c[12]
    crc_out[21] = c[13]
    crc_out[22] = c[14]
    crc_out[23] = c[15]^c[16]^c[17]^c[18]^c[19]^c[20]^c[21]^c[22]^c[23]^d[0]^d[1]^d[2]^d[3]^d[4]^d[5]^d[6]^d[7]

    # Recombine bits into a 24-bit integer
    return sum(bit << i for i, bit in enumerate(crc_out))


def compute_crc(octets: bytes, crc: int = 0xFFFFFF) -> int:
    for byte in octets:
        crc = crc_step(crc, byte)
    return (crc & 0xFFFFFF)  ^ 0xFFFFFF


# CLI usage
if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="Compute 24-bit CRC of a binary file.")
    parser.add_argument("file", help="Path to the binary file")
    parser.add_argument("--init", type=lambda x: int(x, 0), default=0xFFFFFF,
                        help="Initial CRC value (default: 0xFFFFFF)")
    args = parser.parse_args()

    with open(args.file, "rb") as f:
        data = f.read()

    result = compute_crc(data, args.init)
    print(f"CRC: {result:#08x}")