Этим летом вышла очередная игра из серии Batman Arkham, в ПК версии которой оказалось столько багов, что было принято беспрецедентное решение снять её с продаж. Я решил посмотреть, что же там такого ужасного.

Среди прочих наблюдается такой баг, на первый взгляд, случайный: иногда, когда Бэтмен прыгает с крыши, вместо того, чтобы ровно планировать, он колбасится некоторое время, потом делает довольно глубокий нырок, и только потом выравнивается. В результате в лучшем случае — весьма нежелательная потеря высоты, в худшем можно спугнуть врагов, а то и вообще свалиться им на голову.

На скриншоте изображён этот момент: вместо того, чтобы лететь вперёд, Бэтмен повернулся вниз головой, демонстрируя полнейшее пренебрежение к происходящему. Аналогичный баг был в предыдущей игре (Arkham Origins), и он до сих пор не исправлен. Видимо тот же самый кривой код был перенесён в новую игру. Попробуем найти, какие ошибки делают программисты в играх такого уровня, и исправить их.

В Origins баг был не таким неприятным: Бэтмен колбасился, но высоты не терял. А тут он падает вниз, что очень раздражает и мешает игре. Для начала попробуем уточнить, при каких условиях проявляется баг. Это оказывается не так просто. Пытаясь повторить глюк, можно сотни раз прыгать с крыши, и всё будет нормально. Однако, как только начинаешь играть, он появляется, причём в самые неудачные моменты. Вот как это выглядит:



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

Почему же так происходит? Как вообще можно найти в игре место с этой ошибкой? Оказывается, можно. Для этого воспользуемся Cheat Engine, который уже не раз упоминался на хабре. Принцип примерно такой:

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



Это оказалась середина длиннющей подпрограммы, почти наполовину состоящей из вычислений с плавающей точкой. Видимо это и есть код, полностью определяющий весь полёт Бэтмена. Начнём потихоньку его изучать. Как нам сообщил отладчик, скорость изменяется при выполнении команд, выделенных зеленым, значит она содержится в [rdi+0000144C], а перед этим вычисляется в регистре xmm8 (выделено красным).

Проверим это. Заменим команду subss на addss, и теперь скорость не будет падать, а только увеличиваться. Получился забавный аттракцион: можно носиться на огромной скорости по улицам, даже быстрее, чем в бэтмобиле, при этом не теряя высоты. Попадать в повороты на такой скорости становится трудновато. В нормальной игре это конечно, невозможно, то есть мы убедились, что действительно нашли код, отвечающий за полёт Бэтмена.



Теперь попробуем наоборот. Заменим обе команды на «subss xmm8,xmm8», то есть вычтем регистр сам из себя, в результате скорость должна стать равной нулю. Запустим игру. И тут мы обнаруживаем, что перед полётом имеется переходный этап, как раз та первая секунда, от момента, когда Бэтмен делает шаг в пустоту, до того, как он полностью расправит крылья. В этот момент срабатывает изменённая нами команда, и Бэтмен застывает в воздухе.

Это оказалось очень удобно. Теперь не нужно постоянно прыгать с крыши под определённым углом, при этом пытаясь дёрнуть мышкой в нужный момент, чтобы воспроизвести баг. Мы поймали тот самый момент, переход между прыжком и полётом, когда он происходит. Теперь отлично видно: пока камера смотрит выше определённого угла (примерно на линии горизонта), всё нормально, но как только она опускается ниже, вместе с ней опускается и Бэтмен, и после этого любое движение мышью вверх приводит к багу.



Настало время искать ошибку в коде. Попытки отключать куски программы наугад ничего не дали. Бэтмен застывает в нелепых позах, летит не туда, куда надо, вертится как волчок, но баг не исчезает. Остаётся кропотливо анализировать, что где хранится, и какие вычисления делаются. Начинаю просматривать всё ту же подпрограмму с начала, и вскоре находится такой фрагмент:



Не иначе как трем 16-битным значениям (в регистрах eax,edx,ecx) делают расширение знака. Это сразу наводит на мысль о трёх измерениях. А ну-ка посмотрим, что там в регистрах? Небольшие числа с разным знаком. Подвигаем мышью — значения изменяются. Видимо это реакция на манипулятор в виде векторов. Обнулим одно из значений, и убедимся, что Бэтмен теперь не реагирует на движение мыши вверх-вниз, а только в стороны. Конкретно это первое число из трёх, и оно сохраняется в памяти в ячейке [rsp+70] (выделено зелёным). Это поможет нам повторить баг в любой нужный момент.

