import sys

def calculate_offsets_from_mcuid(mcuid):
    """
    Calcule les offsets de modification à partir du MCUID.
    :param mcuid: MCUID sous forme de chaîne hexadécimale (32 caractères)
    :return: Liste des offsets calculés
    """
    if len(mcuid) != 32:
        raise ValueError("Le MCUID doit contenir exactement 32 caractères hexadécimaux.")

    mcuid_bytes = bytes.fromhex(mcuid)
    
    # Calcul des valeurs dérivées du MCUID
    mcuid_sum = sum(mcuid_bytes)
    mcuid_xor = 0
    for b in mcuid_bytes:
        mcuid_xor ^= b

    # Définition des offsets principaux basés sur le MCUID
    offset1 = (mcuid_sum * 3440) % 0x800000  # Normalisation pour rester dans la plage
    offset2 = (mcuid_xor * 61800) % 0x800000  # Normalisation

    return [offset1, offset2]

def apply_immo_off_patch(data, mcuid):
    """
    Applique la correction IMMO OFF sur un fichier binaire en fonction du MCUID.
    :param data: Bytes du fichier original
    :param mcuid: MCUID sous forme de chaîne hexadécimale
    :return: Bytes modifiés
    """
    data = bytearray(data)
    offsets = calculate_offsets_from_mcuid(mcuid)

    # Patch 1 : Désactivation de l'IMMO à l'offset calculé
    patch1 = [(offsets[0], 0x00), (offsets[0] + 1, 0x00), (offsets[0] + 2, 0x00), (offsets[0] + 3, 0x00)]
    
    # Patch 2 : Modifications des paramètres IMMO
    patch2 = [
        (offsets[1], 0x91), (offsets[1] + 1, 0x00), (offsets[1] + 2, 0xF1), (offsets[1] + 3, 0xFA),
        (offsets[1] + 4, 0x19), (offsets[1] + 6, 0x04), (offsets[1] + 7, 0x01), (offsets[1] + 8, 0x91),
        (offsets[1] + 9, 0x30), (offsets[1] + 11, 0xF6), (offsets[1] + 12, 0x7B), (offsets[1] + 13, 0x40)
    ]

    # Appliquer les modifications
    for addr, value in patch1 + patch2:
        if 0 <= addr < len(data):  # Vérifier que l'offset est dans la plage valide
            data[addr] = value
    
    return bytes(data)

if __name__ == "__main__":
    if len(sys.argv) != 4:
        print("Usage: python3 md1cs003.py <input_file> <output_file> <MCUID>")
        sys.exit(1)

    input_file = sys.argv[1]
    output_file = sys.argv[2]
    mcuid = sys.argv[3]

    try:
        # Lire le fichier original
        with open(input_file, "rb") as f:
            original_data = f.read()

        # Appliquer l'IMMO OFF
        modified_data = apply_immo_off_patch(original_data, mcuid)

        # Sauvegarder le fichier modifié
        with open(output_file, "wb") as f:
            f.write(modified_data)

        print(f"IMMO OFF appliqué avec succès ! Fichier sauvegardé : {output_file}")

    except Exception as e:
        print(f"Erreur : {e}")
        sys.exit(1)
