#!/bin/bash

if [ -z "$1" ]; then
    echo "Usage: $0 <fichier_binaire>"
    exit 1
fi

TARGET_FILE="$1"

# 1. Sauvegarde de sécurité
cp "$TARGET_FILE" "${TARGET_FILE}.bak"
echo "[*] Sauvegarde créée : ${TARGET_FILE}.bak"

# 2. Exécution des patchs d'instructions (Python)
echo "[*] Application des patchs d'instructions (Détection N0120 / N0115)..."
python3 -c "
import sys
import struct

file_path = sys.argv[1]
with open(file_path, 'rb') as f:
    data = bytearray(f.read())

patched_p1 = False

# --- 1er PATCH : Version N0120 (2 octets NOP) ---
patterns_n0120 = [
    (b'\x30\x62\x00\x21\xF2\x6B\x07\x20', 'N0120 Pattern 1.1 (30 62)'),
    (b'\x20\x62\x00\x21\xE2\x6B\x07\x20', 'N0120 Pattern 1.2 (20 62)')
]
for pattern, name in patterns_n0120:
    offset = data.find(pattern)
    if offset != -1:
        data[offset:offset+2] = b'\x00\xBF'
        if offset + 14 <= len(data):
            data[offset+12:offset+14] = b'\x00\xBF'
            print(f'[+] Matériel détecté : Numworks N0120')
            print(f'[+] {name} patché (NOPs insérés).')
            patched_p1 = True
            break

# --- 1er PATCH : Version N0115 (4 octets NOP, offset + 18) ---
# Si le pattern N0120 n'a pas été trouvé, on cherche celui du N0115
if not patched_p1:
    # Pattern : C5 F8 14 0C 10 21 D5 F8 -> En binaire : \xC5\xF8\x14\x0C\x10\x21\xD5\xF8
    pattern_n0115 = b'\xC5\xF8\x14\x0C\x10\x21\xD5\xF8'
    offset_n0115 = data.find(pattern_n0115)
    
    if offset_n0115 != -1:
        print(f'[+] Matériel détecté : Numworks N0115')
        
        # Écriture de 2 NOPs (4 octets) à l'offset de base
        data[offset_n0115:offset_n0115+4] = b'\x00\xBF\x00\xBF'
        
        # Écriture de 2 NOPs (4 octets) à l'offset + 18
        offset_2 = offset_n0115 + 18
        if offset_2 + 4 <= len(data):
            data[offset_2:offset_2+4] = b'\x00\xBF\x00\xBF'
            print(f'[+] Pattern N0115 patché (4 octets NOP en 0x{offset_n0115:X} et 0x{offset_2:X}).')
            patched_p1 = True
        else:
            print('[-] Erreur : L\'offset + 18 pour N0115 dépasse la taille du fichier.')

if not patched_p1:
    print('[-] Attention : Aucun pattern pour le 1er patch (N0120 ou N0115) n\'a été trouvé.')


# --- 2ème PATCH : BL 0xBC00 dynamique (Commun ou à vérifier selon le modèle) ---
pattern_p2 = b'\x6B\x46\x10\x68\x51\x68'
offset_p2 = data.find(pattern_p2)

if offset_p2 != -1:
    patch_address = offset_p2 + 22
    target_address = 0xBC00
    pc_address = patch_address + 4
    jump_offset = target_address - pc_address
    
    # Encodage ARM Thumb-2 BL
    jump_val = jump_offset >> 1
    S = 1 if jump_val < 0 else 0
    if jump_val < 0:
        jump_val = (1 << 24) + jump_val 
        
    I1 = (jump_val >> 22) & 1
    I2 = (jump_val >> 21) & 1
    J1 = int(not (I1 ^ S))
    J2 = int(not (I2 ^ S))
    
    imm10 = (jump_val >> 11) & 0x3FF
    imm11 = jump_val & 0x7FF
    
    first_half = 0xF000 | (S << 10) | imm10
    second_half = 0xF800 | (J1 << 13) | (J2 << 11) | imm11
    
    bl_bytes = struct.pack('<HH', first_half, second_half)
    
    if patch_address + 4 <= len(data):
        data[patch_address:patch_address+4] = bl_bytes
        print(f'[+] Patch 2 appliqué à l\'offset 0x{patch_address:X} (BL 0xBC00)')
        
        # On ne sauvegarde que si au moins un des patchs a fonctionné
        with open(file_path, 'wb') as f:
            f.write(data)
    else:
        print('[-] Erreur : L\'offset du BL dépasse la taille du fichier.')
else:
    print('[-] Pattern 2 (BL) non trouvé.')
" "$TARGET_FILE"

# 3. Injection du code et des ressources (dd)
echo "[*] Injection du code et des ressources en 0xBC00+..."

if [ -f "main115.bin" ] && [ -f "image.bin" ] && [ -f "about.bin" ]; then
    dd if=main115.bin of="$TARGET_FILE" bs=1 seek=48128 conv=notrunc 2>/dev/null
    dd if=image.bin of="$TARGET_FILE" bs=1 seek=49344 conv=notrunc 2>/dev/null
    dd if=about.bin of="$TARGET_FILE" bs=1 seek=50992 conv=notrunc 2>/dev/null
    echo "[+] Code et ressources injectés avec succès !"
    python3 -c "
import sys
import struct

file_path = sys.argv[1]
with open(file_path, 'rb') as f:
    data = bytearray(f.read())

patterns_screen = [
    (b'\x08\xB5\x01\x22\x00\x21\x06\x48', 'Screen 115'),
    (b'\x08\xB5\x01\x22\x03\x21\x06\x48', 'Screen 120')
]

for pattern, name in patterns_screen:
    offset = data.find(pattern)
    print(name,offset)
    if offset!=-1 and name=='Screen 115':
        data[0xbc04:0xbc06] = b'\x00\xBF'
        data[0xbdf0] = (offset+1) % 256
        data[0xbdf1] = (offset//256) % 256
        print(f'[+] {name} patché avec succès.')
        # Sauvegarde du fichier modifié
        with open(file_path, 'wb') as f:
            f.write(data)

" "$TARGET_FILE"
else
    echo "[-] Erreur : Fichiers ressources manquants pour l'injection dd."
    exit 1
fi

echo "[+] Processus de patch terminé !"
