Автор Тема: Русификация Dwarf Fortress  (Прочитано 637544 раз)

0 Пользователей и 4 Гостей просматривают эту тему.

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1455 : 01 Октября 2013, 21:41:59 »
6E5BD4| Downward Stairway| Лестница Вниз|
67F2E8|Down Stair|Лестница вниз|
69323C|Downward Stairway|Лестница вниз|
67F2DC|Up Stair|Лестница вверх|
69322C|Upward Stairway|Лестница вверх|
6E5B7C| Upward Stairway| Лестница вверх|
6E5A8C| Cavern Floor| Пол Пещеры|


Возможно ли здесь перейти к единообразию ?
Думаю, должно быть так:
- то что начинается с пробела - все маленькими буквами
- то что без пробела в начале - только первая буква большая.

UPD. Подправил
« Последнее редактирование: 01 Октября 2013, 23:08:46 от insolor »

Оффлайн Determinant

  • Новичок
  • *
  • Сообщений: 24
    • Просмотр профиля
Русификация Dwarf Fortress
« Ответ #1456 : 09 Октября 2013, 21:29:35 »
У меня просьба, если я конечно в ту тему попал  :)
Эта библиотека отвечает за перевод экрана с мыслями дварфов?
Можно сменить кнопку ее включения с Ctrl на что-то другое, а то переназначены клавиши, левый Ctrl (и Alt) постоянно используется и в итоге на экране происходит тихий ужас. А без перевода экрана с мыслями и толку с перевода то особого нету :(
« Последнее редактирование: 09 Октября 2013, 21:35:28 от Determinant »

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1457 : 10 Октября 2013, 20:43:04 »
У меня просьба, если я конечно в ту тему попал  :)
Эта библиотека отвечает за перевод экрана с мыслями дварфов?
Можно сменить кнопку ее включения с Ctrl на что-то другое, а то переназначены клавиши, левый Ctrl (и Alt) постоянно используется и в итоге на экране происходит тихий ужас. А без перевода экрана с мыслями и толку с перевода то особого нету :(
Перенес в общую тему по русификации. По этому вопросу пиши участнику mialax личку.

Да, и alt вроде бы не переназначен, только левый ctrl.

Оффлайн liwoner

  • Новичок
  • *
  • Сообщений: 5
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1458 : 21 Октября 2013, 19:33:31 »
Всем привет, я новичек здесь на форуме и пока еще не разобрался толком. У меня есть большой опыт в реверсинге и желание поучавствовать в этом проекте. Я пока-что изучаю данный раздел форума и есть некоторые вопросы. Вы планируете русификатор делать только для Windows или и для остальных платформ?

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1459 : 21 Октября 2013, 22:17:51 »
Всем привет, я новичек здесь на форуме и пока еще не разобрался толком. У меня есть большой опыт в реверсинге и желание поучавствовать в этом проекте. Я пока-что изучаю данный раздел форума и есть некоторые вопросы. Вы планируете русификатор делать только для Windows или и для остальных платформ?
Добро пожаловать.
Русификатор под другие платформы планируется, но сроки неизвестны. Через какое-то время будет обновление патча, исправляющее некоторые побочные эффекты русификации ("северный олень" несколькими постами выше). Но сначала немного разберусь с учебой.
Параллельно ведется работа над скриптом на питоне, сглаживающем огрехи русификации, см тему: http://forum.dfwk.ru/index.php/topic,1491.0.html
На этом фронте уже достигнуты некоторые положительные результаты, но до окончательной победы еще далеко.

Если есть еще вопросы, спрашивай.
« Последнее редактирование: 21 Октября 2013, 22:38:48 от insolor »

Оффлайн liwoner

  • Новичок
  • *
  • Сообщений: 5
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1460 : 21 Октября 2013, 23:03:51 »
Вот он ты какой, северный олень

опасно для моска: ассемблер
.text:00A04B90                 mov     edi, 0Fh        ; len
.text:00A04B95                 mov     eax, offset aNameFortress ; ": Name Fortress"
.text:00A04B9A                 lea     esi, [esp+0C4h+strBuf] ; a5
.text:00A04B9E                 mov     [esp+0C4h+strBuf.cap], edi
.text:00A04BA2                 mov     [esp+0C4h+strBuf.len], 0
.text:00A04BAA                 mov     [esp+0C4h+strBuf.text], 0
.text:00A04BAF                 call    string_constructor

Для сравнения, "честный" код, без использования значения в нескольких местах:
.text:00A04C0D                 mov     edi, 0Ch        ; len
.text:00A04C12                 mov     eax, offset aNameGroup ; ": Name Group"
.text:00A04C17                 lea     esi, [esp+0C4h+strBuf] ; a5
.text:00A04C1B                 mov     [esp+0C4h+strBuf.cap], 0Fh
.text:00A04C23                 mov     [esp+0C4h+strBuf.len], 0
.text:00A04C2B                 mov     [esp+0C4h+strBuf.text], 0
.text:00A04C30                 call    string_constructor

Отсюда и растут ноги у некоторых вылетов при превышении длины в 15 (0Fh) символов. Осталось научить патч обрабатывать такие ситуации.
[свернуть]

Хм.. получается здесь вылет при чтении из RAW? хм, я сейчас говорю наугад, еще не ковырялся с отладчиком, но...  Как я понял, этот код эквивалентен:

   std::string aNameFortress (": Name Fortress");
   //Или
   std:string aNameGroup (": Name Group");

я думаю, что эти строки используются в дальнейшем как для поиска участка строки из RAW файла, где следует заменить ее на определенный текст.  Вылет здесь возможен только в одном случае, если заменить это ключевое слово (ведь они используются как теги) на другую строку, которая будет длиной меньше текущей. Может не стоит их менять ?. Я, возможно, сделал не очень удачное предположение, поправьте если так. Кста, можно простыми словами получить инструкцию как наткнуться там на вылет ?

Оффлайн keepmind

  • Новичок
  • *
  • Сообщений: 15
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1461 : 22 Октября 2013, 00:35:49 »
Кто нибудь нашел способ вводить русский текст в меню "менеджера" для поиска предметов?

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1462 : 22 Октября 2013, 08:16:36 »
Вот он ты какой, северный олень

опасно для моска: ассемблер
.text:00A04B90                 mov     edi, 0Fh        ; len
.text:00A04B95                 mov     eax, offset aNameFortress ; ": Name Fortress"
.text:00A04B9A                 lea     esi, [esp+0C4h+strBuf] ; a5
.text:00A04B9E                 mov     [esp+0C4h+strBuf.cap], edi
.text:00A04BA2                 mov     [esp+0C4h+strBuf.len], 0
.text:00A04BAA                 mov     [esp+0C4h+strBuf.text], 0
.text:00A04BAF                 call    string_constructor

Для сравнения, "честный" код, без использования значения в нескольких местах:
.text:00A04C0D                 mov     edi, 0Ch        ; len
.text:00A04C12                 mov     eax, offset aNameGroup ; ": Name Group"
.text:00A04C17                 lea     esi, [esp+0C4h+strBuf] ; a5
.text:00A04C1B                 mov     [esp+0C4h+strBuf.cap], 0Fh
.text:00A04C23                 mov     [esp+0C4h+strBuf.len], 0
.text:00A04C2B                 mov     [esp+0C4h+strBuf.text], 0
.text:00A04C30                 call    string_constructor

Отсюда и растут ноги у некоторых вылетов при превышении длины в 15 (0Fh) символов. Осталось научить патч обрабатывать такие ситуации.
[свернуть]

Хм.. получается здесь вылет при чтении из RAW? хм, я сейчас говорю наугад, еще не ковырялся с отладчиком, но...  Как я понял, этот код эквивалентен:

   std::string aNameFortress (": Name Fortress");
   //Или
   std:string aNameGroup (": Name Group");

я думаю, что эти строки используются в дальнейшем как для поиска участка строки из RAW файла, где следует заменить ее на определенный текст.  Вылет здесь возможен только в одном случае, если заменить это ключевое слово (ведь они используются как теги) на другую строку, которая будет длиной меньше текущей. Может не стоит их менять ?. Я, возможно, сделал не очень удачное предположение, поправьте если так. Кста, можно простыми словами получить инструкцию как наткнуться там на вылет ?
Да, это что-то вроде std::string aNameFortress (": Name Fortress");
Нет, эти строки не используются при поиске в равках. Тут дело в другом.
Спойлер
В физической структуре STL строки внутри есть буфер под короткую строку (до 15 символов), если строка более длинная, то вместо внутреннего буфера используется буфер в куче (начало внутреннего буфера используется как указатель). Поле .cap в структуре показывает текущий размер буфера, при пустой строке и строке короче 16 символов значение этого поля равняется длине внутреннего буфера (в конструктор передается изначально пустая строка и указатель на обычную нуль-терменированную строку символов). Во втором случае если пропатчить длину строки (в инструкции mov edi, n), ничего плохого не случится. Если же пропатчить длину первом случае, то это значение повлияет и на значение размера буфера, тогда программа будет считать, что размер внутреннего буфера заведомо подходит под строку, и при попытке записать во внутренний буфер строку длиннее его фактического размера произойдет затирание данных сначала в структуре, а потом и за ее границами в стеке.

Решение: в конкретных подозрительных случаях (длина исходной строки равна 15, длина новой строки больше длины исходной, ну и идет передача параметров через регистры edi, eax, esi) вызывать не конструктор строки, а переходник, принудительно заменяющий значение поля .cap на 15 и передающий управление уже на конструктор.

т.е. как-то так:

...
call chunk ; здесь было call string_constructor
...
chunk:
mov [esi+.cap], 15
jmp string_constructor
[свернуть]

Как наткнуться на вылет: в trans.txt есть строки помеченные как ==, это значит что длина перевода подогнана под длину оригинала. Если изменить длину перевода (обычно в большую сторону, но иногда вылетает и при меньшей длине), то при попытке показать (на самом деле инициализировать) эту строку игра вылетит.

Кто нибудь нашел способ вводить русский текст в меню "менеджера" для поиска предметов?
Пока нет.
P.S. Если переводить предметы не с помощью патча, а с помощью скрипта, то теоретически можно будет искать по английскому названию. На практике это пока не пробовал.
« Последнее редактирование: 22 Октября 2013, 11:27:49 от insolor »

Оффлайн liwoner

  • Новичок
  • *
  • Сообщений: 5
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1463 : 22 Октября 2013, 11:54:44 »
Теперь стало понятней. Получить вылет так и не получилось, пока что. Идею понял. Есть интересный способ осуществить твою идею. Не нужно постоянно переписывать вызов на string_constructor. Можно изменить сам string_constructor (такой хук часто используется для перехвата различных функций в готовых модулях, называется Jmp detour).  Смысл его такой:
 1) берем адрес string_constructor
 2)  Копируем такое количество байт от начала функции, чтобы туда поместился jmp address и эти байты не нарушали инструкции. Обычно это около 5-7 байт, но есть простой код на C для автоопределения его размера.
 3) Скопированные байты переносим в любое свободное местов в сегменте кода (если статичный перехват делаем). За ними пишем Jmp На следующую инструкцию после скопированных байт.
 4) на место этих байтов пишем Jmp на наш обработчик вызова функции string_constructor, где и проводим манипуляции с любыми параметрами функции string_constructor. Здесь можно добавить простую проверку на размер данных и корректировки их в случае чего.
 5) В конце нашего обработчика ставим jmp на адрес содержищий скопированные байты + jmp

