#!/usr/bin/env python3 """ Интерактивный скрипт распаковки текстов из игр на CatSystem2. Извлекает только .cst и .cstl файлы, учитывая порядок файлов обновлений. """ import subprocess import sys import shutil import tempfile from pathlib import Path # Путь к утилите exkifint_v3.exe BASE_DIR = Path(__file__).resolve().parent TOOL_EXE = BASE_DIR / "tool" / "exkifint_v3.exe" def clean_path(user_input: str) -> Path: return Path(user_input.strip().strip('"').strip("'")) def main(): if not TOOL_EXE.exists(): print(f"Ошибка: Исполняемый файл утилиты не найден: {TOOL_EXE}") sys.exit(1) # 1. Запрос пути к папке с игрой game_dir_input = input("Укажите путь к папке с игрой: ") game_dir = clean_path(game_dir_input) if not game_dir.is_dir(): print(f"Ошибка: Папка '{game_dir}' не существует.") sys.exit(1) # 2. Поиск exe-файлов и выбор exe_files = list(game_dir.glob("*.exe")) if not exe_files: print("В указанной папке не найдено .exe файлов!") sys.exit(1) print("\nНайденные исполняемые файлы:") for i, exe in enumerate(exe_files, 1): print(f"[{i}] {exe.name}") exe_choice = input("\nУкажите цифру нужного exe и нажмите Enter: ").strip() try: exe_index = int(exe_choice) - 1 if exe_index < 0 or exe_index >= len(exe_files): raise ValueError selected_exe = exe_files[exe_index] except ValueError: print("Ошибка: Неверный выбор.") sys.exit(1) # 3. Название папки вывода out_name = input("\nНазвание папки куда складывать извлечённые файлы [update00 по умолчанию]: ").strip() if not out_name: out_name = "update00" # Значение по умолчанию out_dir = BASE_DIR / out_name text_dir = out_dir / "text" loc_dir = out_dir / "localized_text" # Создаем целевые папки text_dir.mkdir(parents=True, exist_ok=True) loc_dir.mkdir(parents=True, exist_ok=True) # Список базовых архивов и апдейтов в порядке приоритета (как в unpack.py) target_archives = ["scene.int", "fes.int", "config.int"] for i in range(20): # Добавляем update00.int - update19.int target_archives.append(f"update{i:02d}.int") print(f"\nНачинаю извлечение текста. Папка вывода: {out_dir}") cst_count = 0 cstl_count = 0 # 4. Распаковка во временную папку для фильтрации # Используем tempfile, чтобы мусор автоматически удалился после завершения with tempfile.TemporaryDirectory() as temp_dir: temp_path = Path(temp_dir) # Распаковываем архивы по очереди. Файлы из апдейтов будут # перезаписывать базовые во временной папке. for archive_name in target_archives: archive_path = game_dir / archive_name if archive_path.exists(): print(f"Обработка архива: {archive_name}...") cmd = [str(TOOL_EXE), str(archive_path), str(selected_exe)] subprocess.run( cmd, cwd=str(temp_path), capture_output=True, text=True, encoding="cp1251", errors="replace" ) # 5. Поиск и перенос только нужных текстовых форматов print("Сортировка извлеченных файлов...") for file in temp_path.rglob("*"): if file.is_file(): if file.suffix.lower() == ".cst": shutil.copy2(file, text_dir / file.name) cst_count += 1 elif file.suffix.lower() == ".cstl": shutil.copy2(file, loc_dir / file.name) cstl_count += 1 # Временная папка со всем нетекстовым мусором автоматически удаляется здесь print(f"\nГотово!") print(f"Извлечено .cst файлов: {cst_count} -> {text_dir}") print(f"Извлечено .cstl файлов: {cstl_count} -> {loc_dir}") if __name__ == "__main__": main()