Главная arrow Документация arrow Пойнтеры. Часть третья.
23.05.2017 г.

Последние Комментарии

Final Fantasy II 14.05.2017 г.
Incredible Crash Dummies 09.05.2017 г.
Monster Tale [NDS] 04.05.2017 г.

Гостевая Книга

Char
Обратите внимание на Faselei с Neo Geo Pocket. На
Краткие новости
Уважаемые посетители сайта! Поздравляем всех вас с днём защитника отечества! К этому знаменательному событию мы приготовили для вас небольшой перевод - Pachinko Daisakusen (NES). Эта игра повествует о нелёгких буднях обычного офисного работника, который в минуту опасности становится секретным агентом 008! Он должен играть в автоматы патинко и зарабатывать деньги, чтобы потом купить оружие и разобраться со всеми шпионами и врагами. Смерть шпионам! Героям троекратное ура!

23

 
Цитаты
Борхес Хорхе Луис: "Оригинал неверен по отношению к переводу."
Внимание! Всем-всем-всем!
Товарищи! Если у кого-то из вас вдруг завалялись ненужные (или не очень нужные) картриджи денди - не дайте пропасть добру! Приму в дар, скопирую и верну хозяину или куплю/обменяю любые интересные картриджи, особенно редкие или пиратские. С предложениями обращайтесь НА ФОРУМ или В ЛИЧКУ. Подпись: Guyver.
Пойнтеры. Часть третья. Печать E-mail
Автор Mefistotel   
30.12.2014 г.

ПОИНТЕРЫ. ЧАСТЬ ТРЕТЬЯ. (автор: Mefistotel, помощь и корректировка: Джинни, Marat)

Введение
 

В этой документации мне бы хотелось осветить некоторые приёмы по работе с указателями. Довольно часто бывают такие случаи при переводе, когда найдены 2-х байтные относительные указатели (рабочий диапазон 0xFFFF или 64 килобайта), но места в блоке под русский текст недостаточно. Более того, в пределах 64 килобайт после блока с текстом свободного места также нет в явном виде, а двухбайтные указатели дальше адресовать не могут. Чтобы качество перевода не пострадало от технических ограничений такого типа, существует чудодейственные способы выхода из ситуации. Можно попросту заменить 2-х байтные относительные указатели (рабочий диапазон 0xFFFF или 64 килобайта) на 4-х байтные абсолютные (рабочий диапазон 0xFFFFFF или 16 мегабайт). Как это сделать рассмотрим на примере следующих игр для SEGA GENESIS Toejam & Earl (J) (REV02) [!].gen и Langrisser II (J) (REV02) [T+Eng_M.I.J.E.T.].gen. Для выполнения задачи нам понадобятся шестнадцатеричный редактор (к примеру, Translhextion 1.6с Chief-NET Edition), минимальное знание ассемблера для процессора M68000 и трезвый ум. Необязательно, но для наглядности можно воспользоваться дизассемблером IDA PRO 6.1 с Sega Loader-ом.


Toejam & Earl (J) (REV02) [!].gen

В этой игре большая часть текста разбросана по рому в виде одной-двух строк, и указатели на них 2-х байтные относительные. Но на счастье переводчика при загрузке указателей на строки идёт одна лишняя инструкция (NOP). Рассмотрим подробнее, на примере строки [bogus ... game over], которая находится по адресам 0x23646-0x23659.
 
bogus
Указатель на эту строку находится по адресу 0x23574 и равен 0x00D2. Он относителен своего адреса, то есть к значению адреса прибавляем значение указателя и получаем адрес строки (0x23574 + 0x00D2 = 0x20D36). Если присмотреться, то перед и после значения указателя идут машинные коды двух инструкций: PEA (48 7A) и NOP (4E 71).
Для наглядности также можно загрузить ром в дизассемблер IDA PRO 6.1, нажать G и ввести адрес указателя 0x23572. Увидим команду загрузки указателя и текст, на который он указывает:
 
pea
 
Таким образом, процедура загрузки указателя на строку выглядит так и занимает 6 байт:
PEA #$00D2 NOP
 
Инструкция PEA записывает в стек двухбайтный адрес данных (строки в нашем случае), рассчитанный по формуле: АДРЕС ИНСТРУКЦИИ + 2 + ЗНАЧЕНИЕ (в нашем случае 0x00D2). А инструкция NOP ничего не делает и является лишней. В стек значение записывается для того, чтобы функция, которая вызывается инструкцией JSR, могла загрузить это значение из стека в регистр. А затем загрузить строку по указанному адресу [bogus ... game over].