Таким образом мы подсовываем свою функцию, перед выполнением любого string_constructor. Сейчас пытаюсь отловить вылет. Без успехов.

Оффлайн liwoner

  • Новичок
  • *
  • Сообщений: 5
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1464 : 22 Октября 2013, 12:03:16 »
Естественно перед финальным jmp не забываем восстановить стек (если использовали) и параметры. Можно еще другим способом сотворить чудо ) Если у меня получится отловить вылет, что бы убедиться самому, я смогу сделать коммит для патча, который и будет делать магию. Только придется выучить синтаксис нового языка. Или сделать DLL с экспортируемой функцией PatchDamnFile()
« Последнее редактирование: 22 Октября 2013, 12:20:44 от liwoner »

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1465 : 22 Октября 2013, 13:32:00 »
Теперь стало понятней. Получить вылет так и не получилось, пока что. Идею понял. Есть интересный способ осуществить твою идею. Не нужно постоянно переписывать вызов на string_constructor. Можно изменить сам string_constructor (такой хук часто используется для перехвата различных функций в готовых модулях, называется Jmp detour).  Смысл его такой:
 1) берем адрес string_constructor
 2)  Копируем такое количество байт от начала функции, чтобы туда поместился jmp address и эти байты не нарушали инструкции. Обычно это около 5-7 байт, но есть простой код на C для автоопределения его размера.
 3) Скопированные байты переносим в любое свободное местов в сегменте кода (если статичный перехват делаем). За ними пишем Jmp На следующую инструкцию после скопированных байт.
 4) на место этих байтов пишем Jmp на наш обработчик вызова функции string_constructor, где и проводим манипуляции с любыми параметрами функции string_constructor. Здесь можно добавить простую проверку на размер данных и корректировки их в случае чего.
 5) В конце нашего обработчика ставим jmp на адрес содержищий скопированные байты + jmp