Попробовав выполнять программу дальше по шагам, я быстро запутался в условных переходах и вычислениях. Однако, дойдя до знакомого места, где вычисляется скорость, я заметил в одном из регистров число, похожее на ранее найденные векторы. Только теперь это оказалась не мышь, а сам Бэтмен, а именно угол его наклона к горизонту, тангаж, если можно так сказать. В нормальном состоянии он имеет значения от -2548 до -15000, то есть от положения чуть ниже горизонта, до почти вертикально вниз.

Теперь воспроизводим баг. И тут оказывается, что когда Бэтмена колбасит, в этом регистре оказывается не нормальная ориентация, а какое-то произвольное число, причём даже не 16-битное, а 32-битное! Это всё объясняет. Где-то в вычислениях происходит ошибка, переполнение, или что-то вроде того, и в итоге Бэтмена мотает, как осенний лист на ветру.

Чтобы проверить это, смоделируем ситуацию. Найдём то место в памяти, где сохраняется «ошибочное» значение, и заменим его 32-битной константой. Получаем Бэтмена, застывшего в полете под фиксированным углом.



В ответ на движение мыши он поворачивает, расправляет крылья, двигает головой. Но его наклон к горизонту остаётся постоянным, причём неправильным. Бэтмен не может так летать, он не собирался так летать, к этому приводит ошибка при вычислении. К текущему углу добавляется неопределённое число, и хотя для рендеринга оно подгоняется под нужные пределы, в памяти хранится в непотребном виде. В каждом следующем цикле они достают это число, берут от него младшие 16 бит, и получают чёрт-те что. Поэтому процесс «дёргания» продолжается довольно долго, пока каким-то чудом число всё-таки не попадёт в правильный диапазон. Тогда бэтмен успокаивается и начинает лететь нормально.

И вот я снова блуждаю в коде, пытаясь определить, где в вычислениях что-то пошло не так. Из всей подпрограммы в 9 килобайт участок поиска сузился до примерно 1 килобайта, но понять здесь что-нибудь по-прежнему трудно. Через некоторое время я стал склоняться к мысли, что всё это будет слишком сложно, как вдруг заметил, что во многих SSE регистрах находится так называемое Nan (нечисло). Замечательно. Так вот в чём дело! Где-то в вычислениях получилось Nan, а стоит нечислу появиться один раз, как все операции с его участием тоже приведут к Nan, и пошло-поехало. Теперь нам достаточно пройти весь цикл по шагам, внимательно наблюдая, когда впервые появится Nan, и мы найдём то, что нам нужно:



Вот после выделенного вызова, оно и возникает. В этот момент xmm1 = 0.5, a xmm0 = -0.01. Заходим внутрь, и оказываемся в msvcr100.dll, функция powf (возведение в степень), то есть в данном случае, берется корень из отрицательного числа. Откуда же оно взялось, и почему это происходит так редко? После подробного изучения удалось выяснить, что здесь вычисляется. Рассмотрим на примере нормальную ситуацию:

В xmm0 у нас 600 — это крейсерская скорость Бэтмена. Из [rdi+0000144C] в xmm2 загружается 731 — это текущая скорость Бэтмена (заметим, это то же смещение, что в первом фрагменте кода, рассмотренном в самом начале). Затем они вычитаются (subss xmm2,xmm0), получается 131. Далее из [rdi+000013EC] берется 2200 — максимальная скорость, умножается на константу, опять вычитается xmm0 (600), получается 1270. Делим первую разницу на вторую (divss xmm2,xmm1), получаем 0,1031. Теперь это умножается на ранее вычисленный в xmm14 коэффициент (он зависит от угла, но сейчас это не важно, главное, что он всегда положительный), в итоге получаем 0,0268. Дальнейшее мы уже знаем, вычисляем из этого корень, всё хорошо.

А теперь, что получается, когда Бэтмен прыгает с крыши. Вся эта ветка выполняется, только если двинуть мышкой вверх, чтобы вычислить, на сколько можно повернуться вверх за следующий квант времени. В этот момент скорость Бэтмена оказалась равной 599. Из неё вычитают 600, получается -1, результат всей формулы отрицательный, и берут квадратный корень. Вот тут и получается Nan. Все дальнейшие вычисления совершенно очевидно идут насмарку, «нечисла» множатся, переводятся в 32-битное целое и в итоге мы получаем то, что видели.

Найдём это же место в предыдущей игре — Arkham Origins. Оказалось, там всё практически то же самое: крейсерская скорость Бэтмена тоже 600, поэтому подпрограмма нашлась почти сразу. Правда угол планирования немного ниже, вычисления идут на FPU, а корень вычисляется другим вызовом msvcr100.dll (потому что двойная точность)



