Версия для печати темы

Нажмите сюда для просмотра этой темы в оригинальном формате

CTPAX-X _ Ресурсы _ The Neverhood

Автор: -=CHE@TER=- Jul 9 2011, 12:33

Пишу сейчас страничку для сайта (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

$10410127 - "AACCHFFD" wink.gif
Правда у меня демка с какими-то артефактами работает...
_ttp://fastpic.ru/view/25/2011/0710/5d5d4d76cb7d379fd6feb5c044daacc0.png.html

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

Автор: -=CHE@TER=- Jul 10 2011, 04:30

QUOTE(Axsis @ Jul 9 2011, 20:07) *
$10410127 - "AACCHFFD" wink.gif
Вай!!! Шайтан!!! (*улыбается*)
Обязательно выражу тебе благодарность в статье за помощь с генерацией строк для кодов.


QUOTE(Axsis @ Jul 9 2011, 20:07) *
Правда у меня демка с какими-то артефактами работает...
Я через D3DWindower (_ttp://www.old-games.ru/utils/soft/) игры запускаю - так и дебажить удобнее, когда игра в окне. Кстати, замени ещё в исполняемом файле игры (убирает cli и sti, чтобы для запуска режим совместимости не требовался):
000196BF: FA 90
000196E2: FB 90
Может, после этого пойдёт нормально.

QUOTE(Axsis @ Jul 9 2011, 20:07) *
Алгоритм опишу чуть позже, а может к тому времени и сам разберёшь, он на самом деле довольно прост.
Слушай, если не сложно, опиши, пожалуйста, а то я сам как-то пока не допираю. В принципе, он был бы прост, если бы не гадское условие "If C >= $20 Then C:=C - $20;", которое портит всё малину.

С нетерпением хочется посмотреть какие коды есть в игре и что они делают.
Сколько ещё нераскрытых тайн хранят в себе игры! (*улыбается*)
Я, например, натолкнулся на такой интересный код как kimberly (если у меня на сайте страничку с Powerslave читал) - кто знает, что интересного есть здесь. (*улыбается*)

Автор: Axsis Jul 11 2011, 14:15

В общем каждый символ кода (цифра или буква) сдвигает бит, которым 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-й бит.)

Описание получилось немного дурацкое, но думаю ты разберёшься unsure.gif

Автор: -=CHE@TER=- Jul 11 2011, 17:05

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

Автор: -=CHE@TER=- Jul 16 2011, 08:44

Вот так:

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

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-го июля, напрашивается вопрос - чем вызвано такое одновременное возобновление интереса к этой игре? или это просто совпадение? smile.gif

Автор: -=CHE@TER=- Jul 17 2011, 07:29

QUOTE(Axsis @ Jul 16 2011, 20:00) *
google на запрос "c:\NevShot.bmp" первой же выдаёт ссылку на "лицокнигу":
_ttp://www.facebook.com/note.php?note_id=186139338110083

заметка свежая - от 7 июля. учитывая, что и тема начата 9-го июля, напрашивается вопрос - чем вызвано такое одновременное возобновление интереса к этой игре? или это просто совпадение? smile.gif
Оба! Поражаюсь, где ты всё это находишь. (*улыбается*)
Я просто начал ковырять игру 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. (*улыбается*)
Скоро обо всём напишу.

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

30094E80 - GBAACBCIA - решает загадку с поворотом крана, на котором прикреплён мишка (рядом с роботом); для окончания нужно будет потом просто нажать кнопку сверху
18B0C402 - AIDAEABDA - решает загадку с картинками, которые надо открывать парами
A50535B1 - DABABBACBFBCBA - решает задачку с мышкой и сыром
0ED06400 - JCAFBABAA - решает головоломку с пятнашками в виде буквы "H" в начале
9A4804AA - ABBBCICCBAC - устанавливает кристаллы правильно в уменьшающей машине (BOBBY)
030564C1 - FACCABBFAG - решает загадку с жидкостью для увеличения на экране c уменьшающей машиной (BOBBY)
655CF022 - ADGAAACAABBBCA - решает загадку с жидкостью для увеличения на экране со статуями
412213CB - ABCAAACEDCFB - пускает воду на экране, с музыкальными трубками; если набрать второй раз - решает задачку с ними (позволяет открыть дверь при нажатии на кнопку)
151AD442 - AEDBBABBADBB - решает загадку с тремя ключами в конце игры
14210006 - AANEEB - please - решает задачку с динамитом
AA0E6C00 - JABACAAFBBB - открывает веритикальный ползунок внутри пушки; если набрать второй раз - то открывает горизонтальный
0110AC40 - FDABBED - решает головоломку с кубиками для управления мостом
3108760F - AAAFABAAEEDAC - открывает дверь с тремя засовами в начале
20C11A08 - CFBADFAF - решает задачку с радио - открывает левую дверь - наружу (колокольчик должен быть нажат!)
109B5000 - LBBABACE - решает задачку с радио - открывает правую дверь - внутрь (колокольчик должен быть нажат!)
56530108 - CEHACBCABB - решает загадку на двери со знаками (рядом с крутящимся домом давящим овец снизу)
C8C004D4 - BBBACLADCA - выкидывает из радиобудки на улицу (чтобы не крутить приёмник)
2C034A29 - CBDBCBAIABC - даёт все видеокассеты (работает на любом экране с проигрывателем)

Автор: -=CHE@TER=- Jan 1 2012, 14:14

Так, почистил и переместил тему сюда.
Ещё раз отдельное спасибо товарищу Axsis'у за помощь с кодами!
Прочитать про коды и всё остальное теперь можно вот здесь:

http://ctpax-cheater.losthost.org/htmldocs/nvh.htm

Автор: -=CHE@TER=- Apr 22 2014, 13:00

Вчера обновил (так, мелкое обновление перед перемещением на другую площадку) патч для 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

Ты уверен, что смотрел http://siberian-studio.ru/loc_piratruz.php?game=TheNeverhood? Может в нём именно это и исправили. На других дисках также встречалась официальная заплатка, которая лично мне неизвестно что исправляет.

Автор: -=CHE@TER=- Apr 24 2014, 05:46

Тут проблема в том, что фиг знает как отличить первое издание от второго.
Я когда искал в Интернете диски с "Фаргусом", то там хорошо, если написано что перевод от "Фаргус", а то и вовсе просто "русский перевод" - и сиди гадай, "Рисёч" это или кто.
Другую версию "Фаргуса" я какую-то находил, но там было очень забавно - на диске файлы NHC.EXE и HD.BLB были тупо заменены... версией от "Рисёча". То ли кто-то сам диск собирал, то ли это действительно так вторая версия от "Фаргус" выглядела - фиг знает.
Просто выкачивать все версии которые только попадаются (это с учётом того, что некоторые могут быть одними и теми же, только залитыми на разные обменники) - удовольствие ниже среднего, так что я забил на эту затею, поэтому на сайте и написал тогда (сейчас уже убрал это объявление из статьи), что если у кого-то проблемы с версией от "Фаргус", то пусть мне пишут, чтобы это точно была та самая битая версия.
Если ты мне с обеих версий (1 и 2) предоставишь файлы NHC.EXE и HD.BLB я могу поглядеть что там изменили.

Автор: Siberian GRemlin Apr 24 2014, 13:14

Проверил. Второе издание отличается только исправленным файлом «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

Ну, значит моё исправление точно лишним не будет. (*улыбается*)
A.BLB - это, вроде бы, Audio, нет? Интересно, что там поправили.
Вообще, здесь, на самом деле, интересно - проходимы ли обе эти версии и в какой момент игра падает.
Архив этот на диске, кстати, нельзя поправить - для этого придётся делать полную nocd-установку и там уже исправлять.
К слову сказать, любая версия от "Фаргуса" проходима при одном условии: запрещается нажимать клавишу "ESC". (*улыбается*) Т.е. проходить игру нужно за один присест, что, конечно же, жутко неудобно, да и удовольствия мало.
Вообще, у "Фаргус" перевод тяп-ляп сделан, это касается всего: как криво перерисованной графики, изуродованных видеофайлов, так и самих архивов - они криво перепакованны. К примеру размер в архиве у некоторых файлов указан больше, чем они там на самом деле есть. Распакованный буфер тоже часто больше чем необходим, но тут уж лучше больше, чем меньше. Возможно, кстати, в A.BLB такой косяк и приводил к краху игры.
У "Рисёча" всё аккуратно, но они невкупили, что все файлы в оригинале выравнивались на 32 бита (4 байта), так что у них всё упаковано назад впритык, хотя для игры это и не критично, но доступ и операции были бы чуток быстрее.
И последнее, что хочу сказать - у В.Анисимовского (автор Game Audio Player) в доках по формату (BLB-SFX.TXT) куча недоработок. Я в исходных кодах дал http://wiki.multimedia.cx/index.php?title=BLB на сайт, где все поля архива расписаны. Только то, что они по формату изображения там пишут, читать не нужно (там тоже недоработки) - тут уже только в исходные коды SCUMMVM залазить чтобы разобраться.

Автор: Siberian GRemlin Mar 26 2018, 08:45

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

Автор: -=CHE@TER=- Mar 26 2018, 09:47

QUOTE(Siberian GRemlin @ Mar 26 2018, 08:45) *
Какие технические сложности могут возникнуть при переводе данной игры с нуля?
Кучно вы пошли, кучно. (*улыбается*)
У меня неделю назад один товарищ спрашивал как текст стены достать (он видеообзор делает). Я ему вытащил тексты из всех трёх версий (оригинал и два перевода) стены, писем-подсказок (второй экран игры, вниз по лестнице) и там ещё что-то было. А, кажись, текст на машинке "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

Товарищ закончил видео:
https://www.youtube.com/watch?v=IAklyZbnEHk (2018)
https://www.youtube.com/watch?v=qbe2C0uTC3c (2022)
На мой взгляд получилось очень годно (если закрыть глаза на странно моргающие картинки при fadein и fadeout), кроме того разобрана стена, подсказки (и их кривизна в переводе) и сами переводы. Видеообзоры The Neverhood и его переводов которые видел до этого, были обычными бла-бла-бла в общем и целом об игре.
Кстати говоря о переводах, я тут подумал, что Neverhood, по идее, должно было бы переводиться как "Нигдетамия". Если я правильно понимаю, что название игры образовано от слова neighborhood, т.е. окрестность, какая-то область.

Автор: Siberian GRemlin Mar 28 2018, 13:54

Нет, «hood» это суффикс, используемый в существительных английского языка. «Небывальщина» — вполне адекватный перевод названия игры. Можно перевести и как «Небылица» или иным синонимом.

Автор: -=CHE@TER=- Apr 12 2018, 15:55

Кстати, что-то я протупил - в игре есть несколько моментов, которые будет сложно переводить.
Например история на видеокассетах - т.е. там либо все ролики пережимать и добавлять субтитры, либо переозвучивать. Плюс, на вскидку, три реплики, к которым субтитров не вставишь (ибо там не видео): телевизор на потолке ("Klaymen! Say knock-knock!"), орущий Willie ("Klaymen! Up here!") у робота с медведем и ещё глаз, который говорит "а это ты? иди нафиг". Может ещё что есть, но я сходу не вспомню.

Автор: -=CHE@TER=- Apr 11 2020, 13:25

Ну, начну в хронологическом порядке про хеши - с замены абракадабры подобранной "в лоб" для The Neverhood на нормальные слова и словосочетания.
Хотя, конечно, началось с того, что в начале недели решил хеши подобрать к C&C:RA1 demo, но об этом я в другой теме напишу. Пока разбирался как бы забрутфорсить RA1, решил вернуться к The Neverhood и сделать атаку не просто по словарю (1 слову), а комбинацию из двух слов, ибо по одному слову подбирался только код "skipper" (ну и "please", но он и так известен был). Стандартно это выглядело бы так:

CODE
for (j = 0; j < max_words; 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(...);
    }
  }
}
Два вложенных цикла (по i и j), где слова склеиваются каждое с каждым.
Понятно, что код выше не оптимизированный, его можно оптимизировать, посчитав, например, один раз длинну каждого слова и далее делать не 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
// начало
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
Таким образом, хеш для строки из двух символов "0A" будет равен 192 или 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
QUOTE
8580A64D = CLINTON SUCKS (игра вышла в 1996, а президентом (если это тот Clinton) он был с 1993 по 2001, так что кто знает?..)
A50535B1 = DISPOSES MATRIARCHY
56530108 = PIROZHOK RIME
8141A000 = DEFILED COW
4339581D = SOVKHOZ SINISTRUOUS
C8C004D4 = GOLD PEDERAST