Таким образом мы подсовываем свою функцию, перед выполнением любого string_constructor. Сейчас пытаюсь отловить вылет. Без успехов.
Дело в том, что "string_constructor" на самом деле не одна единственная функция. Есть несколько функций, вызывающихся с теми же параметрами (длина в edi, сишная строка в eax, stl строка в esi), работающих схожим образом. В текущей версии trans.txt я отловил порядка десяти-двадцати проблемных строк, и адрес конструктора в них часто различается. Мое решение мне видится более простым.

Вообще во всем DF есть достаточно много разных методов инициализации строк, вплоть до копирования строки несколькими мувам (например пункты меню на титульном экране), в таких случаях мувы заменял на rep movsd.

По поводу свободного места - патч добавляет в экзешник новую секцию, первоначально туда перемещались только длинные строки, но сейчас там есть некоторое количество кода (типа инструкций установки длины строки).

Да, в патче уже есть анализатор длин инструкций, и даже прототип дизассемблера :) Единственно, что все писано на малоизвестном в наших краях языке Euphoria, в общем-то я ССЗБ, но на момент начала работы над русификацией это был наиболее близкий мне язык. С++ я практически не знаю, знаю Си, но изобретать с нуля нужные мне структуры данных меня как-то не радовало. Подумываю переписать на что-то более "конвенциональное" типа Object Pascal, но это скорее мечты :)