Подведём итоги исследований. Полёт Бэтмена был задуман таким образом, что его скорость никогда не должна быть меньше 600. Когда он летит ровно, его скорость 600. Если он немного накреняется вниз, скорость возрастает. Когда он выравнивается, она плавно снижается до 600, но никогда не должна быть меньше. В результате программисты думали, что разница скоростей никогда не будет отрицательной, и спокойно вычисляют из этого квадратный корень.

Они сделали 3 ошибки. Не учли, что при определённых условиях вычисленная по их формуле скорость может упасть ниже 600. Потом не проверили, что берут корень из отрицательного числа. А потом вычисляли и хранили результат в 32-битной переменной, а брали от неё только 16 бит, в результате корень из отрицательного числа может браться всего один раз, а Бэтмена потом будет колбасить секунд десять.

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

Как исправить ошибку? Например, для Arkham Knight перед вычислением корня добавим команду «maxps xmm2,xmm9» (максимум), так как в xmm9 у нас ноль, результат всегда будет положительным. Для Origins используем команду «fabs» (модуль). Запускаем игру и убеждаемся, что глюков больше нет: Бэтмен не дёргается, а летит куда нужно.

Можно даже написать скрипты, которые найдут код по уникальной последовательности байт и исправят его. В принципе, для Origins можно прямо изменить.ехе-шник, а вот Arkham Knight защищен Denuvo, поэтому код можно менять только в памяти, когда игра уже загружена, что и делает Cheat Engine.

скрипт для Arkham Knight
<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="18">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"Fix gliding bug"</Description>
      <LastState Activated="0"/>
      <Color>80000008</Color>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

aobscanmodule(INJECT,BatmanAK.exe,F3 41 0F 59 D6 F3 0F 10 8F 28 14 00 00 0F 28 C2 E8 D4)
alloc(newmem,$1000,INJECT)

label(code)
label(return)

newmem:

code:
  mulss xmm2,xmm14
  maxps xmm2,xmm9
  jmp return

INJECT:
  jmp code
return:
registersymbol(INJECT)

[DISABLE]

INJECT:
  db F3 41 0F 59 D6

unregistersymbol(INJECT)
dealloc(newmem)

</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols/>
</CheatTable>

скрипт для Arkham Origins
<?xml version="1.0" encoding="utf-8"?>
<CheatTable CheatEngineTableVersion="18">
  <CheatEntries>
    <CheatEntry>
      <ID>0</ID>
      <Description>"Fix gliding bug (Origins)"</Description>
      <LastState Activated="1"/>
      <Color>80000008</Color>
      <VariableType>Auto Assembler Script</VariableType>
      <AssemblerScript>[ENABLE]

aobscanmodule(INJECT,BatmanOrigins.exe,D9 86 E8 0B 00 00 E8 3E)
alloc(newmem,$1000)

label(code)
label(return)

newmem:

code:
  fabs
  fld dword ptr [esi+00000BE8]
  jmp return

INJECT:
  jmp code
  nop
return:
registersymbol(INJECT)

[DISABLE]

INJECT:
  db D9 86 E8 0B 00 00

unregistersymbol(INJECT)
dealloc(newmem)


</AssemblerScript>
    </CheatEntry>
  </CheatEntries>
  <UserdefinedSymbols>
    <SymbolEntry>
      <Name>INJECT</Name>
      <Address> 00E3AB33</Address>
    </SymbolEntry>
  </UserdefinedSymbols>
</CheatTable>

Те, кто не хочет лезть в код игры, могут просто не трогать мышку в начале прыжка, или по крайней мере не двигать ей вверх. Ну и надеяться, что когда-нибудь разработчики это исправят. Кстати, пока я готовил пост, они выпустили очередной патч, после которого, похоже, всё стало ещё хуже. У многих игра стала вылетать, и пока не была возвращена в продажу. Впрочем, теперь я этому не удивлён.