Брутфорсить с тремя словами я начал, но быстро эту идею забросил (от этого остались только пара кодов начинающихся с "a..."), ибо:
370100 слов * 35 минут (перебор двух слов) = 12953500 минут = ((12953500 / 60) / 24) / 365 ~ 24.6
В общем 25 лет. Даже если я разобью на 4 ядра и заоптимизирую - это будет около 6 лет.
Но проблема тут даже не в этом, а в том, что пары слов дали мне 12 с лишним тысяч строк совпадений.
Сколько мне вариантов дадут три слова мне даже думать не хочется, ведь это же потом ещё и отсматривать придётся.
По хорошему из словаря бы выкинуть все странные и редкоиспользующиеся слова, добавить современные, тогда и перебирать было бы быстрее и результат был бы осмысленнее.
Но на это тоже нужно много времени, поэтому пусть уж будет как есть.

Автор: hidefromkgb Nov 23 2020, 10:42

Я верно понимаю, что перебиралось всё со скоростью 370100² / 35 / 60 ~ 65 миллионов XOR операций в секунду?

Спрашиваю, потому что у меня здесь есть игровая видеокарта NVidia RTX 2070s с теоретической пиковой производительностью в 10 триллионов (т.е. 10 миллионов миллионов) операций в секунду, а это означает что третью степень она посчитает за менее чем два часа.

