Пользователь
0,0
рейтинг
7 сентября 2015 в 18:56

Разработка → Реверс-инжиниринг полёта Бэтмена



Этим летом вышла очередная игра из серии 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>

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

Подробнее
Реклама

Самое читаемое Разработка

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

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

    Поймали злодеи академика, математика и программиста. Привели их на крышу высотного дома и сказали, что внизу натянут тент, кто спрыгнет и на тент попадет, тот жив останется. Академик развел теорию, долго чего-то думал, прыгнул – разбился. Математик быстро посчитал, прикинул, все учел, прыгнул и попал на тент, спасся. Программист думает: ну, математик все сосчитал, я сейчас так же сделаю. Разбегается, прыгает, и с воплем «Блин, перепутал знак!» улетает в небо…
    • –11
      <зануда stat="on">Мой дед называл этот анекдот бородатым.</зануда>
      
      • +10
        Ваш ник мумифицирует бороду деда.
      • +21
        И что? найдутся те, кто читает впервые.
      • +8
        «И что дед таки разбился? Не он задолбал прыгать туда-сюда, пристрелили нафиг»
  • +21
    Вот интересно. Вы реверс-инжинирингом смогли выловить и пофиксить баг. Неужели при всех нынешних мощнейших средствах отладки разработчики игры не могут докопаться до этой проблемы самостоятельно уже несколько лет (Origins вышел в 2013ом). Противная же проблема, играть мешает жутко.
    • +8
    • +34
      Может быть пытались, но voron-vp.livejournal.com/42033.html
      • +1
        Вот так и не отличишь, правда это или шутка.
        /me ушёл думать
        • 0
          Персонажи есть, компанию угадать нетрудно, можно и проверить.
    • 0
      Средства отладки со временем становятся только хуже. В релизе из-за все более умного компилятора дебаггер показывает что угодно, но только не значения переменных и не ту строку, которая сейчас исполняется. В дебаге, программа просто работает в 100 раз медленнее и нужно очень долго ждать загрузки (да и удастся ли вообще повторить баг при паре fps?).

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

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

      • +8
        По разному 1000 раз прыгнуть с крыши — это работа отдела тестирования. Можно и автоматизировать, если баг есть.
        По поводу низкого FPS в дебаге — ну, вы не правы. При нормальном подходе можно и тестовую сцену собрать, которая FPS не будет садить и даст проверить физику. В общем — проблема не в средствах отладки, а в лени и жадности — скорее выпустить продукт, не потратив времени и денег на толковых специалистов.
    • +1
      А при чём тут средства отладки? Это коммерческий продукт: купоны сострижены, никто больше никому ничего не должен, разработчики заняты N+1 игрой.
    • +10
      Ну а что вы хотите? Вот я вчера акриловую ванну устанавливал… с ней крепления шли родные. Знаете, сколько там багов?

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

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

      Это наводит на мысли, что проблема не в технологиях, а всё же в людях, а именно, в организации производства продукта.
      Владелец фирмы вовсе не заботится о качестве продукта, который его фирма производит. Видимо, прибыль есть и им этого достаточно.
    • 0
      Думаю потому что у них в голове сотни других конструкций до которых еще никто из третьих лиц не дошел.
      Ссылку на пост им в саппорт кинуть, исправят утверждениями.
    • +4
      А вы думаете у них больше тасков нет? Есть процесс разработки, и никто не даст вам времени сидеть и ковыряться с багом который всплывает иногда, при опреределенных обстоятельствах, не факт что эти обстоятельства нашли и определили. Возможно у них этот баг висит в багтрекере, но до него еще руки не дошли.
  • –54
    В играх от 3-го лица мышку лучше вообще не трогать — для них есть геймпад.
    • –49
      минусуют те, кто не смог купить геймпад. зря. они недорогие — а удовольствие от игры несравнимо другое.
      • +5
        вы просто в GTA: Vice City не играли ;)
        • +3
          Не играл. Играл в 4-ю часть. Геймпад отложил и играл мышью. Это же шутер. А прицеливаться удобнее мышью.
          А вот Ведьмак, серия AC, серия Arkham, файтинги — это не шутеры, быстрое прицеливание не нужно — зато нужно быстрое движение персонажа и быстрое нажатие кропок. Мышь преимуществ не даёт, а у клавиатуры преимуществ вообще нет.

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

          А в такие игры как Ori или Super Meatboy вообще почти невозможно без пада играть, о чём честно предупреждают.
        • 0
          Кстати аналоговые тормоз и газ это очень круто и на клаве не воспроизводимо вообще.
          • 0
            Не понимаю, почему до сих никто не сделал клавиатуру с реакцией на силу нажатия на клавиши (WASD достаточно).
            • +5
              Будьте первым — станете миллионером. Может быть.
      • –1
        о да! в несравнимо худшую сторону.
        • +3
          Вообще-то вся серия Arkham изначально сделана под геймпад.

          Кроме того на геймпаде можно играть откинувшись в кресле — это огромный плюс.
        • 0
          Кстати описанный баг не проявляется при игре с геймпадом. По крайней мере за 20 часов игры я с ним не сталкивался.
      • 0
        Играю на геймпаде только в фут сим и гоночки, больше ни на что он не пригоден. Мне не в кайф играть с автоприцелом.
        • +1
          Любопытство разобрало — а что такое фут сим? Не нашел в поисковике.
          • 0
            Футбольные симуляторы, наверное.
          • +7
            Симулятор ступни (англ. foot simulator). Правым стиком двигаете правую ступню, левым — левую. На кнопки — шевеление пальцами. При наступании на детальку от лего геймпад вибрирует.
            • +8
              Главная задача, провести Мизинец (не тот, что Петир Бейлиш) среди полного опасностей мира Мебели.
              Коллега, мы изобрели новый жанр!
            • +2
              Я бы на вашем месте перестраховался и сначала бы выложил готовую игру в Стим. Представляете как бы она была популярна у летсплееров на ютюбе :D
            • +2
              Octodad?
              • +1
                QWOP
        • +2
          Автоприцела в бенмене нет.
      • +9
        Ну у меня есть два геймпада, они и правда недорогие. В файтинги/Trine с женой или другом поиграть, например.
        Но я все равно играю почти во все игры с мыши и клавиатуры. Даже в некоторые файтинги! Лично мне гораздо удобнее управляться таким образом. Но я не кричу на каждом углу «Вы меня минусуете, потому что не можете купить нормальную клаву/мышь/геймпад/руль/джойстик».
        • 0
          Когда у меня временно не было своего места для компьютера, меня спас длинный HDMI кабель, телевизор и Dual Shock 4. С ними я прошел GTA 4 и Fallout: New Vegas прямо сидя на диване :-) Свои плюсы есть. Конечно, есть игры, где намного больше удовольствия с клавиатурой и мышью (с джойстиком там просто будет мучение).
      • 0
        Удовольствия от мыши, может, и правда меньше — но в начале каждого третьего прохождения игры на ютубе я слышу фразу: «в этот раз я играю с геймпада, поэтому в игре могу тупить, не обращайте внимания».

        Конечно, это дело привычки — но новые игры выходят регулярно, перепроходить их, как правило, не интересно, — и у каждой свое управление. Если для клавиатуры WASD уже стандарт — то назначение стиков геймпада каждая игра понимает по-своему.
        • +1
          А в каких играх от 3-его лица назначение стиков отличается от «левым ходить, правым смотреть» — не подскажете?
      • 0
        Есть игры от третьего лица в которых мышь необходима. Взять хотя бы StarConflict с его догфайтами в кучах астероидов.
    • +2
      И да, спасибо за минусовую карму. Все мои публикации на хабре распубликованы. Они не пропадут, перенесу в другое место.
      • 0
        Да уж, система «саморегулирования» Хабра как всегда «на высоте». Я, скажем честно, тоже не согласен с вашим мнением насчет игровых контроллеров, но за что тут сливать карму — вообще не понимаю. Ну, немного заносчиво высказались, ну подумаешь — немного же. Без какой-нибудь ругани или там истерики или политических высказываний. Зачем вам минуса в карму отправлять — хоть убей, не пойму, как не пойму и в чем тут положительный эффект системы «саморегулирования».
        • 0
          Что бы убирать неугодных, если ты думаешь не так как все, то тебя сольют, что бы ты не высказывал своего мнения.
          • 0
            В других местах с доводами о том, что для многих игр контроллер подходит лучше, чем клавиатура, охотно согласятся.
        • +4
          Карма была слита за оскорбления. Мне вот, к примеру, неприятно читать, будто бы я просто «не смог» купить геймпад. А для кого-то это может оказаться и вовсе больным местом…
          • 0
            На тот момент мой первый нейтральный комментарий про геймпад уже набрал -20
            • 0
              Потому что он написан в пассивно-агрессивной манере и касается вкусовщины. А о вкусах, как правило, спорить нет никакого смысла.
          • 0
            для того кто реально не может по причине крайней бедности — у меня есть логитековский клон контроллера xbox 360, готов подарить.
          • +1
            По-моему, для выражения мысли «мне не нравится ваше мнение» нужно использовать минусы на комментарии. И автору коммента будет понятно, что его мнение как минимум не находит общественной поддержки, и из общественной жизни Хабра он за это мнение не «выключится».
            «Выключать» хабрапользователя надо за оголтелую неадекватность и прямые оскорбления.
            Иначе все это похоже на систему доносов при тоталитарном государстве. «Мне не нравится мнение соседа — пусть его посадят с глаз долой».
        • +6
          Пост про высший пилотаж — правку гейзенбага без исходников, зачем тут комменты «минусуют те, кто не смог купить геймпад»?
          Здесь вообще не место холивару геймпад/клава, тем более в таком тоне.
          • 0
            Ну и мне на хабре тоже не место — так решило сообщество, поэтому мои публикации, добавленные в избранное тысячами человек, и имеющие больше сотни тысяч просмотров (я не хвалюсь, это просто статистика), переезжают в другое место.

            Этого бага при игре на геймпадах нет.
            • +2
              … к вопросу о том, что все что не лежит у вас на жестком диске — может пропасть…
              • 0
                Обычно любят утверждать противоположное — что из интернета ничего нельзя удалить.
                • 0
                  Из интернета и правда ничего нельзя удалить — если ставить целью именно удаление некоторой информации из всего интернета.

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

            Мне кажется, что это не самый удачный вариант. Прямая обратная реакция в этом случае неуместна.
            Более правильным был бы подсчет «индекса мизантропии». И учет этого индекса при начислении баллов кармы.
            Другими словами: чем больше ты минусуешь — тем меньше ты сам получишь от чужих плюсов в свою карму.
            В этом случае нет прямой зависимости от конкретного действия. Ведь минусы бывают вполне оправданными. Но есть глобальное воздействие если ты склонен минусовать постоянно.
            • +2
              На мой взгляд, очень даже уместна. Минусить человеку карму, это плохо, это демотивирует человека, портит ему настроение и лишает возможности и желания общаться через комментарии. Проблема в том что хаюроюзеры в целом не понимают, что минус в карму это последнее дело и его надо ставить, когда вы для себя решили что человек мудак и вы тут его не хотите видеть. Часто бывает что у человека и статьи есть и комменты в целом положительные и все равно ему сливают карму за один комментарий, как вышестоящему товарищу, просто потому что этот комментарий не понравился или просто следуя тупому стадному инстинкту. Хотя если не понравился комментарий, нужно ставить минус комментарию.
              В результате, надо 100 раз подумать прежде писать комментарий, который не следует общему мнению, даже если ты положительный товарищ с положительной оценкой комментариям и статьям, так как тебя легко могут слить в большой минус вот такие вот не сознательные или в комплексом вахтера.
      • +1
        мде, сочувствую нужно скопипастить ваши статьи на всякий, а то тут куча народа толкового уже свалила или ушла в инактив(не пишут статей) а если еще и статьи удалять начнут нахрен этот хабр вообще тогда нужен, особенно доставляет как ребят минусуют на -70 в статьях про политику
        • 0
          Да я уже скопипастил, см. в профиль
          • 0
            В профиле написано «В связи с», но где же эта связь?
        • 0
          Ага. Лучше бы сами статьи про политику так же минусовали…
      • +1
        Все мои публикации на хабре распубликованы.

        Тут вы тоже не правы. Например, я не могу поставить вам плюс в карму для компенсации минусов за неудачный комментарий, потому что плюсование кармы пользователей без опубликованный статей невозможно.
        • 0
          Окей, одну запубликую обратно. :)
        • –1
          А вот минусованию вижу это не помеха, карма ещё просела.

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

          И да, слова насчёт недорогих геймпадов беру обратно, заказал вчера за 3000 р. контроллер Xbox One, недорогим он мне не показался.
    • –3
      Геймпады пригодны только для платформеров и файтингов, во все остальное играть мучительно больно.
  • 0
    С данным багом не сталкивался(сейчас прохожу ее), но фризы при загрузке мира заметны очень :)
  • +5
    Может разработчикам написать? Хотя проигнорируют скорее всего, но вдруг.
    • +4
      Я думаю, что если, как пишет автор, игру сняли в продаж, то тех разработчиков там уже может и не быть.
      • 0
        Нее.Они выпустили ее летом. Из-за багов сняли с продаж. Сейчас делаю патч. Как сделают, тогда снова выпустят в продажу. Они же еще дополнения делать будут. Там season pass есть даже.
  • +2
    Со стороны действия в статье похожи на магию. Очень интересно, спасибо!
    PS. На PS4 с багом действительно ни разу не сталкивался
  • +4
    Очень занимательно, спасибо!
    Можно предположить, что в мире игры очень много состояния, и какие-то области памяти содержат значения, которые в разное время растут и убывают. Сильно мешали подобные значения при поиске скорости персонажа? Или прием с «увеличили, потом уменьшили» отсек большинство мусора?
    • +7
      Верно. Даже после 2-3 циклов «увеличили-уменьшили» осталось несколько сотен значений, и все они синхронно меняются со скоростью. Для поиска единственного правильного существуют и другие методики, типа наблюдения за ними в реальном времени, отсечения заведомо неправильных, перебор в конце концов.
  • +3
    Мда, «эффективный» менеджмент Warner Bros запарывает уже вторую игру о бэтмене из пока лучшей серии.
  • –6
    Не знаю, уместно ли здесь такое, но все же..
    • +22
      Я понял, нужно было написать «Снимаю шляпу»
  • +55
    Снимаю шляпу. Патчить физику на уровне ассемблера… просто нет слов.
  • +12
    Снимаю шляпу, очень сильно. При прочтении создавалось впечатление поиска иголки в стоге сена. Впрочем, так оно и есть.
  • +5
    Аплодирую стоя. До самого конца не верил, что удастся докопаться до проблемы.
  • 0
    Статья крутая! Проясните, пожалуйста пару моментов.
    Это оказалась середина длиннющей подпрограммы, почти наполовину состоящей из вычислений с плавающей точкой. Видимо это и есть код, полностью определяющий весь полёт Бэтмена. Начнём потихоньку его изучать. Как нам сообщил отладчик, скорость изменяется при выполнении команд, выделенных зеленым, значит она содержится в [rdi+0000144C], а перед этим вычисляется в регистре xmm8 (выделено красным).

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

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

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

      2. Немного ранее если посмотреть по коду в xmm9 заносится 0. Я конечно не могу быть полностью уверенным, что каким-нибудь условным переходом мы не попадём сюда с другим значением в xmm9, но если это случится, можно будет исправить ;)
  • +22
    Этот труд стоит того чтобы перевести и ткнуть носом издателей\разработчиков. Пользы для общества с рускоязычной статьи почти что 0, а вот такая же на реддите или блоке cynical brit'a может сильно изменить доверие к предзаказам громикх AAA игр вообще и к студии-разработчику в частности. Используя аргументы воде «вот, тут человек без исходников понял что происходит», а эти ребята до сих пор бананы пинают… А тут может и издатель подтянется, мол «а мы и не знали» :)
    • +1
      В лицензионном соглашении, как правило, написано: DO NOT DISASSEMBLY/DECOMPILE. Каким бы душком от этого кода ни пахло, его просто нельзя вскрывать (по крайней мере, на глазах у издателя). Вы только представьте – отсудить денег за игру, которую толком и продать нельзя!
      • +4
        Согласно российскому законодательству это весьма спорный пункт, разве нет? Статья 1280 ГК РФ. Особенно в случае, если лицензия приобретена а) законно б) указанный баг нарушает функционал продукта.
      • +2
        В России можно. Законодательство прямо разрешает :)
      • +1
        Во Франции право расковыривания программ превыше любого соглашения и зашито в законе. Поэтому компания, которая работает во Франции должна это учитывать.
      • 0
        Это актуально в том случае, если копия у автора — лицензионная :)))
        Ибо если автор принял лицензионное соглашение — то вы правы. Если нет — то это уже другая статья :)
        • +3
          Пункты лицензионного соглашения противоречащие законодательству — ничтожны =)
  • +1
    Вот у меня, пока я читал статью, в голове звучал вопрос. Почему же чудесная компания, выпускающая этот чудесный продукт, не наймет толковых людей? Таких как автор статьи.
    • +10
      так им и платить надо толково…
    • 0
      Потому что им нужно штамповать больше одинаковых игр, а не баги править.
  • +9
    Только теперь это оказалась не мышь, а сам Бэтмен
    В этом месте на секунду случился когнитивный диссонанс =)

    Отличная статья, спасибо!
  • –2
    Снимаю шляпу!
  • +7
    Шикарно!
    Если не секрет, сколько времени у вас примерно ушло, чтобы обнаружить и пофиксить баг?
    • +6
      Это происходило в течение нескольких дней, поэтому трудно сказать. Где-то 5-10 часов. Я тут очень кратко всё описал, в основном удачные моменты. Если рассказать о всех фейлах, которые были в процессе поиска, возможно, будет даже интереснее. Это было действительно похоже на детектив. Например, я записывал видео со множеством полётов, и потом анализировал запись, пытаясь определить, при каких условиях появляется баг. Много времени ушло на то, чтобы докопаться до смысла вычислений. Чтобы можно было не просто написать «я тут нашёл, они берут корень из отрицательного числа», а что именно они делают, и почему.
  • +4
    Вот это вот всё что Вы проделали, это для меня кажется чем-то из разряда квантовой хромодинамики и теории струн. Браво брависсимо!
  • +4
    Статья на 5. Особенно порадовал не столько сам поиск ошибки, но и записанные ролики с помежуточными результатами.
    А бесконечный полет бэтмена — так вообще заглядение!
  • +4
    Ну что, ура! :)
    Our October patch was focused on a large number of functional and stability-related bug fixes, including issues reported by the community. Outside of adding PC support for the Season Pass DLC & Photo Mode features, the following noteworthy PC bugs were addressed:

    Fixed a bug where Batman’s glide would glitch causing him to flip upside down due to negative numbers in glide speed calculations – shout out to uns3en and ID_Daemon
    ...

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