Перевод игр для NES

Итак, в вас проснулся творческий потенциал и хочется перевести игру? Или, как у меня, просто желание узнать, как это делается в теории?

Тогда читайте дальше.

В отличие от современных игр (и то, не всегда), в играх для классических приставок вся информация записывалась в один единственный ром, то есть нечитаемый для человека бинарный набор. Не было никаких отдельных файлов с текстами, отдельной графики, которые можно было бы отредактировать. Вся информация была сжата в один маленький ромчик и зачастую программистам приходилось очень экономить и ухищряться, чтобы запихнуть все целиком. Поэтому тексты игр обычно были где-то спрятаны и закодированы так, что прочитать их было не так-то просто (ведь программисты не использовали стандартные кодировки и не использовали текстовые файлы). Хотя текстовые файлы тех времён могли использовать кодировку (ещё была проблема с кучей языков и их поддержкой), но в игре было все немного сложнее и одновременно проще. У вас была картинка для буквы (тайл) и код для этой буквы. Этот код не имел ничего общего с буквами в текстовых файлах. Просто значение и игра сама как-то знала, что если стоит этот код, то он соответствует такой-то букве (картинке). Весь смысл перевода заключается в трёх пунктах:

  • Понять, какие значения кодируют какие буквы
  • Найти эти буквы в графике и перерисовать
  • Переписать тексты на свой язык, используя новые связки код-буква.

Давайте возьмём в пример игру Excitebike. В ней есть немного текста, который можно перевести.

Во-первых, нужно как-то узнать, какие коды (шестнадцатеричные значения) соответствуют буквам вообще. Ведь мы видим на экране слово NINTENDO, значит оно где-то должно быть в файле. Но это не всегда так. Иногда в игре вы видите текст, но он не собран из букв, а просто является рисунком. Тогда искать бесполезно и нужно искать сам рисунок и переделывать его. Но, в принципе, если видишь какой-то текст часто и в одинаковой форме, то скорее всего он собран из букв.
Теперь надо найти эти буквы и их значения. Вы можете заняться этим вручную, это очень занятно (криптолингвистика…), но есть и более простые решения. Общий смысл заключается в том, что вы берёте некое слово и начинаете искать значения, которые могут подходить к буквам этого слова. При этом используется тот факт, что буквы почти всегда хранятся в алфавитном порядке. К примеру, если искать слово NINTENDO, то нужно искать значения, расстояния между которыми соответствуют расстояниям между позициями букв. Это очень уникальное слово, так что даже будет достаточно искать только три первые буквы. Расстояния между ними будет 1,-5,1 (то есть, если принять позицию буквы за 1, буква N находится на 5 позиций ниже). Конечно, речь идёт об относительном расстоянии (а сам процесс носит название Relative Search). Некоторые утилиты могут перенять у вас эту работу и быстро найдут необходимые адреса и значения. Вот программа и будет искать последовательности 1,-5,1 … пока не наткнётся на 17,12,17.

Утилита RomSearcher предназначена как раз для этого случая. Вы включаете игру и ждёте экрана с текстом. В Excitebike это будет главное меню. Теперь берём любое слово и используем его для поиска в утилите. Утилита находит вам положение слова и высчитывает сдвиг от стандартного порядка из-за заголовка в файле (поэтому адреса не совпадают). Вы можете экспортировать файл, где текст будет читабельным. Его только надо найти, но теперь вы можете пользоваться поиском текста. Однако адреса букв в экспортированном файле не такие, как в оригинале!

В принципе, вы можете использовать этот файл для перевода и потом сказать утилите вернуть изменения обратно, но лучше работать именно с оригиналом игры.

Теперь можно открыть экспортированный файл в шестнадцатеричном редакторе и найти адрес буквы (просто ищите слово, которое вы задавали). В этом файле тексты будут читабельны (в отличие от оригинала). Скорее всего, вы также разу наткнётесь и на алфавит. Во всяком случае, это именно то, что вам нужно сделать – найти алфавит или буквы. Кликая на буквы вы будете видеть их адреса и значения. Например, выбрав N вы получите значение 4D.

Теперь открывайте оригинальный файл в  шестнадцатеричном редакторе и ищите адреса найденных в другом файле букв. То есть выбирайте букву алфавита в экспортированном файле и запоминайте адрес буквы. Теперь просто идите в тот же самый адрес в оригинале и там будет стоять какое-то другое значение (в нашем случае 17).

Открывайте текстовый файл и начинайте составлять таблицы.  Пишите адрес и соответствующую ему букву. И так для всех найденных букв. Сохраняйте список в форме ##=$, где ## является значением и $ буквой. К примеру, для экспортированного файла таблица будет выглядеть так:

33=
37=0
38=1
39=2
3A=3
3B=4
3C=5
3D=6
3E=7
3F=8
40=9
41=A
42=B

Соханяйте файл с окончанием tbl, это так называемая Thingy Table. Если теперь открыть оригинальный файл в редакторе, который поддерживает такие таблицы (например, Gold Finger), то можете загрузить таблицу и часть значений примет форму букв. С таблицей выше вы сможете читать экспортированный ром. Для оригинала нужно будет сделать другую таблицу. Лучше всего сразу делать для оригинала.

