Загрузка данных
import os
import json
import struct
import re
# Точный путь к твоим JSON
JSON_FOLDER = os.path.expanduser("~/Downloads/files/original/json_output")
OUTPUT_FOLDER = "romfs/SCRIPT"
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
if not os.path.exists(JSON_FOLDER):
JSON_FOLDER = "files/original/json_output"
if not os.path.exists(JSON_FOLDER):
print("ОШИБКА: Папка с JSON не найдена!")
exit()
print("=== ЗАПУСК УМНОЙ СБОРКИ РУСИФИКАTOPA ===")
total_built = 0
# Функция для поиска первой группы цифр в названии файла (например, '203')
def get_file_number(name):
match = re.search(r'\d+', name)
return match.group(0) if match else None
# Составляем карту JSON файлов по их номерам
json_map = {}
for j_name in os.listdir(JSON_FOLDER):
if j_name.lower().endswith(".json"):
num = get_file_number(j_name)
if num:
json_map[num] = os.path.join(JSON_FOLDER, j_name)
# Перебираем файлы в текущей папке
for file_name in os.listdir("."):
# Игнорируем сам скрипт и системные файлы
if os.path.isfile(file_name) and not file_name.endswith(".py") and file_name != "README.txt":
num = get_file_number(file_name)
# Если нашли совпадение по номеру — шьем перевод прямо в этот файл!
if num and num in json_map:
json_path = json_map[num]
with open(file_name, "rb") as f:
data = bytearray(f.read())
with open(json_path, "r", encoding="utf-8") as jf:
try:
translations = json.load(jf)
except Exception as e:
print(f"Ошибка чтения JSON {num}: {e}")
continue
items = []
for addr_str, text in translations.items():
# Вытаскиваем HEX-адрес из скобок [0x...]
addr_hex = addr_str.replace("[0x", "").replace("]", "")
offset = int(addr_hex, 16)
items.append((offset, text))
# Сортировка с конца к началу (чтобы сдвиги байт не ломали адреса)
items.sort(key=lambda x: x[0], reverse=True)
for offset, text in items:
# Кодируем русский в UTF-8 для Nintendo Switch
new_bytes = text.encode('utf-8') + b'\x00'
orig_len = 0
# Считаем длину оригинального текста в байтах до \x00
while (offset + orig_len) < len(data) and data[offset + orig_len] != 0:
orig_len += 1
orig_len += 1
if (offset + orig_len) <= len(data):
data[offset : offset + orig_len] = new_bytes
# Самый главный технический шаг: пересчитываем HEX-числа указателей движка
diff = len(new_bytes) - orig_len
if diff != 0:
for i in range(0, len(data) - 4, 4):
val = struct.unpack("<I", data[i:i+4])[0]
if val > offset and val < len(data):
data[i:i+4] = struct.pack("<I", val + diff)
# Сохраняем файл строго под расширением .DAT (как просит STORY.cpk игры)
out_name = f"{num}.DAT"
with open(os.path.join(OUTPUT_FOLDER, out_name), "wb") as out:
out.write(data)
total_built += 1
print(f"[{total_built}] Успешно собран файл русификатора: {out_name}")
print(f"\n=== СБОРКА ИЗ ТЕКСТОВЫХ ФАЙЛОВ ЗАВЕРШЕНА! ===")
print(f"Всего создано файлов в папке '{OUTPUT_FOLDER}': {total_built}")