Автор: -=CHE@TER=- Nov 23 2020, 13:01

QUOTE(hidefromkgb @ Nov 23 2020, 10:42) *
Я верно понимаю, что перебиралось всё со скоростью 370100² / 35 / 60 ~ 65 миллионов XOR операций в секунду?
Ну, наверное. Я не знаю какая тут производительность - Pentium 1,5 ГГц.

QUOTE(hidefromkgb @ Nov 23 2020, 10:42) *
Спрашиваю, потому что у меня здесь есть игровая видеокарта NVidia RTX 2070s с теоретической пиковой производительностью в 10 триллионов (т.е. 10 миллионов миллионов) операций в секунду, а это означает что третью степень она посчитает за менее чем два часа.
Так я ж и пишу - больше 2-х слов перебирать смысла нет - там столько коллизий будет, что ты запаришься их отсматривать в поисках осмысленных выражений. Там уже анализатор текста, ИИ и прочие нейронные сети писать придётся. (*улыбается*)

Автор: -=CHE@TER=- Jul 19 2022, 15:22

QUOTE
Rigel (перевод и графика) и -=CHE@TER=- (техническая часть) выпустили полный русский текстовый корректный перевод игры The Neverhood Chronicles (DreamWorks Interactive / The Neverhood, Inc. / 1996). "Корректный перевод" означает, что перевод сделан максимально близко к оригиналу, а не так, как это было у издателей "Дядюшка Рисёч" и "Фаргус". Переведено всё: видеоролики, записки, стена, все рисунки с надписями и даже головоломка с уменьшающей машиной (в этом месте существующие прохождения не помогут, думайте сами). Перевод полностью текстовый. Это означает, что в видеороликах, где есть речь или надписи на английском языке, были добавлены внешние текстовые субтитры. Также добавлена поддержка двух упомянутых выше русских версий от издателей "Дядюшка Рисёч" и "Фаргус", где "на лету" исправляются поломанные файлы ресурсов, позволяя играть без ошибок и вылетов. В этом случае необходимо выбрать "<original>" при запуске, чтобы эти версии работали "как есть", без подключения перевода (который настоятельно рекомендуется использовать только с оригинальной английской версией игры).
По технической части перевод включает в себя такие вещи, как:
- исправление ошибок оригинальной игры;
- игра больше не работает с реестром и при полной установке полностью переносима (portable);
- режимы "DirectDraw Emulated" и новый "Compatibility renderer", работающий на любой системе;
- поддержка джойстиков и игровых устройств;
- автоматическое исправление ресурсов у версий от издателей "Дядюшка Рисёч" и "Фаргус", чтобы они не рушили игру (исправлены только ошибки, приводящие к аварийному завершению программы, всё остальное нетронуто и оставлено как есть);
- возможность добавлять свои переводы на других языках - сделан полный набор утилит переводчика (Language Translation Kit);
- и многое-многое другое - см. файл "NHC-READ.TXT" с полным списком изменений.