Комментарии (98)


  1. pehat
    07.09.2015 19:11
    +70

    Для Origins используем команду «fabs» (модуль)

    Поймали злодеи академика, математика и программиста. Привели их на крышу высотного дома и сказали, что внизу натянут тент, кто спрыгнет и на тент попадет, тот жив останется. Академик развел теорию, долго чего-то думал, прыгнул – разбился. Математик быстро посчитал, прикинул, все учел, прыгнул и попал на тент, спасся. Программист думает: ну, математик все сосчитал, я сейчас так же сделаю. Разбегается, прыгает, и с воплем «Блин, перепутал знак!» улетает в небо…


    1. novoxudonoser
      07.09.2015 20:14
      -11

      <зануда stat="on">Мой дед называл этот анекдот бородатым.</зануда>
      


      1. pehat
        07.09.2015 21:16
        +10

        Ваш ник мумифицирует бороду деда.


      1. Juster
        07.09.2015 22:08
        +21

        И что? найдутся те, кто читает впервые.


      1. kivsiak
        08.09.2015 01:59
        +8

        «И что дед таки разбился? Не он задолбал прыгать туда-сюда, пристрелили нафиг»


  1. Starche
    07.09.2015 19:21
    +21

    Вот интересно. Вы реверс-инжинирингом смогли выловить и пофиксить баг. Неужели при всех нынешних мощнейших средствах отладки разработчики игры не могут докопаться до этой проблемы самостоятельно уже несколько лет (Origins вышел в 2013ом). Противная же проблема, играть мешает жутко.



    1. outcoldman
      07.09.2015 19:31
      +34

      Может быть пытались, но voron-vp.livejournal.com/42033.html


      1. Lamaster
        07.09.2015 23:01
        +1

        Вот так и не отличишь, правда это или шутка.
        /me ушёл думать


        1. pehat
          08.09.2015 02:26

          Персонажи есть, компанию угадать нетрудно, можно и проверить.


    1. halyavin
      07.09.2015 23:57

      Средства отладки со временем становятся только хуже. В релизе из-за все более умного компилятора дебаггер показывает что угодно, но только не значения переменных и не ту строку, которая сейчас исполняется. В дебаге, программа просто работает в 100 раз медленнее и нужно очень долго ждать загрузки (да и удастся ли вообще повторить баг при паре fps?).

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

      Каждое исправление плохо воспроизводимого бага — это мини-подвиг.


      1. GavriKos
        08.09.2015 08:24
        +8

        По разному 1000 раз прыгнуть с крыши — это работа отдела тестирования. Можно и автоматизировать, если баг есть.
        По поводу низкого FPS в дебаге — ну, вы не правы. При нормальном подходе можно и тестовую сцену собрать, которая FPS не будет садить и даст проверить физику. В общем — проблема не в средствах отладки, а в лени и жадности — скорее выпустить продукт, не потратив времени и денег на толковых специалистов.


    1. AMDmi3
      08.09.2015 00:08
      +1

      А при чём тут средства отладки? Это коммерческий продукт: купоны сострижены, никто больше никому ничего не должен, разработчики заняты N+1 игрой.


    1. Sheh
      08.09.2015 06:37
      +10

      Ну а что вы хотите? Вот я вчера акриловую ванну устанавливал… с ней крепления шли родные. Знаете, сколько там багов?

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

      Вобщем, вместо прогнозируемого 1 часа потратил 4

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


    1. Dywar
      08.09.2015 09:46

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


    1. taliban
      08.09.2015 09:51
      +4

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


  1. varnav
    07.09.2015 19:26
    -54

    В играх от 3-го лица мышку лучше вообще не трогать — для них есть геймпад.


    1. varnav
      07.09.2015 23:05
      -49

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


      1. mannaro
        08.09.2015 00:06
        +5

        вы просто в GTA: Vice City не играли ;)


        1. varnav
          08.09.2015 11:13
          +3

          Не играл. Играл в 4-ю часть. Геймпад отложил и играл мышью. Это же шутер. А прицеливаться удобнее мышью.
          А вот Ведьмак, серия AC, серия Arkham, файтинги — это не шутеры, быстрое прицеливание не нужно — зато нужно быстрое движение персонажа и быстрое нажатие кропок. Мышь преимуществ не даёт, а у клавиатуры преимуществ вообще нет.

          Кстати в AC преимущество джойстика заметно больше всего — возможность прыгать с места в любую сторону, независимо от направления взгляда, на клавиатуре вообще не воспроизводима, также как и например шаг при небольшом отклонении стика и бег при большем отклонении.

          А в такие игры как Ori или Super Meatboy вообще почти невозможно без пада играть, о чём честно предупреждают.


        1. varnav
          08.09.2015 14:49

          Кстати аналоговые тормоз и газ это очень круто и на клаве не воспроизводимо вообще.


          1. AlexanderG
            08.09.2015 20:31

            Не понимаю, почему до сих никто не сделал клавиатуру с реакцией на силу нажатия на клавиши (WASD достаточно).


            1. varnav
              08.09.2015 23:23
              +5

              Будьте первым — станете миллионером. Может быть.


      1. ZimM
        08.09.2015 02:38
        -1

        о да! в несравнимо худшую сторону.


        1. varnav
          08.09.2015 10:59
          +3

          Вообще-то вся серия Arkham изначально сделана под геймпад.

          Кроме того на геймпаде можно играть откинувшись в кресле — это огромный плюс.


        1. varnav
          08.09.2015 11:21

          Кстати описанный баг не проявляется при игре с геймпадом. По крайней мере за 20 часов игры я с ним не сталкивался.


      1. SerDIDG
        08.09.2015 03:09

        Играю на геймпаде только в фут сим и гоночки, больше ни на что он не пригоден. Мне не в кайф играть с автоприцелом.


        1. Snakecatcher
          08.09.2015 09:55
          +1

          Любопытство разобрало — а что такое фут сим? Не нашел в поисковике.


          1. REU
            08.09.2015 10:08

            Футбольные симуляторы, наверное.


          1. realscorp
            08.09.2015 12:33
            +7

            Симулятор ступни (англ. foot simulator). Правым стиком двигаете правую ступню, левым — левую. На кнопки — шевеление пальцами. При наступании на детальку от лего геймпад вибрирует.


            1. Snakecatcher
              08.09.2015 14:05
              +8

              Главная задача, провести Мизинец (не тот, что Петир Бейлиш) среди полного опасностей мира Мебели.
              Коллега, мы изобрели новый жанр!


            1. SerDIDG
              08.09.2015 16:59
              +2

              Я бы на вашем месте перестраховался и сначала бы выложил готовую игру в Стим. Представляете как бы она была популярна у летсплееров на ютюбе :D


              1. halyavin
                09.09.2015 13:28

                Поздно, летсплееры уже в это играют (go home you're drunk): www.youtube.com/watch?v=EP7BXsNAa1E.


            1. AlexanderG
              08.09.2015 20:32
              +2

              Octodad?


              1. ArtRoman
                09.09.2015 13:20
                +1

                QWOP


        1. varnav
          08.09.2015 10:55
          +2

          Автоприцела в бенмене нет.


      1. Ogra
        08.09.2015 07:22
        +9

        Ну у меня есть два геймпада, они и правда недорогие. В файтинги/Trine с женой или другом поиграть, например.
        Но я все равно играю почти во все игры с мыши и клавиатуры. Даже в некоторые файтинги! Лично мне гораздо удобнее управляться таким образом. Но я не кричу на каждом углу «Вы меня минусуете, потому что не можете купить нормальную клаву/мышь/геймпад/руль/джойстик».


        1. Hertz
          08.09.2015 13:51

          Когда у меня временно не было своего места для компьютера, меня спас длинный HDMI кабель, телевизор и Dual Shock 4. С ними я прошел GTA 4 и Fallout: New Vegas прямо сидя на диване :-) Свои плюсы есть. Конечно, есть игры, где намного больше удовольствия с клавиатурой и мышью (с джойстиком там просто будет мучение).


      1. mayorovp
        08.09.2015 09:29

        Удовольствия от мыши, может, и правда меньше — но в начале каждого третьего прохождения игры на ютубе я слышу фразу: «в этот раз я играю с геймпада, поэтому в игре могу тупить, не обращайте внимания».

        Конечно, это дело привычки — но новые игры выходят регулярно, перепроходить их, как правило, не интересно, — и у каждой свое управление. Если для клавиатуры WASD уже стандарт — то назначение стиков геймпада каждая игра понимает по-своему.


        1. varnav
          08.09.2015 11:19
          +1

          А в каких играх от 3-его лица назначение стиков отличается от «левым ходить, правым смотреть» — не подскажете?


      1. TheRaven
        08.09.2015 11:30

        Есть игры от третьего лица в которых мышь необходима. Взять хотя бы StarConflict с его догфайтами в кучах астероидов.


    1. varnav
      08.09.2015 11:41
      +2

      И да, спасибо за минусовую карму. Все мои публикации на хабре распубликованы. Они не пропадут, перенесу в другое место.


      1. realscorp
        08.09.2015 12:47

        Да уж, система «саморегулирования» Хабра как всегда «на высоте». Я, скажем честно, тоже не согласен с вашим мнением насчет игровых контроллеров, но за что тут сливать карму — вообще не понимаю. Ну, немного заносчиво высказались, ну подумаешь — немного же. Без какой-нибудь ругани или там истерики или политических высказываний. Зачем вам минуса в карму отправлять — хоть убей, не пойму, как не пойму и в чем тут положительный эффект системы «саморегулирования».


        1. REU
          08.09.2015 12:50

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


          1. varnav
            08.09.2015 13:13

            В других местах с доводами о том, что для многих игр контроллер подходит лучше, чем клавиатура, охотно согласятся.


        1. mayorovp
          08.09.2015 13:20
          +4

          Карма была слита за оскорбления. Мне вот, к примеру, неприятно читать, будто бы я просто «не смог» купить геймпад. А для кого-то это может оказаться и вовсе больным местом…


          1. varnav
            08.09.2015 14:36

            На тот момент мой первый нейтральный комментарий про геймпад уже набрал -20


            1. AlexanderG
              08.09.2015 20:34

              Потому что он написан в пассивно-агрессивной манере и касается вкусовщины. А о вкусах, как правило, спорить нет никакого смысла.


          1. varnav
            08.09.2015 23:30

            для того кто реально не может по причине крайней бедности — у меня есть логитековский клон контроллера xbox 360, готов подарить.


          1. realscorp
            09.09.2015 07:46
            +1

            По-моему, для выражения мысли «мне не нравится ваше мнение» нужно использовать минусы на комментарии. И автору коммента будет понятно, что его мнение как минимум не находит общественной поддержки, и из общественной жизни Хабра он за это мнение не «выключится».
            «Выключать» хабрапользователя надо за оголтелую неадекватность и прямые оскорбления.
            Иначе все это похоже на систему доносов при тоталитарном государстве. «Мне не нравится мнение соседа — пусть его посадят с глаз долой».


        1. Ogra
          08.09.2015 13:21
          +6

          Пост про высший пилотаж — правку гейзенбага без исходников, зачем тут комменты «минусуют те, кто не смог купить геймпад»?
          Здесь вообще не место холивару геймпад/клава, тем более в таком тоне.


          1. varnav
            08.09.2015 14:42

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

            Этого бага при игре на геймпадах нет.


            1. TheRaven
              08.09.2015 15:43
              +2

              … к вопросу о том, что все что не лежит у вас на жестком диске — может пропасть…


              1. varnav
                08.09.2015 17:04

                Обычно любят утверждать противоположное — что из интернета ничего нельзя удалить.


                1. mayorovp
                  08.09.2015 21:16

                  Из интернета и правда ничего нельзя удалить — если ставить целью именно удаление некоторой информации из всего интернета.

                  Удалить же конкретную единицу информации с конкретной площадки — куда проще.


              1. AlexanderG
                08.09.2015 20:34
                +1

                Столкнулся с этим, когда отложил «на будущее» несколько редких видео на ютубе — исчезли.


        1. Diaver
          08.09.2015 18:07
          +1

          Я как-то предлагал администрации ввести правило, когда минус в карту дает пол минуса самому минусующему, чтобы народ задумался что делает перед тем как демотивировать человека, но в администрации как всегда ответили: «Все отлично, ничего менять не будем».
          Вот и получаем ситуацию, когда за один комментарий сливают человека полностью. В результате, каждый перед как написать свое мнение тысячу раз подумает, а лучше вообще ничего писать не будет, хотя комменты на хабре зачастую интереснее читать чем сами статьи. И последнее время их все меньше и меньше после введения новой системы.
          Печаль…


          1. stigory
            09.09.2015 04:47

            минус в карту дает пол минуса самому минусующему

            Мне кажется, что это не самый удачный вариант. Прямая обратная реакция в этом случае неуместна.
            Более правильным был бы подсчет «индекса мизантропии». И учет этого индекса при начислении баллов кармы.
            Другими словами: чем больше ты минусуешь — тем меньше ты сам получишь от чужих плюсов в свою карму.
            В этом случае нет прямой зависимости от конкретного действия. Ведь минусы бывают вполне оправданными. Но есть глобальное воздействие если ты склонен минусовать постоянно.


            1. Diaver
              09.09.2015 10:26
              +2

              На мой взгляд, очень даже уместна. Минусить человеку карму, это плохо, это демотивирует человека, портит ему настроение и лишает возможности и желания общаться через комментарии. Проблема в том что хаюроюзеры в целом не понимают, что минус в карму это последнее дело и его надо ставить, когда вы для себя решили что человек мудак и вы тут его не хотите видеть. Часто бывает что у человека и статьи есть и комменты в целом положительные и все равно ему сливают карму за один комментарий, как вышестоящему товарищу, просто потому что этот комментарий не понравился или просто следуя тупому стадному инстинкту. Хотя если не понравился комментарий, нужно ставить минус комментарию.
              В результате, надо 100 раз подумать прежде писать комментарий, который не следует общему мнению, даже если ты положительный товарищ с положительной оценкой комментариям и статьям, так как тебя легко могут слить в большой минус вот такие вот не сознательные или в комплексом вахтера.


      1. vayho
        08.09.2015 17:32
        +1

        мде, сочувствую нужно скопипастить ваши статьи на всякий, а то тут куча народа толкового уже свалила или ушла в инактив(не пишут статей) а если еще и статьи удалять начнут нахрен этот хабр вообще тогда нужен, особенно доставляет как ребят минусуют на -70 в статьях про политику


        1. varnav
          08.09.2015 18:02

          Да я уже скопипастил, см. в профиль


          1. Maccimo
            08.09.2015 22:03

            В профиле написано «В связи с», но где же эта связь?


        1. mayorovp
          08.09.2015 21:19

          Ага. Лучше бы сами статьи про политику так же минусовали…


      1. realscorp
        09.09.2015 07:50
        +1

        Все мои публикации на хабре распубликованы.

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


        1. varnav
          09.09.2015 09:04

          Окей, одну запубликую обратно. :)


        1. varnav
          09.09.2015 09:10
          -1

          А вот минусованию вижу это не помеха, карма ещё просела.

          Такой режим саморегуляции Аристотель называл охлократией.

          И да, слова насчёт недорогих геймпадов беру обратно, заказал вчера за 3000 р. контроллер Xbox One, недорогим он мне не показался.


    1. s5656
      08.09.2015 11:51
      -3

      Геймпады пригодны только для платформеров и файтингов, во все остальное играть мучительно больно.


  1. jonic
    07.09.2015 19:49

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


  1. agranom555
    07.09.2015 20:19
    +5

    Может разработчикам написать? Хотя проигнорируют скорее всего, но вдруг.


    1. clamaw
      07.09.2015 20:52
      +4

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


      1. agranom555
        08.09.2015 16:42

        Нее.Они выпустили ее летом. Из-за багов сняли с продаж. Сейчас делаю патч. Как сделают, тогда снова выпустят в продажу. Они же еще дополнения делать будут. Там season pass есть даже.


  1. cher11
    07.09.2015 20:38
    +2

    Со стороны действия в статье похожи на магию. Очень интересно, спасибо!
    PS. На PS4 с багом действительно ни разу не сталкивался


  1. Hertz
    07.09.2015 20:48
    +4

    Очень занимательно, спасибо!
    Можно предположить, что в мире игры очень много состояния, и какие-то области памяти содержат значения, которые в разное время растут и убывают. Сильно мешали подобные значения при поиске скорости персонажа? Или прием с «увеличили, потом уменьшили» отсек большинство мусора?


    1. ID_Daemon
      07.09.2015 21:46
      +7

      Верно. Даже после 2-3 циклов «увеличили-уменьшили» осталось несколько сотен значений, и все они синхронно меняются со скоростью. Для поиска единственного правильного существуют и другие методики, типа наблюдения за ними в реальном времени, отсечения заведомо неправильных, перебор в конце концов.


  1. SerDIDG
    07.09.2015 21:21
    +3

    Мда, «эффективный» менеджмент Warner Bros запарывает уже вторую игру о бэтмене из пока лучшей серии.


  1. barabanus
    07.09.2015 21:42
    -6

    Не знаю, уместно ли здесь такое, но все же..


    1. barabanus
      08.09.2015 00:05
      +22

      Я понял, нужно было написать «Снимаю шляпу»


  1. n0dwis
    07.09.2015 22:58
    +55

    Снимаю шляпу. Патчить физику на уровне ассемблера… просто нет слов.


  1. Zyoma
    07.09.2015 23:01
    +12

    Снимаю шляпу, очень сильно. При прочтении создавалось впечатление поиска иголки в стоге сена. Впрочем, так оно и есть.


  1. ReklatsMasters
    07.09.2015 23:30
    +5

    Аплодирую стоя. До самого конца не верил, что удастся докопаться до проблемы.


  1. zo_oz
    07.09.2015 23:45

    Статья крутая! Проясните, пожалуйста пару моментов.

    Это оказалась середина длиннющей подпрограммы, почти наполовину состоящей из вычислений с плавающей точкой. Видимо это и есть код, полностью определяющий весь полёт Бэтмена. Начнём потихоньку его изучать. Как нам сообщил отладчик, скорость изменяется при выполнении команд, выделенных зеленым, значит она содержится в [rdi+0000144C], а перед этим вычисляется в регистре xmm8 (выделено красным).

    Как вы сходу определили что нужные инструкции лежат по адресам 56F5CD и 56F5DD? а например не по 56F5E8? Или сходу — это только в статье, а на самом деле после отладки?
    Как исправить ошибку? Например, для Arkham Knight перед вычислением корня добавим команду «maxps xmm2,xmm9» (максимум), так как в xmm9 у нас ноль, результат всегда будет положительным. Для Origins используем команду «fabs» (модуль). Запускаем игру и убеждаемся, что глюков больше нет: Бэтмен не дёргается, а летит куда нужно.

    А что лежит в xmm9? Почему вы уверены что там всегда 0? Или это регистр вообще не используется?

    Еще раз спасибо за статью, логика ошибки понятна, это же порт с консоли…


    1. ID_Daemon
      07.09.2015 23:51
      +2

      1. Аппаратная точка останова ставится на ячейку памяти, чтобы определить, какие инструкции меняют её содержимое. В ходе выполнения игры Cheat Engine запоминает все адреса и выдаёт список.

      2. Немного ранее если посмотреть по коду в xmm9 заносится 0. Я конечно не могу быть полностью уверенным, что каким-нибудь условным переходом мы не попадём сюда с другим значением в xmm9, но если это случится, можно будет исправить ;)


  1. Vanger13
    08.09.2015 00:07
    +22

    Этот труд стоит того чтобы перевести и ткнуть носом издателей\разработчиков. Пользы для общества с рускоязычной статьи почти что 0, а вот такая же на реддите или блоке cynical brit'a может сильно изменить доверие к предзаказам громикх AAA игр вообще и к студии-разработчику в частности. Используя аргументы воде «вот, тут человек без исходников понял что происходит», а эти ребята до сих пор бананы пинают… А тут может и издатель подтянется, мол «а мы и не знали» :)


    1. pehat
      08.09.2015 03:04
      +1

      В лицензионном соглашении, как правило, написано: DO NOT DISASSEMBLY/DECOMPILE. Каким бы душком от этого кода ни пахло, его просто нельзя вскрывать (по крайней мере, на глазах у издателя). Вы только представьте – отсудить денег за игру, которую толком и продать нельзя!


      1. Areso
        08.09.2015 06:10
        +4

        Согласно российскому законодательству это весьма спорный пункт, разве нет? Статья 1280 ГК РФ. Особенно в случае, если лицензия приобретена а) законно б) указанный баг нарушает функционал продукта.


      1. norguhtar
        08.09.2015 10:24
        +2

        В России можно. Законодательство прямо разрешает :)


      1. nikitasius
        08.09.2015 13:57
        +1

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


      1. Muzzy0
        09.09.2015 11:28

        Это актуально в том случае, если копия у автора — лицензионная :)))
        Ибо если автор принял лицензионное соглашение — то вы правы. Если нет — то это уже другая статья :)


        1. Ogra
          09.09.2015 11:48
          +3

          Пункты лицензионного соглашения противоречащие законодательству — ничтожны =)


  1. boblenin
    08.09.2015 01:24
    +1

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


    1. vorphalack
      08.09.2015 02:00
      +10

      так им и платить надо толково…


    1. AMDmi3
      08.09.2015 05:03

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


  1. cjmaxik
    08.09.2015 02:53
    +9

    Только теперь это оказалась не мышь, а сам Бэтмен
    В этом месте на секунду случился когнитивный диссонанс =)

    Отличная статья, спасибо!


  1. igordata
    08.09.2015 08:35
    -2

    Снимаю шляпу!


  1. SHVV
    08.09.2015 08:41
    +7

    Шикарно!
    Если не секрет, сколько времени у вас примерно ушло, чтобы обнаружить и пофиксить баг?


    1. ID_Daemon
      08.09.2015 18:46
      +6

      Это происходило в течение нескольких дней, поэтому трудно сказать. Где-то 5-10 часов. Я тут очень кратко всё описал, в основном удачные моменты. Если рассказать о всех фейлах, которые были в процессе поиска, возможно, будет даже интереснее. Это было действительно похоже на детектив. Например, я записывал видео со множеством полётов, и потом анализировал запись, пытаясь определить, при каких условиях появляется баг. Много времени ушло на то, чтобы докопаться до смысла вычислений. Чтобы можно было не просто написать «я тут нашёл, они берут корень из отрицательного числа», а что именно они делают, и почему.


  1. Orgazmo
    08.09.2015 12:58
    +4

    Вот это вот всё что Вы проделали, это для меня кажется чем-то из разряда квантовой хромодинамики и теории струн. Браво брависсимо!


  1. TimsTims
    08.09.2015 15:46
    +4

    Статья на 5. Особенно порадовал не столько сам поиск ошибки, но и записанные ролики с помежуточными результатами.
    А бесконечный полет бэтмена — так вообще заглядение!