The Neverhood, хеш алгоритм |
Добро пожаловать, гость ( Вход | Регистрация )
The Neverhood, хеш алгоритм |
-=CHE@TER=- |
Jul 9 2011, 12:33
Сообщение
#1
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Пишу сейчас страничку для сайта (ctpax-cheater) для игры The Neverhood.
В игре во всю используется вот такая хеш-функция (я её немножно переписал под свои нужды): CODE // The Neverhood hash routine Const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; Function StrHash(S: String): Longword; Var I, C, K: Longword; Begin result:=0; C:=0; For I:=1 To Length(S) Do Begin S[I]:=UpCase(S[I]); K:=Pos(S[I], chars); If K <> 0 Then Begin If K <= 10 Then // Digits C:=C + (Ord(S[I]) + $16 - $40) Else C:=C + (Ord(S[I]) - $40); If C >= $20 Then C:=C - $20; result:=result xor (1 ShL C); End; End; End; Т.е. игнорируется всё, что не цифры и английские буквы, затем от получившегося считается хеш. В demo-версии эта функция находится в sub_425C10. Ею зашифрованы как коды, так и имена файлов в .BLB архивах. В Интернете нагуглил только два кода (там ещё один есть, но он неработающий - что-то забыли): fastforward - увеличивает скорость игры в два раза (хеш $843070C0) happybirthdayklaymen - работает только на первом экране - перекидывает игрока на второй (*улыбается*) (хеш $188B2105) После набора кода нужно нажать ENTER. Перед набором, кстати, тоже неплохо будет - вдруг уже что-то нажимали (ENTER отправляет код на обработку и чистит буфер ввода для кода). Однако, если поглядеть под отладчиком даже demo-версию - кодов там дохрена и больше (вернее хешей). Плюс они раскиданы по нескольким разным функциям (как два кода выше), что затрудняет работу с ними. Есть, например, хеш $10410127 - он сохраняет текущий кадр игры в c:\NevShot.bmp (даже во время проигрывания smack-видео!). Но вот какой код ему соответствует - хрен знает. Есть два способа посмотреть все коды: 1) Заменить хеши на известные значения. 2) Brute-force (полный перебор). 1-ый способ очень неудобен, потому что: а) Все хеши кодов внутри какого-то case/switch и они должны быть заменены на соответствующие (т.е. отсортированы по возрастанию, а не как попало). б) Они разбросаны по разным функциям, так что бегать между ними очень неудобно. в) Этот способ неудобен ещё и тем, что его нельзя предложить всем имеющим игру - им придётся её как минимум патчить. Перебор же очень трудоёмкий, даже если выбросить оттуда UpCase (т.е. заведомо перебирать только заглавные буквы и цифры) и оптимизировать. Я заметил, что в этом алгоритме на каждом шаге зажигается или гасится (если уже был зажжён) 1 бит в хеше. Т.е. для упомянутого хеша $10410127 слово-пароль должно состоять как минимум из 8 знаков (с учётом того, что ни один бит не выключался), так как в этом числе 8 не нулевых бит. Собственно, вопрос: кто-нибудь может предложить простой и быстрый алгоритм для перебора? Может быть я чего-то не вижу и здесь можно гораздо быстрее и проще хеш подобрать. Мне не обязательно получить именно тот код, который задумывался создателями - какая-нибудь последовательность типа "bsb99dc" - тоже сойдёт. |
Axsis |
Jul 9 2011, 20:07
Сообщение
#2
|
Advanced Member Группа: CTPAX-X Сообщений: 121 Регистрация: 6-February 08 Пользователь №: 374 Спасибо сказали: 149 раз(а) |
$10410127 - "AACCHFFD"
Правда у меня демка с какими-то артефактами работает... _ttp://fastpic.ru/view/25/2011/0710/5d5d4d76cb7d379fd6feb5c044daacc0.png.html Алгоритм опишу чуть позже, а может к тому времени и сам разберёшь, он на самом деле довольно прост. Спасибо сказали:
|
-=CHE@TER=- |
Jul 10 2011, 04:30
Сообщение
#3
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
$10410127 - "AACCHFFD" Вай!!! Шайтан!!! (*улыбается*)Обязательно выражу тебе благодарность в статье за помощь с генерацией строк для кодов. Правда у меня демка с какими-то артефактами работает... Я через D3DWindower (_ttp://www.old-games.ru/utils/soft/) игры запускаю - так и дебажить удобнее, когда игра в окне. Кстати, замени ещё в исполняемом файле игры (убирает cli и sti, чтобы для запуска режим совместимости не требовался):000196BF: FA 90 000196E2: FB 90 Может, после этого пойдёт нормально. Алгоритм опишу чуть позже, а может к тому времени и сам разберёшь, он на самом деле довольно прост. Слушай, если не сложно, опиши, пожалуйста, а то я сам как-то пока не допираю. В принципе, он был бы прост, если бы не гадское условие "If C >= $20 Then C:=C - $20;", которое портит всё малину.С нетерпением хочется посмотреть какие коды есть в игре и что они делают. Сколько ещё нераскрытых тайн хранят в себе игры! (*улыбается*) Я, например, натолкнулся на такой интересный код как kimberly (если у меня на сайте страничку с Powerslave читал) - кто знает, что интересного есть здесь. (*улыбается*) |
Axsis |
Jul 11 2011, 14:15
Сообщение
#4
|
Advanced Member Группа: CTPAX-X Сообщений: 121 Регистрация: 6-February 08 Пользователь №: 374 Спасибо сказали: 149 раз(а) |
В общем каждый символ кода (цифра или буква) сдвигает бит, которым xor'ится хеш, на определённое количество бит влево. Для цифр от 0 до 9 значение сдвига равно от 6 до 15 ($30+$16-$40=6); для букв это значение равно от 1 до 26 ($41-$40=1). Причём сдвиг например для 3-го символа отсчитывается не от 0-го бита а от величины сдвига для 2-го символа. Когда сдвиг превышает размер хеша, т.е. 32 бита, он уменьшается на 32, т.е. гоняется по кругу (те самые "If C >= $20 Then C:=C - $20;").
Для восстановления исходной фразы (на самом деле, лишь одной из множества исходных фраз, дающих одинаковый хеш) нужно проделать следующее: записываем хеш в двоичном виде, в little endian (для примера рассмотрим хеш $843070C0): CODE 10000100 00110000 01110000 11000000 и начинаем разбирать зажженные биты от младшего к старшему (справа налево, пронумеровав их от 0 до 31). Чтобы зажечь 6-й бит нам нужно было сдвинуть единицу (нулевой бит) на 6 бит влево. Сдвигу в 6 бит соответствует 6-я буква - "F". Чтобы зажечь следующий, 7-й, бит нужно сдвинуть на 1 бит (считаем от предыдущего зажженного - от 6-го бита), для этого нужна буква "A". Далее, для 12-го бита - смещение 5, и соответственно буква "E", и т.д. Для зажжения всех 9-ти бит нам понадобится минимум 9 букв - "FAEAAFAEE". По идее, этот код даст такой же хеш как и "fastforward", а значит и действовать будет так же. Если нужно зажечь 0-й бит в хеше, то, т.к. сделать это сразу не получится, его надо зажигать последним, перепрыгнув через 32 бита (если бы нам надо было зажечь его в нашем примере, то нужно было бы дописать в конец кода ещё букву "A" - "FAEAAFAEEA". Мы получили бы смещение 32, которое превратилось бы в 0 и зажегся бы 0-й бит.) Описание получилось немного дурацкое, но думаю ты разберёшься Спасибо сказали:
|
-=CHE@TER=- |
Jul 11 2011, 17:05
Сообщение
#5
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Спасибо большое!
Примерно понял, в ближайшее время попробую программку накидать - сейчас уже просто спать валюсь. Про проверку сегодня дошло тоже, что это перескок через 32 бита, который можно было проще и быстрее сделать - через and и маску, а не вычитание с проверкой, но уж, как сделали. (*улыбается*) |
-=CHE@TER=- |
Jul 16 2011, 08:44
Сообщение
#6
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Вот так:
CODE Function HashToStr(Hash: Longword): String; Var K: Longword; Begin result:=''; While Hash > 0 Do Begin K:=0; Repeat K:=K + 1; asm mov eax, Hash ror eax, 1 mov Hash, eax end; If K > 26 Then Begin result:='26 BIT OVERFLOW!!!'; Exit; End; Until ((Hash And 1) <> 0); Hash:=(Hash And $FFFFFFFE); result:=result + chars[10 + K]; // skip digits End; End; Коды-то получил, да только хрен пойми, что они делают. Только один понял (MBAFBG), а остальные - никак. Коды для уровней (в другой функции обрабатываются) вообще работают только на определённых сценах. Например код happybirthdayklaymen работает только на первой сцене. В принципе в IDA видны какие-то номера, но как узнать к каким сценам они относятся - непонятно. Кто-нибудь хочет потестировать и сказать что коды делают? А то просто так их писать неудобно - вроде как, описание хочется. $0B835D39 - CAACBAABBAFAABE $00881000 - LGD $10410127 - AACCHFFD - screenshot "c:\NevShot.bmp" $0E103409 - CGBAGEAAE $44A82242 - AECDFBBCD $4339581D - BAAGABBCAACAEB $4F88D504 - BFBBBADDAAAAC $46900820 - EFICBAD $843070C0 - FAEAAFAEE - fastforward $8141A000 - MBAFBG - turn on developer mode (to turn off - restart the game) F1,F2 - stop game (not sure whats different between this two) F3 - slow motion F4 - normal speed F5 - show/hide positions F6 - show/hide items/buttons (take affect on the main menu buttons too) F7 - show/hide HIT_FLOOR bars F8 - show/hide active zone bars F9 - show/hide scene layers F10 - go to window menu (like ALT in window mode) F11 - show/hide animated area F12 - take screenshot in current folder with names "Neverhood###.bmp", where ### - number from 001 to 999 / NHC.exe.loc_410C88 [12->0Ch] $8580A64D - BACCACBHABEA $9208201E - AAAAIFFCC $96302C41 - FDABGADABCA // levels ?.. $188B2105 - BFECABDDAD - happybirthdayklaymen - scene_1 to scene_2 $00342624 - BCDACEBA $21E64A00 - IBCCACAAAE $040424D0 - DBACCEH $80006358 - CABBADAQ Добавлено: А! Ладно, у меня есть одна идея. |
Axsis |
Jul 16 2011, 20:00
Сообщение
#7
|
Advanced Member Группа: CTPAX-X Сообщений: 121 Регистрация: 6-February 08 Пользователь №: 374 Спасибо сказали: 149 раз(а) |
google на запрос "c:\NevShot.bmp" первой же выдаёт ссылку на "лицокнигу":
_ttp://www.facebook.com/note.php?note_id=186139338110083 QUOTE The developers of The Neverhood created secret shortcuts to make testing faster and easier. Most of these "cheats" were removed from the retail version, but a few are still there. While playing the game, hit the ENTER key, type one of the codes below, and then hit ENTER again. When the cheat code is right you will hear a short sound effect. For codes that solve specific puzzles, you have to already be in that part of the game. Here are some codes that you can try out: FastForward Makes everything move faster. Doing it again will set the speed back to normal. Great for getting through the Hall of Records! ScreenSnapShot Saves a screen shot image to your hard drive as a file called c:\NevShot.bmp. Doing it again will overwrite the previous one, so you have to move or rename the file each time. HappyBirthdayKlaymen Gets you out of the Nursery (the first room) LetMeOutOfHere Gets you out of the Nursery Lobby (the second room with the rings and Venus Fly Trap) Please Solves the panel puzzle in the Dynamite Shack заметка свежая - от 7 июля. учитывая, что и тема начата 9-го июля, напрашивается вопрос - чем вызвано такое одновременное возобновление интереса к этой игре? или это просто совпадение? Спасибо сказали:
|
-=CHE@TER=- |
Jul 17 2011, 07:29
Сообщение
#8
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
google на запрос "c:\NevShot.bmp" первой же выдаёт ссылку на "лицокнигу": Оба! Поражаюсь, где ты всё это находишь. (*улыбается*)_ttp://www.facebook.com/note.php?note_id=186139338110083 заметка свежая - от 7 июля. учитывая, что и тема начата 9-го июля, напрашивается вопрос - чем вызвано такое одновременное возобновление интереса к этой игре? или это просто совпадение? Я просто начал ковырять игру 2009.11.02 (эта дата стоит у меня в конце .HTM файла со статьёй). Но, в силу тех или иных причин, всё это затянулось надолго... у меня там ещё пара игр не начатых, хотя написать о них хочется - даже и не знаю когда время будет. Что касается конкретно кодов, то дата у файла с программой-брутфорсом у меня 2011.02.19 - значит и коды я начал где-то в это время (может от силы на неделю раньше) ковырять. Не оправдываюсь - просто говорю как есть. В плагиате меня, наверное, трудно заподозрить, нет? (*улыбается*) А насчёт кодов, я как раз где-то в феврале по всякому насиловал все известные мне поисковые системы и никаких результатов отличных от fastforward и happybirthdayklaymen не было. Если бы другие коды были - я обязательно их бы привёл, так как когда пишу об игре, то скрупулёзно собираю всю имеющуюся информацию воедино. Надо будет ещё раз по поисковикам пробежаться. Насчёт кодов - спасибо! Теперь я понял, что их надо будет пробовать ещё и при решении паззлов. Хочу у себя на сайте написать страничку с хешами и попросить всех, кто найдёт где они используются, написать об этом мне - я добавлю на сайт и выражу благодарность человеку, который их нашёл. Насчёт совпадения - тоже несколько этим удивлён. (*улыбается*) Как известно, события развиваются по спирали, так что, возможно, прошёл тот срок, после которого начинается новый виток интереса к этой игре. P.S. Последние два кода - новые. У меня нет для них хешей - видимо, проверяются в какой-то другой функции... блин, что же они так коды-то разбросали? LetMeOutOfHere - это в NHC.EXE.sub_446C40 - там ещё 8 хешей, походу (cmp edi, ########)... Please - это NHC.EXE.loc_453C10 - там, вроде бы, один код. Я, кажется, понял как искать коды надо - перед ними всегда такой код: cmp eax, 0Dh ; видимо, последняя нажатая клавиша - ENTER jg short loc_неважно jz loc_где_проверка_хеша_кода cmp eax, 1 jz short loc_неважно Но главное, там везде вызывается sub_401740 - надо будет от этого отталкиваться. О!!! Всё решает Олька + бряк на sub_401740. (*улыбается*) Скоро обо всём напишу. Быстро пробежался по игре, вот что удалось проверить. Не удалось обнаружить код для пропуска здоровенного экрана с историей страны и кода для включения радио (нужно возвращаться и дёргать за кольцо). много кодов |
-=CHE@TER=- |
Jan 1 2012, 14:14
Сообщение
#9
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Так, почистил и переместил тему сюда.
Ещё раз отдельное спасибо товарищу Axsis'у за помощь с кодами! Прочитать про коды и всё остальное теперь можно вот здесь: The Neverhood Chronicles |
-=CHE@TER=- |
Apr 22 2014, 13:00
Сообщение
#10
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Вчера обновил (так, мелкое обновление перед перемещением на другую площадку) патч для The Neverhood - со мной связался один товарищ и помог его оттестировать, так что теперь в него включено и исправление версии от "Фаргус". Если кто забыл или не в курсе, то эта версия падала при вызове меню. Существующие исправления этой проблемы заключались в тупом копировании и замены файлов NHC.EXE и HD.BLB от версии "Рисёча", что исправлением назвать можно было с натяжкой.
Как оказалось, в "Фаргус" криво закодировали две картинки: одна с надписью "опции" в главном меню, а вторая с надписями "загрузка отмена" для меню "Загрузка игры". Обе картинки были нормальные, но в хвосте, почему-то, содержали мусор из-за которого после декодирования изображение получалось больше чем нужно, происходило переполнение буфера и картинка начинала уничтожать память игры. Таким образом игра падала либо при вызове меню, либо при входе в подменю загрузки игры. Я поглядел картинки (они кроме PKWARE implode были сжаты неким алгоритмом RLE) и просто занулил один байт в каждой остановив распаковку после того как надпись полностью распаковалась, но за пределы отведённого ей буфера картинка ещё не вышла. Потом упаковал обратно (ещё то развлечение было - см. исходные коды, файл resource/packinfo.txt). Одна картинка упаковалась на пару байт меньше, а вот другая больше, так что пришлось мусорные байты в хвосте занулять, пока она не стала в упакованном виде такая же как и оригинальная. После этого я заменил их в HD.BLB и всё стало нормально (т.к. в упаковонном виде они столько же занимают или меньше и распакованного буфера под них хватает - специально таблицу размещения файлов в архиве проверял). А вот теперь интересное - встал вопрос как делать патч? Дело в том, что различия в упакованных данных были слишком большие, так что пришлось полностью хранить патченные файлы для замены. Если кто помнит, то у меня все патчи можно как поставить, так и откатить. Если я включу в ресурсы патча только исправленные картинки, то мне где-то нужно будет сохранять оригинальные. Если и оригинальные и исправленные... то меня жаба давить начинает место зря тратить (около 8 Кб в сумме, но теме не менее). И тут меня осенило! Я выравнял файлы, чтобы они были одного размера - ко второму просто в хвост дописал байты из хвоста его оригинала, а затем поXORил оба патченных файла на их оригинальные версии. Получились этакие файлы-маски. Теперь всё что мне осталось - это записать CRC32 оригинального файла и изменённого. После чего патч выглядел так: Если ((CRC32_файла_в_архиве = CRC32_оригинального_файла) И (Install = Истина)) // ставим патч ИЛИ ((CRC32_файла_в_архиве = CRC32_патченного_файла) И (Install = Ложь)) // откатываем патч Тогда for i:=1 to file_size do file_in_archive[i]:=file_in_archive[i] xor xored_data[i]; file_in_archive - это как раз файл, который мы прочитали из архива, а xored_data - это файл-маска, полученный как "байты_оригинального_файла XOR байты_патченного_файла". Как мы помним, операция XOR чем удобна, что возвращает всё взад-назад. Рассмотрим на примере: $12 (original) xor $34 (patched) => $26 (xored) Но тогда: $12 (original) xor $26 (xored) => $34 (patched) $34 (patched) xor $26 (xored) => $12 (original) Т.е. благодаря созданной маске мы можем одной и той же операцией (XOR) как ставить патч, так и откатывать! И всё что нам нужно, так это хранить две CRC32 (жалкие 4*2 = 8 байт) для оригинального и патченного файла (для каждого файла, которые мы будем заменять), чтобы знать когда какой ставить, а также случайно не поставить патч на другую версию игры. Иными словами, я в размер одного файла, впихнул сразу два: оригинальный и патченный! |
Siberian GRemlin |
Apr 23 2014, 12:50
Сообщение
#11
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Ты уверен, что смотрел второе, исправленное издание от «Фаргуса»? Может в нём именно это и исправили. На других дисках также встречалась официальная заплатка, которая лично мне неизвестно что исправляет.
Спасибо сказали:
|
-=CHE@TER=- |
Apr 24 2014, 05:46
Сообщение
#12
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Тут проблема в том, что фиг знает как отличить первое издание от второго.
Я когда искал в Интернете диски с "Фаргусом", то там хорошо, если написано что перевод от "Фаргус", а то и вовсе просто "русский перевод" - и сиди гадай, "Рисёч" это или кто. Другую версию "Фаргуса" я какую-то находил, но там было очень забавно - на диске файлы NHC.EXE и HD.BLB были тупо заменены... версией от "Рисёча". То ли кто-то сам диск собирал, то ли это действительно так вторая версия от "Фаргус" выглядела - фиг знает. Просто выкачивать все версии которые только попадаются (это с учётом того, что некоторые могут быть одними и теми же, только залитыми на разные обменники) - удовольствие ниже среднего, так что я забил на эту затею, поэтому на сайте и написал тогда (сейчас уже убрал это объявление из статьи), что если у кого-то проблемы с версией от "Фаргус", то пусть мне пишут, чтобы это точно была та самая битая версия. Если ты мне с обеих версий (1 и 2) предоставишь файлы NHC.EXE и HD.BLB я могу поглядеть что там изменили. |
Siberian GRemlin |
Apr 24 2014, 13:14
Сообщение
#13
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Проверил. Второе издание отличается только исправленным файлом «DATA\A.BLB», заплатка также содержит только его. Описание заплатки.
QUOTE Hебывальщина (Neverhood) ------------------------ Если пpи пpохождении игpы Windows выдает системнyю ошибкy и закpывает игpy, то необходимо yстановить повеpх игpы этy пpогpаммy. запyстите SETUP.EXE Спасибо сказали:
|
-=CHE@TER=- |
Apr 24 2014, 14:11
Сообщение
#14
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Ну, значит моё исправление точно лишним не будет. (*улыбается*)
A.BLB - это, вроде бы, Audio, нет? Интересно, что там поправили. Вообще, здесь, на самом деле, интересно - проходимы ли обе эти версии и в какой момент игра падает. Архив этот на диске, кстати, нельзя поправить - для этого придётся делать полную nocd-установку и там уже исправлять. К слову сказать, любая версия от "Фаргуса" проходима при одном условии: запрещается нажимать клавишу "ESC". (*улыбается*) Т.е. проходить игру нужно за один присест, что, конечно же, жутко неудобно, да и удовольствия мало. Вообще, у "Фаргус" перевод тяп-ляп сделан, это касается всего: как криво перерисованной графики, изуродованных видеофайлов, так и самих архивов - они криво перепакованны. К примеру размер в архиве у некоторых файлов указан больше, чем они там на самом деле есть. Распакованный буфер тоже часто больше чем необходим, но тут уж лучше больше, чем меньше. Возможно, кстати, в A.BLB такой косяк и приводил к краху игры. У "Рисёча" всё аккуратно, но они невкупили, что все файлы в оригинале выравнивались на 32 бита (4 байта), так что у них всё упаковано назад впритык, хотя для игры это и не критично, но доступ и операции были бы чуток быстрее. И последнее, что хочу сказать - у В.Анисимовского (автор Game Audio Player) в доках по формату (BLB-SFX.TXT) куча недоработок. Я в исходных кодах дал ссылку на сайт, где все поля архива расписаны. Только то, что они по формату изображения там пишут, читать не нужно (там тоже недоработки) - тут уже только в исходные коды SCUMMVM залазить чтобы разобраться. |
Siberian GRemlin |
Mar 26 2018, 08:45
Сообщение
#15
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Какие технические сложности могут возникнуть при переводе данной игры с нуля?
|
-=CHE@TER=- |
Mar 26 2018, 09:47
Сообщение
#16
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Какие технические сложности могут возникнуть при переводе данной игры с нуля? Кучно вы пошли, кучно. (*улыбается*)У меня неделю назад один товарищ спрашивал как текст стены достать (он видеообзор делает). Я ему вытащил тексты из всех трёх версий (оригинал и два перевода) стены, писем-подсказок (второй экран игры, вниз по лестнице) и там ещё что-то было. А, кажись, текст на машинке "BOBBY" (это который подсказка для правильной комбинации: Blue Orange Blue Blue Yellow). Он, к моему удивлению, тоже как строка хранится. Товарищ предложил сделать нормальный перевод (поправить существующие) и даже вызвался помочь стену перевести, но мне это не особо интересно, так что я отказался, ибо лучше перевод с нуля делать, чем править то что есть. Итак, что нужно, чтобы сделать нормальный перевод: - самая главная проблема - все тексты хранятся в I.BLB, который лежит на CD-диске, так что перевод - это либо пересобрать полностью образ, либо делать portable-версию (с No-CD и установщиком с оригинального диска); - видеоролики: .SMK, там часть надписей, но Smacker старый, а Smacker Tools из RadVideoTools, вроде бы, делает только новый (по-хорошему, разобрать формат сжатия, в том же ffmpeg, вроде бы, есть, и изменить только кадры с текстом, чтобы качество при пережатии совсем не упало); - текст пунктов меню и ещё там пара других вещей - это картинки, в собственном формате игры, описание формата можно в исходных кодах SCUMMVM подсмотреть, я их вытаскивал из перевода "Фаргуса", ибо они были криво упакованы из-за чего игра валилась (переполнение памяти); текст, кстати, с прозрачностью (там только буквы и прозрачный фон), так что как его в "Фаргусе" умудрились запороть я даже представить себе не могу (см. перевод "Рисёча"); - тексты, как я уже сказал, лежат в I.BLB, это обычный текст, но, как и многое другое, сжат, в принципе, сжатие можно для переведённых файлов отключить (флагами в заголовке таблицы размещения файлов делается); - формат файлов-текстов из I.BLB (после распаковки!): DWORD count; // количество строк DWORD [count]; // относительные смещения (т.е. после этой таблицы - первое смещение 0) на начало строк Все строки ASCIIZ (т.е. с завершающим нулём). Но! Один такой указатель может указывать на насколько строк: CODE Dear Klaymen,| |Please feed my|pet flytrap. He|eats ring-food.| |I do not.| |Love Willie| | Здесь символы "|" - это нули. Поэтому чтобы узнать сколько реально данных в одной строке, нужно брать разницу между следующим смещением и текущим (или концом файла, если смещение последнее). - шрифты - это, видимо, реальная проблема, потому что и "Фаргус", и "Рисёч" заменили английские буквы русскими и у каждого из них своя таблица перекодировки (мне пришлось её по ходу дела восстанавливать, чтобы текст читаемый был); формат шрифтов мне неизвестен (ну, т.е. картинку-то с ними достать можно, а вот где лежат размеры и смещения для неё, т.е. какой символ с какой позиции брать и какая у него ширина/высота - этого я не знаю, но, опять же, в SCUMMVM подсмотреть можно); - ну и хорошо бы при упаковке взад-назад, как в игре, вернуть сжатие где оно есть и сохранить выравнивание на 32 бита (4 байта) для каждого файла в .BLB, как это было в оригинале. Вроде бы, всё. |
-=CHE@TER=- |
Mar 28 2018, 10:16
Сообщение
#17
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Товарищ закончил видео:
The Neverhood - адаптация от Дядюшки Рисеча или перевод Фаргуса? [Фикализация] (2022) На мой взгляд получилось очень годно (если закрыть глаза на странно моргающие картинки при fadein и fadeout), кроме того разобрана стена, подсказки (и их кривизна в переводе) и сами переводы. Видеообзоры The Neverhood и его переводов которые видел до этого, были обычными бла-бла-бла в общем и целом об игре. Кстати говоря о переводах, я тут подумал, что Neverhood, по идее, должно было бы переводиться как "Нигдетамия". Если я правильно понимаю, что название игры образовано от слова neighborhood, т.е. окрестность, какая-то область. |
Siberian GRemlin |
Mar 28 2018, 13:54
Сообщение
#18
|
Advanced Member Группа: CTPAX-X Сообщений: 537 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 221 раз(а) |
Нет, «hood» это суффикс, используемый в существительных английского языка. «Небывальщина» — вполне адекватный перевод названия игры. Можно перевести и как «Небылица» или иным синонимом.
Спасибо сказали:
|
-=CHE@TER=- |
Apr 12 2018, 15:55
Сообщение
#19
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Кстати, что-то я протупил - в игре есть несколько моментов, которые будет сложно переводить.
Например история на видеокассетах - т.е. там либо все ролики пережимать и добавлять субтитры, либо переозвучивать. Плюс, на вскидку, три реплики, к которым субтитров не вставишь (ибо там не видео): телевизор на потолке ("Klaymen! Say knock-knock!"), орущий Willie ("Klaymen! Up here!") у робота с медведем и ещё глаз, который говорит "а это ты? иди нафиг". Может ещё что есть, но я сходу не вспомню. |
-=CHE@TER=- |
Apr 11 2020, 13:25
Сообщение
#20
|
Walter Sullivan Группа: Root Admin Сообщений: 1,361 Регистрация: 4-February 08 Пользователь №: 3 Спасибо сказали: 314 раз(а) |
Ну, начну в хронологическом порядке про хеши - с замены абракадабры подобранной "в лоб" для The Neverhood на нормальные слова и словосочетания.
Хотя, конечно, началось с того, что в начале недели решил хеши подобрать к C&C:RA1 demo, но об этом я в другой теме напишу. Пока разбирался как бы забрутфорсить RA1, решил вернуться к The Neverhood и сделать атаку не просто по словарю (1 слову), а комбинацию из двух слов, ибо по одному слову подбирался только код "skipper" (ну и "please", но он и так известен был). Стандартно это выглядело бы так: CODE for (j = 0; j < max_words; j++) { Два вложенных цикла (по i и j), где слова склеиваются каждое с каждым.for (i = 0; i < max_words; i++) { strcpy(str_buff, wordlist[i]); strcat(str_buff, wordlist[j]); hash = Nev_Hash(str_buff); if ((hash == ...) || (hash == ...) ...) { save_hash_to_file(...); } } } Понятно, что код выше не оптимизированный, его можно оптимизировать, посчитав, например, один раз длинну каждого слова и далее делать не strcpy() и strcat(), а один раз в верхнем цикле memcpy() и второй раз уже memcpy() с длины первого слова. Копирование памяти работает куда быстрее, чем strcpy() и strcat() которым приходится длинну строки считать. Ну и всякого по мелочи: перевести сразу все строки в верхний регистр, чтобы отключить это в функции хеша и т.д. И я уже хотел было всё это начать делать, но тут спросил себя: все эти вещи, безусловно, дадут прирост, но не настолько большой как хотелось бы, так что можно ли как-то посчитать от каждого слова хеш и уже складывать хеши, что будет в разы быстрее? Помните алгоритм хеширования? См. выше Axsis очень подробно его объяснил. Каждая буква, по сути, это сдвиг, на сколько сдвинуть, затем xor'ить этот бит. При сдвиге за 31 снова попадаем на ноль и так по кругу. Давайте посмотрим на примере. Пусть нам нужно посчитать хеш от строки из двух символов: "0A" (ноль и 'a'). Код нуля 48, код 'A' - 65. Хеш функция считает так: shift += isdigit(ch) ? (ch - 64 + 22) : (ch - 64); Т.е. если это цифра, то: 48 - 64 + 22 = 6 (для нуля) А если это буква, то просто: 65 - 64 = 1 (для буквы 'A') Т.е. хеш для строки "0A" будет: CODE // начало Таким образом, хеш для строки из двух символов "0A" будет равен 192 или 1100 0000 в двоичном представлении.shift = 0; hash = 0; // для нуля shift += 48 - 64 + 22; // 6 shift &= 0x1F; // не более 31 hash ^= (1 << shift); // hash == 0 ^ (1 << 6) == 64 (0100 0000) // для букв 'A' shift += 65 - 64; // 7 (6 + 1) shift &= 0x1F; // не более 31 hash ^= (1 << shift); // hash == 64 ^ (1 << 7) == 64 ^ 128 ==> 192 == 0100 0000 ^ 1000 0000 == 1100 0000 А теперь предположим, что у нас есть изначально хеши отдельно от нуля и отдельно от 'A'. Можно ли их сложить? Конечно! 'A': hash = 64 (0100 0000); shift = 6 '0': hash = 2 (0000 0010); shift = 1 Чтобы получить хеш от суммы слов, нам нужно взять второй хеш, затем циклически (т.е. когда сдвинутые биты появляются справа, а не исчезают) сдвинуть его влево на значение shift, которое осталось после подсчёта первого хеша, после чего будет достаточно сделать xor на хеш первого слова! CODE #pragma pack(push, 1) typedef struct { char *value; // ссылка на слово из словаря для вывода в файл uint32_t hash; // хеш этого слова uint8_t shift; // сдвиг после подсчёта хеша } bin_list; #pragma pack(pop) uint32_t __inline__ merge_hash(bin_list *a, bin_list *b) { return(a->hash ^ ((b->hash << a->shift) | (b->hash >> (32 - a->shift)))); } Таким образом, всё что нам будет нужно - это один раз посчитать подсчитать хеши от всех слов и сохранить их вместе со значением сдвига, а дальше работать с ними как с простыми числами! Скорость работы получилась просто взрывная - я все пары слов на 1 ядре перебрал за 35 минут! Сейчас только понял, что можно было ещё дальше оптимизировать - заранее посчитать все 32 формы сдвига для каждого хеша и тупо брать по такому массиву, через a->shift как индекс и затем делать xor - будет ещё быстрее, но сожрёт дополнительно 4*32 = 128 байт на каждое слово. 370100 слов * 128 = 47 372 800 (~45 Mb) В принципе, по памяти терпимо - это даже не 100 Мб. Совпадений, кстати, сказать, было достаточно много, так что пришлось их вручную просматривать. Мне кажется, я угадал только с тремя кодами: itsshowtime hellobemocked workedupdrying Возможно ещё эти: mydeeds craneprotectsfrolicks С кодом для получения всех видеокассет мне крупно повезло - программа выдала мне такое совпадение первым же вариантом: CHOWTIME ITS Откуда я уже сразу догадался какой код там был - It's showtime (потому что слова showtime в словаре, через который я делал атаку, почему-то не было). Причём для сайта мне пришлось выбирать наиболее подходящие, да и просто культурные варианты. Под катом примеры того, что можно было получить. WARNING EXPLICIT LANGUAGE Брутфорсить с тремя словами я начал, но быстро эту идею забросил (от этого остались только пара кодов начинающихся с "a..."), ибо: 370100 слов * 35 минут (перебор двух слов) = 12953500 минут = ((12953500 / 60) / 24) / 365 ~ 24.6 В общем 25 лет. Даже если я разобью на 4 ядра и заоптимизирую - это будет около 6 лет. Но проблема тут даже не в этом, а в том, что пары слов дали мне 12 с лишним тысяч строк совпадений. Сколько мне вариантов дадут три слова мне даже думать не хочется, ведь это же потом ещё и отсматривать придётся. По хорошему из словаря бы выкинуть все странные и редкоиспользующиеся слова, добавить современные, тогда и перебирать было бы быстрее и результат был бы осмысленнее. Но на это тоже нужно много времени, поэтому пусть уж будет как есть. |
Упрощённая версия | Сейчас: 1st November 2024 - 13:29 |