Перевод, исходные коды и утилиты ко всему можно взять здесь:
http://ctpax-cheater.losthost.org/htmldocs/nvh.htm#nvh_addon

Также рекомендуется к просмотру обновлённый обзор русских переводов издателей "Дядюшка Рисёч" и "Фаргус" от Rigel, приуроченный к выходу перевода - это второе издание обзора - переработанное и дополненное многими новыми интересными находками, а также теперь без ненормативной лексики и другого шок-контента:
https://www.youtube.com/watch?v=qbe2C0uTC3c


Siberian GRemlin, извини, что я тебя не предупредил, но, во-первых, Rigel ещё до тебя предлагал мне переводом заняться, а, во-вторых, мы выпустили перевод под максимально свободными лицензиями (для технической и творческой части) - каждый может делать с ним всё что захочет - мы полностью отдаём перевод и все его файлы в свободный доступ. В частности мы пытаемся договориться с разработчиками SCUMMVM, чтобы его поддержку туда добавили.

Автор: Siberian GRemlin Jul 19 2022, 15:36

Э-э, а я тут каким боком? Меня хороший человек, конечно, просил не так давно перевести эту игру за вознаграждение, но у меня на это времени совсем не было и я даже не брался.

Ссылку я ему отправил, надеюсь, ему понравится.