Теперь вам надо перерисовать буквы. Открывайте оригинальный ром с помощью программы Tile Layer Pro и ищите буквы. Перерисовывайте их и одновременно записывайте, какая английская буква становится какой русской. Это чтобы знать, как потом перекодировать русские буквы и указать к ним соответствующие значения. Иначе выйдет такая белиберда:

Screenshot Excitebike

Всё потому, что русские буквы стоят на месте английских! Надо теперь тексты на русские, используя таблицу символов и учитывая замены в графике. При этом очень важно придерживаться правила – русский текст по возможности не длиннее оригинала!

Итак, ищем в экспортированном из RomSearch файле слово NINTENDO, находим адрес 5824. Буква N стоит в оффсете 5851 и там стоит значение 4E. Ищем теперь в оригинале адрес 5824, затем более подробно 5851 и (справа уже не будет читабельного текста) видим, что в букве N соответствует значение 17.

excitebike_hes_shifted

Экспортированный из RomSearch: NINTENDO=4E 49 4E 54 45 4E 44 4F

excitebike_hes_orig

Оригинал: NINTENDO=17 12 17 1D 0E 17 0D 18

Теперь, просто для остальных букв высчитать и записать в новую таблицу. Затем пересчитать, какие значения будут для каких русских букв. Для этого смотрим, какой код соответствует русской букве, которая встала на место английской. После этого можно писать перевод и этот перевод в итоге будет переведён в соответствующие значения.

Так что выглядеть будет теперь вот так. Осталось совсем немного!

Excitebike trans

Прошерстив оригинальный ром, я вычислил адреса букв (по ходу дела будете находить и другие):

  • FC=
  • 00=0
  • 01=1
  • 02=2
  • 03=3
  • 04=4
  • 05=5
  • 06=6
  • 07=7
  • 08=8
  • 09=9
  • 0A=A
  • 0B=B
  • 0C=C
  • 0D=D
  • 0E=E
  • 0F=F
  • 10=G
  • 11=H
  • 12=I
  • 13=J
  • 14=K
  • 15=L
  • 16=M
  • 17=N
  • 18=O
  • 19=P
  • 1A=Q
  • 1B=R
  • 1C=S
  • 1D=T
  • 1E=U
  • 1F=V
  • 20=W
  • 21=X
  • 22=Y
  • 23=Z
  • 3A=@

В оригинальном роме графика выглядит вот так:

Я нашёл одно из мест с буквами (на самом деле их чуть больше).

excitebike_rom_pictures_org

 

И перерисовал буквы:

excitebike_rom_pictures_rus

Теперь установил следуующие соответствия (слева hex-значение и соотв. английская буква, справа русская буква согласно перерисованному изображению):

0A=A A
0B=B Б
0C=C В
0D=D Г
0E=E Д
0F=F Е
10=G Ж
11=H З
12=I И
13=J К
14=K Л
15=L М
16=M Н
17=N О
18=O П
19=P Р
1A=Q С
1B=R Т
1C=S У
1D=T Ф
1E=U Х
1F=V Ц
20=W Ч
21=X Ш
22=Y Э
23=Z Я

Что это значит для нас теперь?

Что слово NINTENDO в HEX имеет значение (N)17(I)12(N)17(T)1D(E)0E(N)17(D)0D(O)18 (мы уже вычислили это выше), и одновременно, что русское слово НИНТЕНДО имеет теперь значение (в роме с перерисованной графикой): (Н)16(И)12(Н)16(Т)1B(Е)0F(Н)16(Д)0E(О)17. Всё из-за того, что у меня русский алфафит не сходится с английским (разумеется) и я выкинул пару букв.

Для перевода вам понадобится кастомный “транслитератор”. Точнее, какая-нибудь утилита, которая будет конвертировать русские тексты в необходимые коды.

Я быстро написал простую утилиту, которую ещё надо доработать. Она позволяет вам переводить русские буквы в коды и сразу проверять длину:

tbl_conv

Один большой нюанс мы затронули, но ещё не рассмотрели ближе. Это касается двух проблем:

1)алфавит русский длиннее алфавита английского

2)русские тексты почти всегда длиннее английских

С первой проблемой можно справиться различными путями, но самый простой из них – использовать по возможности только большие буквы и занять ими английские большие и маленькие буквы, если они есть. Или же использовать другие символы, которые не понадобятся, или даже (если есть) японский алфавит. Если букв мало, посмотрите, какие русские буквы не будут встречаться и выкиньте их. Сэкономьте на буквах Ё, Й, Ъ, Щ, так как буквы и так мелкие и по контексту будет понятно, какая тут нужна.

В итоге пришлось даже пару раз перерисовать буквы и выкинуть ненужные, чтобы вставить необходимые.