Оффлайн liwoner

  • Новичок
  • *
  • Сообщений: 5
    • Просмотр профиля
Отредактировал
« Ответ #1466 : 22 Октября 2013, 14:00:12 »
Надо подумать. Можно получить список строк и их вариантов, при котором игра вылетает ? я хочу попробовать исправить проблему способом что описал выше ?

PS. Если код одинаковый, отличаются только адреса, то можно находить такие участки с помощью сигнатур, как с этим плагином для олли http://tuts4you.com/download.php?view.3079

пример
MOV DWORD PTR DS:[EAX],EBP
MOV EBP,EAX
015886F9   A1 18906901         MOV EAX,DWORD PTR DS:[1699018]
015886FE   33C5                      XOR EAX,EBP
01588700   50                          PUSH EAX
01588701   FF75 FC                 PUSH DWORD PTR SS:[EBP-4]
01588704   C745 FC FFFFFFFF MOV DWORD PTR SS:[EBP-4],-1
0158870B   8D45 F4                 LEA EAX,DWORD PTR SS:[EBP-C]
0158870E   64:A3 00000000    MOV DWORD PTR FS:[0],EAX

89 28 8B E8 A1 ?? ?? ?? ?? 33 C5 50 FF 75 FC C7 45 ?? ?? ?? ?? ?? 8D 45 F4 64 A3 ?? ?? ?? ??
« Последнее редактирование: 22 Октября 2013, 14:23:46 от liwoner »

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Отредактировал
« Ответ #1467 : 22 Октября 2013, 14:59:32 »
Можно получить список строк и их вариантов, при котором игра вылетает ?
Прямо сейчас я этот список не могу выдать, к тому же многое зависит от того, что в какой-то момент перевод какой-то из строк может поменяться (в сторону увеличения длины) и эта строка добавится в этот список. Смысл в том, что патч довольно автономен - он находит экзешник DF, находит файлик словаря trans.txt (пары оригинал-перевод, смещения оригинала не даны - то что идет перед первым в строке | оставлено для удобства), и на выходе получается готовый пропатченный экзешник. Патч работает на версиях DF 0.34 - 0.34.11 без изменений, скорее всего будет работать и в следующем релизе, достаточно будет добавить в trans.txt перевод новых строк, появившихся в экзешнике.