Автор: -=CHE@TER=- Jul 19 2022, 15:45

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

Автор: Siberian GRemlin Jul 19 2022, 16:05

QUOTE(-=CHE@TER=- @ Jul 19 2022, 22:45) *
Просто ты на предыдущей странице спрашивал про то какие технические проблемы могут возникнуть при переводе и я подумал, что ты размышляешь над тем чтобы самому перевод сделать.
Я и размышлял, так как меня просили об этом. Просто, к тому времени я уже взял на себя куда большие обязательства и никак не мог ими пренебречь. Выкроить время на эту игру так и не удалось. Офигеть, прошло уже 4 года.

Автор: Siberian GRemlin Aug 13 2022, 09:51

Друг спрашивает, стоит ли ждать перевода «Skullmonkeys»?

Автор: -=CHE@TER=- Aug 13 2022, 15:02

Мы с Rigel даже никогда не затрагивали этот вопрос в переписке.
Точно скажу, что у меня в планах нет, да, думаю, и у него тоже.
Причины по которым я таким переводом заниматься вряд ли буду:
1. Это не моя любимая игра и кроме видосов на тытрубе ничего о ней не знаю. Сюда же отнесу что меня эта аркада не заинтересовала, к тому же, судя по многочисленным отзывам, она ещё и достаточно капризная (например, чтобы убить врага нужно точно пиксель-в-пиксель приземлиться ровно на середину его головы сверху иначе сразу гибнешь сам).
2. Это игра для PSX, а, значит, красивого решения с перехватчиком не получиться сделать - нужно будет именно пересобирать и менять ресурсы.
3. Не особо понимаю что там переводить кроме пуктов меню и пары субтитров в видеороликах. Это же аркада, там нет стен текста. Иными словами усилий для перевода по технической части будет нужно много, а переводить-то толком и нечего (возможно, конечно, я чего-то не знаю, т.к. никогда не играл сам, и где-то в этой игре есть большой объём текста...). Это даже не как из пушки по воробьям стрелять, а как ядерной боеголовкой по муравьям.