Вторая проблема гораздо серьёзнее. Тут надо работать с пойнтерами, которые указывают на расположение текстов. Пойнтер, указывающий на начало текста имеет свой адрес. Если мы сдвинем текст (а точнее мы хотим его сдвинуть, например из-за длины), то надо будет сдвинуть и адрес пойнтера. Это значит, что где-то в роме этот пойнтер надо будет поправить, иначе произойдёт несостыковка и код не найдёт того, что искал. Но оставим пока-что этот вопрос, так как это уже сильно продвинутый хакинг. Подбробнее можете прочитать здесь в одной из статей.

Итак, остался только перевод.

Для перевода самого рома используйте программу Gold Finger, так как она позволяет вам отображать только известные (по загружаемой таблице) буквы, а всё остальное показывается знаком #:

excitebike_rom_gf

Обратите внимание, что вверху стоит слово MIMRFMEN. Это уже переведённое слово NINTENDO! Всё потому, что наша таблица всё ещё настроена на английские буквы. Вот когда мы поменяем её на русскую, здесь появится слово НИНТЕНДО, а все непереведённые слова станут тарабарщиной из кириллицы.

Теперь давайте переведём слово TEMP. Речь идёт о температуре. Давайте же переведём как ТЕМП. Просто и понятно!

Код, который соответствует русским буквам: 1B 0F 15 18. Вот и вводим эти коды.

excitebike_rom_gf_TEMP

И проверяем в эмуляторе:

EXCITEBIKE_r-0

Ура! К переведённому НИНТЕНДО добавилась надпись ТЕМП!

Давайте закончим дело.

EXCITEBIKE_r-1 EXCITEBIKE_r-2 EXCITEBIKE_r-3

Остаются нерешёнными следующие проблемы:

 

Надписи на кругах MAP, LAP и FINISH. В последнем случае даже буквы заменены на кириллицу, но само слово долго не мог найти. Оказывается, буквы стояли на очень большом расстоянии. Пришлось загружать таблицу только из букв и отключать все неопознанные знаки. После этого я смог найти этот текст.

Фразы

“G O”, “O V E R H E A T”, когда ты перегреваешься. Они “спрятаны” довольно странно. Во-первых, они используют другие буквы из другой части рома. Эти буквы были всё ещё закодированы. Во-вторых, почему-то оба слова записаны в роме задом наперёд!

Я сделал новую таблицу для первой половины рома (его графическая часть разбита на две части с адресами от 00 до FF. Там было всего 10 букв. Они используются в словах LP, LAP, OVER HEAT и GO. Может быть ещё в каких-то, но их надо ещё найти.

C9=O
DB=L
DC=A
DD=P
DE=T
E1=E
EE=V
EF=R
F8=H
F9=G

В Gold Finger я увидел следующее:

excitebike_overheat

Смотрите в нижней правой части, там можно увидеть последовательность TAEH#REVO. Оказывается, это и есть наш OVER HEAT! Тут же рядом, на следующей строчке спряталось слово GO. Они обрамлены какими-то кодами, видимо прозрачностью или что-то типа того. Так же надо теперь искать и LAP.

Буква “В” в слове “ВРЕМЯ” белого цвета. Я не знаю, как поменять цвет этой буквы. См. скриншот выше.

На этом всё!

Ах, да. Сюрприз! Раз уж вы дочитали до конца, надо вас поощрить.

Современные эмуляторы могут сильно упростить создание таблиц. Запустите игру и затем выберите в меню Debug->PPU Viewer. Это, так сказать, графическая начинка рома, загруженная в видеопамять.

Здесь вам покажут всю графику и одновременно здесь можно найти значения для всех букв! Курсор стоит на букве A и внизу стоит значение $0A. То же, что и в нашей таблице! Вот так можно быстро найти все буквы.

excitebike_ppu

Но не сильно радуйтесь. К примеру, в игре Galaxian вы можете легко найти коды букв, но они не будут совпадать с оригинальными из-за того, что в файле есть заголовок и все значения сдвигаются! Там будет смещение на два десятка позиций. Но, всё же, это неплохой способ находить коды для букв. Просто надо всегда учитывать сдвиг из-за заголовка (header).

Найти переведённую игру вы можете здесь.

 

Итак, алгоритм перевода таков:

  1. Открыть ром в эмуляторе и выписать коды букв (используйте функцию Debug-PPU Viewer
  2. Открыть ром в GF и использовать таблицу, чтобы найти слова. Сверить, совпадают ли адреса из эмулятора и сдвинуть, если понадобится
  3. Найти и выписать слова из игры в Excel в столбец А. В столбец C ввести =Length(A1), в столбец D Length(B1). Это будет проверка длины. Перевод писать в столбец B.
  4. Написать переводы, учитывая длину. Если слова короче, затирать ненужные места пробелами.
  5. Вычислить, какие буквы кириллицы используются в переводах
  6. Проверить, влезут ли все буквы (подсчитать их в Tile Lyaer Pro). Если нет, проверить перевод или найти возможность сохранить дополнительные буквы
  7. Перерисовать буквы в оригинальном роме, учитывая только используемые
  8. Занести переводы в оригинал и сохранить как перевод
34089 Всего 6 Сегодня

Оставьте комментарий

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.