#!/usr/bin/env python3
import os
import sys
import argparse

def calculate_crc32(buf, init_value=0xEDB88320):
    """
    Расчет CRC32 по алгоритму, аналогичному C-функции fullcalk_crc32
    """
    crc = 0xFFFFFFFF
    
    for byte in buf:
        val = (crc ^ byte) & 0xFF
        
        for _ in range(8):
            if val & 1:
                val = (val >> 1) ^ init_value
            else:
                val = val >> 1
        
        crc = val ^ (crc >> 8)
    
    return crc ^ 0xFFFFFFFF

def main():
    parser = argparse.ArgumentParser(description='Создание BCT файла из BIN файла')
    parser.add_argument('input_file', help='Входной файл с расширением .bin')
    parser.add_argument('--offset', '-o', type=int, default=0,
                       help='Начальное смещение в файле .bct (по умолчанию: 0)')
    parser.add_argument('--crc-init', type=lambda x: int(x, 0), default=0xEDB88320,
                       help='Начальное значение для CRC в hex (по умолчанию: 0xEDB88320)')
    
    args = parser.parse_args()
    
    # Проверяем расширение файла
    if not args.input_file.lower().endswith('.bin'):
        print(f"Ошибка: Файл должен иметь расширение .bin")
        sys.exit(1)
    
    # Проверяем существование файла
    if not os.path.exists(args.input_file):
        print(f"Ошибка: Файл '{args.input_file}' не найден")
        sys.exit(1)
    
    # Проверяем, что смещение не отрицательное
    if args.offset < 0:
        print(f"Ошибка: Смещение не может быть отрицательным")
        sys.exit(1)
    
    try:
        # Читаем входной бинарный файл
        with open(args.input_file, 'rb') as f:
            bin_data = f.read()
        
        # Размер BCT файла (122880 байт)
        bct_size = 122880
        
        # Создаем BCT данные в памяти
        bct_data = bytearray()
        
        # 1. Заполняем начало файла нулями до указанного смещения
        bct_data.extend(bytes(args.offset))
        
        # 2. Копируем данные из .bin файла
        bct_data.extend(bin_data)
        
        # 3. Заполняем оставшееся пространство (если есть)
        current_pos = args.offset + len(bin_data)
        
        # Проверяем, не превышает ли размер BIN допустимый размер
        if current_pos > bct_size:
            print(f"Ошибка: Размер BIN файла ({len(bin_data)} байт) слишком большой")
            print(f"Максимальный размер BIN для BCT при смещении {args.offset}: {bct_size - args.offset} байт")
            sys.exit(1)
        
        # Заполняем оставшееся пространство шаблоном 0x39, 0xE3
        remaining_size = bct_size - current_pos
        
        # Создаем паттерн для заполнения
        pattern = bytes([0x39, 0xE3])
        
        # Вычисляем сколько раз нужно повторить паттерн
        full_patterns = remaining_size // 2
        remainder = remaining_size % 2
        
        # Заполняем полными паттернами
        for _ in range(full_patterns):
            bct_data.extend(pattern)
        
        # Если есть остаток (нечетный байт), добавляем 0x39
        if remainder:
            bct_data.append(0x39)
        
        # 4. Расчет CRC32 для всего BCT файла
        crc = calculate_crc32(bct_data, args.crc_init)
        
        # 5. Создаем имя файла на основе CRC
        crc_hex = f"{crc:08X}"  # 8 символов в верхнем регистре
        output_file = f"{crc_hex}.bct"
        
        # 6. Сохраняем файл с именем CRC
        with open(output_file, 'wb') as f:
            f.write(bct_data)
        
        print(f"Файл успешно создан: {output_file}")
        print(f"Размер выходного файла: {len(bct_data)} байт")
        print(f"Размер исходного BIN: {len(bin_data)} байт")
        print(f"Начальное смещение: {args.offset} байт")
        print(f"Инициализация CRC: 0x{args.crc_init:08X}")
        print(f"Рассчитанная CRC32: 0x{crc_hex}")
        print(f"Свободное место заполнено паттерном 0x39 0xE3")
        
    except Exception as e:
        print(f"Ошибка при обработке файла: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()