116 lines
4.8 KiB
Python
116 lines
4.8 KiB
Python
#!/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() |