Для изменения указателя на 4-х байтный, необходимо изменить инструкцию PEA на другую или просто заменить указатель на 4-х байтный. В роме меняем машинный код с 487A00D24E71 на 2F3C000FFE60 (инструкция Move) и получаем:


MOVE #$000FFE60, -(sp)


Эта процедура занимает также 6 байтов, то есть 2 байта 2F3C - это код инструкции Move, а 00 0F FE 60 - наш новый 4-х байтный указатель, который был выбран исходя из свободного места в роме (диапазон адресов 0xFFE60-0xFFFFF). Таким образом, были изменены инструкции на загрузку адреса строки в стек. Так как NOP была лишней, то мы вписали 4-х байтный адрес строки вместо 2-х байтного.
Теперь останется перенести строку на новый адрес в роме (0x000FFE60), не забывая поставить стопбайт /00 в конец строки. Ниже на скриншоте показано результат - длина строки была увеличена с 19 до 28 символов. Если найти адрес строки в видеопамяти, то можно ещё больше удлинить строку, а также оцентровать её.

move
 
transl
 
Стоит отметить, что данный случай со свободными байтами является скорее исключением из правил и довольно редко встречается.


Langrisser II (J) (REV02) [T+Eng_M.I.J.E.T.].gen

Рассмотрим вариант, который встречается наиболее часто в ромах. В игре также встречаются 2-х байтные относительные указатели, но лишние инструкции отсутствуют.
Для многих геймеров не секрет, что если в игровом сценарии подвести курсор к левому верхнему краю экрана в точку с координатами 2:2 и зажать кнопку В на несколько секунд, то откроется музыкальный тест. Стрелками вверх и вниз на крестовине джойстика можно выбрать и прослушать мелодии и звуки из игры.
 
 
Блок с названием композиций и звуков (далее музыкальный блок) в роме расположен по адресам 0xAE67C-0xAE99E. После него сразу же идёт массивный блок с названиями и описания предметов. Немного ниже есть даже небольшой кусок свободного места (0xAF7F0-0xAFFFF), а дальше сплошной код и данные.
Так вот, единственный относительный 2-х байтный указатель 0x5A7A на весь музыкальный блок находится по адресу 0xA8C00. Он относителен своего адреса (0xA8C00 + 0x5A7A = 0xAE67C), как и в предыдущей рассматриваемой игре. Строки в блоке отделяются стопбайтом /00 и можно спокойно менять их длину. Выделенного места не хватит под литературный перевод музыкального блока на русский язык, а имеющееся в пределах 64 килобайт свободное место уйдёт под перевод описаний и названий предметов. В такой ситуации нужно перенести музыкальный блок в другое место, изменив указатель с 2-х байтного на 4-х байтный. Рассмотрим внимательнее инструкции около нашего указателя:
 

move_b
 

Инструкция MOVE (1038) загружает байт данных (номер строки в блоке) с адреса 0xFFFFA6C8 в оперативной памяти в регистр D0, а инструкция LEA (43FA) записывает в регистр A1 двухбайтный адрес данных (строки в нашем случае), рассчитанный по формуле: АДРЕС ИНСТРУКЦИИ + 2 + ЗНАЧЕНИЕ (в нашем случае 0x5A7A). Далее инструкцией BSR вызывается функция, которая загружает это значение из стека в регистр, затем загружается строка по указанному адресу [Stop Music].
В данном случае просто заменить инструкцию LEA на MOVE с изменением понтера не выйдет, так как вся операция загрузки указателя занимает 4 байта. Необходимо переместить всю подпрограмму в другое место. Для этого с адреса 0xA8BFC прописываем переход на новый адрес, по которому имеется свободное место в роме (к примеру, в диапазоне 0x1BC612-0x1BFFFF):

JSR 001BС700 NOP

(4EB9001BС7004E71)


И куда переместили, прописываем нашу первичную подпрограмму:

MOVE.B<$A6C8>,D0 LEA #$XXXXXXXX,A1 RTS

(1038A6C843F9XXXXXXXX4E75)

где XXXXXXXX - наш новый 4-х байтный указатель на музыкальный блок,
RTS - возвращает в исходное место.
После этого не забываем перенести сам блок на новое место. Для наглядности покажем в хексредакторе, что было сделано:

 

 

В качестве эпилога

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

Последнее обновление ( 15.03.2016 г. )
 
« Пред.   След. »
home contact search contact search