#!/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 create_padded_section(data, target_size, pattern, offset=0):
    """
    Создает секцию заданного размера с заполнением паттерном.
    """
    section = bytearray()
    
    # Добавляем смещение (нули)
    section.extend(bytes(offset))
    
    # Добавляем данные
    section.extend(data)
    
    # Проверяем размер
    current_pos = offset + len(data)
    if current_pos > target_size:
        raise ValueError(f"Размер данных с учетом смещения ({current_pos} байт) превышает размер секции ({target_size} байт)")
    
    # Заполняем оставшееся место паттерном
    remaining_size = target_size - current_pos
    full_patterns = remaining_size // len(pattern)
    remainder = remaining_size % len(pattern)
    
    for _ in range(full_patterns):
        section.extend(pattern)
    
    if remainder:
        section.extend(pattern[:remainder])
        
    return section

def main():
    parser = argparse.ArgumentParser(description='Создание XCT контейнера из двух BIN файлов')
    parser.add_argument('bct_bin', help='Входной файл для BCT зоны (расширение .bin)')
    parser.add_argument('wct_bin', help='Входной файл для WCT зоны (расширение .bin)')
    parser.add_argument('--bct-offset', type=int, default=0,
                       help='Начальное смещение в BCT зоне (по умолчанию: 0)')
    parser.add_argument('--wct-offset', type=int, default=0,
                       help='Начальное смещение в WCT зоне (по умолчанию: 0)')
    parser.add_argument('--crc-init', type=lambda x: int(x, 0), default=0xEDB88320,
                       help='Начальное значение для CRC в hex (по умолчанию: 0xEDB88320)')
    
    args = parser.parse_args()
    
    # Проверки существования файлов
    for fpath in [args.bct_bin, args.wct_bin]:
        if not os.path.exists(fpath):
            print(f"Ошибка: Файл '{fpath}' не найден")
            sys.exit(1)
        if not fpath.lower().endswith('.bin'):
            print(f"Ошибка: Файл '{fpath}' должен иметь расширение .bin")
            sys.exit(1)
            
    # Проверка смещений
    if args.bct_offset < 0 or args.wct_offset < 0:
        print("Ошибка: Смещение не может быть отрицательным")
        sys.exit(1)

    try:
        # Размеры зон
        BCT_SIZE = 122880
        WCT_SIZE = 1048576
        
        # Чтение входных файлов
        with open(args.bct_bin, 'rb') as f:
            bct_bin_data = f.read()
        with open(args.wct_bin, 'rb') as f:
            wct_bin_data = f.read()
            
        # Создание BCT секции
        bct_pattern = bytes([0x39, 0xE3])
        bct_section = create_padded_section(bct_bin_data, BCT_SIZE, bct_pattern, args.bct_offset)
        
        # Создание WCT секции
        wct_pattern = bytes([0xFF, 0xFF])
        wct_section = create_padded_section(wct_bin_data, WCT_SIZE, wct_pattern, args.wct_offset)
        
        # Формирование полного контейнера XCT
        xct_data = bytearray()
        xct_data.extend(bct_section)
        xct_data.extend(wct_section)
        
        # Расчет CRC32 для всего контейнера
        crc = calculate_crc32(xct_data, args.crc_init)
        
        # Создание имени файла
        crc_hex = f"{crc:08X}"
        output_file = f"{crc_hex}.xct"
        
        # Сохранение файла
        with open(output_file, 'wb') as f:
            f.write(xct_data)
            
        # Вывод информации
        print(f"Файл успешно создан: {output_file}")
        print(f"Размер выходного файла: {len(xct_data)} байт")
        print(f"  - BCT зона: {BCT_SIZE} байт (смещение: {args.bct_offset}, данные: {len(bct_bin_data)} байт)")
        print(f"  - WCT зона: {WCT_SIZE} байт (смещение: {args.wct_offset}, данные: {len(wct_bin_data)} байт)")
        print(f"Инициализация CRC: 0x{args.crc_init:08X}")
        print(f"Рассчитанная CRC32: 0x{crc_hex}")
        
    except ValueError as e:
        print(f"Ошибка размера данных: {e}")
        sys.exit(1)
    except Exception as e:
        print(f"Ошибка при обработке файла: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()