Если интересно, есть общее описание работы патча:
https://bitbucket.org/insolor/dfrus/wiki/Algo
https://bitbucket.org/insolor/dfrus/wiki/AlgoOverview

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

Оффлайн keepmind

  • Новичок
  • *
  • Сообщений: 15
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1468 : 22 Октября 2013, 15:38:58 »
Скопировал свой пост из соседней темы по changetext:

insolor,
1. некоторые переведенные строки в игре оказываются обрезанными, можешь исправить?
2. И еще в DF есть строки с содержанием апострофа(') вот такие например:
"Dyer's Shop"
"Soap Maker's Workshop"
в changetext.py  такие не внесешь.
3. И еще можно ли с помощью changetext.py перевести мысли дварфов, описание тварей(там где текст пишется не буквами а состоит из тайлов)?


Написал небольшую программу для облегчения гугло-перевода)

Краткая инструкция:
1. Перевести changetext.log в отдельный файл, например в translated.log
2. Передать программе эти два файла в параметры(например bat файлом) программе так:
trans_.exe changetext.log translated.log **минимальная длинна строки(чтобы игнорировались строки типа "a","1"...)**
3. В папке с программой появится готовый файл trans_.txt

Сама программа

PS: В архиве еще немного подправленный скрипт changetext.py insolor'a для подхвата полученного файла.

Оффлайн insolor

  • Глобальный модератор
  • Ветеран
  • *****
  • Сообщений: 1064
  • Adequate Reverse Engineer
    • Просмотр профиля
Re: Русификация Dwarf Fortress
« Ответ #1469 : 22 Октября 2013, 15:46:21 »
Скопировал свой пост из соседней темы по changetext:

insolor,
1. некоторые переведенные строки в игре оказываются обрезанными, можешь исправить?
2. И еще в DF есть строки с содержанием апострофа(') вот такие например:
"Dyer's Shop"
"Soap Maker's Workshop"
в changetext.py  такие не внесешь.
3. И еще можно ли с помощью changetext.py перевести мысли дварфов, описание тварей(там где текст пишется не буквами а состоит из тайлов)?


Написал небольшую программу для облегчения гугло-перевода)

Краткая инструкция:
1. Перевести changetext.log в отдельный файл, например в translated.log
2. Передать программе эти два файла в параметры(например bat файлом) программе так:
trans_.exe changetext.log translated.log **минимальная длинна строки(чтобы игнорировались строки типа "a","1"...)**
3. В папке с программой появится готовый файл trans_.txt

Сама программа

PS: В архиве еще немного подправленный скрипт changetext.py insolor'a для подхвата полученного файла.
Ответил в теме по changetext